mirror of
https://github.com/google/nomulus
synced 2026-01-30 01:22:23 +00:00
Compare commits
11 Commits
show
...
nomulus-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c64992c73 | ||
|
|
e8c789a401 | ||
|
|
ca1d525e28 | ||
|
|
55dc735ba0 | ||
|
|
ff6d327183 | ||
|
|
79bcb227be | ||
|
|
e489539df4 | ||
|
|
dd66664e42 | ||
|
|
7bdbd89e4d | ||
|
|
987a648296 | ||
|
|
d2f955a488 |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
*/
|
||||
|
||||
@@ -298,6 +298,7 @@ public class RdapMetrics {
|
||||
.setSearchType(SearchType.NONE)
|
||||
.setWildcardType(WildcardType.INVALID)
|
||||
.setPrefixLength(0)
|
||||
.setRegistrarSpecified(false)
|
||||
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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({})
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -12,6 +12,7 @@ KmsSecret
|
||||
KmsSecretRevision
|
||||
Modification
|
||||
OneTime
|
||||
PollMessage
|
||||
PremiumList
|
||||
PremiumListEntry
|
||||
PremiumListRevision
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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%",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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%",
|
||||
|
||||
@@ -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%",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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%",
|
||||
|
||||
@@ -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%",
|
||||
|
||||
@@ -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%",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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%",
|
||||
|
||||
@@ -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" :
|
||||
[
|
||||
|
||||
@@ -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" :
|
||||
[
|
||||
|
||||
@@ -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" :
|
||||
[
|
||||
|
||||
@@ -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": [
|
||||
{
|
||||
|
||||
@@ -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": [
|
||||
{
|
||||
|
||||
@@ -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" :
|
||||
[
|
||||
{
|
||||
|
||||
@@ -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" :
|
||||
[
|
||||
{
|
||||
|
||||
@@ -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%",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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%",
|
||||
|
||||
@@ -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%",
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
],
|
||||
"rdapConformance":[
|
||||
"rdap_level_0",
|
||||
"icann_rdap_response_profile_0"
|
||||
"icann_rdap_response_profile_0",
|
||||
"icann_rdap_technical_implementation_guide_0"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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" :
|
||||
[
|
||||
{
|
||||
|
||||
@@ -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" :
|
||||
[
|
||||
{
|
||||
|
||||
@@ -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" :
|
||||
[
|
||||
{
|
||||
|
||||
@@ -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" :
|
||||
[
|
||||
{
|
||||
|
||||
@@ -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" :
|
||||
[
|
||||
|
||||
@@ -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" :
|
||||
[
|
||||
{
|
||||
|
||||
@@ -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":
|
||||
[
|
||||
{
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user