1
0
mirror of https://github.com/google/nomulus synced 2026-01-30 01:22:23 +00:00

Compare commits

..

11 Commits

Author SHA1 Message Date
weiminyu
7c64992c73 Cloned from CL 251456914 by 'g4 patch'.
Original change by cpovirk@cpovirk:rosie251284456-0055_Rosie:31511:citc on 2019/06/04 09:48:27.

Update to Truth 0.45, and address deprecations.

Renames may include:
- containsAllOf => containsAtLeast
- containsAllIn => containsAtLeastElementsIn
- isSameAs => isSameInstanceAs
- isOrdered => isInOrder
- isStrictlyOrdered => isInStrictOrder

The other major change is to change custom subjects to extend raw Subject instead of supplying type parameters. The type parameters are being removed from Subject. This CL will temporarily produce rawtypes warnings, which will go away when I remove the type parameters (as soon as this batch of CLs is submitted).

Some CLs in this batch also migrate calls away from actualAsString(). Its literal replacement is `"<" + actual + ">"` (unless an object overrides actualCustomStringRepresentation()), but usually I've made a larger change, such as switching from an old-style "Not true that..." failure message to one generated with the Fact API. In that case, the new code usually contains a direct reference to this.actual (a field that I occasionally had to create). Another larger change I sometimes made is to switch from a manual check-and-fail approach to instead use check(...). And sometimes I just remove a withMessage() call that's no longer necessary now that the code uses check(...), or I introduce a check(...) call. (An assertion made with check(...) automatically includes the actual value from the original subject, so there's no need to set it again with withMessage().)

Finally, there's one CL in this batch in which I migrate a Correspondence subclass to instead use Correspondence.from.

END_PUBLIC

If this is too many changes at once, let me know, and I can split it up and/or explain further. In the past, I've erred on the side of sending separate CLs for each change, which has required some owners to manually reapply each one, so now I'm trying this way.

Thanks again for your patience. There is an outside chance that this will be the last CL I send you before Truth 1.0 -- but certainly no promises :)

More information:
  Renames:
    []
    []
    []
  Removing type parameters: []
  Migration from old fail*(...) methods to new ones and to check(...): []
  Changes that replace assert*(...) with introduce check(...): []
  Correspondence subclass to Correspondence.from: []

Tested:
    TAP --sample ran all affected tests and none failed
    []

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=251921007
2019-06-07 11:46:44 -04:00
jianglai
e8c789a401 Fix builder error
We need to first populate the apt sources before installing anything. It was working on my machine because the layer was cached. After I purged all images I was able to replicate the same error message.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=251918035
2019-06-07 11:44:57 -04:00
guyben
ca1d525e28 Conform to RDAP Technical Implementation Guide
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=251864499
2019-06-07 11:43:09 -04:00
mcilwain
55dc735ba0 Export PollMessage entities to BigQuery
It would be nice to be able to query them using SQL in order to debug
some potential issues registrars might be facing.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=251863662
2019-06-07 11:41:22 -04:00
mcilwain
ff6d327183 Allow reserved domains to be created during quiet periods
We'll use this for LRP. This is safe because we must specifically reserve a
domain by including it in a reserved list, create an associated allocation
token, and distribute that token, before a create would succeed.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=250901144
2019-06-06 10:53:27 -04:00
gbrodman
79bcb227be De-duplicate flow documentation error reasons on a per-code basis
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=250894847
2019-06-06 10:51:43 -04:00
guyben
e489539df4 Enable more DNS update metrics on production
They are useful for viewing and diagnosing problems, and are not that
expensive.

We aren't enabling all the metrics though - the whole "per batch / per domain"
performance indicators are still disabled

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=250876554
2019-06-06 10:49:55 -04:00
mcilwain
dd66664e42 Add tests that some domain operations work in quiet periods
This specifically includes info, transfer, and update. Note that normal
domain creates do not work in quiet periods and are not expected to.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=250755940
2019-06-06 10:48:05 -04:00
mcilwain
7bdbd89e4d Add test that anchor tenants can be created in quiet period
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=250752454
2019-06-06 10:46:14 -04:00
mcilwain
987a648296 Smear out DNS updates over time when updating DNS for all domains
These updates can generally ran slowly in the background (i.e. they're low
priority), and shouldn't clog up the system to the point where they slow down
live incoming customer-requested updates.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=250732171
2019-06-06 10:44:27 -04:00
gbrodman
d2f955a488 Split ResourceAlreadyExistsException based on if this client owns the resource
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=250728711
2019-06-06 10:42:38 -04:00
118 changed files with 1486 additions and 1067 deletions

View File

@@ -35,8 +35,8 @@ com.google.oauth-client:google-oauth-client:1.27.0
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
com.google.template:soy:2018-03-14
com.google.truth.extensions:truth-java8-extension:0.44
com.google.truth:truth:0.44
com.google.truth.extensions:truth-java8-extension:0.45
com.google.truth:truth:0.45
com.googlecode.java-diff-utils:diffutils:1.3.0
com.ibm.icu:icu4j:57.1
commons-codec:commons-codec:1.10

View File

@@ -35,8 +35,8 @@ com.google.oauth-client:google-oauth-client:1.27.0
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
com.google.template:soy:2018-03-14
com.google.truth.extensions:truth-java8-extension:0.44
com.google.truth:truth:0.44
com.google.truth.extensions:truth-java8-extension:0.45
com.google.truth:truth:0.45
com.googlecode.java-diff-utils:diffutils:1.3.0
com.ibm.icu:icu4j:57.1
commons-codec:commons-codec:1.10

View File

@@ -35,8 +35,8 @@ com.google.oauth-client:google-oauth-client:1.27.0
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
com.google.template:soy:2018-03-14
com.google.truth.extensions:truth-java8-extension:0.44
com.google.truth:truth:0.44
com.google.truth.extensions:truth-java8-extension:0.45
com.google.truth:truth:0.45
com.googlecode.java-diff-utils:diffutils:1.3.0
com.ibm.icu:icu4j:57.1
commons-codec:commons-codec:1.10

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -83,24 +83,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -120,7 +118,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -142,10 +140,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.annotation:javax.annotation-api:1.2

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -82,24 +82,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -119,7 +117,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
io.grpc:grpc-netty:1.17.1
@@ -140,10 +138,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.annotation:javax.annotation-api:1.2

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -83,24 +83,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -122,7 +120,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -144,10 +142,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.annotation:javax.annotation-api:1.2

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -85,13 +85,11 @@ com.google.guava:guava-testlib:25.0-jre
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
@@ -99,18 +97,18 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.4
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
com.google.re2j:re2j:1.1
com.google.template:soy:2018-03-14
com.google.truth.extensions:truth-java8-extension:0.44
com.google.truth:truth:0.44
com.google.truth.extensions:truth-java8-extension:0.45
com.google.truth:truth:0.45
com.googlecode.charts4j:charts4j:1.3
com.googlecode.java-diff-utils:diffutils:1.3.0
com.googlecode.json-simple:json-simple:1.1.1
@@ -130,7 +128,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -152,10 +150,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -84,13 +84,11 @@ com.google.guava:guava-testlib:25.0-jre
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
@@ -98,18 +96,18 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.4
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
com.google.re2j:re2j:1.1
com.google.template:soy:2018-03-14
com.google.truth.extensions:truth-java8-extension:0.44
com.google.truth:truth:0.44
com.google.truth.extensions:truth-java8-extension:0.45
com.google.truth:truth:0.45
com.googlecode.charts4j:charts4j:1.3
com.googlecode.java-diff-utils:diffutils:1.3.0
com.googlecode.json-simple:json-simple:1.1.1
@@ -129,7 +127,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
io.grpc:grpc-netty:1.17.1
@@ -150,10 +148,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -85,13 +85,11 @@ com.google.guava:guava-testlib:25.0-jre
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
@@ -99,18 +97,18 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.4
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
com.google.re2j:re2j:1.1
com.google.template:soy:2018-03-14
com.google.truth.extensions:truth-java8-extension:0.44
com.google.truth:truth:0.44
com.google.truth.extensions:truth-java8-extension:0.45
com.google.truth:truth:0.45
com.googlecode.charts4j:charts4j:1.3
com.googlecode.java-diff-utils:diffutils:1.3.0
com.googlecode.json-simple:json-simple:1.1.1
@@ -132,7 +130,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -154,10 +152,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0

View File

@@ -71,8 +71,8 @@ ext {
'com.google.protobuf:protobuf-java:2.6.0',
'com.google.re2j:re2j:1.1',
'com.google.template:soy:2018-03-14',
'com.google.truth.extensions:truth-java8-extension:0.44',
'com.google.truth:truth:0.44',
'com.google.truth.extensions:truth-java8-extension:0.45',
'com.google.truth:truth:0.45',
'com.ibm.icu:icu4j:57.1',
'com.jcraft:jsch:0.1.55',
'com.jcraft:jzlib:1.1.3',

View File

@@ -14,7 +14,7 @@ com.moowork.gradle:gradle-node-plugin:1.2.0
com.moowork.node:com.moowork.node.gradle.plugin:1.2.0
com.netflix.nebula:gradle-lint-plugin:10.4.2
com.netflix.nebula:nebula-gradle-interop:1.0.7
com.netflix.nebula:nebula-test:7.2.4
com.netflix.nebula:nebula-test:7.2.5
commons-codec:commons-codec:1.9
commons-io:commons-io:2.5
commons-lang:commons-lang:2.6

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -85,13 +85,11 @@ com.google.guava:guava-testlib:25.0-jre
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
@@ -99,18 +97,18 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.4
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
com.google.re2j:re2j:1.1
com.google.template:soy:2018-03-14
com.google.truth.extensions:truth-java8-extension:0.44
com.google.truth:truth:0.44
com.google.truth.extensions:truth-java8-extension:0.45
com.google.truth:truth:0.45
com.googlecode.charts4j:charts4j:1.3
com.googlecode.java-diff-utils:diffutils:1.3.0
com.googlecode.json-simple:json-simple:1.1.1
@@ -132,7 +130,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -154,10 +152,10 @@ io.netty:netty-handler:4.1.31.Final
io.netty:netty-resolver:4.1.31.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.31.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -85,13 +85,11 @@ com.google.guava:guava-testlib:25.0-jre
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
@@ -99,18 +97,18 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.4
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
com.google.re2j:re2j:1.1
com.google.template:soy:2018-03-14
com.google.truth.extensions:truth-java8-extension:0.44
com.google.truth:truth:0.44
com.google.truth.extensions:truth-java8-extension:0.45
com.google.truth:truth:0.45
com.googlecode.charts4j:charts4j:1.3
com.googlecode.java-diff-utils:diffutils:1.3.0
com.googlecode.json-simple:json-simple:1.1.1
@@ -132,7 +130,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
io.grpc:grpc-netty:1.17.1
@@ -153,10 +151,10 @@ io.netty:netty-handler:4.1.31.Final
io.netty:netty-resolver:4.1.31.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.31.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -85,13 +85,11 @@ com.google.guava:guava-testlib:25.0-jre
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
@@ -99,18 +97,18 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.4
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
com.google.re2j:re2j:1.1
com.google.template:soy:2018-03-14
com.google.truth.extensions:truth-java8-extension:0.44
com.google.truth:truth:0.44
com.google.truth.extensions:truth-java8-extension:0.45
com.google.truth:truth:0.45
com.googlecode.charts4j:charts4j:1.3
com.googlecode.java-diff-utils:diffutils:1.3.0
com.googlecode.json-simple:json-simple:1.1.1
@@ -132,7 +130,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -154,10 +152,10 @@ io.netty:netty-handler:4.1.31.Final
io.netty:netty-resolver:4.1.31.Final
io.netty:netty-tcnative-boringssl-static:2.0.22.Final
io.netty:netty-transport:4.1.31.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -83,24 +83,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -122,7 +120,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -144,10 +142,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.annotation:javax.annotation-api:1.2

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -83,24 +83,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -122,7 +120,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -144,10 +142,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.annotation:javax.annotation-api:1.2

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -83,24 +83,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -122,7 +120,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -144,10 +142,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.annotation:javax.annotation-api:1.2

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -83,24 +83,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -122,7 +120,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -144,10 +142,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.annotation:javax.annotation-api:1.2

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -85,13 +85,11 @@ com.google.guava:guava-testlib:25.0-jre
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
@@ -99,18 +97,18 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.4
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
com.google.re2j:re2j:1.1
com.google.template:soy:2018-03-14
com.google.truth.extensions:truth-java8-extension:0.44
com.google.truth:truth:0.44
com.google.truth.extensions:truth-java8-extension:0.45
com.google.truth:truth:0.45
com.googlecode.charts4j:charts4j:1.3
com.googlecode.java-diff-utils:diffutils:1.3.0
com.googlecode.json-simple:json-simple:1.1.1
@@ -132,7 +130,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -154,10 +152,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -85,13 +85,11 @@ com.google.guava:guava-testlib:25.0-jre
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
@@ -99,18 +97,18 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.4
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
com.google.re2j:re2j:1.1
com.google.template:soy:2018-03-14
com.google.truth.extensions:truth-java8-extension:0.44
com.google.truth:truth:0.44
com.google.truth.extensions:truth-java8-extension:0.45
com.google.truth:truth:0.45
com.googlecode.charts4j:charts4j:1.3
com.googlecode.java-diff-utils:diffutils:1.3.0
com.googlecode.json-simple:json-simple:1.1.1
@@ -132,7 +130,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
io.grpc:grpc-netty:1.17.1
@@ -153,10 +151,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0

View File

@@ -9,11 +9,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.8
com.fasterxml.jackson.core:jackson-core:2.9.8
com.fasterxml.jackson.core:jackson-databind:2.9.8
com.github.luben:zstd-jni:1.3.8-3
com.google.api-client:google-api-client-appengine:1.28.0
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.28.0
com.google.api-client:google-api-client:1.28.0
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.0
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.44.0
@@ -85,13 +85,11 @@ com.google.guava:guava-testlib:25.0-jre
com.google.guava:guava:27.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-apache:2.0.0
com.google.http-client:google-http-client-appengine:1.28.0
com.google.http-client:google-http-client-jackson2:1.28.0
com.google.http-client:google-http-client-appengine:1.29.1
com.google.http-client:google-http-client-jackson2:1.29.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-jdo:1.28.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.28.0
com.google.http-client:google-http-client:1.29.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.1
@@ -99,18 +97,18 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.4
com.google.monitoring-client:metrics:1.0.4
com.google.monitoring-client:stackdriver:1.0.4
com.google.oauth-client:google-oauth-client-appengine:1.28.0
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.28.0
com.google.oauth-client:google-oauth-client:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.0
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
com.google.re2j:re2j:1.1
com.google.template:soy:2018-03-14
com.google.truth.extensions:truth-java8-extension:0.44
com.google.truth:truth:0.44
com.google.truth.extensions:truth-java8-extension:0.45
com.google.truth:truth:0.45
com.googlecode.charts4j:charts4j:1.3
com.googlecode.java-diff-utils:diffutils:1.3.0
com.googlecode.json-simple:json-simple:1.1.1
@@ -132,7 +130,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.17.1
io.grpc:grpc-context:1.18.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -154,10 +152,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.18.0
io.opencensus:opencensus-api:0.19.2
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.18.0
io.opencensus:opencensus-contrib-http-util:0.19.2
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0

View File

@@ -220,10 +220,15 @@ public class DnsMetrics {
Duration processingDuration,
int numberOfDomains,
int numberOfHosts) {
// We don't want to record all these metrics in production, as they are quite expensive
commitCount.increment(tld, status.name(), dnsWriter);
domainsCommittedCount.incrementBy(numberOfDomains, tld, status.name(), dnsWriter);
hostsCommittedCount.incrementBy(numberOfHosts, tld, status.name(), dnsWriter);
// We don't want to record the following metrics in production, as they are quite expensive
if (registryEnvironment == RegistryEnvironment.PRODUCTION) {
return;
}
int batchSize = numberOfDomains + numberOfHosts;
processingTimePerCommitDist.record(
@@ -244,10 +249,6 @@ public class DnsMetrics {
totalBatchSizePerCommitDist.record(batchSize, tld, status.name(), dnsWriter);
totalBatchSizePerItemDist.record(batchSize, batchSize, tld, status.name(), dnsWriter);
commitCount.increment(tld, status.name(), dnsWriter);
domainsCommittedCount.incrementBy(numberOfDomains, tld, status.name(), dnsWriter);
hostsCommittedCount.incrementBy(numberOfHosts, tld, status.name(), dnsWriter);
}
void recordActionResult(

View File

@@ -103,16 +103,16 @@ public class DnsQueue {
@VisibleForTesting
long leaseTasksBatchSize = QueueConstants.maxLeaseCount();
/**
* Enqueues the given task type with the given target name to the DNS queue.
*/
private TaskHandle addToQueue(TargetType targetType, String targetName, String tld) {
/** Enqueues the given task type with the given target name to the DNS queue. */
private TaskHandle addToQueue(
TargetType targetType, String targetName, String tld, Duration countdown) {
logger.atInfo().log(
"Adding task type=%s, target=%s, tld=%s to pull queue %s (%d tasks currently on queue)",
targetType, targetName, tld, DNS_PULL_QUEUE_NAME, queue.fetchStatistics().getNumTasks());
return queue.add(
TaskOptions.Builder.withDefaults()
.method(Method.PULL)
.countdownMillis(countdown.getMillis())
.param(DNS_TARGET_TYPE_PARAM, targetType.toString())
.param(DNS_TARGET_NAME_PARAM, targetName)
.param(DNS_TARGET_CREATE_TIME_PARAM, clock.nowUtc().toString())
@@ -127,20 +127,27 @@ public class DnsQueue {
Registries.findTldForName(InternetDomainName.from(fullyQualifiedHostName));
checkArgument(tld.isPresent(),
String.format("%s is not a subordinate host to a known tld", fullyQualifiedHostName));
return addToQueue(TargetType.HOST, fullyQualifiedHostName, tld.get().toString());
return addToQueue(TargetType.HOST, fullyQualifiedHostName, tld.get().toString(), Duration.ZERO);
}
/** Adds a task to the queue to refresh the DNS information for the specified domain. */
/** Enqueues a task to refresh DNS for the specified domain now. */
public TaskHandle addDomainRefreshTask(String fullyQualifiedDomainName) {
return addDomainRefreshTask(fullyQualifiedDomainName, Duration.ZERO);
}
/** Enqueues a task to refresh DNS for the specified domain at some point in the future. */
public TaskHandle addDomainRefreshTask(String fullyQualifiedDomainName, Duration countdown) {
return addToQueue(
TargetType.DOMAIN,
fullyQualifiedDomainName,
assertTldExists(getTldFromDomainName(fullyQualifiedDomainName)));
assertTldExists(getTldFromDomainName(fullyQualifiedDomainName)),
countdown);
}
/** Adds a task to the queue to refresh the DNS information for the specified zone. */
public TaskHandle addZoneRefreshTask(String fullyQualifiedZoneName) {
return addToQueue(TargetType.ZONE, fullyQualifiedZoneName, fullyQualifiedZoneName);
return addToQueue(
TargetType.ZONE, fullyQualifiedZoneName, fullyQualifiedZoneName, Duration.ZERO);
}
/**

View File

@@ -163,15 +163,18 @@ public final class MarkdownDocumentationFormatter {
for (Long code : flowDoc.getErrorsByCode().keySet()) {
output.append(String.format("* %d\n", code));
flowDoc.getErrorsByCode().get(code).stream()
.map(ErrorCase::getReason)
.distinct()
.forEach(
reason -> {
output.append(" * ");
String wrappedReason = reflow(fixHtml(reason), LINE_WIDTH - 8);
for (ErrorCase error : flowDoc.getErrorsByCode().get(code)) {
output.append(" * ");
String wrappedReason = reflow(fixHtml(error.getReason()), LINE_WIDTH - 8);
// Replace internal newlines with indentation and strip the final newline.
output.append(wrappedReason.trim().replace("\n", "\n" + INDENT8));
output.append('\n');
}
// Replace internal newlines with indentation and strip the final newline.
output.append(wrappedReason.trim().replace("\n", "\n" + INDENT8));
output.append('\n');
});
}
output.append('\n');
}

View File

@@ -31,7 +31,8 @@ import google.registry.flows.EppException.ParameterValueRangeErrorException;
import google.registry.flows.exceptions.MissingTransferRequestAuthInfoException;
import google.registry.flows.exceptions.NotPendingTransferException;
import google.registry.flows.exceptions.NotTransferInitiatorException;
import google.registry.flows.exceptions.ResourceAlreadyExistsException;
import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientException;
import google.registry.flows.exceptions.ResourceCreateContentionException;
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
import google.registry.flows.exceptions.ResourceToDeleteIsReferencedException;
import google.registry.flows.exceptions.TooManyResourceChecksException;
@@ -45,6 +46,7 @@ import google.registry.model.eppcommon.StatusValue;
import google.registry.model.index.ForeignKeyIndex;
import google.registry.model.transfer.TransferStatus;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
@@ -131,9 +133,16 @@ public final class ResourceFlowUtils {
}
public static <R extends EppResource> void verifyResourceDoesNotExist(
Class<R> clazz, String targetId, DateTime now) throws EppException {
if (loadAndGetKey(clazz, targetId, now) != null) {
throw new ResourceAlreadyExistsException(targetId);
Class<R> clazz, String targetId, DateTime now, String clientId) throws EppException {
Key<R> key = loadAndGetKey(clazz, targetId, now);
if (key != null) {
R resource = ofy().load().key(key).now();
// These are similar exceptions, but we can track them internally as log-based metrics.
if (Objects.equals(clientId, resource.getPersistedCurrentSponsorClientId())) {
throw new ResourceAlreadyExistsForThisClientException(targetId);
} else {
throw new ResourceCreateContentionException(targetId);
}
}
}

View File

@@ -29,6 +29,8 @@ import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientException;
import google.registry.flows.exceptions.ResourceCreateContentionException;
import google.registry.model.contact.ContactCommand.Create;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.metadata.MetadataExtension;
@@ -46,7 +48,8 @@ import org.joda.time.DateTime;
/**
* An EPP flow that creates a new contact.
*
* @error {@link google.registry.flows.exceptions.ResourceAlreadyExistsException}
* @error {@link ResourceAlreadyExistsForThisClientException}
* @error {@link ResourceCreateContentionException}
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
*/
@@ -69,7 +72,7 @@ public final class ContactCreateFlow implements TransactionalFlow {
validateClientIsLoggedIn(clientId);
Create command = (Create) resourceCommand;
DateTime now = ofy().getTransactionTime();
verifyResourceDoesNotExist(ContactResource.class, targetId, now);
verifyResourceDoesNotExist(ContactResource.class, targetId, now, clientId);
ContactResource newContact =
new ContactResource.Builder()
.setContactId(targetId)

View File

@@ -44,6 +44,7 @@ import static google.registry.model.EppResourceUtils.createDomainRepoId;
import static google.registry.model.eppcommon.StatusValue.SERVER_HOLD;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY;
import static google.registry.model.registry.Registry.TldState.QUIET_PERIOD;
import static google.registry.model.registry.Registry.TldState.START_DATE_SUNRISE;
import static google.registry.model.registry.label.ReservationType.NAME_COLLISION;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
@@ -68,6 +69,8 @@ import google.registry.flows.custom.DomainCreateFlowCustomLogic.BeforeResponsePa
import google.registry.flows.custom.DomainCreateFlowCustomLogic.BeforeResponseReturnData;
import google.registry.flows.custom.EntityChanges;
import google.registry.flows.domain.token.AllocationTokenFlowUtils;
import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientException;
import google.registry.flows.exceptions.ResourceCreateContentionException;
import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag;
@@ -114,13 +117,19 @@ import org.joda.time.Duration;
/**
* An EPP flow that creates a new domain resource.
*
* @error {@link google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException}
* @error {@link google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException}
* @error {@link google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException}
* @error {@link google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException}
* @error {@link google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException}
* @error {@link google.registry.flows.exceptions.OnlyToolCanPassMetadataException}
* @error {@link google.registry.flows.exceptions.ResourceAlreadyExistsException}
* @error {@link ResourceAlreadyExistsForThisClientException}
* @error {@link ResourceCreateContentionException}
* @error {@link google.registry.flows.EppException.UnimplementedExtensionException}
* @error {@link google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException}
* @error {@link google.registry.flows.FlowUtils.UnknownCurrencyEppException}
@@ -218,7 +227,7 @@ public class DomainCreateFlow implements TransactionalFlow {
verifyUnitIsYears(period);
int years = period.getValue();
validateRegistrationPeriod(years);
verifyResourceDoesNotExist(DomainBase.class, targetId, now);
verifyResourceDoesNotExist(DomainBase.class, targetId, now, clientId);
// Validate that this is actually a legal domain name on a TLD that the registrar has access to.
InternetDomainName domainName = validateDomainName(command.getFullyQualifiedDomainName());
String domainLabel = domainName.parts().get(0);
@@ -246,11 +255,12 @@ public class DomainCreateFlow implements TransactionalFlow {
// registering premium domains.
if (!isSuperuser) {
checkAllowedAccessToTld(clientId, registry.getTldStr());
verifyIsGaOrIsSpecialCase(tldState, isAnchorTenant, hasSignedMarks);
boolean isValidReservedCreate = isValidReservedCreate(domainName, allocationToken);
verifyIsGaOrIsSpecialCase(tldState, isAnchorTenant, isValidReservedCreate, hasSignedMarks);
if (launchCreate.isPresent()) {
verifyLaunchPhaseMatchesRegistryPhase(registry, launchCreate.get(), now);
}
if (!isAnchorTenant && !isValidReservedCreate(domainName, allocationToken)) {
if (!isAnchorTenant && !isValidReservedCreate) {
verifyNotReserved(domainName, isSunriseCreate);
}
if (hasClaimsNotice) {
@@ -415,7 +425,10 @@ public class DomainCreateFlow implements TransactionalFlow {
* non-superusers.
*/
private void verifyIsGaOrIsSpecialCase(
TldState tldState, boolean isAnchorTenant, boolean hasSignedMarks)
TldState tldState,
boolean isAnchorTenant,
boolean isValidReservedCreate,
boolean hasSignedMarks)
throws NoGeneralRegistrationsInCurrentPhaseException,
MustHaveSignedMarksInCurrentPhaseException {
// Anchor Tenant overrides any other consideration to allow registration.
@@ -436,6 +449,13 @@ public class DomainCreateFlow implements TransactionalFlow {
return;
}
// We allow creates of specifically reserved domain names during quiet periods.
if (QUIET_PERIOD.equals(tldState)) {
if (isValidReservedCreate) {
return;
}
}
// All other phases do not allow registration
throw new NoGeneralRegistrationsInCurrentPhaseException();
}

View File

@@ -0,0 +1,27 @@
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows.exceptions;
import google.registry.flows.EppException.ObjectAlreadyExistsException;
/** Resource with this id already exists. */
// This is different from ResourceCreateContentionException in that this is used in situations where
// the requesting client already owns this resource. Javadoc and exception message are the same for
// backcompat purposes.
public class ResourceAlreadyExistsForThisClientException extends ObjectAlreadyExistsException {
public ResourceAlreadyExistsForThisClientException(String resourceId) {
super(String.format("Object with given ID (%s) already exists", resourceId));
}
}

View File

@@ -17,8 +17,11 @@ package google.registry.flows.exceptions;
import google.registry.flows.EppException.ObjectAlreadyExistsException;
/** Resource with this id already exists. */
public class ResourceAlreadyExistsException extends ObjectAlreadyExistsException {
public ResourceAlreadyExistsException(String resourceId) {
// This is different from ResourceAlreadyExistsForThisClientException in that this is used in
// resource creation contention situations, where another client owns this resource. Javadoc and
// exception message are the same for backcompat purposes.
public class ResourceCreateContentionException extends ObjectAlreadyExistsException {
public ResourceCreateContentionException(String resourceId) {
super(String.format("Object with given ID (%s) already exists", resourceId));
}
}

View File

@@ -37,6 +37,8 @@ import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientException;
import google.registry.flows.exceptions.ResourceCreateContentionException;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.DomainBase;
import google.registry.model.domain.metadata.MetadataExtension;
@@ -64,7 +66,8 @@ import org.joda.time.DateTime;
* update DNS.
*
* @error {@link google.registry.flows.FlowUtils.IpAddressVersionMismatchException}
* @error {@link google.registry.flows.exceptions.ResourceAlreadyExistsException}
* @error {@link ResourceAlreadyExistsForThisClientException}
* @error {@link ResourceCreateContentionException}
* @error {@link HostFlowUtils.HostNameTooLongException}
* @error {@link HostFlowUtils.HostNameTooShallowException}
* @error {@link HostFlowUtils.InvalidHostNameException}
@@ -101,7 +104,7 @@ public final class HostCreateFlow implements TransactionalFlow {
validateClientIsLoggedIn(clientId);
Create command = (Create) resourceCommand;
DateTime now = ofy().getTransactionTime();
verifyResourceDoesNotExist(HostResource.class, targetId, now);
verifyResourceDoesNotExist(HostResource.class, targetId, now, clientId);
// The superordinate domain of the host object if creating an in-bailiwick host, or null if
// creating an external host. This is looked up before we actually create the Host object so
// we can detect error conditions earlier.

View File

@@ -31,6 +31,7 @@ import google.registry.model.Buildable;
import google.registry.model.EppResource;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.ExternalMessagingName;
import google.registry.model.annotations.ReportedOn;
import google.registry.model.domain.DomainRenewData;
import google.registry.model.eppoutput.EppResponse.ResponseData;
import google.registry.model.poll.PendingActionNotificationResponse.ContactPendingActionNotificationResponse;
@@ -65,6 +66,7 @@ import org.joda.time.DateTime;
* Command</a>
*/
@Entity
@ReportedOn
@ExternalMessagingName("message")
public abstract class PollMessage extends ImmutableObject
implements Buildable, TransferServerApproveEntity {

View File

@@ -17,9 +17,7 @@ package google.registry.rdap;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.request.Actions.getPathForAction;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
@@ -29,30 +27,22 @@ import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.re2j.Pattern;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.cmd.Query;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.EppResource;
import google.registry.model.registrar.Registrar;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.rdap.RdapMetrics.WildcardType;
import google.registry.rdap.RdapObjectClasses.ErrorResponse;
import google.registry.rdap.RdapObjectClasses.ReplyPayloadBase;
import google.registry.rdap.RdapObjectClasses.TopLevelReplyObject;
import google.registry.rdap.RdapSearchResults.BaseSearchResponse;
import google.registry.rdap.RdapSearchResults.IncompletenessWarningType;
import google.registry.request.Action;
import google.registry.request.HttpException;
import google.registry.request.HttpException.UnprocessableEntityException;
import google.registry.request.Parameter;
import google.registry.request.RequestMethod;
import google.registry.request.RequestPath;
import google.registry.request.Response;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.inject.Inject;
import org.joda.time.DateTime;
@@ -67,13 +57,6 @@ public abstract class RdapActionBase implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
/**
* Pattern for checking LDH names, which must officially contains only alphanumeric plus dots and
* hyphens. In this case, allow the wildcard asterisk as well.
*/
static final Pattern LDH_PATTERN = Pattern.compile("[-.a-zA-Z0-9*]+");
private static final int RESULT_SET_SIZE_SCALING_FACTOR = 30;
private static final MediaType RESPONSE_MEDIA_TYPE =
MediaType.create("application", "rdap+json").withCharset(UTF_8);
@@ -88,7 +71,6 @@ public abstract class RdapActionBase implements Runnable {
@Inject @RequestPath String requestPath;
@Inject RdapAuthorization rdapAuthorization;
@Inject RdapJsonFormatter rdapJsonFormatter;
@Inject @Parameter("registrar") Optional<String> registrarParam;
@Inject @Parameter("includeDeleted") Optional<Boolean> includeDeletedParam;
@Inject @Parameter("formatOutput") Optional<Boolean> formatOutputParam;
@Inject @Config("rdapResultSetMaxSize") int rdapResultSetMaxSize;
@@ -121,6 +103,8 @@ public abstract class RdapActionBase implements Runnable {
/**
* Does the actual search and returns an RDAP JSON object.
*
* RFC7480 4.1 - we have to support GET and HEAD.
*
* @param pathSearchString the search string in the URL path
* @param isHeadRequest whether the returned map will actually be used. HTTP HEAD requests don't
* actually return anything. However, we usually still want to go through the process of
@@ -135,30 +119,37 @@ public abstract class RdapActionBase implements Runnable {
@Override
public void run() {
metricInformationBuilder.setIncludeDeleted(includeDeletedParam.orElse(false));
metricInformationBuilder.setRegistrarSpecified(registrarParam.isPresent());
metricInformationBuilder.setRole(rdapAuthorization.role());
metricInformationBuilder.setRequestMethod(requestMethod);
metricInformationBuilder.setEndpointType(endpointType);
// RFC7480 4.2 - servers receiving an RDAP request return an entity with a Content-Type header
// containing the RDAP-specific JSON media type.
response.setContentType(RESPONSE_MEDIA_TYPE);
// RDAP Technical Implementation Guide 1.13 - when responding to RDAP valid requests, we MUST
// include the Access-Control-Allow-Origin, which MUST be "*" unless otherwise specified.
response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
try {
// Extract what we're searching for from the request path. Some RDAP commands use trailing
// data in the path itself (e.g. /rdap/domain/mydomain.com), and some use the query string
// (e.g. /rdap/domains?name=mydomain); the query parameters are extracted by the subclasses
// directly as needed.
response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
URI uri = new URI(requestPath);
String pathProper = uri.getPath();
checkArgument(
pathProper.startsWith(getActionPath()),
"%s doesn't start with %s", pathProper, getActionPath());
String pathSearchString = pathProper.substring(getActionPath().length());
logger.atInfo().log("path search string: '%s'", pathSearchString);
ReplyPayloadBase replyObject =
getJsonObjectForResource(
pathProper.substring(getActionPath().length()), requestMethod == Action.Method.HEAD);
getJsonObjectForResource(pathSearchString, requestMethod == Action.Method.HEAD);
if (replyObject instanceof BaseSearchResponse) {
metricInformationBuilder.setIncompletenessWarningType(
((BaseSearchResponse) replyObject).incompletenessWarningType());
}
// RFC7480 5.1 - if the server has the information requested and wishes to respond, it returns
// that answer in the body of a 200 (OK) response
response.setStatus(SC_OK);
response.setContentType(RESPONSE_MEDIA_TYPE);
setPayload(replyObject);
metricInformationBuilder.setStatusCode(SC_OK);
} catch (HttpException e) {
@@ -177,7 +168,6 @@ public abstract class RdapActionBase implements Runnable {
void setError(int status, String title, String description) {
metricInformationBuilder.setStatusCode(status);
response.setStatus(status);
response.setContentType(RESPONSE_MEDIA_TYPE);
try {
setPayload(ErrorResponse.create(status, title, description));
} catch (Exception ex) {
@@ -204,11 +194,6 @@ public abstract class RdapActionBase implements Runnable {
response.setPayload(gson.toJson(topLevelObject.toJson()));
}
/** Returns the registrar on which results should be filtered, or absent(). */
Optional<String> getDesiredRegistrar() {
return registrarParam;
}
/**
* Returns true if the query should include deleted items.
*
@@ -247,43 +232,16 @@ public abstract class RdapActionBase implements Runnable {
eppResource.getPersistedCurrentSponsorClientId()));
}
/**
* Returns true if the EPP resource should be visible.
*
* <p>This is true iff: 1. The resource is not deleted, or the request wants to see deleted items,
* and is authorized to do so, and: 2. The request did not specify a registrar to filter on, or
* the registrar matches.
*/
boolean shouldBeVisible(EppResource eppResource) {
return isAuthorized(eppResource)
&& (!registrarParam.isPresent()
|| registrarParam.get().equals(eppResource.getPersistedCurrentSponsorClientId()));
}
/**
* Returns true if the EPP resource should be visible.
*
* <p>This is true iff: 1. The passed in resource exists and is not deleted (deleted ones will
* have been projected forward in time to empty), 2. The request did not specify a registrar to
* filter on, or the registrar matches.
*/
boolean shouldBeVisible(Optional<? extends EppResource> eppResource) {
return eppResource.isPresent() && shouldBeVisible(eppResource.get());
}
/**
* Returns true if the registrar should be visible.
*
* <p>This is true iff:
* 1. The resource is active and publicly visible, or the request wants to see deleted items, and
* is authorized to do so, and:
* 2. The request did not specify a registrar to filter on, or the registrar matches.
* <p>This is true iff: The resource is active and publicly visible, or the request wants to see
* deleted items, and is authorized to do so
*/
boolean shouldBeVisible(Registrar registrar) {
boolean isAuthorized(Registrar registrar) {
return (registrar.isLiveAndPubliclyVisible()
|| (shouldIncludeDeleted()
&& rdapAuthorization.isAuthorizedForClientId(registrar.getClientId())))
&& (!registrarParam.isPresent() || registrarParam.get().equals(registrar.getClientId()));
&& rdapAuthorization.isAuthorizedForClientId(registrar.getClientId())));
}
String canonicalizeName(String name) {
@@ -294,250 +252,6 @@ public abstract class RdapActionBase implements Runnable {
return name;
}
int getStandardQuerySizeLimit() {
return shouldIncludeDeleted()
? (RESULT_SET_SIZE_SCALING_FACTOR * (rdapResultSetMaxSize + 1))
: (rdapResultSetMaxSize + 1);
}
static <T extends EppResource> Query<T> queryItems(
Class<T> clazz,
String filterField,
RdapSearchPattern partialStringQuery,
DeletedItemHandling deletedItemHandling,
int resultSetMaxSize) {
return queryItems(
clazz,
filterField,
partialStringQuery,
Optional.empty(),
deletedItemHandling,
resultSetMaxSize);
}
/**
* Handles prefix searches in cases where, if we need to filter out deleted items, there are no
* pending deletes.
*
* <p>In such cases, it is sufficient to check whether {@code deletionTime} is equal to
* {@code END_OF_TIME}, because any other value means it has already been deleted. This allows us
* to use an equality query for the deletion time.
*
* @param clazz the type of resource to be queried
* @param filterField the database field of interest
* @param partialStringQuery the details of the search string; if there is no wildcard, an
* equality query is used; if there is a wildcard, a range query is used instead; the
* initial string should not be empty, and any search suffix will be ignored, so the caller
* must filter the results if a suffix is specified
* @param cursorString if a cursor is present, this parameter should specify the cursor string, to
* skip any results up to and including the string; empty() if there is no cursor
* @param deletedItemHandling whether to include or exclude deleted items
* @param resultSetMaxSize the maximum number of results to return
* @return the query object
*/
static <T extends EppResource> Query<T> queryItems(
Class<T> clazz,
String filterField,
RdapSearchPattern partialStringQuery,
Optional<String> cursorString,
DeletedItemHandling deletedItemHandling,
int resultSetMaxSize) {
if (partialStringQuery.getInitialString().length()
< RdapSearchPattern.MIN_INITIAL_STRING_LENGTH) {
throw new UnprocessableEntityException(
String.format(
"Initial search string must be at least %d characters",
RdapSearchPattern.MIN_INITIAL_STRING_LENGTH));
}
Query<T> query = ofy().load().type(clazz);
if (!partialStringQuery.getHasWildcard()) {
query = query.filter(filterField, partialStringQuery.getInitialString());
} else {
// Ignore the suffix; the caller will need to filter on the suffix, if any.
query = query
.filter(filterField + " >=", partialStringQuery.getInitialString())
.filter(filterField + " <", partialStringQuery.getNextInitialString());
}
if (cursorString.isPresent()) {
query = query.filter(filterField + " >", cursorString.get());
}
return setOtherQueryAttributes(query, deletedItemHandling, resultSetMaxSize);
}
/**
* Handles searches using a simple string rather than an {@link RdapSearchPattern}.
*
* <p>Since the filter is not an inequality, we can support also checking a cursor string against
* a different field (which involves an inequality on that field).
*
* @param clazz the type of resource to be queried
* @param filterField the database field of interest
* @param queryString the search string
* @param cursorField the field which should be compared to the cursor string, or empty() if the
* key should be compared to a key created from the cursor string
* @param cursorString if a cursor is present, this parameter should specify the cursor string, to
* skip any results up to and including the string; empty() if there is no cursor
* @param deletedItemHandling whether to include or exclude deleted items
* @param resultSetMaxSize the maximum number of results to return
* @return the query object
*/
static <T extends EppResource> Query<T> queryItems(
Class<T> clazz,
String filterField,
String queryString,
Optional<String> cursorField,
Optional<String> cursorString,
DeletedItemHandling deletedItemHandling,
int resultSetMaxSize) {
if (queryString.length() < RdapSearchPattern.MIN_INITIAL_STRING_LENGTH) {
throw new UnprocessableEntityException(
String.format(
"Initial search string must be at least %d characters",
RdapSearchPattern.MIN_INITIAL_STRING_LENGTH));
}
Query<T> query = ofy().load().type(clazz).filter(filterField, queryString);
if (cursorString.isPresent()) {
if (cursorField.isPresent()) {
query = query.filter(cursorField.get() + " >", cursorString.get());
} else {
query = query.filterKey(">", Key.create(clazz, cursorString.get()));
}
}
return setOtherQueryAttributes(query, deletedItemHandling, resultSetMaxSize);
}
/** Handles searches where the field to be searched is the key. */
static <T extends EppResource> Query<T> queryItemsByKey(
Class<T> clazz,
RdapSearchPattern partialStringQuery,
Optional<String> cursorString,
DeletedItemHandling deletedItemHandling,
int resultSetMaxSize) {
if (partialStringQuery.getInitialString().length()
< RdapSearchPattern.MIN_INITIAL_STRING_LENGTH) {
throw new UnprocessableEntityException(
String.format(
"Initial search string must be at least %d characters",
RdapSearchPattern.MIN_INITIAL_STRING_LENGTH));
}
Query<T> query = ofy().load().type(clazz);
if (!partialStringQuery.getHasWildcard()) {
query = query.filterKey("=", Key.create(clazz, partialStringQuery.getInitialString()));
} else {
// Ignore the suffix; the caller will need to filter on the suffix, if any.
query = query
.filterKey(">=", Key.create(clazz, partialStringQuery.getInitialString()))
.filterKey("<", Key.create(clazz, partialStringQuery.getNextInitialString()));
}
if (cursorString.isPresent()) {
query = query.filterKey(">", Key.create(clazz, cursorString.get()));
}
return setOtherQueryAttributes(query, deletedItemHandling, resultSetMaxSize);
}
/** Handles searches by key using a simple string. */
static <T extends EppResource> Query<T> queryItemsByKey(
Class<T> clazz,
String queryString,
DeletedItemHandling deletedItemHandling,
int resultSetMaxSize) {
if (queryString.length() < RdapSearchPattern.MIN_INITIAL_STRING_LENGTH) {
throw new UnprocessableEntityException(
String.format(
"Initial search string must be at least %d characters",
RdapSearchPattern.MIN_INITIAL_STRING_LENGTH));
}
Query<T> query = ofy().load().type(clazz).filterKey("=", Key.create(clazz, queryString));
return setOtherQueryAttributes(query, deletedItemHandling, resultSetMaxSize);
}
private static <T extends EppResource> Query<T> setOtherQueryAttributes(
Query<T> query, DeletedItemHandling deletedItemHandling, int resultSetMaxSize) {
if (deletedItemHandling != DeletedItemHandling.INCLUDE) {
query = query.filter("deletionTime", END_OF_TIME);
}
return query.limit(resultSetMaxSize);
}
/**
* Runs the given query, and checks for permissioning if necessary.
*
* @param query an already-defined query to be run; a filter on currentSponsorClientId will be
* added if appropriate
* @param checkForVisibility true if the results should be checked to make sure they are visible;
* normally this should be equal to the shouldIncludeDeleted setting, but in cases where the
* query could not check deletion status (due to Datastore limitations such as the limit of
* one field queried for inequality, for instance), it may need to be set to true even when
* not including deleted records
* @param querySizeLimit the maximum number of items the query is expected to return, usually
* because the limit has been set
* @return an {@link RdapResultSet} object containing the list of resources and an incompleteness
* warning flag, which is set to MIGHT_BE_INCOMPLETE iff any resources were excluded due to
* lack of visibility, and the resulting list of resources is less than the maximum allowable,
* and the number of items returned by the query is greater than or equal to the maximum
* number we might have expected
*/
<T extends EppResource> RdapResultSet<T> getMatchingResources(
Query<T> query, boolean checkForVisibility, int querySizeLimit) {
Optional<String> desiredRegistrar = getDesiredRegistrar();
if (desiredRegistrar.isPresent()) {
query = query.filter("currentSponsorClientId", desiredRegistrar.get());
}
if (!checkForVisibility) {
return RdapResultSet.create(query.list());
}
// If we are including deleted resources, we need to check that we're authorized for each one.
List<T> resources = new ArrayList<>();
int numResourcesQueried = 0;
boolean someExcluded = false;
for (T resource : query) {
if (shouldBeVisible(resource)) {
resources.add(resource);
} else {
someExcluded = true;
}
numResourcesQueried++;
if (resources.size() > rdapResultSetMaxSize) {
break;
}
}
// The incompleteness problem comes about because we don't know how many items to fetch. We want
// to return rdapResultSetMaxSize worth of items, but some might be excluded, so we fetch more
// just in case. But how many more? That's the potential problem, addressed with the three way
// AND statement:
// 1. If we didn't exclude any items, then we can't have the incompleteness problem.
// 2. If have a full result set batch (rdapResultSetMaxSize items), we must by definition be
// giving the user a complete result set.
// 3. If we started with fewer than querySizeLimit items, then there weren't any more items that
// we missed. Even if we return fewer than rdapResultSetMaxSize items, it isn't because we
// didn't fetch enough to start.
// Only if all three conditions are true might things be incomplete. In other words, we fetched
// as many as our limit allowed, but then excluded so many that we wound up with less than a
// full result set's worth of results.
return RdapResultSet.create(
resources,
(someExcluded
&& (resources.size() < rdapResultSetMaxSize)
&& (numResourcesQueried >= querySizeLimit))
? IncompletenessWarningType.MIGHT_BE_INCOMPLETE
: IncompletenessWarningType.COMPLETE,
numResourcesQueried);
}
RdapSearchPattern recordWildcardType(RdapSearchPattern partialStringQuery) {
if (!partialStringQuery.getHasWildcard()) {
metricInformationBuilder.setWildcardType(WildcardType.NO_WILDCARD);
} else if (partialStringQuery.getSuffix() == null) {
metricInformationBuilder.setWildcardType(WildcardType.PREFIX);
} else if (partialStringQuery.getInitialString().isEmpty()) {
metricInformationBuilder.setWildcardType(WildcardType.SUFFIX);
} else {
metricInformationBuilder.setWildcardType(WildcardType.PREFIX_AND_SUFFIX);
}
metricInformationBuilder.setPrefixLength(partialStringQuery.getInitialString().length());
return partialStringQuery;
}
/** Returns the DateTime this request took place. */
DateTime getRequestTime() {
return rdapJsonFormatter.getRequestTime();

View File

@@ -48,6 +48,11 @@ final class RdapDataStructures {
// Conformance to the RDAP Response Profile V2.1
// (see section 1.3)
jsonArray.add("icann_rdap_response_profile_0");
// Conformance to the RDAP Technical Implementation Guide V2.1
// (see section 1.14)
jsonArray.add("icann_rdap_technical_implementation_guide_0");
return jsonArray;
}
}

View File

@@ -47,6 +47,8 @@ public class RdapDomainAction extends RdapActionBase {
@Override
public RdapDomain getJsonObjectForResource(String pathSearchString, boolean isHeadRequest) {
// RDAP Technical Implementation Guide 2.1.1 - we must support A-label (Punycode) and U-label
// (Unicode) formats. canonicalizeName will transform Unicode to Punycode so we support both.
pathSearchString = canonicalizeName(pathSearchString);
try {
validateDomainName(pathSearchString);
@@ -62,7 +64,12 @@ public class RdapDomainAction extends RdapActionBase {
DomainBase.class,
pathSearchString,
shouldIncludeDeleted() ? START_OF_TIME : rdapJsonFormatter.getRequestTime());
if (!shouldBeVisible(domainBase)) {
if (!domainBase.isPresent() || !isAuthorized(domainBase.get())) {
// RFC7480 5.3 - if the server wishes to respond that it doesn't have data satisfying the
// query, it MUST reply with 404 response code.
//
// Note we don't do RFC7480 5.3 - returning a different code if we wish to say "this info
// exists but we don't want to show it to you", because we DON'T wish to say that.
throw new NotFoundException(pathSearchString + " not found");
}
return rdapJsonFormatter.createRdapDomain(domainBase.get(), OutputDataType.FULL);

View File

@@ -44,7 +44,6 @@ import google.registry.request.HttpException.NotFoundException;
import google.registry.request.HttpException.UnprocessableEntityException;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.util.Idn;
import google.registry.util.NonFinalForTesting;
import java.net.InetAddress;
import java.util.Comparator;
@@ -62,6 +61,9 @@ import javax.inject.Inject;
* (RDAP) Query Format</a>
* @see <a href="http://tools.ietf.org/html/rfc7483">RFC 7483: JSON Responses for the Registration
* Data Access Protocol (RDAP)</a>
*
* TODO(guyben):This isn't required by the RDAP Technical Implementation Guide, and hence should be
* deleted, at least until it's actually required.
*/
@Action(
service = Action.Service.PUBAPI,
@@ -90,41 +92,29 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
* <p>The RDAP spec allows for domain search by domain name, nameserver name or nameserver IP.
*/
@Override
public DomainSearchResponse getJsonObjectForResource(
String pathSearchString, boolean isHeadRequest) {
public DomainSearchResponse getSearchResponse(boolean isHeadRequest) {
// RDAP syntax example: /rdap/domains?name=exam*.com.
// The pathSearchString is not used by search commands.
if (pathSearchString.length() > 0) {
throw new BadRequestException("Unexpected path");
}
if (Booleans.countTrue(nameParam.isPresent(), nsLdhNameParam.isPresent(), nsIpParam.isPresent())
!= 1) {
throw new BadRequestException(
"You must specify either name=XXXX, nsLdhName=YYYY or nsIp=ZZZZ");
}
decodeCursorToken();
DomainSearchResponse results;
if (nameParam.isPresent()) {
metricInformationBuilder.setSearchType(SearchType.BY_DOMAIN_NAME);
// syntax: /rdap/domains?name=exam*.com
String asciiName;
try {
asciiName = Idn.toASCII(nameParam.get());
} catch (Exception e) {
throw new BadRequestException("Invalid value of nsLdhName parameter");
}
results = searchByDomainName(recordWildcardType(RdapSearchPattern.create(asciiName, true)));
results =
searchByDomainName(
recordWildcardType(
RdapSearchPattern.createFromLdhOrUnicodeDomainName(nameParam.get())));
} else if (nsLdhNameParam.isPresent()) {
metricInformationBuilder.setSearchType(SearchType.BY_NAMESERVER_NAME);
// syntax: /rdap/domains?nsLdhName=ns1.exam*.com
// RFC 7482 appears to say that Unicode domains must be specified using punycode when
// passed to nsLdhName, so IDN.toASCII is not called here.
if (!LDH_PATTERN.matcher(nsLdhNameParam.get()).matches()) {
throw new BadRequestException("Invalid value of nsLdhName parameter");
}
results =
searchByNameserverLdhName(
recordWildcardType(RdapSearchPattern.create(nsLdhNameParam.get(), true)));
recordWildcardType(RdapSearchPattern.createFromLdhDomainName(nsLdhNameParam.get())));
} else {
metricInformationBuilder.setSearchType(SearchType.BY_NAMESERVER_ADDRESS);
metricInformationBuilder.setWildcardType(WildcardType.NO_WILDCARD);
@@ -189,7 +179,9 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
Optional<DomainBase> domainBase =
loadByForeignKey(DomainBase.class, partialStringQuery.getInitialString(), getRequestTime());
return makeSearchResults(
shouldBeVisible(domainBase) ? ImmutableList.of(domainBase.get()) : ImmutableList.of());
shouldBeVisible(domainBase)
? ImmutableList.of(domainBase.get())
: ImmutableList.of());
}
/** Searches for domains by domain name with an initial string, wildcard and possible suffix. */
@@ -294,6 +286,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
HostResource.class,
"fullyQualifiedHostName",
partialStringQuery,
Optional.empty(),
DeletedItemHandling.EXCLUDE,
maxNameserversInFirstStage);
Optional<String> desiredRegistrar = getDesiredRegistrar();

View File

@@ -16,6 +16,7 @@ package google.registry.rdap;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.rdap.RdapUtils.getRegistrarByIanaIdentifier;
import static google.registry.rdap.RdapUtils.getRegistrarByName;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.HEAD;
@@ -29,7 +30,6 @@ import google.registry.rdap.RdapJsonFormatter.OutputDataType;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.rdap.RdapObjectClasses.RdapEntity;
import google.registry.request.Action;
import google.registry.request.HttpException.BadRequestException;
import google.registry.request.HttpException.NotFoundException;
import google.registry.request.auth.Auth;
import java.util.Optional;
@@ -63,31 +63,46 @@ public class RdapEntityAction extends RdapActionBase {
public RdapEntity getJsonObjectForResource(
String pathSearchString, boolean isHeadRequest) {
// The query string is not used; the RDAP syntax is /rdap/entity/handle (the handle is the roid
// for contacts and the client identifier for registrars). Since RDAP's concept of an entity
// for contacts and the client identifier/fn for registrars). Since RDAP's concept of an entity
// includes both contacts and registrars, search for one first, then the other.
boolean wasValidKey = false;
// RDAP Technical Implementation Guide 2.3.1 - MUST support contact entity lookup using the
// handle
if (ROID_PATTERN.matcher(pathSearchString).matches()) {
wasValidKey = true;
Key<ContactResource> contactKey = Key.create(ContactResource.class, pathSearchString);
ContactResource contactResource = ofy().load().key(contactKey).now();
// As per Andy Newton on the regext mailing list, contacts by themselves have no role, since
// they are global, and might have different roles for different domains.
if ((contactResource != null) && shouldBeVisible(contactResource)) {
if (contactResource != null && isAuthorized(contactResource)) {
return rdapJsonFormatter.createRdapContactEntity(
contactResource, ImmutableSet.of(), OutputDataType.FULL);
}
}
// RDAP Technical Implementation Guide 2.4.1 - MUST support registrar entity lookup using the
// IANA ID as handle
Long ianaIdentifier = Longs.tryParse(pathSearchString);
if (ianaIdentifier != null) {
wasValidKey = true;
Optional<Registrar> registrar = getRegistrarByIanaIdentifier(ianaIdentifier);
if (registrar.isPresent() && shouldBeVisible(registrar.get())) {
if (registrar.isPresent() && isAuthorized(registrar.get())) {
return rdapJsonFormatter.createRdapRegistrarEntity(registrar.get(), OutputDataType.FULL);
}
}
// RDAP Technical Implementation Guide 2.4.2 - MUST support registrar entity lookup using the
// fn as handle
Optional<Registrar> registrar = getRegistrarByName(pathSearchString);
if (registrar.isPresent() && isAuthorized(registrar.get())) {
return rdapJsonFormatter.createRdapRegistrarEntity(registrar.get(), OutputDataType.FULL);
}
// At this point, we have failed to find either a contact or a registrar.
throw wasValidKey
? new NotFoundException(pathSearchString + " not found")
: new BadRequestException(pathSearchString + " is not a valid entity handle");
//
// RFC7480 5.3 - if the server wishes to respond that it doesn't have data satisfying the
// query, it MUST reply with 404 response code.
//
// Note we don't do RFC7480 5.3 - returning a different code if we wish to say "this info
// exists but we don't want to show it to you", because we DON'T wish to say that.
throw new NotFoundException(pathSearchString + " not found");
}
}

View File

@@ -72,6 +72,9 @@ import javax.inject.Inject;
* (RDAP) Query Format</a>
* @see <a href="http://tools.ietf.org/html/rfc7483">RFC 7483: JSON Responses for the Registration
* Data Access Protocol (RDAP)</a>
*
* TODO(guyben):This isn't required by the RDAP Technical Implementation Guide, and hence should be
* deleted, at least until it's actually required.
*/
@Action(
service = Action.Service.PUBAPI,
@@ -109,14 +112,9 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
/** Parses the parameters and calls the appropriate search function. */
@Override
public EntitySearchResponse getJsonObjectForResource(
String pathSearchString, boolean isHeadRequest) {
public EntitySearchResponse getSearchResponse(boolean isHeadRequest) {
// RDAP syntax example: /rdap/entities?fn=Bobby%20Joe*.
// The pathSearchString is not used by search commands.
if (pathSearchString.length() > 0) {
throw new BadRequestException("Unexpected path");
}
if (Booleans.countTrue(fnParam.isPresent(), handleParam.isPresent()) != 1) {
throw new BadRequestException("You must specify either fn=XXXX or handle=YYYY");
}
@@ -133,8 +131,6 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
throw new BadRequestException("Subtype parameter must specify contacts, registrars or all");
}
// Decode the cursor token and extract the prefix and string portions.
decodeCursorToken();
CursorType cursorType;
Optional<String> cursorQueryString;
if (!cursorString.isPresent()) {
@@ -162,7 +158,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
// The name is the contact name or registrar name (not registrar contact name).
results =
searchByName(
recordWildcardType(RdapSearchPattern.create(fnParam.get(), false)),
recordWildcardType(RdapSearchPattern.createFromUnicodeString(fnParam.get())),
cursorType,
cursorQueryString,
subtype);
@@ -174,7 +170,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
// The handle is either the contact roid or the registrar clientId.
results =
searchByHandle(
recordWildcardType(RdapSearchPattern.create(handleParam.get(), false)),
recordWildcardType(RdapSearchPattern.createFromUnicodeString(handleParam.get())),
cursorType,
cursorQueryString,
subtype);

View File

@@ -82,6 +82,8 @@ public class RdapIcannStandardInformation {
/**
* Required by ICANN RDAP Profile section 1.4.9, as corrected by Gustavo Lozano of ICANN.
*
* Also mentioned in the RDAP Technical Implementation Guide 3.6.
*
* @see <a href="http://mm.icann.org/pipermail/gtld-tech/2016-October/000822.html">Questions about
* the ICANN RDAP Profile</a>
*/
@@ -96,6 +98,8 @@ public class RdapIcannStandardInformation {
/**
* Required by ICANN RDAP Profile section 1.4.8, as corrected by Gustavo Lozano of ICANN.
*
* Also mentioned in the RDAP Technical Implementation Guide 3.5.
*
* @see <a href="http://mm.icann.org/pipermail/gtld-tech/2016-October/000822.html">Questions about
* the ICANN RDAP Profile</a>
*/

View File

@@ -298,6 +298,7 @@ public class RdapMetrics {
.setSearchType(SearchType.NONE)
.setWildcardType(WildcardType.INVALID)
.setPrefixLength(0)
.setRegistrarSpecified(false)
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE);
}
}

View File

@@ -47,6 +47,8 @@ public class RdapNameserverAction extends RdapActionBase {
@Override
public RdapNameserver getJsonObjectForResource(String pathSearchString, boolean isHeadRequest) {
// RDAP Technical Implementation Guide 2.2.1 - we must support A-label (Punycode) and U-label
// (Unicode) formats. canonicalizeName will transform Unicode to Punycode so we support both.
pathSearchString = canonicalizeName(pathSearchString);
// The RDAP syntax is /rdap/nameserver/ns1.mydomain.com.
try {
@@ -64,7 +66,12 @@ public class RdapNameserverAction extends RdapActionBase {
HostResource.class,
pathSearchString,
shouldIncludeDeleted() ? START_OF_TIME : getRequestTime());
if (!shouldBeVisible(hostResource)) {
if (!hostResource.isPresent() || !isAuthorized(hostResource.get())) {
// RFC7480 5.3 - if the server wishes to respond that it doesn't have data satisfying the
// query, it MUST reply with 404 response code.
//
// Note we don't do RFC7480 5.3 - returning a different code if we wish to say "this info
// exists but we don't want to show it to you", because we DON'T wish to say that.
throw new NotFoundException(pathSearchString + " not found");
}
return rdapJsonFormatter.createRdapNameserver(hostResource.get(), OutputDataType.FULL);

View File

@@ -36,7 +36,6 @@ import google.registry.request.HttpException.NotFoundException;
import google.registry.request.HttpException.UnprocessableEntityException;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.util.Idn;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
@@ -79,30 +78,26 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
* <p>The RDAP spec allows nameserver search by either name or IP address.
*/
@Override
public NameserverSearchResponse getJsonObjectForResource(
String pathSearchString, boolean isHeadRequest) {
public NameserverSearchResponse getSearchResponse(boolean isHeadRequest) {
// RDAP syntax example: /rdap/nameservers?name=ns*.example.com.
// The pathSearchString is not used by search commands.
if (pathSearchString.length() > 0) {
throw new BadRequestException("Unexpected path");
}
if (Booleans.countTrue(nameParam.isPresent(), ipParam.isPresent()) != 1) {
throw new BadRequestException("You must specify either name=XXXX or ip=YYYY");
}
decodeCursorToken();
NameserverSearchResponse results;
if (nameParam.isPresent()) {
// RDAP Technical Implementation Guilde 2.2.3 - we MAY support nameserver search queries based
// on a "nameserver search pattern" as defined in RFC7482
//
// syntax: /rdap/nameservers?name=exam*.com
metricInformationBuilder.setSearchType(SearchType.BY_NAMESERVER_NAME);
if (!LDH_PATTERN.matcher(nameParam.get()).matches()) {
throw new BadRequestException(
"Name parameter must contain only letters, dots"
+ " and hyphens, and an optional single wildcard");
}
results =
searchByName(
recordWildcardType(RdapSearchPattern.create(Idn.toASCII(nameParam.get()), true)));
recordWildcardType(
RdapSearchPattern.createFromLdhOrUnicodeDomainName(nameParam.get())));
} else {
// RDAP Technical Implementation Guide 2.2.3 - we MUST support nameserver search queries based
// on IP address as defined in RFC7482 3.2.2. Doesn't require pattern matching
//
// syntax: /rdap/nameservers?ip=1.2.3.4
metricInformationBuilder.setSearchType(SearchType.BY_NAMESERVER_ADDRESS);
InetAddress inetAddress;
@@ -130,22 +125,22 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
// nameservers are desired, because there may be multiple nameservers with the same name.
if (!partialStringQuery.getHasWildcard() && !shouldIncludeDeleted()) {
return searchByNameUsingForeignKey(partialStringQuery);
}
// Handle queries with a wildcard (or including deleted entries). If there is a suffix, it
// should be a domain that we manage, so we can look up the domain and search through the
// subordinate hosts. This is more efficient, and lets us permit wildcard searches with no
// initial string. Deleted nameservers cannot be searched using a suffix, because the logic
// of the deletion status of the superordinate domain versus the deletion status of the
// subordinate host gets too messy.
} else if (partialStringQuery.getSuffix() != null) {
if (partialStringQuery.getSuffix() != null) {
if (shouldIncludeDeleted()) {
throw new UnprocessableEntityException(
"A suffix after a wildcard is not allowed when searching for deleted nameservers");
}
return searchByNameUsingSuperordinateDomain(partialStringQuery);
// Handle queries with a wildcard (or deleted entries included), but no suffix.
} else {
return searchByNameUsingPrefix(partialStringQuery);
}
// Handle queries with a wildcard (or deleted entries included), but no suffix.
return searchByNameUsingPrefix(partialStringQuery);
}
/**
@@ -155,21 +150,21 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
*/
private NameserverSearchResponse searchByNameUsingForeignKey(
RdapSearchPattern partialStringQuery) {
Optional<HostResource> hostResource =
loadByForeignKey(
HostResource.class, partialStringQuery.getInitialString(), getRequestTime());
if (!shouldBeVisible(hostResource)) {
metricInformationBuilder.setNumHostsRetrieved(0);
throw new NotFoundException("No nameservers found");
}
metricInformationBuilder.setNumHostsRetrieved(1);
NameserverSearchResponse.Builder builder =
NameserverSearchResponse.builder()
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE);
builder
.nameserverSearchResultsBuilder()
.add(rdapJsonFormatter.createRdapNameserver(hostResource.get(), OutputDataType.FULL));
Optional<HostResource> hostResource =
loadByForeignKey(
HostResource.class, partialStringQuery.getInitialString(), getRequestTime());
metricInformationBuilder.setNumHostsRetrieved(hostResource.isPresent() ? 1 : 0);
if (shouldBeVisible(hostResource)) {
builder
.nameserverSearchResultsBuilder()
.add(rdapJsonFormatter.createRdapNameserver(hostResource.get(), OutputDataType.FULL));
}
return builder.build();
}
@@ -215,7 +210,8 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
/**
* Searches for nameservers by name with a prefix and wildcard.
*
* <p>There are no pending deletes for hosts, so we can call {@link RdapActionBase#queryItems}.
* <p>There are no pending deletes for hosts, so we can call {@link
* RdapSearchActionBase#queryItems}.
*/
private NameserverSearchResponse searchByNameUsingPrefix(RdapSearchPattern partialStringQuery) {
// Add 1 so we can detect truncation.
@@ -238,13 +234,13 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
int querySizeLimit = getStandardQuerySizeLimit();
Query<HostResource> query =
queryItems(
HostResource.class,
"inetAddresses",
inetAddress.getHostAddress(),
Optional.empty(),
cursorString,
getDeletedItemHandling(),
querySizeLimit);
HostResource.class,
"inetAddresses",
inetAddress.getHostAddress(),
Optional.empty(),
cursorString,
getDeletedItemHandling(),
querySizeLimit);
return makeSearchResults(
getMatchingResources(query, shouldIncludeDeleted(), querySizeLimit), CursorType.ADDRESS);
}

View File

@@ -163,7 +163,7 @@ final class RdapObjectClasses {
*
* <p>RFC 7483 specifies that the top-level object should include an entry indicating the
* conformance level. ICANN RDAP spec for 15feb19 mandates several additional entries, in sections
* 2.6.3, 2.11 of the Response Profile and 3.3.2, 3.5, of the Technical Implementation Guide.
* 2.6.3, 2.11 of the Response Profile and 3.3, 3.5, of the Technical Implementation Guide.
*/
@AutoValue
@RestrictJsonNames({})

View File

@@ -14,17 +14,29 @@
package google.registry.rdap;
import static java.nio.charset.StandardCharsets.UTF_8;
import static com.google.common.base.Charsets.UTF_8;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.cmd.Query;
import google.registry.model.EppResource;
import google.registry.model.registrar.Registrar;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.rdap.RdapMetrics.WildcardType;
import google.registry.rdap.RdapSearchResults.BaseSearchResponse;
import google.registry.rdap.RdapSearchResults.IncompletenessWarningType;
import google.registry.request.HttpException.BadRequestException;
import google.registry.request.HttpException.UnprocessableEntityException;
import google.registry.request.Parameter;
import google.registry.request.ParameterMap;
import google.registry.request.RequestUrl;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;
@@ -39,9 +51,12 @@ import javax.inject.Inject;
*/
public abstract class RdapSearchActionBase extends RdapActionBase {
private static final int RESULT_SET_SIZE_SCALING_FACTOR = 30;
@Inject @RequestUrl String requestUrl;
@Inject @ParameterMap ImmutableListMultimap<String, String> parameterMap;
@Inject @Parameter("cursor") Optional<String> cursorTokenParam;
@Inject @Parameter("registrar") Optional<String> registrarParam;
protected Optional<String> cursorString;
@@ -49,6 +64,20 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
super(humanReadableObjectTypeName, endpointType);
}
@Override
public final BaseSearchResponse getJsonObjectForResource(
String pathSearchString, boolean isHeadRequest) {
// The pathSearchString is not used by search commands.
if (pathSearchString.length() > 0) {
throw new BadRequestException("Unexpected path");
}
decodeCursorToken();
metricInformationBuilder.setRegistrarSpecified(registrarParam.isPresent());
return getSearchResponse(isHeadRequest);
}
public abstract BaseSearchResponse getSearchResponse(boolean isHeadRequest);
/**
* Decodes the cursor token passed in the HTTP request.
*
@@ -57,14 +86,9 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
* than the cursor value.
*/
protected void decodeCursorToken() {
if (!cursorTokenParam.isPresent()) {
cursorString = Optional.empty();
} else {
cursorString =
Optional.of(
new String(
Base64.getDecoder().decode(cursorTokenParam.get().getBytes(UTF_8)), UTF_8));
}
cursorString =
cursorTokenParam.map(
cursor -> new String(Base64.getDecoder().decode(cursor.getBytes(UTF_8)), UTF_8));
}
/** Returns an encoded cursor token to pass back in the RDAP JSON link strings. */
@@ -77,6 +101,121 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
return getRequestUrlWithExtraParameter(parameterName, ImmutableList.of(parameterValue));
}
/** Returns the registrar on which results should be filtered, or absent(). */
protected Optional<String> getDesiredRegistrar() {
return registrarParam;
}
protected boolean shouldBeVisible(Optional<? extends EppResource> eppResource) {
return eppResource.isPresent() && shouldBeVisible(eppResource.get());
}
/**
* Returns true if the EPP resource should be visible.
*
* <p>This is true iff:
* 1. The resource is not deleted, or the request wants to see deleted items, and is authorized to
* do so, and:
* 2. The request did not specify a registrar to filter on, or the registrar matches.
*/
protected boolean shouldBeVisible(EppResource eppResource) {
return isAuthorized(eppResource)
&& (!registrarParam.isPresent()
|| registrarParam.get().equals(eppResource.getPersistedCurrentSponsorClientId()));
}
/**
* Returns true if the EPP resource should be visible.
*
* <p>This is true iff:
* 1. The resource is not deleted, or the request wants to see deleted items, and is authorized to
* do so, and:
* 2. The request did not specify a registrar to filter on, or the registrar matches.
*/
protected boolean shouldBeVisible(Registrar registrar) {
return isAuthorized(registrar)
&& (!registrarParam.isPresent() || registrarParam.get().equals(registrar.getClientId()));
}
/**
* Runs the given query, and checks for permissioning if necessary.
*
* @param query an already-defined query to be run; a filter on currentSponsorClientId will be
* added if appropriate
* @param checkForVisibility true if the results should be checked to make sure they are visible;
* normally this should be equal to the shouldIncludeDeleted setting, but in cases where the
* query could not check deletion status (due to Datastore limitations such as the limit of
* one field queried for inequality, for instance), it may need to be set to true even when
* not including deleted records
* @param querySizeLimit the maximum number of items the query is expected to return, usually
* because the limit has been set
* @return an {@link RdapResultSet} object containing the list of resources and an incompleteness
* warning flag, which is set to MIGHT_BE_INCOMPLETE iff any resources were excluded due to
* lack of visibility, and the resulting list of resources is less than the maximum allowable,
* and the number of items returned by the query is greater than or equal to the maximum
* number we might have expected
*/
<T extends EppResource> RdapResultSet<T> getMatchingResources(
Query<T> query, boolean checkForVisibility, int querySizeLimit) {
Optional<String> desiredRegistrar = getDesiredRegistrar();
if (desiredRegistrar.isPresent()) {
query = query.filter("currentSponsorClientId", desiredRegistrar.get());
}
if (!checkForVisibility) {
return RdapResultSet.create(query.list());
}
// If we are including deleted resources, we need to check that we're authorized for each one.
List<T> resources = new ArrayList<>();
int numResourcesQueried = 0;
boolean someExcluded = false;
for (T resource : query) {
if (shouldBeVisible(resource)) {
resources.add(resource);
} else {
someExcluded = true;
}
numResourcesQueried++;
if (resources.size() > rdapResultSetMaxSize) {
break;
}
}
// The incompleteness problem comes about because we don't know how many items to fetch. We want
// to return rdapResultSetMaxSize worth of items, but some might be excluded, so we fetch more
// just in case. But how many more? That's the potential problem, addressed with the three way
// AND statement:
// 1. If we didn't exclude any items, then we can't have the incompleteness problem.
// 2. If have a full result set batch (rdapResultSetMaxSize items), we must by definition be
// giving the user a complete result set.
// 3. If we started with fewer than querySizeLimit items, then there weren't any more items that
// we missed. Even if we return fewer than rdapResultSetMaxSize items, it isn't because we
// didn't fetch enough to start.
// Only if all three conditions are true might things be incomplete. In other words, we fetched
// as many as our limit allowed, but then excluded so many that we wound up with less than a
// full result set's worth of results.
return RdapResultSet.create(
resources,
(someExcluded
&& (resources.size() < rdapResultSetMaxSize)
&& (numResourcesQueried >= querySizeLimit))
? IncompletenessWarningType.MIGHT_BE_INCOMPLETE
: IncompletenessWarningType.COMPLETE,
numResourcesQueried);
}
RdapSearchPattern recordWildcardType(RdapSearchPattern partialStringQuery) {
if (!partialStringQuery.getHasWildcard()) {
metricInformationBuilder.setWildcardType(WildcardType.NO_WILDCARD);
} else if (partialStringQuery.getSuffix() == null) {
metricInformationBuilder.setWildcardType(WildcardType.PREFIX);
} else if (partialStringQuery.getInitialString().isEmpty()) {
metricInformationBuilder.setWildcardType(WildcardType.SUFFIX);
} else {
metricInformationBuilder.setWildcardType(WildcardType.PREFIX_AND_SUFFIX);
}
metricInformationBuilder.setPrefixLength(partialStringQuery.getInitialString().length());
return partialStringQuery;
}
/**
* Returns the original request URL, but with the specified parameter added or overridden.
*
@@ -123,4 +262,158 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
URI createNavigationUri(String cursor) {
return URI.create(getRequestUrlWithExtraParameter("cursor", encodeCursorToken(cursor)));
}
// We want to return rdapResultSetMaxSize + 1 results, so that we know if there are "extra"
// results (in which case we'll have a "next" link in the RDAP response).
// In case that we want to return deleted results as well, we have to scale the number of results
// to be (more) sure we got everything.
int getStandardQuerySizeLimit() {
return shouldIncludeDeleted()
? (RESULT_SET_SIZE_SCALING_FACTOR * (rdapResultSetMaxSize + 1))
: (rdapResultSetMaxSize + 1);
}
/**
* Handles prefix searches in cases where, if we need to filter out deleted items, there are no
* pending deletes.
*
* <p>In such cases, it is sufficient to check whether {@code deletionTime} is equal to
* {@code END_OF_TIME}, because any other value means it has already been deleted. This allows us
* to use an equality query for the deletion time.
*
* @param clazz the type of resource to be queried
* @param filterField the database field of interest
* @param partialStringQuery the details of the search string; if there is no wildcard, an
* equality query is used; if there is a wildcard, a range query is used instead; the
* initial string should not be empty, and any search suffix will be ignored, so the caller
* must filter the results if a suffix is specified
* @param cursorString if a cursor is present, this parameter should specify the cursor string, to
* skip any results up to and including the string; empty() if there is no cursor
* @param deletedItemHandling whether to include or exclude deleted items
* @param resultSetMaxSize the maximum number of results to return
* @return the query object
*/
static <T extends EppResource> Query<T> queryItems(
Class<T> clazz,
String filterField,
RdapSearchPattern partialStringQuery,
Optional<String> cursorString,
DeletedItemHandling deletedItemHandling,
int resultSetMaxSize) {
if (partialStringQuery.getInitialString().length()
< RdapSearchPattern.MIN_INITIAL_STRING_LENGTH) {
throw new UnprocessableEntityException(
String.format(
"Initial search string must be at least %d characters",
RdapSearchPattern.MIN_INITIAL_STRING_LENGTH));
}
Query<T> query = ofy().load().type(clazz);
if (!partialStringQuery.getHasWildcard()) {
query = query.filter(filterField, partialStringQuery.getInitialString());
} else {
// Ignore the suffix; the caller will need to filter on the suffix, if any.
query = query
.filter(filterField + " >=", partialStringQuery.getInitialString())
.filter(filterField + " <", partialStringQuery.getNextInitialString());
}
if (cursorString.isPresent()) {
query = query.filter(filterField + " >", cursorString.get());
}
return setOtherQueryAttributes(query, deletedItemHandling, resultSetMaxSize);
}
/**
* Handles searches using a simple string rather than an {@link RdapSearchPattern}.
*
* <p>Since the filter is not an inequality, we can support also checking a cursor string against
* a different field (which involves an inequality on that field).
*
* @param clazz the type of resource to be queried
* @param filterField the database field of interest
* @param queryString the search string
* @param cursorField the field which should be compared to the cursor string, or empty() if the
* key should be compared to a key created from the cursor string
* @param cursorString if a cursor is present, this parameter should specify the cursor string, to
* skip any results up to and including the string; empty() if there is no cursor
* @param deletedItemHandling whether to include or exclude deleted items
* @param resultSetMaxSize the maximum number of results to return
* @return the query object
*/
static <T extends EppResource> Query<T> queryItems(
Class<T> clazz,
String filterField,
String queryString,
Optional<String> cursorField,
Optional<String> cursorString,
DeletedItemHandling deletedItemHandling,
int resultSetMaxSize) {
if (queryString.length() < RdapSearchPattern.MIN_INITIAL_STRING_LENGTH) {
throw new UnprocessableEntityException(
String.format(
"Initial search string must be at least %d characters",
RdapSearchPattern.MIN_INITIAL_STRING_LENGTH));
}
Query<T> query = ofy().load().type(clazz).filter(filterField, queryString);
if (cursorString.isPresent()) {
if (cursorField.isPresent()) {
query = query.filter(cursorField.get() + " >", cursorString.get());
} else {
query = query.filterKey(">", Key.create(clazz, cursorString.get()));
}
}
return setOtherQueryAttributes(query, deletedItemHandling, resultSetMaxSize);
}
/** Handles searches where the field to be searched is the key. */
static <T extends EppResource> Query<T> queryItemsByKey(
Class<T> clazz,
RdapSearchPattern partialStringQuery,
Optional<String> cursorString,
DeletedItemHandling deletedItemHandling,
int resultSetMaxSize) {
if (partialStringQuery.getInitialString().length()
< RdapSearchPattern.MIN_INITIAL_STRING_LENGTH) {
throw new UnprocessableEntityException(
String.format(
"Initial search string must be at least %d characters",
RdapSearchPattern.MIN_INITIAL_STRING_LENGTH));
}
Query<T> query = ofy().load().type(clazz);
if (!partialStringQuery.getHasWildcard()) {
query = query.filterKey("=", Key.create(clazz, partialStringQuery.getInitialString()));
} else {
// Ignore the suffix; the caller will need to filter on the suffix, if any.
query = query
.filterKey(">=", Key.create(clazz, partialStringQuery.getInitialString()))
.filterKey("<", Key.create(clazz, partialStringQuery.getNextInitialString()));
}
if (cursorString.isPresent()) {
query = query.filterKey(">", Key.create(clazz, cursorString.get()));
}
return setOtherQueryAttributes(query, deletedItemHandling, resultSetMaxSize);
}
/** Handles searches by key using a simple string. */
static <T extends EppResource> Query<T> queryItemsByKey(
Class<T> clazz,
String queryString,
DeletedItemHandling deletedItemHandling,
int resultSetMaxSize) {
if (queryString.length() < RdapSearchPattern.MIN_INITIAL_STRING_LENGTH) {
throw new UnprocessableEntityException(
String.format(
"Initial search string must be at least %d characters",
RdapSearchPattern.MIN_INITIAL_STRING_LENGTH));
}
Query<T> query = ofy().load().type(clazz).filterKey("=", Key.create(clazz, queryString));
return setOtherQueryAttributes(query, deletedItemHandling, resultSetMaxSize);
}
static <T extends EppResource> Query<T> setOtherQueryAttributes(
Query<T> query, DeletedItemHandling deletedItemHandling, int resultSetMaxSize) {
if (deletedItemHandling != DeletedItemHandling.INCLUDE) {
query = query.filter("deletionTime", END_OF_TIME);
}
return query.limit(resultSetMaxSize);
}
}

View File

@@ -14,9 +14,13 @@
package google.registry.rdap;
import static google.registry.util.DomainNameUtils.ACE_PREFIX;
import com.google.common.base.Strings;
import google.registry.request.HttpException.BadRequestException;
import google.registry.request.HttpException.UnprocessableEntityException;
import google.registry.util.Idn;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
/**
@@ -32,6 +36,19 @@ public final class RdapSearchPattern {
static final int MIN_INITIAL_STRING_LENGTH = 2;
/**
* Pattern for allowed LDH searches.
*
* <p>Based on RFC7482 4.1. Must contains only alphanumeric plus dots and hyphens. A single
* whildcard asterix is allowed - but if exists must be the last character of a domain name label
* (so exam* and exam*.com are allowed, but exam*le.com isn't allowd)
*
* <p>The prefix is in group(1), and the suffix without the dot (if it exists) is in group(4). If
* there's no wildcard, group(2) is empty.
*/
static final Pattern LDH_PATTERN =
Pattern.compile("([-.a-zA-Z0-9]*)([*]([.]([-.a-zA-Z0-9]+))?)?");
/** String before the wildcard character. */
private final String initialString;
@@ -78,51 +95,83 @@ public final class RdapSearchPattern {
}
/**
* Creates a SearchPattern using the provided search pattern string.
* Creates a SearchPattern using the provided search pattern string in Unicode.
*
* @param pattern the string containing the partial match pattern
* @param allowSuffix true if a suffix is allowed after the wildcard
* <p>The search query might end in an asterix, in which case that asterix is considered a
* wildcard and can match 0 or more characters. Without that asterix - the match will be exact.
*
* @throws UnprocessableEntityException if {@code pattern} does not meet the requirements of RFC
* 7482
* @param searchQuery the string containing the partial match pattern, optionally ending in a
* wildcard asterix
* @throws UnprocessableEntityException if {@code pattern} has a wildcard not at the end of the
* query
*/
public static RdapSearchPattern create(String pattern, boolean allowSuffix) {
String initialString;
boolean hasWildcard;
String suffix;
// If there's no wildcard character, just lump everything into the initial string.
int wildcardPos = pattern.indexOf('*');
if (wildcardPos < 0) {
initialString = pattern;
hasWildcard = false;
suffix = null;
} else if (pattern.indexOf('*', wildcardPos + 1) >= 0) {
throw new UnprocessableEntityException("Only one wildcard allowed");
} else {
hasWildcard = true;
// Check for a suffix (e.g. exam*.com or ns*.example.com).
if (pattern.length() > wildcardPos + 1) {
if (!allowSuffix) {
throw new UnprocessableEntityException("Suffix not allowed after wildcard");
}
if ((pattern.length() == wildcardPos + 2) || (pattern.charAt(wildcardPos + 1) != '.')) {
throw new UnprocessableEntityException(
"Suffix after wildcard must be one or more domain"
+ " name labels, e.g. exam*.tld, ns*.example.tld");
}
suffix = pattern.substring(wildcardPos + 2);
} else {
suffix = null;
}
initialString = pattern.substring(0, wildcardPos);
if (initialString.startsWith(ACE_PREFIX) && (initialString.length() < 7)) {
throw new UnprocessableEntityException(
"At least seven characters must be specified for punycode domain searches");
}
public static RdapSearchPattern createFromUnicodeString(String searchQuery) {
int wildcardLocation = searchQuery.indexOf('*');
if (wildcardLocation < 0) {
return new RdapSearchPattern(searchQuery, false, null);
}
if (wildcardLocation == searchQuery.length() - 1) {
return new RdapSearchPattern(searchQuery.substring(0, wildcardLocation), true, null);
}
throw new UnprocessableEntityException(
String.format(
"Query can only have a single wildcard, and it must be at the end of the query, but"
+ " was: '%s'",
searchQuery));
}
/**
* Creates a SearchPattern using the provided domain search pattern in LDH format.
*
* <p>The domain search pattern can have a single wildcard asterix that can match 0 or more
* charecters. If such an asterix exists - it must be at the end of a domain label.
*
* @param searchQuery the string containing the partial match pattern
* @throws UnprocessableEntityException if {@code pattern} does not meet the requirements of RFC
* 7482
*/
public static RdapSearchPattern createFromLdhDomainName(String searchQuery) {
Matcher matcher = LDH_PATTERN.matcher(searchQuery);
if (!matcher.matches()) {
throw new UnprocessableEntityException(
String.format(
"Query can only have a single wildcard, and it must be at the end of a label,"
+ " but was: '%s'",
searchQuery));
}
String initialString = matcher.group(1);
boolean hasWildcard = !Strings.isNullOrEmpty(matcher.group(2));
String suffix = Strings.emptyToNull(matcher.group(4));
return new RdapSearchPattern(initialString, hasWildcard, suffix);
}
/**
* Creates a SearchPattern using the provided domain search pattern in LDH or Unicode format.
*
* <p>The domain search pattern can have a single wildcard asterix that can match 0 or more
* charecters. If such an asterix exists - it must be at the end of a domain label.
*
* <p>In theory, according to RFC7482 4.1 - we should make some checks about partial matching in
* unicode queries. We don't, but we might want to just disable partial matches for unicode inputs
* (meaning if it doesn't match LDH_PATTERN, then don't allow wildcard at all).
*
* @param searchQuery the string containing the partial match pattern
* @throws UnprocessableEntityException if {@code pattern} does not meet the requirements of RFC
* 7482
*/
public static RdapSearchPattern createFromLdhOrUnicodeDomainName(String searchQuery) {
String ldhSearchQuery;
try {
ldhSearchQuery = Idn.toASCII(searchQuery);
} catch (Exception e) {
throw new BadRequestException(
String.format("Invalid value of searchQuery: '%s'", searchQuery), e);
}
return RdapSearchPattern.createFromLdhDomainName(ldhSearchQuery);
}
/**
* Checks a string to make sure that it matches the search pattern.
*

View File

@@ -14,6 +14,7 @@
package google.registry.rdap;
import com.google.common.base.Ascii;
import com.google.common.collect.Streams;
import google.registry.model.registrar.Registrar;
import java.util.Objects;
@@ -30,4 +31,17 @@ public final class RdapUtils {
.filter(registrar -> Objects.equals(ianaIdentifier, registrar.getIanaIdentifier()))
.findFirst();
}
/**
* Looks up a registrar by its name.
*
* <p>Used for RDAP Technical Implementation Guide 2.4.2 - search of registrar by the fn element.
*
* <p>For convenience, we use case insensitive search.
*/
static Optional<Registrar> getRegistrarByName(String registrarName) {
return Streams.stream(Registrar.loadAllCached())
.filter(registrar -> Ascii.equalsIgnoreCase(registrarName, registrar.getRegistrarName()))
.findFirst();
}
}

View File

@@ -1647,10 +1647,10 @@ def com_google_template_soy():
def com_google_truth():
java_import_external(
name = "com_google_truth",
jar_sha256 = "a9e6796786c9c77a5fe19b08e72fe0a620d53166df423d8861af9ebef4dc4247",
jar_sha256 = "0f7dced2a16e55a77e44fc3ff9c5be98d4bf4bb30abc18d78ffd735df950a69f",
jar_urls = [
"http://maven.ibiblio.org/maven2/com/google/truth/truth/0.44/truth-0.44.jar",
"http://repo1.maven.org/maven2/com/google/truth/truth/0.44/truth-0.44.jar",
"http://maven.ibiblio.org/maven2/com/google/truth/truth/0.45/truth-0.45.jar",
"http://repo1.maven.org/maven2/com/google/truth/truth/0.45/truth-0.45.jar",
],
licenses = ["notice"], # The Apache Software License, Version 2.0
testonly_ = True,
@@ -1666,10 +1666,10 @@ def com_google_truth():
def com_google_truth_extensions_truth_java8_extension():
java_import_external(
name = "com_google_truth_extensions_truth_java8_extension",
jar_sha256 = "da4d94dc952c65914bf9e3c0b4f4a05f5aea536aa5de9a4660b859409dda4bad",
jar_sha256 = "dc1fedf6c13b1b1a4c4fa3e810f11df070ea4701765f05176f8bdcb5520c7de4",
jar_urls = [
"http://maven.ibiblio.org/maven2/com/google/truth/extensions/truth-java8-extension/0.44/truth-java8-extension-0.44.jar",
"http://central.maven.org/maven2/com/google/truth/extensions/truth-java8-extension/0.44/truth-java8-extension-0.44.jar",
"http://maven.ibiblio.org/maven2/com/google/truth/extensions/truth-java8-extension/0.45/truth-java8-extension-0.45.jar",
"http://central.maven.org/maven2/com/google/truth/extensions/truth-java8-extension/0.45/truth-java8-extension-0.45.jar",
],
licenses = ["notice"], # The Apache Software License, Version 2.0
testonly_ = True,

View File

@@ -14,6 +14,7 @@
package google.registry.tools.server;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.mapreduce.inputs.EppResourceInputs.createEntityInput;
import static google.registry.model.EppResourceUtils.isActive;
import static google.registry.model.registry.Registries.assertTldsExist;
@@ -32,9 +33,11 @@ import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.NonFinalForTesting;
import java.util.Random;
import javax.inject.Inject;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Duration;
/**
* A mapreduce that enqueues DNS publish tasks on all active domains on the specified TLD(s).
@@ -46,6 +49,11 @@ import org.joda.time.DateTimeZone;
* <p>Because there are no auth settings in the {@link Action} annotation, this command can only be
* run internally, or by pretending to be internal by setting the X-AppEngine-QueueName header,
* which only admin users can do.
*
* <p>You must pass in a number of <code>smearMinutes</code> as a URL parameter so that the DNS
* queue doesn't get overloaded. A rough rule of thumb for Cloud DNS is 1 minute per every 1,000
* domains. This smears the updates out over the next N minutes. For small TLDs consisting of fewer
* than 1,000 domains, passing in 1 is fine (which will execute all the updates immediately).
*/
@Action(
service = Action.Service.TOOLS,
@@ -57,18 +65,30 @@ public class RefreshDnsForAllDomainsAction implements Runnable {
@Inject MapreduceRunner mrRunner;
@Inject Response response;
@Inject @Parameter(PARAM_TLDS) ImmutableSet<String> tlds;
@Inject RefreshDnsForAllDomainsAction() {}
@Inject
@Parameter(PARAM_TLDS)
ImmutableSet<String> tlds;
@Inject
@Parameter("smearMinutes")
int smearMinutes;
@Inject Random random;
@Inject
RefreshDnsForAllDomainsAction() {}
@Override
public void run() {
assertTldsExist(tlds);
checkArgument(smearMinutes > 0, "Must specify a positive number of smear minutes");
mrRunner
.setJobName("Refresh DNS for all domains")
.setModuleName("tools")
.setDefaultMapShards(10)
.runMapOnly(
new RefreshDnsForAllDomainsActionMapper(tlds),
new RefreshDnsForAllDomainsActionMapper(tlds, smearMinutes, random),
ImmutableList.of(createEntityInput(DomainBase.class)))
.sendLinkToMapreduceConsole(response);
}
@@ -77,14 +97,19 @@ public class RefreshDnsForAllDomainsAction implements Runnable {
public static class RefreshDnsForAllDomainsActionMapper
extends Mapper<DomainBase, Void, Void> {
private static final long serialVersionUID = 1455544013508953083L;
private static final long serialVersionUID = -5103865047156795489L;
@NonFinalForTesting private static DnsQueue dnsQueue = DnsQueue.create();
private final ImmutableSet<String> tlds;
private final int smearMinutes;
private final Random random;
RefreshDnsForAllDomainsActionMapper(ImmutableSet<String> tlds) {
RefreshDnsForAllDomainsActionMapper(
ImmutableSet<String> tlds, int smearMinutes, Random random) {
this.tlds = tlds;
this.smearMinutes = smearMinutes;
this.random = random;
}
@Override
@@ -93,7 +118,9 @@ public class RefreshDnsForAllDomainsAction implements Runnable {
if (tlds.contains(domain.getTld())) {
if (isActive(domain, DateTime.now(DateTimeZone.UTC))) {
try {
dnsQueue.addDomainRefreshTask(domainName);
// Smear the task execution time over the next N minutes.
dnsQueue.addDomainRefreshTask(
domainName, Duration.standardMinutes(random.nextInt(smearMinutes)));
getContext().incrementCounter("active domains refreshed");
} catch (Throwable t) {
logger.atSevere().withCause(t).log(

View File

@@ -108,4 +108,10 @@ public class ToolsServerModule {
String provideJobId(HttpServletRequest req) {
return extractRequiredParameter(req, "jobId");
}
@Provides
@Parameter("smearMinutes")
static int provideSmearMinutes(HttpServletRequest req) {
return extractIntParameter(req, "smearMinutes");
}
}

View File

@@ -22,6 +22,7 @@ import dagger.Provides;
import java.security.NoSuchAlgorithmException;
import java.security.ProviderException;
import java.security.SecureRandom;
import java.util.Random;
import javax.inject.Named;
import javax.inject.Singleton;
@@ -48,7 +49,6 @@ public abstract class UtilsModule {
abstract AppEngineServiceUtils provideAppEngineServiceUtils(
AppEngineServiceUtilsImpl appEngineServiceUtilsImpl);
@Singleton
@Provides
public static SecureRandom provideSecureRandom() {
@@ -59,6 +59,10 @@ public abstract class UtilsModule {
}
}
@Binds
@Singleton
abstract Random provideSecureRandomAsRandom(SecureRandom random);
@Singleton
@Provides
@Named("base58StringGenerator")

View File

@@ -12,6 +12,7 @@ KmsSecret
KmsSecretRevision
Modification
OneTime
PollMessage
PremiumList
PremiumListEntry
PremiumListRevision

View File

@@ -17,8 +17,10 @@ package google.registry.flows.contact;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.ContactResourceSubject.assertAboutContacts;
import static google.registry.testing.DatastoreHelper.assertNoBillingEvents;
import static google.registry.testing.DatastoreHelper.newContactResource;
import static google.registry.testing.DatastoreHelper.persistActiveContact;
import static google.registry.testing.DatastoreHelper.persistDeletedContact;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
import static google.registry.testing.JUnitBackports.assertThrows;
@@ -26,7 +28,8 @@ import google.registry.flows.EppException;
import google.registry.flows.ResourceFlowTestCase;
import google.registry.flows.contact.ContactFlowUtils.BadInternationalizedPostalInfoException;
import google.registry.flows.contact.ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException;
import google.registry.flows.exceptions.ResourceAlreadyExistsException;
import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientException;
import google.registry.flows.exceptions.ResourceCreateContentionException;
import google.registry.model.contact.ContactResource;
import org.joda.time.DateTime;
import org.junit.Test;
@@ -44,8 +47,10 @@ public class ContactCreateFlowTest
assertTransactionalFlow(true);
runFlowAssertResponse(loadFile("contact_create_response.xml"));
// Check that the contact was created and persisted with a history entry.
assertAboutContacts().that(reloadResourceByForeignKey())
.hasOnlyOneHistoryEntryWhich().hasNoXml();
assertAboutContacts()
.that(reloadResourceByForeignKey())
.hasOnlyOneHistoryEntryWhich()
.hasNoXml();
assertNoBillingEvents();
assertEppResourceIndexEntityFor(reloadResourceByForeignKey());
}
@@ -70,8 +75,8 @@ public class ContactCreateFlowTest
@Test
public void testFailure_alreadyExists() throws Exception {
persistActiveContact(getUniqueIdFromCommand());
ResourceAlreadyExistsException thrown =
assertThrows(ResourceAlreadyExistsException.class, this::runFlow);
ResourceAlreadyExistsForThisClientException thrown =
assertThrows(ResourceAlreadyExistsForThisClientException.class, this::runFlow);
assertThat(thrown)
.hasMessageThat()
.contains(
@@ -79,6 +84,22 @@ public class ContactCreateFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_resourceContention() throws Exception {
String targetId = getUniqueIdFromCommand();
persistResource(
newContactResource(targetId)
.asBuilder()
.setPersistedCurrentSponsorClientId("NewRegistrar")
.build());
ResourceCreateContentionException thrown =
assertThrows(ResourceCreateContentionException.class, this::runFlow);
assertThat(thrown)
.hasMessageThat()
.contains(String.format("Object with given ID (%s) already exists", targetId));
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testSuccess_nonAsciiInLocAddress() throws Exception {
setEppInput("contact_create_hebrew_loc.xml");

View File

@@ -40,6 +40,7 @@ import static google.registry.testing.DatastoreHelper.deleteTld;
import static google.registry.testing.DatastoreHelper.getHistoryEntries;
import static google.registry.testing.DatastoreHelper.loadRegistrar;
import static google.registry.testing.DatastoreHelper.newContactResource;
import static google.registry.testing.DatastoreHelper.newDomainBase;
import static google.registry.testing.DatastoreHelper.newHostResource;
import static google.registry.testing.DatastoreHelper.persistActiveContact;
import static google.registry.testing.DatastoreHelper.persistActiveDomain;
@@ -134,7 +135,8 @@ import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTok
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException;
import google.registry.flows.exceptions.OnlyToolCanPassMetadataException;
import google.registry.flows.exceptions.ResourceAlreadyExistsException;
import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientException;
import google.registry.flows.exceptions.ResourceCreateContentionException;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason;
@@ -965,8 +967,8 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
public void testFailure_alreadyExists() throws Exception {
persistContactsAndHosts();
persistActiveDomain(getUniqueIdFromCommand());
ResourceAlreadyExistsException thrown =
assertThrows(ResourceAlreadyExistsException.class, this::runFlow);
ResourceAlreadyExistsForThisClientException thrown =
assertThrows(ResourceAlreadyExistsForThisClientException.class, this::runFlow);
assertAboutEppExceptions()
.that(thrown)
.marshalsToXml()
@@ -975,6 +977,23 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
String.format("Object with given ID (%s) already exists", getUniqueIdFromCommand()));
}
@Test
public void testFailure_resourceContention() throws Exception {
persistContactsAndHosts();
String targetId = getUniqueIdFromCommand();
persistResource(
newDomainBase(targetId)
.asBuilder()
.setPersistedCurrentSponsorClientId("NewRegistrar")
.build());
ResourceCreateContentionException thrown =
assertThrows(ResourceCreateContentionException.class, this::runFlow);
assertThat(thrown)
.hasMessageThat()
.contains(String.format("Object with given ID (%s) already exists", targetId));
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_reserved() {
setEppInput("domain_create_reserved.xml");
@@ -1089,6 +1108,27 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
assertAllocationTokenWasRedeemed("abcDEF23456");
}
@Test
public void testSuccess_anchorTenant_duringQuietPeriodBeforeSunrise() throws Exception {
persistResource(
Registry.get("tld")
.asBuilder()
.setTldStateTransitions(
ImmutableSortedMap.of(
START_OF_TIME, PREDELEGATION,
DateTime.parse("1999-01-01T00:00:00Z"), QUIET_PERIOD,
// The anchor tenant is created here, on 1999-04-03
DateTime.parse("1999-07-01T00:00:00Z"), START_DATE_SUNRISE,
DateTime.parse("2000-01-01T00:00:00Z"), GENERAL_AVAILABILITY))
.build());
setEppInput("domain_create_anchor_allocationtoken.xml");
persistContactsAndHosts();
runFlowAssertResponse(loadFile("domain_create_anchor_response.xml"));
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT), allocationToken);
assertNoLordn();
assertAllocationTokenWasRedeemed("abcDEF23456");
}
@Test
public void testSuccess_reservedDomain_viaAllocationTokenExtension() throws Exception {
allocationToken =
@@ -1109,6 +1149,30 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
assertAllocationTokenWasRedeemed("abc123");
}
@Test
public void testSuccess_reservedDomain_viaAllocationTokenExtension_inQuietPeriod()
throws Exception {
persistResource(
Registry.get("tld")
.asBuilder()
.setTldStateTransitions(ImmutableSortedMap.of(START_OF_TIME, QUIET_PERIOD))
.build());
allocationToken =
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(SINGLE_USE)
.setDomainName("resdom.tld")
.build());
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "resdom.tld"));
persistContactsAndHosts();
runFlowAssertResponse(
loadFile("domain_create_response.xml", ImmutableMap.of("DOMAIN", "resdom.tld")));
assertSuccessfulCreate("tld", ImmutableSet.of(RESERVED), allocationToken);
assertNoLordn();
assertAllocationTokenWasRedeemed("abc123");
}
private void assertAllocationTokenWasRedeemed(String token) throws Exception {
AllocationToken reloadedToken =
ofy().load().key(Key.create(AllocationToken.class, token)).now();

View File

@@ -17,6 +17,7 @@ package google.registry.flows.domain;
import static com.google.common.io.BaseEncoding.base16;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registry.TldState.QUIET_PERIOD;
import static google.registry.testing.DatastoreHelper.assertNoBillingEvents;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.newDomainBase;
@@ -26,10 +27,12 @@ import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
import static google.registry.testing.JUnitBackports.assertThrows;
import static google.registry.testing.TestDataHelper.updateSubstitutions;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.FlowUtils.UnknownCurrencyEppException;
@@ -55,6 +58,7 @@ import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.ofy.RequestCapturingAsyncDatastoreService;
import google.registry.model.registry.Registry;
import google.registry.testing.AppEngineRule;
import org.joda.time.DateTime;
import org.junit.Before;
@@ -269,6 +273,16 @@ public class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Dom
doSuccessfulTest("domain_info_response.xml", false);
}
@Test
public void testSuccess_inQuietPeriod() throws Exception {
persistResource(
Registry.get("tld")
.asBuilder()
.setTldStateTransitions(ImmutableSortedMap.of(START_OF_TIME, QUIET_PERIOD))
.build());
doSuccessfulTest("domain_info_response.xml");
}
@Test
public void testSuccess_secDns() throws Exception {
persistTestEntities(false);

View File

@@ -23,6 +23,7 @@ import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
import static google.registry.batch.AsyncTaskEnqueuer.PATH_RESAVE_ENTITY;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registry.TldState.QUIET_PERIOD;
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_CREATE;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST;
@@ -874,6 +875,17 @@ public class DomainTransferRequestFlowTest
doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml");
}
@Test
public void testSuccess_inQuietPeriod() throws Exception {
setupDomain("example", "tld");
persistResource(
Registry.get("tld")
.asBuilder()
.setTldStateTransitions(ImmutableSortedMap.of(START_OF_TIME, QUIET_PERIOD))
.build());
doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml");
}
@Test
public void testFailure_multiYearPeriod() {
setupDomain("example", "tld");

View File

@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.eppcommon.StatusValue.SERVER_UPDATE_PROHIBITED;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registry.TldState.QUIET_PERIOD;
import static google.registry.testing.DatastoreHelper.assertBillingEvents;
import static google.registry.testing.DatastoreHelper.assertNoBillingEvents;
import static google.registry.testing.DatastoreHelper.createTld;
@@ -37,11 +38,13 @@ import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptio
import static google.registry.testing.HistoryEntrySubject.assertAboutHistoryEntries;
import static google.registry.testing.JUnitBackports.assertThrows;
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.joda.money.CurrencyUnit.USD;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.googlecode.objectify.Key;
import google.registry.config.RegistryConfig;
import google.registry.flows.EppException;
@@ -229,6 +232,18 @@ public class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow,
}
}
@Test
public void testSuccess_inQuietPeriod() throws Exception {
persistResource(
Registry.get("tld")
.asBuilder()
.setTldStateTransitions(ImmutableSortedMap.of(START_OF_TIME, QUIET_PERIOD))
.build());
persistReferencedEntities();
persistDomain();
doSuccessfulTest();
}
@Test
public void testFailure_emptyRegistrant() throws Exception {
setEppInput("domain_update_empty_registrant.xml");

View File

@@ -20,6 +20,7 @@ import static google.registry.testing.DatastoreHelper.assertNoBillingEvents;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.createTlds;
import static google.registry.testing.DatastoreHelper.newDomainBase;
import static google.registry.testing.DatastoreHelper.newHostResource;
import static google.registry.testing.DatastoreHelper.persistActiveDomain;
import static google.registry.testing.DatastoreHelper.persistActiveHost;
import static google.registry.testing.DatastoreHelper.persistDeletedHost;
@@ -37,7 +38,8 @@ import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.FlowUtils.IpAddressVersionMismatchException;
import google.registry.flows.ResourceFlowTestCase;
import google.registry.flows.exceptions.ResourceAlreadyExistsException;
import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientException;
import google.registry.flows.exceptions.ResourceCreateContentionException;
import google.registry.flows.host.HostCreateFlow.SubordinateHostMustHaveIpException;
import google.registry.flows.host.HostCreateFlow.UnexpectedExternalHostIpException;
import google.registry.flows.host.HostFlowUtils.HostNameNotLowerCaseException;
@@ -200,14 +202,31 @@ public class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, Hos
public void testFailure_alreadyExists() throws Exception {
setEppHostCreateInput("ns1.example.tld", null);
persistActiveHost(getUniqueIdFromCommand());
ResourceAlreadyExistsException thrown =
assertThrows(ResourceAlreadyExistsException.class, this::runFlow);
ResourceAlreadyExistsForThisClientException thrown =
assertThrows(ResourceAlreadyExistsForThisClientException.class, this::runFlow);
assertThat(thrown)
.hasMessageThat()
.contains(
String.format("Object with given ID (%s) already exists", getUniqueIdFromCommand()));
}
@Test
public void testFailure_resourceContention() throws Exception {
setEppHostCreateInput("ns1.example.tld", null);
String targetId = getUniqueIdFromCommand();
persistResource(
newHostResource(targetId)
.asBuilder()
.setPersistedCurrentSponsorClientId("NewRegistrar")
.build());
ResourceCreateContentionException thrown =
assertThrows(ResourceCreateContentionException.class, this::runFlow);
assertThat(thrown)
.hasMessageThat()
.contains(String.format("Object with given ID (%s) already exists", targetId));
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_nonLowerCaseHostname() {
setEppHostCreateInput("ns1.EXAMPLE.tld", null);

View File

@@ -42,7 +42,7 @@ public class EntityClassesTest {
@Test
public void testEntityClasses_inAlphabeticalOrder() {
assertThat(ALL_CLASSES).isStrictlyOrdered(QUALIFIED_CLASS_NAME_ORDERING);
assertThat(ALL_CLASSES).isInStrictOrder(QUALIFIED_CLASS_NAME_ORDERING);
}
@Test

View File

@@ -86,7 +86,6 @@ public class RdapActionBaseTestCase<A extends RdapActionBase> {
inject.setStaticField(Ofy.class, "clock", clock);
action = TypeUtils.instantiate(rdapActionClass);
action.includeDeletedParam = Optional.empty();
action.registrarParam = Optional.empty();
action.formatOutputParam = Optional.empty();
action.response = response;
action.rdapJsonFormatter = RdapTestHelper.getTestRdapJsonFormatter(clock);

View File

@@ -45,7 +45,12 @@ public final class RdapDataStructuresTest {
@Test
public void testRdapConformance() {
assertThat(RdapConformance.INSTANCE.toJson())
.isEqualTo(createJson("['rdap_level_0','icann_rdap_response_profile_0']"));
.isEqualTo(createJson(
"[",
" 'rdap_level_0',",
" 'icann_rdap_response_profile_0',",
" 'icann_rdap_technical_implementation_guide_0'",
"]"));
}
@Test

View File

@@ -273,20 +273,6 @@ public class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainActio
assertProperResponseForCatLol("cat.lol", "rdap_domain.json");
}
@Test
public void testValidDomain_works_sameRegistrarRequested() {
action.registrarParam = Optional.of("evilregistrar");
login("evilregistrar");
assertProperResponseForCatLol("cat.lol", "rdap_domain.json");
}
@Test
public void testValidDomain_notFound_differentRegistrarRequested() {
action.registrarParam = Optional.of("idnregistrar");
generateActualJson("cat.lol");
assertThat(response.getStatus()).isEqualTo(404);
}
@Test
public void testValidDomain_asAdministrator_works() {
loginAsAdmin();

View File

@@ -663,10 +663,11 @@ public class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDom
@Test
public void testInvalidWildcard_rejected() {
assertThat(generateActualJson(RequestType.NAME, "exam*ple"))
.isEqualTo(generateExpectedJsonError(
"Suffix after wildcard must be one or more domain"
+ " name labels, e.g. exam*.tld, ns*.example.tld",
422));
.isEqualTo(
generateExpectedJsonError(
"Query can only have a single wildcard, and it must be at the end of a label, but"
+ " was: 'exam*ple'",
422));
assertThat(response.getStatus()).isEqualTo(422);
verifyErrorMetrics(SearchType.BY_DOMAIN_NAME, Optional.empty(), 422);
}
@@ -674,7 +675,11 @@ public class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDom
@Test
public void testMultipleWildcards_rejected() {
assertThat(generateActualJson(RequestType.NAME, "*.*"))
.isEqualTo(generateExpectedJsonError("Only one wildcard allowed", 422));
.isEqualTo(
generateExpectedJsonError(
"Query can only have a single wildcard, and it must be at the end of a label, but"
+ " was: '*.*'",
422));
assertThat(response.getStatus()).isEqualTo(422);
verifyErrorMetrics(SearchType.BY_DOMAIN_NAME, Optional.empty(), 422);
}
@@ -1297,7 +1302,7 @@ public class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDom
@Test
public void testNameserverMatchWithWildcardAndEmptySuffix_unprocessable() {
rememberWildcardType("ns*.");
rememberWildcardTypeInvalid();
generateActualJson(RequestType.NS_LDH_NAME, "ns*.");
assertThat(response.getStatus()).isEqualTo(422);
verifyErrorMetrics(SearchType.BY_NAMESERVER_NAME, Optional.empty(), 422);
@@ -1331,8 +1336,8 @@ public class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDom
metricWildcardType = WildcardType.INVALID;
metricPrefixLength = 0;
generateActualJson(RequestType.NS_LDH_NAME, "ns1.cat.みんな");
assertThat(response.getStatus()).isEqualTo(400);
verifyErrorMetrics(SearchType.BY_NAMESERVER_NAME, Optional.empty(), 400);
assertThat(response.getStatus()).isEqualTo(422);
verifyErrorMetrics(SearchType.BY_NAMESERVER_NAME, Optional.empty(), 422);
}
@Test

View File

@@ -163,76 +163,64 @@ public class RdapEntityActionTest extends RdapActionBaseTestCase<RdapEntityActio
return obj;
}
private void runSuccessfulTest(String queryString, String fileName) {
runSuccessfulTest(queryString, "(◕‿◕)", "active", null, fileName);
private void runSuccessfulHandleTest(String handleQuery, String fileName) {
runSuccessfulHandleTest(handleQuery, "(◕‿◕)", "active", null, fileName);
}
private void runSuccessfulTest(String queryString, String fullName, String fileName) {
runSuccessfulTest(queryString, fullName, "active", null, fileName);
private void runSuccessfulHandleTest(String handleQuery, String fullName, String fileName) {
runSuccessfulHandleTest(handleQuery, fullName, "active", null, fileName);
}
private void runSuccessfulTest(
String queryString,
private void runSuccessfulHandleTest(
String handleQuery,
String fullName,
String rdapStatus,
String address,
String fileName) {
assertThat(generateActualJson(queryString))
assertThat(generateActualJson(handleQuery))
.isEqualTo(
generateExpectedJsonWithTopLevelEntries(
queryString, fullName, rdapStatus, address, fileName));
handleQuery, fullName, rdapStatus, address, fileName));
assertThat(response.getStatus()).isEqualTo(200);
}
private void runNotFoundTest(String queryString) {
assertThat(generateActualJson(queryString))
.isEqualTo(generateExpectedJsonError(queryString + " not found", 404));
private void runNotFoundTest(String handleQuery) {
assertThat(generateActualJson(handleQuery))
.isEqualTo(generateExpectedJsonError(handleQuery + " not found", 404));
assertThat(response.getStatus()).isEqualTo(404);
}
@Test
public void testInvalidEntity_returns400() {
assertThat(generateActualJson("invalid/entity/handle")).isEqualTo(
generateExpectedJsonError(
"invalid/entity/handle is not a valid entity handle",
400));
assertThat(response.getStatus()).isEqualTo(400);
public void testUnknownEntity_RoidPattern_notFound() {
runNotFoundTest("_MISSING-ENTITY_");
}
@Test
public void testUnknownEntity_notFound() {
runNotFoundTest("_MISSING-ENTITY_");
public void testUnknownEntity_IanaPattern_notFound() {
runNotFoundTest("123");
}
@Test
public void testUnknownEntity_notRoidNotIana_notFound() {
// Since we allow search by registrar name, every string is a possible name
runNotFoundTest("some,random,string");
}
@Test
public void testValidRegistrantContact_works() {
login("evilregistrar");
runSuccessfulTest(registrant.getRepoId(), "rdap_associated_contact.json");
}
@Test
public void testValidRegistrantContact_found_sameRegistrarRequested() {
login("evilregistrar");
action.registrarParam = Optional.of("evilregistrar");
runSuccessfulTest(registrant.getRepoId(), "rdap_associated_contact.json");
}
@Test
public void testValidRegistrantContact_notFound_differentRegistrarRequested() {
login("evilregistrar");
action.registrarParam = Optional.of("idnregistrar");
runNotFoundTest(registrant.getRepoId());
runSuccessfulHandleTest(registrant.getRepoId(), "rdap_associated_contact.json");
}
@Test
public void testValidRegistrantContact_found_asAdministrator() {
loginAsAdmin();
runSuccessfulTest(registrant.getRepoId(), "rdap_associated_contact.json");
runSuccessfulHandleTest(registrant.getRepoId(), "rdap_associated_contact.json");
}
@Test
public void testValidRegistrantContact_found_notLoggedIn() {
runSuccessfulTest(
runSuccessfulHandleTest(
registrant.getRepoId(),
"(◕‿◕)",
"active",
@@ -243,7 +231,7 @@ public class RdapEntityActionTest extends RdapActionBaseTestCase<RdapEntityActio
@Test
public void testValidRegistrantContact_found_loggedInAsOtherRegistrar() {
login("otherregistrar");
runSuccessfulTest(
runSuccessfulHandleTest(
registrant.getRepoId(),
"(◕‿◕)",
"active",
@@ -254,19 +242,19 @@ public class RdapEntityActionTest extends RdapActionBaseTestCase<RdapEntityActio
@Test
public void testValidAdminContact_works() {
login("evilregistrar");
runSuccessfulTest(adminContact.getRepoId(), "rdap_associated_contact.json");
runSuccessfulHandleTest(adminContact.getRepoId(), "rdap_associated_contact.json");
}
@Test
public void testValidTechContact_works() {
login("evilregistrar");
runSuccessfulTest(techContact.getRepoId(), "rdap_associated_contact.json");
runSuccessfulHandleTest(techContact.getRepoId(), "rdap_associated_contact.json");
}
@Test
public void testValidDisconnectedContact_works() {
login("evilregistrar");
runSuccessfulTest(disconnectedContact.getRepoId(), "rdap_contact.json");
runSuccessfulHandleTest(disconnectedContact.getRepoId(), "rdap_contact.json");
}
@Test
@@ -297,7 +285,7 @@ public class RdapEntityActionTest extends RdapActionBaseTestCase<RdapEntityActio
public void testDeletedContact_found_loggedInAsCorrectRegistrar() {
login("evilregistrar");
action.includeDeletedParam = Optional.of(true);
runSuccessfulTest(
runSuccessfulHandleTest(
deletedContact.getRepoId(),
"",
"inactive",
@@ -309,7 +297,7 @@ public class RdapEntityActionTest extends RdapActionBaseTestCase<RdapEntityActio
public void testDeletedContact_found_loggedInAsAdmin() {
loginAsAdmin();
action.includeDeletedParam = Optional.of(true);
runSuccessfulTest(
runSuccessfulHandleTest(
deletedContact.getRepoId(),
"",
"inactive",
@@ -319,29 +307,26 @@ public class RdapEntityActionTest extends RdapActionBaseTestCase<RdapEntityActio
@Test
public void testRegistrar_found() {
runSuccessfulTest("101", "Yes Virginia <script>", "rdap_registrar.json");
runSuccessfulHandleTest("101", "Yes Virginia <script>", "rdap_registrar.json");
}
@Test
public void testRegistrarByName_found() {
assertThat(generateActualJson("IDN%20Registrar"))
.isEqualTo(
generateExpectedJsonWithTopLevelEntries(
"102", "IDN Registrar", "active", null, "rdap_registrar.json"));
assertThat(response.getStatus()).isEqualTo(200);
}
@Test
public void testRegistrar102_works() {
runSuccessfulTest("102", "IDN Registrar", "rdap_registrar.json");
}
@Test
public void testRegistrar102_found_requestingSameRegistrar() {
action.registrarParam = Optional.of("idnregistrar");
runSuccessfulTest("102", "IDN Registrar", "rdap_registrar.json");
}
@Test
public void testRegistrar102_notFound_requestingOtherRegistrar() {
action.registrarParam = Optional.of("1tldregistrar");
runNotFoundTest("102");
runSuccessfulHandleTest("102", "IDN Registrar", "rdap_registrar.json");
}
@Test
public void testRegistrar103_works() {
runSuccessfulTest("103", "Multilevel Registrar", "rdap_registrar.json");
runSuccessfulHandleTest("103", "Multilevel Registrar", "rdap_registrar.json");
}
@Test
@@ -359,7 +344,7 @@ public class RdapEntityActionTest extends RdapActionBaseTestCase<RdapEntityActio
public void testRegistrar104_found_deletedFlagWhenLoggedIn() {
login("deletedregistrar");
action.includeDeletedParam = Optional.of(true);
runSuccessfulTest(
runSuccessfulHandleTest(
"104", "Yes Virginia <script>", "inactive", null, "rdap_registrar.json");
}
@@ -374,7 +359,7 @@ public class RdapEntityActionTest extends RdapActionBaseTestCase<RdapEntityActio
public void testRegistrar104_found_deletedFlagWhenLoggedInAsAdmin() {
loginAsAdmin();
action.includeDeletedParam = Optional.of(true);
runSuccessfulTest(
runSuccessfulHandleTest(
"104", "Yes Virginia <script>", "inactive", null, "rdap_registrar.json");
}

View File

@@ -412,7 +412,10 @@ public class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEnt
public void testNameMatch_suffixRejected() {
assertThat(generateActualJsonWithFullName("exam*ple"))
.isEqualTo(
generateExpectedJsonError("Suffix not allowed after wildcard", 422));
generateExpectedJsonError(
"Query can only have a single wildcard, and it must be at the end of the query,"
+ " but was: 'exam*ple'",
422));
assertThat(response.getStatus()).isEqualTo(422);
verifyErrorMetrics(Optional.empty(), 422);
}
@@ -421,7 +424,10 @@ public class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEnt
public void testHandleMatch_suffixRejected() {
assertThat(generateActualJsonWithHandle("exam*ple"))
.isEqualTo(
generateExpectedJsonError("Suffix not allowed after wildcard", 422));
generateExpectedJsonError(
"Query can only have a single wildcard, and it must be at the end of the query,"
+ " but was: 'exam*ple'",
422));
assertThat(response.getStatus()).isEqualTo(422);
verifyErrorMetrics(Optional.empty(), 422);
}
@@ -429,7 +435,11 @@ public class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEnt
@Test
public void testMultipleWildcards_rejected() {
assertThat(generateActualJsonWithHandle("*.*"))
.isEqualTo(generateExpectedJsonError("Only one wildcard allowed", 422));
.isEqualTo(
generateExpectedJsonError(
"Query can only have a single wildcard, and it must be at the end of the query,"
+ " but was: '*.*'",
422));
assertThat(response.getStatus()).isEqualTo(422);
verifyErrorMetrics(Optional.empty(), 422);
}

View File

@@ -235,30 +235,6 @@ public class RdapNameserverActionTest extends RdapActionBaseTestCase<RdapNameser
assertThat(response.getStatus()).isEqualTo(200);
}
@Test
public void testNameserver_found_sameRegistrarRequested() {
action.registrarParam = Optional.of("TheRegistrar");
assertThat(generateActualJson("ns1.cat.lol"))
.isEqualTo(
generateExpectedJsonWithTopLevelEntries(
"ns1.cat.lol",
ImmutableMap.of(
"HANDLE", "2-ROID",
"ADDRESSTYPE", "v4",
"ADDRESS", "1.2.3.4",
"STATUS", "active"),
"rdap_host.json"));
assertThat(response.getStatus()).isEqualTo(200);
}
@Test
public void testNameserver_notFound_differentRegistrarRequested() {
action.registrarParam = Optional.of("otherregistrar");
action.includeDeletedParam = Optional.of(false);
generateActualJson("ns1.cat.lol");
assertThat(response.getStatus()).isEqualTo(404);
}
@Test
public void testDeletedNameserver_notFound_includeDeletedNotSpecified() {
generateActualJson("nsdeleted.cat.lol");
@@ -322,33 +298,6 @@ public class RdapNameserverActionTest extends RdapActionBaseTestCase<RdapNameser
assertThat(response.getStatus()).isEqualTo(200);
}
@Test
public void testDeletedNameserver_found_sameRegistrarRequested() {
login("TheRegistrar");
action.registrarParam = Optional.of("TheRegistrar");
action.includeDeletedParam = Optional.of(true);
assertThat(generateActualJson("nsdeleted.cat.lol"))
.isEqualTo(
generateExpectedJsonWithTopLevelEntries(
"nsdeleted.cat.lol",
ImmutableMap.of(
"HANDLE", "A-ROID",
"ADDRESSTYPE", "v4",
"ADDRESS", "1.2.3.4",
"STATUS", "inactive"),
"rdap_host.json"));
assertThat(response.getStatus()).isEqualTo(200);
}
@Test
public void testDeletedNameserver_notFound_differentRegistrarRequested() {
login("TheRegistrar");
action.registrarParam = Optional.of("otherregistrar");
action.includeDeletedParam = Optional.of(false);
generateActualJson("ns1.cat.lol");
assertThat(response.getStatus()).isEqualTo(404);
}
@Test
public void testMetrics() {
generateActualJson("ns1.cat.lol");

View File

@@ -258,9 +258,10 @@ public class RdapNameserverSearchActionTest
assertThat(generateActualJsonWithName("exam*ple"))
.isEqualTo(
generateExpectedJsonError(
"Suffix after wildcard must be one or more domain"
+ " name labels, e.g. exam*.tld, ns*.example.tld",
"Query can only have a single wildcard, and it must be at the end of a label, but"
+ " was: 'exam*ple'",
422));
rememberWildcardTypeInvalid();
assertThat(response.getStatus()).isEqualTo(422);
verifyErrorMetrics(Optional.empty(), 422);
}
@@ -279,7 +280,12 @@ public class RdapNameserverSearchActionTest
@Test
public void testMultipleWildcards_rejected() {
assertThat(generateActualJsonWithName("*.*"))
.isEqualTo(generateExpectedJsonError("Only one wildcard allowed", 422));
.isEqualTo(
generateExpectedJsonError(
"Query can only have a single wildcard, and it must be at the end of a label, but"
+ " was: '*.*'",
422));
rememberWildcardTypeInvalid();
assertThat(response.getStatus()).isEqualTo(422);
verifyErrorMetrics(Optional.empty(), 422);
}
@@ -337,7 +343,7 @@ public class RdapNameserverSearchActionTest
action.registrarParam = Optional.of("unicoderegistrar");
generateActualJsonWithName("ns1.cat.lol");
assertThat(response.getStatus()).isEqualTo(404);
verifyErrorMetrics(Optional.of(0L), 404);
verifyErrorMetrics(Optional.of(1L), 404);
}
@Test
@@ -373,13 +379,20 @@ public class RdapNameserverSearchActionTest
}
@Test
public void testNameMatch_ns1_cat_idn_unicode_badRequest() {
// name must use punycode.
generateActualJsonWithName("ns1.cat.みんな");
metricWildcardType = WildcardType.INVALID;
metricPrefixLength = 0;
assertThat(response.getStatus()).isEqualTo(400);
verifyErrorMetrics(Optional.empty(), 400);
public void testNameMatch_ns1_cat_idn_unicode_found() {
assertThat(generateActualJsonWithName("ns1.cat.みんな"))
.isEqualTo(
generateExpectedJsonForNameserver(
"ns1.cat.みんな",
"ns1.cat.xn--q9jyb4c",
"B-ROID",
"v4",
"1.2.3.5",
"rdap_host_unicode.json"));
metricWildcardType = WildcardType.NO_WILDCARD;
metricPrefixLength = 19;
assertThat(response.getStatus()).isEqualTo(200);
verifyMetrics(1);
}
@Test

View File

@@ -43,30 +43,34 @@ public class RdapSearchActionTestCase<A extends RdapSearchActionBase>
public void initRdapSearchActionTestCase() {
action.parameterMap = ImmutableListMultimap.of();
action.cursorTokenParam = Optional.empty();
action.registrarParam = Optional.empty();
action.rdapResultSetMaxSize = 4;
action.requestUrl = "https://example.tld" + actionPath;
action.requestPath = actionPath;
}
void rememberWildcardType(String queryString) {
try {
RdapSearchPattern partialStringQuery = RdapSearchPattern.create(queryString, true);
if (!partialStringQuery.getHasWildcard()) {
metricWildcardType = WildcardType.NO_WILDCARD;
} else if (partialStringQuery.getSuffix() == null) {
metricWildcardType = WildcardType.PREFIX;
} else if (partialStringQuery.getInitialString().isEmpty()) {
metricWildcardType = WildcardType.SUFFIX;
} else {
metricWildcardType = WildcardType.PREFIX_AND_SUFFIX;
}
metricPrefixLength = partialStringQuery.getInitialString().length();
} catch (Exception e) {
metricWildcardType = WildcardType.INVALID;
metricPrefixLength = 0;
void rememberWildcardType(WildcardType wildcardType, int prefixLength) {
metricWildcardType = wildcardType;
metricPrefixLength = prefixLength;
}
void rememberWildcardType(String searchQuery) {
int wildcardLocation = searchQuery.indexOf('*');
if (wildcardLocation < 0) {
rememberWildcardType(WildcardType.NO_WILDCARD, searchQuery.length());
} else if (wildcardLocation == searchQuery.length() - 1) {
rememberWildcardType(WildcardType.PREFIX, wildcardLocation);
} else if (wildcardLocation == 0) {
rememberWildcardType(WildcardType.SUFFIX, wildcardLocation);
} else {
rememberWildcardType(WildcardType.PREFIX_AND_SUFFIX, wildcardLocation);
}
}
void rememberWildcardTypeInvalid() {
rememberWildcardType(WildcardType.INVALID, 0);
}
void verifyMetrics(
EndpointType endpointType,
Action.Method requestMethod,

View File

@@ -28,7 +28,7 @@ public class RdapSearchPatternTest {
@Test
public void testNoWildcards_ok() {
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.create("example.lol", true);
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.createFromLdhDomainName("example.lol");
assertThat(rdapSearchPattern.getInitialString()).isEqualTo("example.lol");
assertThat(rdapSearchPattern.getHasWildcard()).isFalse();
assertThat(rdapSearchPattern.getSuffix()).isNull();
@@ -36,7 +36,7 @@ public class RdapSearchPatternTest {
@Test
public void testWildcardNoTld_ok() {
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.create("exam*", true);
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.createFromLdhDomainName("exam*");
assertThat(rdapSearchPattern.getInitialString()).isEqualTo("exam");
assertThat(rdapSearchPattern.getHasWildcard()).isTrue();
assertThat(rdapSearchPattern.getSuffix()).isNull();
@@ -44,32 +44,52 @@ public class RdapSearchPatternTest {
@Test
public void testWildcardTld_ok() {
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.create("exam*.lol", true);
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.createFromLdhDomainName("exam*.lol");
assertThat(rdapSearchPattern.getInitialString()).isEqualTo("exam");
assertThat(rdapSearchPattern.getHasWildcard()).isTrue();
assertThat(rdapSearchPattern.getSuffix()).isEqualTo("lol");
}
@Test
public void testWildcardAtStart_ok() {
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.createFromLdhDomainName("*.lol");
assertThat(rdapSearchPattern.getInitialString()).isEmpty();
assertThat(rdapSearchPattern.getHasWildcard()).isTrue();
assertThat(rdapSearchPattern.getSuffix()).isEqualTo("lol");
}
@Test
public void testWildcardOnly_ok() {
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.createFromLdhDomainName("*");
assertThat(rdapSearchPattern.getInitialString()).isEmpty();
assertThat(rdapSearchPattern.getHasWildcard()).isTrue();
assertThat(rdapSearchPattern.getSuffix()).isNull();
}
@Test
public void testMultipleWildcards_unprocessable() {
assertThrows(
UnprocessableEntityException.class, () -> RdapSearchPattern.create("ex*am*.lol", true));
UnprocessableEntityException.class,
() -> RdapSearchPattern.createFromLdhDomainName("ex*am*.lol"));
}
@Test
public void testWildcardNotAtEnd_unprocessable() {
assertThrows(UnprocessableEntityException.class, () -> RdapSearchPattern.create("ex*am", true));
assertThrows(
UnprocessableEntityException.class,
() -> RdapSearchPattern.createFromLdhDomainName("ex*am"));
}
@Test
public void testWildcardNotAtEndWithTld_unprocessable() {
assertThrows(
UnprocessableEntityException.class, () -> RdapSearchPattern.create("ex*am.lol", true));
UnprocessableEntityException.class,
() -> RdapSearchPattern.createFromLdhDomainName("ex*am.lol"));
}
@Test
public void testShortString_ok() {
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.create("e", true);
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.createFromLdhDomainName("e");
assertThat(rdapSearchPattern.getInitialString()).isEqualTo("e");
assertThat(rdapSearchPattern.getHasWildcard()).isFalse();
assertThat(rdapSearchPattern.getSuffix()).isNull();
@@ -78,24 +98,45 @@ public class RdapSearchPatternTest {
@Test
public void testZeroLengthSuffix_unprocessable() {
assertThrows(
UnprocessableEntityException.class, () -> RdapSearchPattern.create("exam*.", true));
}
@Test
public void testDisallowedSuffix_unprocessable() {
assertThrows(
UnprocessableEntityException.class, () -> RdapSearchPattern.create("exam*.lol", false));
UnprocessableEntityException.class,
() -> RdapSearchPattern.createFromLdhDomainName("exam*."));
}
@Test
public void testNextInitialString_alpha() {
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.create("exam*.lol", true);
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.createFromLdhDomainName("exam*.lol");
assertThat(rdapSearchPattern.getNextInitialString()).isEqualTo("exan");
}
@Test
public void testNextInitialString_unicode() {
RdapSearchPattern rdapSearchPattern = RdapSearchPattern.create("cat.みんな", true);
assertThat(rdapSearchPattern.getNextInitialString()).isEqualTo("cat.みん");
public void testNextInitialString_unicode_translatedToPunycode() {
RdapSearchPattern rdapSearchPattern =
RdapSearchPattern.createFromLdhOrUnicodeDomainName("cat.みん");
assertThat(rdapSearchPattern.getNextInitialString()).isEqualTo("cat.xn--q9jyb4d");
}
@Test
public void testUnicodeString_noWildcard() {
RdapSearchPattern rdapSearchPattern =
RdapSearchPattern.createFromUnicodeString("unicode みんに string");
assertThat(rdapSearchPattern.getInitialString()).isEqualTo("unicode みんに string");
assertThat(rdapSearchPattern.getHasWildcard()).isFalse();
assertThat(rdapSearchPattern.getSuffix()).isNull();
}
@Test
public void testUnicodeString_withWildcard() {
RdapSearchPattern rdapSearchPattern =
RdapSearchPattern.createFromUnicodeString("unicode みんに string*");
assertThat(rdapSearchPattern.getInitialString()).isEqualTo("unicode みんに string");
assertThat(rdapSearchPattern.getHasWildcard()).isTrue();
assertThat(rdapSearchPattern.getSuffix()).isNull();
}
@Test
public void testUnicodeString_middleWildcard() {
assertThrows(
UnprocessableEntityException.class,
() -> RdapSearchPattern.createFromLdhDomainName("unicode みんに *string"));
}
}

View File

@@ -34,7 +34,8 @@ import java.util.Objects;
public class RdapTestHelper {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private static final Gson GSON =
new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
static JsonElement createJson(String... lines) {
return GSON.fromJson(Joiner.on("\n").join(lines), JsonElement.class);
@@ -47,7 +48,7 @@ public class RdapTestHelper {
}
private static JsonObject createTosNotice(String linkBase) {
return new Gson().toJsonTree(
return GSON.toJsonTree(
ImmutableMap.of(
"title", "RDAP Terms of Service",
"description",
@@ -90,13 +91,12 @@ public class RdapTestHelper {
notices.add(createTosNotice(linkBase));
notices.add(
new Gson()
.toJsonTree(
ImmutableMap.of(
"description",
ImmutableList.of(
"This response conforms to the RDAP Operational Profile for gTLD"
+ " Registries and Registrars version 1.0"))));
GSON.toJsonTree(
ImmutableMap.of(
"description",
ImmutableList.of(
"This response conforms to the RDAP Operational Profile for gTLD"
+ " Registries and Registrars version 1.0"))));
}
static void addDomainBoilerplateNotices(JsonObject jsonObject, String linkBase) {
@@ -107,47 +107,44 @@ public class RdapTestHelper {
notices.add(createTosNotice(linkBase));
notices.add(
new Gson()
.toJsonTree(
ImmutableMap.of(
"description",
ImmutableList.of(
"This response conforms to the RDAP Operational Profile for gTLD"
+ " Registries and Registrars version 1.0"))));
GSON.toJsonTree(
ImmutableMap.of(
"description",
ImmutableList.of(
"This response conforms to the RDAP Operational Profile for gTLD"
+ " Registries and Registrars version 1.0"))));
notices.add(
new Gson()
.toJsonTree(
ImmutableMap.of(
"title",
"Status Codes",
"description",
ImmutableList.of(
"For more information on domain status codes, please visit"
+ " https://icann.org/epp"),
"links",
ImmutableList.of(
ImmutableMap.of(
"value", "https://icann.org/epp",
"rel", "alternate",
"href", "https://icann.org/epp",
"type", "text/html")))));
GSON.toJsonTree(
ImmutableMap.of(
"title",
"Status Codes",
"description",
ImmutableList.of(
"For more information on domain status codes, please visit"
+ " https://icann.org/epp"),
"links",
ImmutableList.of(
ImmutableMap.of(
"value", "https://icann.org/epp",
"rel", "alternate",
"href", "https://icann.org/epp",
"type", "text/html")))));
notices.add(
new Gson()
.toJsonTree(
ImmutableMap.of(
"title",
"RDDS Inaccuracy Complaint Form",
"description",
ImmutableList.of(
"URL of the ICANN RDDS Inaccuracy Complaint Form:"
+ " https://www.icann.org/wicf"),
"links",
ImmutableList.of(
ImmutableMap.of(
"value", "https://www.icann.org/wicf",
"rel", "alternate",
"href", "https://www.icann.org/wicf",
"type", "text/html")))));
GSON.toJsonTree(
ImmutableMap.of(
"title",
"RDDS Inaccuracy Complaint Form",
"description",
ImmutableList.of(
"URL of the ICANN RDDS Inaccuracy Complaint Form:"
+ " https://www.icann.org/wicf"),
"links",
ImmutableList.of(
ImmutableMap.of(
"value", "https://www.icann.org/wicf",
"rel", "alternate",
"href", "https://www.icann.org/wicf",
"type", "text/html")))));
}
static RdapJsonFormatter getTestRdapJsonFormatter(Clock clock) {

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName": "entity",
"handle": "%NAME%",

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName" : "entity",
"handle" : "REDACTED FOR PRIVACY",

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName" : "entity",
"handle" : "%NAME%",

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName" : "entity",
"handle" : "%NAME%",

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName" : "entity",
"handle" : "REDACTED FOR PRIVACY",

View File

@@ -4,7 +4,8 @@
"handle": "%DOMAIN_HANDLE_1%",
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"status": [
"client delete prohibited",

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName": "domain",
"handle": "%DOMAIN_HANDLE_1%",

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName": "domain",
"ldhName": "%DOMAIN_PUNYCODE_NAME_1%",

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName": "domain",
"handle": "%DOMAIN_HANDLE_1%",

View File

@@ -5,7 +5,8 @@
"handle": "%DOMAIN_HANDLE_1%",
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"status": [
"client delete prohibited",

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName": "domain",
"handle": "%DOMAIN_HANDLE_1%",

View File

@@ -83,7 +83,8 @@
],
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices" :
[

View File

@@ -84,7 +84,8 @@
],
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices" :
[

View File

@@ -84,7 +84,8 @@
],
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices" :
[

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"domainSearchResults": [
{

View File

@@ -7,7 +7,8 @@
],
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices": [
{

View File

@@ -1,5 +1,9 @@
{
"rdapConformance" : ["rdap_level_0", "icann_rdap_response_profile_0"],
"rdapConformance" : [
"rdap_level_0",
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices" :
[
{

View File

@@ -1,5 +1,9 @@
{
"rdapConformance" : ["rdap_level_0", "icann_rdap_response_profile_0"],
"rdapConformance" : [
"rdap_level_0",
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices" :
[
{

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName": "nameserver",
"handle": "%HANDLE%",

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"status": [
"active"

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName": "nameserver",
"handle": "%HANDLE%",

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName": "nameserver",
"handle": "%HANDLE%",

View File

@@ -142,9 +142,9 @@
]
}
],
"rdapConformance":
[
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
]
}

View File

@@ -110,6 +110,7 @@
],
"rdapConformance":[
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
]
}

View File

@@ -101,7 +101,11 @@
]
}
],
"rdapConformance": ["rdap_level_0", "icann_rdap_response_profile_0" ],
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices" :
[
{

View File

@@ -116,7 +116,11 @@
]
}
],
"rdapConformance": ["rdap_level_0", "icann_rdap_response_profile_0" ],
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices" :
[
{

View File

@@ -69,7 +69,11 @@
]
}
],
"rdapConformance" : ["rdap_level_0", "icann_rdap_response_profile_0"],
"rdapConformance" : [
"rdap_level_0",
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices" :
[
{

View File

@@ -230,7 +230,11 @@
]
}
],
"rdapConformance": ["rdap_level_0", "icann_rdap_response_profile_0" ],
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices" :
[
{

View File

@@ -91,7 +91,8 @@
],
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices" :
[

View File

@@ -134,7 +134,11 @@
]
}
],
"rdapConformance" : ["rdap_level_0", "icann_rdap_response_profile_0"],
"rdapConformance" : [
"rdap_level_0",
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices" :
[
{

View File

@@ -234,7 +234,11 @@
"roles": ["registrar"]
}
],
"rdapConformance": ["rdap_level_0", "icann_rdap_response_profile_0" ],
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"notices":
[
{

View File

@@ -1,7 +1,8 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0"
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName" : "entity",
"handle" : "%NAME%",

Some files were not shown because too many files have changed in this diff Show More