1
0
mirror of https://github.com/google/nomulus synced 2026-06-09 16:33:02 +00:00

Compare commits

...

17 Commits

Author SHA1 Message Date
Weimin Yu f134c4bf37 Use dependency cache in all Gradle tasks in GCB (#481)
* Use dependency cache in all Gradle tasks in GCB

Make the initial test and the final publishing steps use the shared
dependency cache.

Also make the initial test use the registry's own maven repo instead
of Maven Central.
2020-02-11 14:50:22 -05:00
gbrodman 44921c29d6 Clean up RegistryLockPostAction (#470)
* Clean up RegistryLockPostAction

* pocId -> userEmail when appropriate

* Merge remote-tracking branch 'origin/master' into lockPostImprovements

* Remove pocId
2020-02-11 08:43:44 -07:00
Weimin Yu ce80278ab7 Make Gradle dependency cache shareable in GCB (#479)
* Make Gradle dependency cache shareable in GCB

Make Gradle put its caches in the source tree so that
they can be preserved across steps. When left at their
default location, caches are lost after each step.
2020-02-10 11:20:11 -05:00
Shicong Huang 594ce30122 Auto-apply JPA converters for collection type (#469)
* Auto-apply JPA converters for collection type

* Extract common logic to a base class

* Remove extra lines

* Rebase on master
2020-02-10 10:33:43 -05:00
Weimin Yu 736f788eea Use CA cert in tests (#475)
* Use CA cert in tests

Our tests were using a self-signed cert created by a netty utility.
That cert is not CA, and cannot be used with newer JDK versions
(starting from u242 with Ubuntu openjdk).

Now we generate a unsafe cert for tests. The new cert,
SelfSignedCaCertificate, needs to be made test-only.
To do so we need to refactor both prober and proxy.
2020-02-07 10:23:24 -05:00
Shicong Huang d6f49f5c08 Add JPA annotations to RegistrarContact (#432) 2020-02-06 16:58:15 -05:00
Ben McIlwain 8b9139bc4c Always attempt to save the claims list to Cloud SQL (#472)
* Always attempt to save the claims list to Cloud SQL
2020-02-06 12:21:34 -05:00
Ben McIlwain b148102716 Always save reserved lists to Cloud SQL (#471)
* Always save reserved lists to Cloud SQL

Otherwise it's too easy to forget to run this additional option, and then things will
fall out of sync and start throwing errors.
2020-02-06 12:21:26 -05:00
Shicong Huang 9ea06ebf35 Use JPA @Enumerated to convert enum to string (#466) 2020-02-04 10:50:03 -05:00
gbrodman c0afb9aeee Use randomly-generated base-58 strings for RegistryLock verification codes (#464)
* Use randomly-generated strings for RegistryLock verification codes

We were using UUIDs before which are also fine, but unnecessarily long.
The RegistryLock class itself does not enforce any particular format for
the lock verification codes.
2020-02-03 13:50:54 -05:00
Michael Muller 76d8afe856 Implement dump_golden_schema command in devtool (#467)
* Implement dump_golden_schema command in devtool

Add a dump_golden_schema command so that we can generate the golden schema
in-place without having to do the test -> fail -> copy -> test dance.

Refactor the SQL container functionality from GenerateSqlCommand.  There is
some duplication of code between the dump command and SchemaTest which should
be dealt with in a subsequent PR.

* Reformatted and changes in response to review

* Fix getDockerTag() usage

* Fix "leaked resource"
2020-02-03 13:25:27 -05:00
gbrodman 36787c37fb Add a RegistryLockPostAction and tests (#459)
* Add a RegistryLockPostAction and tests

* Response to CR and more robust email content test

* Fix typo

* Run save + email in a JPA transaction

* Use action in subject
2020-02-03 11:34:01 -05:00
Weimin Yu 36e46097e3 Allow non-CA cert as trust anchor in tests (#468)
* Allow non-CA cert as trust anchor in tests

Stay with the legacy behavior to unblock release build.
We will update the test cert generation code later.

TESTED=reproduced and fixed test failures in builder container
2020-02-03 11:02:52 -05:00
Weimin Yu ce2f98f680 Work around Spinnaker issue wrt variables (#465)
* Work around Spinnaker issue wrt variables

Cloud Build variable reference need to stay from the  ${var} pattern
to prevent Spinnaker from trying to resolve it. In all files that
are used by Spinnaker, we change variable reference to the $var form.

We made the minimum amount of change possible, and will review this
issue after the permanent solution is available.
2020-01-30 13:28:36 -05:00
gbrodman daaf231d39 Add RegistryLockVerifyAction (#461)
* Add RegistryLockVerifyAction

The action takes two parameters
- isLock is a boolean, determining whether we're trying to lock or
unlock a domain
- lockVerificationCode is the UUID by which we'll look up the lock
object in question.

The lock in question must not be expired and must be in a valid lockable
/ unlockable state

* Some responses to CR

* Add slash and move test method

* Add more data and tests

* Fix screenshot
2020-01-29 16:36:39 -05:00
Shicong Huang 955c3d9aeb Fix money conversion for JPY in PremiumListDao (#463) 2020-01-29 13:10:58 -05:00
Shicong Huang d03cea2443 Add JPA annotations to class Registrar (#430)
* Add JPA annotations to class Registrar

* Use array for Java list

* Exclude parent field

* Use 3 columns for address and use text for enum

* Use EnumParameter and 3 properties in Address

* Rename columns and rebase on HEAD
2020-01-29 11:06:23 -05:00
133 changed files with 3747 additions and 1121 deletions
+1
View File
@@ -97,6 +97,7 @@ nomulus.iws
!/gradle/wrapper/**/*.jar
.gradle/
**/build
cloudbuild-caches/
node_modules/**
/repos/
+1 -1
View File
@@ -22,7 +22,7 @@ import sys
import re
# We should never analyze any generated files
UNIVERSALLY_SKIPPED_PATTERNS = {"/build/", "/out/"}
UNIVERSALLY_SKIPPED_PATTERNS = {"/build/", "cloudbuild-caches", "/out/"}
# We can't rely on CI to have the Enum package installed so we do this instead.
FORBIDDEN = 1
REQUIRED = 2
+11 -2
View File
@@ -52,9 +52,11 @@ def outcastTestPatterns = [
def dockerIncompatibleTestPatterns = [
// The webdriver tests start headless Chrome in a Docker container,
// resulting in Docker-in-Docker complications. Likewise,
// GenerateSqlSchemaCommandTest launches postgresql in a docker container.
// GenerateSqlSchemaCommandTest and DumpGoldenSchemaCommandTest launch
// postgresql in a docker container.
"google/registry/webdriver/*",
"google/registry/tools/GenerateSqlSchemaCommandTest.*",
"google/registry/tools/DumpGoldenSchemaCommandTest.*",
// PathParameterTest includes tests which validate that file permissions are
// respected. However when running in Docker the user is root by default, so
// every file is read/write-able. There is no way to exclude specific test
@@ -93,7 +95,11 @@ sourceSets {
nonprod {
java {
compileClasspath += main.output
runtimeClasspath += main.output
// Add the DB runtime classpath to nonprod so we can load the flyway
// scripts.
runtimeClasspath += main.output +
rootProject.project(":db").sourceSets.main.runtimeClasspath
}
}
test {
@@ -321,6 +327,9 @@ dependencies {
// Tool dependencies. used for doc generation.
compile files("${System.properties['java.home']}/../lib/tools.jar")
// Flyway classes needed to generate the golden file.
compile deps['org.flywaydb:flyway-core']
closureCompiler deps['com.google.javascript:closure-compiler']
}
+15 -14
View File
@@ -10,11 +10,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -84,22 +84,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -124,7 +124,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -146,10 +146,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -183,8 +183,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -193,6 +193,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hamcrest:hamcrest-core:1.3
@@ -10,11 +10,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -83,22 +83,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -123,7 +123,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
io.grpc:grpc-netty:1.17.1
@@ -144,10 +144,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -180,8 +180,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -190,6 +190,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hibernate.common:hibernate-commons-annotations:5.1.0.Final
+15 -14
View File
@@ -18,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -95,22 +95,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -135,7 +135,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -157,10 +157,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -194,8 +194,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -204,6 +204,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hamcrest:hamcrest-core:1.3
@@ -18,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -95,22 +95,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -135,7 +135,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -157,10 +157,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -193,8 +193,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -203,6 +203,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hibernate.common:hibernate-commons-annotations:5.1.0.Final
@@ -10,11 +10,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -84,22 +84,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -124,7 +124,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -146,10 +146,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -183,8 +183,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -193,6 +193,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hamcrest:hamcrest-core:1.3
@@ -10,11 +10,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -83,22 +83,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -123,7 +123,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
io.grpc:grpc-netty:1.17.1
@@ -144,10 +144,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -181,8 +181,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -191,6 +191,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hamcrest:hamcrest-core:1.3
@@ -10,11 +10,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -84,22 +84,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -124,7 +124,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -146,10 +146,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -183,8 +183,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -193,6 +193,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hamcrest:hamcrest-core:1.3
@@ -10,11 +10,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -84,22 +84,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -124,7 +124,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -146,10 +146,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -183,8 +183,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -193,6 +193,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hamcrest:hamcrest-core:1.3
+15 -14
View File
@@ -10,11 +10,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -84,22 +84,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -124,7 +124,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -146,10 +146,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -183,8 +183,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -193,6 +193,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hamcrest:hamcrest-core:1.3
@@ -18,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -95,22 +95,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -135,7 +135,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -157,10 +157,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -193,8 +193,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -203,6 +203,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hibernate.common:hibernate-commons-annotations:5.1.0.Final
@@ -10,11 +10,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -86,11 +86,11 @@ com.google.guava:guava-testlib:28.1-jre
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
@@ -98,11 +98,11 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.7
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -133,7 +133,7 @@ io.github.classgraph:classgraph:4.8.52
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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -155,10 +155,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -198,8 +198,8 @@ org.apache.commons:commons-lang3:3.8.1
org.apache.commons:commons-text:1.6
org.apache.ftpserver:ftplet-api:1.0.6
org.apache.ftpserver:ftpserver-core:1.0.6
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.apache.mina:mina-core:2.0.4
org.apache.sshd:sshd-core:2.0.0
org.apache.sshd:sshd-scp:2.0.0
@@ -215,6 +215,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hamcrest:hamcrest-all:1.3
@@ -10,11 +10,11 @@ com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -85,11 +85,11 @@ com.google.guava:guava-testlib:28.1-jre
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
@@ -97,11 +97,11 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.7
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -132,7 +132,7 @@ io.github.classgraph:classgraph:4.8.52
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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
io.grpc:grpc-netty:1.17.1
@@ -153,10 +153,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -196,8 +196,8 @@ org.apache.commons:commons-lang3:3.8.1
org.apache.commons:commons-text:1.6
org.apache.ftpserver:ftplet-api:1.0.6
org.apache.ftpserver:ftpserver-core:1.0.6
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.apache.mina:mina-core:2.0.4
org.apache.sshd:sshd-core:2.0.0
org.apache.sshd:sshd-scp:2.0.0
@@ -213,6 +213,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hamcrest:hamcrest-all:1.3
@@ -18,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -97,11 +97,11 @@ com.google.guava:guava-testlib:28.1-jre
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
@@ -109,11 +109,11 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.7
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -145,7 +145,7 @@ io.github.java-diff-utils:java-diff-utils:4.0
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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -167,10 +167,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -210,8 +210,8 @@ org.apache.commons:commons-lang3:3.8.1
org.apache.commons:commons-text:1.6
org.apache.ftpserver:ftplet-api:1.0.6
org.apache.ftpserver:ftpserver-core:1.0.6
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.apache.mina:mina-core:2.0.4
org.apache.sshd:sshd-core:2.0.0
org.apache.sshd:sshd-scp:2.0.0
@@ -18,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -97,11 +97,11 @@ com.google.guava:guava-testlib:28.1-jre
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
@@ -109,11 +109,11 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.7
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -145,7 +145,7 @@ io.github.java-diff-utils:java-diff-utils:4.0
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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -167,10 +167,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -210,8 +210,8 @@ org.apache.commons:commons-lang3:3.8.1
org.apache.commons:commons-text:1.6
org.apache.ftpserver:ftplet-api:1.0.6
org.apache.ftpserver:ftpserver-core:1.0.6
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.apache.mina:mina-core:2.0.4
org.apache.sshd:sshd-core:2.0.0
org.apache.sshd:sshd-scp:2.0.0
@@ -61,6 +61,16 @@
<url-pattern>/registry-lock-get</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registry-lock-post</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registry-lock-verify</url-pattern>
</servlet-mapping>
<!-- Security config -->
<security-constraint>
<web-resource-collection>
@@ -53,7 +53,6 @@ import java.util.concurrent.ExecutionException;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import org.hibernate.annotations.Type;
import org.joda.time.DateTime;
import org.joda.time.Duration;
@@ -117,7 +116,6 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
DateTime lastEppUpdateTime;
/** Status values associated with this resource. */
@Type(type = "google.registry.model.eppcommon.StatusValue$StatusValueSetType")
@Column(name = "statuses")
// TODO(mmuller): rename to "statuses" once we're off datastore.
Set<StatusValue> status;
@@ -185,7 +185,6 @@ public class DomainBase extends EppResource
String idnTableName;
/** Fully qualified host names of this domain's active subordinate hosts. */
@org.hibernate.annotations.Type(type = "google.registry.persistence.StringSetUserType")
Set<String> subordinateHosts;
/** When this domain's registration will expire. */
@@ -15,16 +15,22 @@
package google.registry.model.eppcommon;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.nullToEmpty;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.googlecode.objectify.annotation.Ignore;
import com.googlecode.objectify.annotation.OnLoad;
import google.registry.model.Buildable;
import google.registry.model.ImmutableObject;
import google.registry.model.JsonMapBuilder;
import google.registry.model.Jsonifiable;
import java.util.List;
import java.util.Map;
import javax.persistence.Embeddable;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
@@ -42,12 +48,21 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
* @see google.registry.model.registrar.RegistrarAddress
*/
@XmlTransient
@Embeddable
@MappedSuperclass
public class Address extends ImmutableObject implements Jsonifiable {
/** The schema validation will enforce that this has 3 lines at most. */
@XmlJavaTypeAdapter(NormalizedStringAdapter.class)
@Transient
List<String> street;
@Ignore String streetLine1;
@Ignore String streetLine2;
@Ignore String streetLine3;
@XmlJavaTypeAdapter(NormalizedStringAdapter.class)
String city;
@@ -64,7 +79,23 @@ public class Address extends ImmutableObject implements Jsonifiable {
String countryCode;
public ImmutableList<String> getStreet() {
return nullToEmptyImmutableCopy(street);
if (street == null && streetLine1 != null) {
return ImmutableList.of(streetLine1, nullToEmpty(streetLine2), nullToEmpty(streetLine3));
} else {
return nullToEmptyImmutableCopy(street);
}
}
public String getStreetLine1() {
return streetLine1;
}
public String getStreetLine2() {
return streetLine2;
}
public String getStreetLine13() {
return streetLine3;
}
public String getCity() {
@@ -139,4 +170,14 @@ public class Address extends ImmutableObject implements Jsonifiable {
return this;
}
}
@OnLoad
void setStreetForCloudSql() {
if (street == null || street.size() == 0) {
return;
}
streetLine1 = street.get(0);
streetLine2 = street.size() >= 2 ? street.get(1) : null;
streetLine3 = street.size() >= 3 ? street.get(2) : null;
}
}
@@ -25,7 +25,6 @@ import google.registry.model.domain.DomainBase;
import google.registry.model.host.HostResource;
import google.registry.model.translators.EnumToAttributeAdapter.EppEnum;
import google.registry.model.translators.StatusValueAdapter;
import google.registry.persistence.EnumSetUserType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
@@ -166,11 +165,4 @@ public enum StatusValue implements EppEnum {
return StatusValue.valueOf(LOWER_CAMEL.to(UPPER_UNDERSCORE, nullToEmpty(xmlName)));
}
/** Hibernate type for sets of {@link StatusValue}. */
public static class StatusValueSetType extends EnumSetUserType<StatusValue> {
@Override
protected Object convertToElem(Object value) {
return StatusValue.valueOf((String) value);
}
}
}
@@ -85,12 +85,28 @@ import java.util.function.Predicate;
import javax.annotation.Nullable;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.joda.money.CurrencyUnit;
import org.joda.time.DateTime;
/** Information about a registrar. */
@ReportedOn
@Entity
@javax.persistence.Entity
@Table(
indexes = {
@javax.persistence.Index(columnList = "registrarName", name = "registrar_name_idx"),
@javax.persistence.Index(
columnList = "ianaIdentifier",
name = "registrar_iana_identifier_idx"),
})
public class Registrar extends ImmutableObject implements Buildable, Jsonifiable {
/** Represents the type of a registrar entity. */
@@ -208,14 +224,17 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
.doTransactionless(
() -> Maps.uniqueIndex(loadAll(), Registrar::getClientId)));
@Parent
Key<EntityGroupRoot> parent = getCrossTldKey();
@Parent @Transient Key<EntityGroupRoot> parent = getCrossTldKey();
/**
* Unique registrar client id. Must conform to "clIDType" as defined in RFC5730.
*
* @see <a href="http://tools.ietf.org/html/rfc5730#section-4.2">Shared Structure Schema</a>
* <p>TODO(shicong): Rename this field to clientId
*/
@Id
@javax.persistence.Id
@Column(name = "client_id", nullable = false)
String clientIdentifier;
/**
@@ -229,12 +248,17 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
* @see <a href="http://www.icann.org/registrar-reports/accredited-list.html">ICANN-Accredited
* Registrars</a>
*/
@Index String registrarName;
@Index
@Column(nullable = false)
String registrarName;
/** The type of this registrar. */
@Column(nullable = false)
@Enumerated(EnumType.STRING)
Type type;
/** The state of this registrar. */
@Enumerated(EnumType.STRING)
State state;
/** The set of TLDs which this registrar is allowed to access. */
@@ -277,6 +301,7 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
String passwordHash;
/** Randomly generated hash salt. */
@Column(name = "password_salt")
String salt;
// The following fields may appear redundant to the above, but are
@@ -287,6 +312,24 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
* unrestricted UTF-8.
*/
@IgnoreSave(IfNull.class)
@Embedded
@AttributeOverrides({
@AttributeOverride(
name = "streetLine1",
column = @Column(name = "localized_address_street_line1")),
@AttributeOverride(
name = "streetLine2",
column = @Column(name = "localized_address_street_line2")),
@AttributeOverride(
name = "streetLine3",
column = @Column(name = "localized_address_street_line3")),
@AttributeOverride(name = "city", column = @Column(name = "localized_address_city")),
@AttributeOverride(name = "state", column = @Column(name = "localized_address_state")),
@AttributeOverride(name = "zip", column = @Column(name = "localized_address_zip")),
@AttributeOverride(
name = "countryCode",
column = @Column(name = "localized_address_country_code"))
})
RegistrarAddress localizedAddress;
/**
@@ -294,6 +337,16 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
* representable in the 7-bit US-ASCII character set.
*/
@IgnoreSave(IfNull.class)
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "streetLine1", column = @Column(name = "i18n_address_street_line1")),
@AttributeOverride(name = "streetLine2", column = @Column(name = "i18n_address_street_line2")),
@AttributeOverride(name = "streetLine3", column = @Column(name = "i18n_address_street_line3")),
@AttributeOverride(name = "city", column = @Column(name = "i18n_address_city")),
@AttributeOverride(name = "state", column = @Column(name = "i18n_address_state")),
@AttributeOverride(name = "zip", column = @Column(name = "i18n_address_zip")),
@AttributeOverride(name = "countryCode", column = @Column(name = "i18n_address_country_code"))
})
RegistrarAddress internationalizedAddress;
/** Voice number. */
@@ -309,16 +362,17 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
/**
* Registrar identifier used for reporting to ICANN.
*
* <ul>
* <li>8 is used for Testing Registrar.
* <li>9997 is used by ICAAN for SLA monitoring.
* <li>9999 is used for cases when the registry operator acts as registrar.
* </ul>
* @see <a href="http://www.iana.org/assignments/registrar-ids/registrar-ids.txt">Registrar IDs</a>
*
* @see <a href="http://www.iana.org/assignments/registrar-ids/registrar-ids.txt">Registrar
* IDs</a>
*/
@Index
@Nullable
Long ianaIdentifier;
@Index @Nullable Long ianaIdentifier;
/** Identifier of registrar used in external billing system (e.g. Oracle). */
@Nullable
@@ -338,18 +392,19 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
*/
@Nullable
@Mapify(CurrencyMapper.class)
@org.hibernate.annotations.Type(type = "google.registry.persistence.CurrencyToBillingMapUserType")
Map<CurrencyUnit, BillingAccountEntry> billingAccountMap;
/** A billing account entry for this registrar, consisting of a currency and an account Id. */
@Embed
static class BillingAccountEntry extends ImmutableObject {
public static class BillingAccountEntry extends ImmutableObject {
CurrencyUnit currency;
String accountId;
BillingAccountEntry() {}
BillingAccountEntry(CurrencyUnit currency, String accountId) {
public BillingAccountEntry(CurrencyUnit currency, String accountId) {
this.accountId = accountId;
this.currency = currency;
}
@@ -366,6 +421,11 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
return billingAccountEntry.currency;
}
}
/** Returns the account id of this entry. */
public String getAccountId() {
return accountId;
}
}
/** URL of registrar's website. */
@@ -390,14 +450,10 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
/** An automatically managed last-saved timestamp. */
UpdateAutoTimestamp lastUpdateTime = UpdateAutoTimestamp.create(null);
/**
* The time that the certificate was last updated.
*/
/** The time that the certificate was last updated. */
DateTime lastCertificateUpdateTime;
/**
* Telephone support passcode (5-digit numeric)
*/
/** Telephone support passcode (5-digit numeric) */
String phonePasscode;
/**
@@ -20,6 +20,7 @@ import static google.registry.util.CollectionUtils.forceEmptyToNull;
import com.google.common.annotations.VisibleForTesting;
import com.googlecode.objectify.annotation.Embed;
import google.registry.model.eppcommon.Address;
import javax.persistence.Embeddable;
/**
* Registrar Address
@@ -29,6 +30,7 @@ import google.registry.model.eppcommon.Address;
* classes.
*/
@Embed
@Embeddable
public class RegistrarAddress extends Address {
@Override
@@ -45,6 +45,9 @@ import google.registry.model.annotations.ReportedOn;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Table;
import javax.persistence.Transient;
/**
* A contact for a Registrar. Note, equality, hashCode and comparable have been overridden to only
@@ -56,10 +59,16 @@ import java.util.Set;
*/
@ReportedOn
@Entity
@javax.persistence.Entity
@Table(
name = "RegistrarPoc",
indexes = {
@javax.persistence.Index(columnList = "gaeUserId", name = "registrarpoc_gae_user_id_idx")
})
// TODO(shicong): Rename the class name to RegistrarPoc after database migration
public class RegistrarContact extends ImmutableObject implements Jsonifiable {
@Parent
Key<Registrar> parent;
@Parent @Transient Key<Registrar> parent;
/**
* Registrar contacts types for partner communication tracking.
@@ -99,6 +108,8 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable {
/** The email address of the contact. */
@Id
@javax.persistence.Id
@Column(nullable = false)
String emailAddress;
/** The voice number of the contact. */
@@ -108,8 +119,8 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable {
String faxNumber;
/**
* Multiple types are used to associate the registrar contact with
* various mailing groups. This data is internal to the registry.
* Multiple types are used to associate the registrar contact with various mailing groups. This
* data is internal to the registry.
*/
Set<Type> types;
@@ -31,6 +31,8 @@ import google.registry.ui.server.registrar.OteStatusAction;
import google.registry.ui.server.registrar.RegistrarConsoleModule;
import google.registry.ui.server.registrar.RegistrarSettingsAction;
import google.registry.ui.server.registrar.RegistryLockGetAction;
import google.registry.ui.server.registrar.RegistryLockPostAction;
import google.registry.ui.server.registrar.RegistryLockVerifyAction;
/** Dagger component with per-request lifetime for "default" App Engine module. */
@RequestScope
@@ -53,6 +55,10 @@ interface FrontendRequestComponent {
RegistryLockGetAction registryLockGetAction();
RegistryLockPostAction registryLockPostAction();
RegistryLockVerifyAction registryLockVerifyAction();
@Subcomponent.Builder
abstract class Builder implements RequestComponentBuilder<FrontendRequestComponent> {
@Override public abstract Builder requestModule(RequestModule requestModule);
@@ -0,0 +1,39 @@
// Copyright 2020 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.persistence;
import google.registry.util.CidrAddressBlock;
import java.util.List;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
/**
* JPA {@link AttributeConverter} for storing/retrieving {@link List<CidrAddressBlock>} objects.
* TODO(shicong): Investigate if we can have one converter for any List type
*/
@Converter(autoApply = true)
public class CidrAddressBlockListConverter extends StringListConverterBase<CidrAddressBlock> {
@Override
String toString(CidrAddressBlock element) {
return element.toString();
}
@Override
CidrAddressBlock fromString(String value) {
return CidrAddressBlock.create(value);
}
}
@@ -0,0 +1,48 @@
// Copyright 2020 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.persistence;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import google.registry.model.registrar.Registrar.BillingAccountEntry;
import java.util.Map;
import org.hibernate.usertype.UserType;
import org.joda.money.CurrencyUnit;
/**
* A custom {@link UserType} for storing/retrieving {@link Map<CurrencyUnit, BillingAccountEntry>}
* objects.
*/
public class CurrencyToBillingMapUserType extends MapUserType {
@Override
public Object toEntityTypeMap(Map<String, String> map) {
return map.entrySet().stream()
.collect(
toImmutableMap(
entry -> CurrencyUnit.of(entry.getKey()),
entry ->
new BillingAccountEntry(CurrencyUnit.of(entry.getKey()), entry.getValue())));
}
@Override
public Map<String, String> toDbSupportedMap(Object map) {
return ((Map<CurrencyUnit, BillingAccountEntry>) map)
.entrySet().stream()
.collect(
toImmutableMap(
entry -> entry.getKey().getCode(), entry -> entry.getValue().getAccountId()));
}
}
@@ -1,98 +0,0 @@
// Copyright 2020 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.persistence;
import java.sql.Array;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Collection;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
/** Generic Hibernate user type to store/retrieve Java collection as an array in Cloud SQL. */
public abstract class GenericCollectionUserType<T extends Collection> extends MutableUserType {
abstract T getNewCollection();
abstract ArrayColumnType getColumnType();
enum ArrayColumnType {
STRING(Types.ARRAY, "text");
final int typeCode;
final String typeName;
ArrayColumnType(int typeCode, String typeName) {
this.typeCode = typeCode;
this.typeName = typeName;
}
int getTypeCode() {
return typeCode;
}
String getTypeName() {
return typeName;
}
String getTypeDdlName() {
return typeName + "[]";
}
}
@Override
public int[] sqlTypes() {
return new int[] {getColumnType().getTypeCode()};
}
@Override
public Object nullSafeGet(
ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
throws HibernateException, SQLException {
if (rs.getArray(names[0]) != null) {
T result = getNewCollection();
for (Object element : (Object[]) rs.getArray(names[0]).getArray()) {
result.add(convertToElem(element));
}
return result;
}
return null;
}
@Override
public void nullSafeSet(
PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
throws HibernateException, SQLException {
if (value == null) {
st.setArray(index, null);
return;
}
T list = (T) value;
Array arr = st.getConnection().createArrayOf(getColumnType().getTypeName(), list.toArray());
st.setArray(index, arr);
}
/**
* Override this to convert an element value retrieved from the database to a different type.
*
* <p>This method is useful when encoding a java type to one of the types that can be used as an
* array element.
*/
protected Object convertToElem(Object columnValue) {
return columnValue;
}
}
@@ -45,13 +45,29 @@ public class MapUserType extends MutableUserType {
public Object nullSafeGet(
ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
throws HibernateException, SQLException {
return rs.getObject(names[0]);
return toEntityTypeMap((Map<String, String>) rs.getObject(names[0]));
}
@Override
public void nullSafeSet(
PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
throws HibernateException, SQLException {
st.setObject(index, value);
st.setObject(index, toDbSupportedMap(value));
}
/**
* Subclass can override this method to convert the {@link Map<String, String>} to a {@link Map}
* of specific type defined in the entity class.
*/
public Object toEntityTypeMap(Map<String, String> map) {
return map;
}
/**
* Subclass can override this method to convert the {@link Map} of specific type to a {@link
* Map<String, String>} that can be stored in the hstore type column.
*/
public Map<String, String> toDbSupportedMap(Object map) {
return (Map<String, String>) map;
}
}
@@ -13,9 +13,10 @@
// limitations under the License.
package google.registry.persistence;
import google.registry.persistence.GenericCollectionUserType.ArrayColumnType;
import java.sql.Types;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.PostgreSQL95Dialect;
import org.hibernate.service.ServiceRegistry;
/** Nomulus mapping rules for column types in Postgresql. */
public class NomulusPostgreSQLDialect extends PostgreSQL95Dialect {
@@ -25,8 +26,15 @@ public class NomulusPostgreSQLDialect extends PostgreSQL95Dialect {
registerColumnType(Types.TIMESTAMP_WITH_TIMEZONE, "timestamptz");
registerColumnType(Types.TIMESTAMP, "timestamptz");
registerColumnType(Types.OTHER, "hstore");
for (ArrayColumnType arrayType : ArrayColumnType.values()) {
registerColumnType(arrayType.getTypeCode(), arrayType.getTypeDdlName());
}
registerColumnType(
StringCollectionDescriptor.COLUMN_TYPE, StringCollectionDescriptor.COLUMN_DDL_NAME);
}
@Override
public void contributeTypes(
TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes(typeContributions, serviceRegistry);
typeContributions.contributeJavaTypeDescriptor(new StringCollectionDescriptor());
typeContributions.contributeSqlTypeDescriptor(new StringCollectionDescriptor());
}
}
@@ -14,24 +14,21 @@
package google.registry.persistence;
import java.util.HashSet;
import google.registry.model.registrar.RegistrarContact.Type;
import java.util.Set;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
/** Abstract Hibernate user type for storing/retrieving {@link Set<Enum<E>>}. */
public class EnumSetUserType<E extends Enum<E>> extends GenericCollectionUserType<Set<Enum<E>>> {
/** JPA {@link AttributeConverter} for storing/retrieving {@link Set<Type>}. */
@Converter(autoApply = true)
public class RegistrarPocSetConverter extends StringSetConverterBase<Type> {
@Override
Set<Enum<E>> getNewCollection() {
return new HashSet<Enum<E>>();
String toString(Type element) {
return element.name();
}
@Override
ArrayColumnType getColumnType() {
return ArrayColumnType.STRING;
}
@Override
public Class returnedClass() {
return Set.class;
Type fromString(String value) {
return Type.valueOf(value);
}
}
@@ -0,0 +1,35 @@
// Copyright 2020 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.persistence;
import google.registry.model.eppcommon.StatusValue;
import java.util.Set;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
/** JPA {@link AttributeConverter} for storing/retrieving {@link Set<StatusValue>}. */
@Converter(autoApply = true)
public class StatusValueSetConverter extends StringSetConverterBase<StatusValue> {
@Override
String toString(StatusValue element) {
return element.name();
}
@Override
StatusValue fromString(String value) {
return StatusValue.valueOf(value);
}
}
@@ -0,0 +1,187 @@
// Copyright 2020 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.persistence;
import static google.registry.persistence.StringCollectionDescriptor.StringCollection;
import com.google.common.collect.ImmutableList;
import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Collection;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.spi.JdbcRecommendedSqlTypeMappingContext;
import org.hibernate.type.descriptor.sql.BasicBinder;
import org.hibernate.type.descriptor.sql.BasicExtractor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
/**
* The {@link JavaTypeDescriptor} and {@link SqlTypeDescriptor} for {@link StringCollection}.
*
* <p>A {@link StringCollection} object is a simple wrapper for a {@link Collection<String>} which
* can be stored as a string array in the database. The {@link JavaTypeDescriptor} and {@link
* SqlTypeDescriptor} is used by JPA/Hibernate to map between the collection and {@link Array} which
* is the actual type that JDBC uses to read from and write to the database.
*
* @see <a
* href="https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#basic-jpa-convert">JPA
* 2.1 AttributeConverters</a>
*/
public class StringCollectionDescriptor extends AbstractTypeDescriptor<StringCollection>
implements SqlTypeDescriptor {
public static final int COLUMN_TYPE = Types.ARRAY;
public static final String COLUMN_NAME = "text";
public static final String COLUMN_DDL_NAME = COLUMN_NAME + "[]";
protected StringCollectionDescriptor() {
super(StringCollection.class);
}
@Override
public StringCollection fromString(String string) {
throw new UnsupportedOperationException(
"Constructing StringCollectionDescriptor from string is not allowed");
}
@Override
public <X> X unwrap(StringCollection value, Class<X> type, WrapperOptions options) {
if (value == null) {
return null;
}
if (Collection.class.isAssignableFrom(type)) {
return (X) value.getCollection();
}
throw unknownUnwrap(type);
}
@Override
public <X> StringCollection wrap(X value, WrapperOptions options) {
if (value == null) {
return null;
}
if (value instanceof Array) {
try {
String[] arr = (String[]) ((Array) value).getArray();
ImmutableList.Builder<String> builder = new ImmutableList.Builder<>();
for (String str : arr) {
builder.add(str);
}
return StringCollection.create(builder.build());
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
throw unknownWrap(value.getClass());
}
@Override
public SqlTypeDescriptor getJdbcRecommendedSqlType(JdbcRecommendedSqlTypeMappingContext context) {
return this;
}
@Override
public int getSqlType() {
return COLUMN_TYPE;
}
@Override
public boolean canBeRemapped() {
return false;
}
@Override
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>(javaTypeDescriptor, this) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
if (value == null) {
st.setArray(index, null);
return;
}
if (value instanceof StringCollection) {
StringCollection stringCollection = (StringCollection) value;
if (stringCollection.getCollection() == null) {
st.setArray(index, null);
} else {
st.setArray(
index,
st.getConnection()
.createArrayOf(COLUMN_NAME, stringCollection.getCollection().toArray()));
}
} else {
throw new UnsupportedOperationException(
String.format(
"Binding type %s is not supported by StringCollectionDescriptor",
value.getClass().getName()));
}
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
// CallableStatement.setArray() doesn't have an overload version for setting array by its
// column name
throw new UnsupportedOperationException(
"Binding array by its column name is not supported");
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicExtractor<X>(javaTypeDescriptor, this) {
@Override
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
return javaTypeDescriptor.wrap(rs.getArray(name), options);
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options)
throws SQLException {
return javaTypeDescriptor.wrap(statement.getArray(index), options);
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
return javaTypeDescriptor.wrap(statement.getArray(name), options);
}
};
}
public static class StringCollection {
private Collection<String> collection;
private StringCollection(Collection<String> collection) {
this.collection = collection;
}
public static StringCollection create(Collection<String> collection) {
return new StringCollection(collection);
}
public Collection<String> getCollection() {
return collection;
}
}
}
@@ -14,24 +14,21 @@
package google.registry.persistence;
import com.google.common.collect.Lists;
import java.util.List;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
/** Abstract Hibernate user type for storing/retrieving {@link List<String>}. */
public class StringListUserType extends GenericCollectionUserType<List<String>> {
/** JPA {@link AttributeConverter} for storing/retrieving {@link List<String>}. */
@Converter(autoApply = true)
public class StringListConverter extends StringListConverterBase<String> {
@Override
List<String> getNewCollection() {
return Lists.newArrayList();
String toString(String element) {
return element;
}
@Override
ArrayColumnType getColumnType() {
return ArrayColumnType.STRING;
}
@Override
public Class returnedClass() {
return List.class;
String fromString(String value) {
return value;
}
}
@@ -0,0 +1,48 @@
// Copyright 2020 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.persistence;
import static com.google.common.collect.ImmutableList.toImmutableList;
import google.registry.persistence.StringCollectionDescriptor.StringCollection;
import java.util.List;
import javax.persistence.AttributeConverter;
/**
* Base JPA converter for {@link List} objects that are stored as an array of strings in the
* database.
*/
public abstract class StringListConverterBase<T>
implements AttributeConverter<List<T>, StringCollection> {
abstract String toString(T element);
abstract T fromString(String value);
@Override
public StringCollection convertToDatabaseColumn(List<T> attribute) {
return attribute == null
? null
: StringCollection.create(
attribute.stream().map(this::toString).collect(toImmutableList()));
}
@Override
public List<T> convertToEntityAttribute(StringCollection dbData) {
return dbData == null || dbData.getCollection() == null
? null
: dbData.getCollection().stream().map(this::fromString).collect(toImmutableList());
}
}
@@ -14,24 +14,21 @@
package google.registry.persistence;
import com.google.common.collect.Sets;
import java.util.Set;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
/** Abstract Hibernate user type for storing/retrieving {@link Set<String>}. */
public class StringSetUserType extends GenericCollectionUserType<Set<String>> {
/** JPA {@link AttributeConverter} for storing/retrieving {@link Set<String>}. */
@Converter(autoApply = true)
public class StringSetConverter extends StringSetConverterBase<String> {
@Override
Set<String> getNewCollection() {
return Sets.newHashSet();
String toString(String element) {
return element;
}
@Override
ArrayColumnType getColumnType() {
return ArrayColumnType.STRING;
}
@Override
public Class returnedClass() {
return Set.class;
String fromString(String value) {
return value;
}
}
@@ -0,0 +1,47 @@
// Copyright 2020 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.persistence;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import google.registry.persistence.StringCollectionDescriptor.StringCollection;
import java.util.Set;
import javax.persistence.AttributeConverter;
/**
* Base JPA converter for {@link Set} objects that are stored as an array of strings in the
* database.
*/
public abstract class StringSetConverterBase<T>
implements AttributeConverter<Set<T>, StringCollection> {
abstract String toString(T element);
abstract T fromString(String value);
@Override
public StringCollection convertToDatabaseColumn(Set<T> attribute) {
return attribute == null
? null
: StringCollection.create(attribute.stream().map(this::toString).collect(toImmutableSet()));
}
@Override
public Set<T> convertToEntityAttribute(StringCollection dbData) {
return dbData == null || dbData.getCollection() == null
? null
: dbData.getCollection().stream().map(this::fromString).collect(toImmutableSet());
}
}
@@ -156,7 +156,11 @@ public class PremiumListDao {
RevisionIdAndLabel.create(premiumList.getRevisionId(), label);
try {
Optional<BigDecimal> price = PremiumListCache.cachePremiumEntries.get(revisionIdAndLabel);
return price.map(p -> Money.of(premiumList.getCurrency(), p));
return price.map(
p ->
Money.of(
premiumList.getCurrency(),
p.setScale(premiumList.getCurrency().getDecimalPlaces())));
} catch (InvalidCacheLoadException | ExecutionException e) {
throw new RuntimeException(
String.format(
@@ -62,12 +62,6 @@ public abstract class CreateOrUpdateReservedListCommand extends MutatingCommand
arity = 1)
Boolean shouldPublish;
@Parameter(
names = {"--also_cloud_sql"},
description =
"Persist reserved list to Cloud SQL in addition to Datastore; defaults to false.")
boolean alsoCloudSql;
google.registry.schema.tld.ReservedList cloudSqlReservedList;
abstract void saveToCloudSql();
@@ -78,23 +72,18 @@ public abstract class CreateOrUpdateReservedListCommand extends MutatingCommand
String output = super.execute();
logger.atInfo().log(output);
String cloudSqlMessage;
if (alsoCloudSql) {
String cloudSqlMessage =
String.format(
"Saved reserved list %s with %d entries",
name, cloudSqlReservedList.getLabelsToReservations().size());
try {
logger.atInfo().log("Saving reserved list to Cloud SQL for TLD %s", name);
saveToCloudSql();
logger.atInfo().log(cloudSqlMessage);
} catch (Throwable e) {
cloudSqlMessage =
String.format(
"Saved reserved list %s with %d entries",
name, cloudSqlReservedList.getLabelsToReservations().size());
try {
logger.atInfo().log("Saving reserved list to Cloud SQL for TLD %s", name);
saveToCloudSql();
logger.atInfo().log(cloudSqlMessage);
} catch (Throwable e) {
cloudSqlMessage =
"Unexpected error saving reserved list to Cloud SQL from nomulus tool command";
logger.atSevere().withCause(e).log(cloudSqlMessage);
}
} else {
cloudSqlMessage = "Persisting reserved list to Cloud SQL is not enabled";
"Unexpected error saving reserved list to Cloud SQL from nomulus tool command";
logger.atSevere().withCause(e).log(cloudSqlMessage);
}
return cloudSqlMessage;
}
@@ -67,11 +67,9 @@ final class CreateReservedListCommand extends CreateOrUpdateReservedListCommand
.setLastUpdateTime(now)
.build();
stageEntityChange(null, reservedList);
if (alsoCloudSql) {
cloudSqlReservedList =
google.registry.schema.tld.ReservedList.create(
name, shouldPublish, parseToReservationsByLabels(allLines));
}
cloudSqlReservedList =
google.registry.schema.tld.ReservedList.create(
name, shouldPublish, parseToReservationsByLabels(allLines));
}
@Override
@@ -32,12 +32,14 @@ import google.registry.model.registry.RegistryLockDao;
import google.registry.model.reporting.HistoryEntry;
import google.registry.schema.domain.RegistryLock;
import google.registry.util.Clock;
import google.registry.util.StringGenerator;
import java.util.Optional;
import java.util.UUID;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Named;
/**
* Utility class for validating and applying {@link RegistryLock}s.
* Utility functions for validating and applying {@link RegistryLock}s.
*
* <p>For both locks and unlocks, a lock must be requested via the createRegistry*Requst methods
* then verified through the verifyAndApply* methods. These methods will verify that the domain in
@@ -45,9 +47,16 @@ import javax.annotation.Nullable;
*/
public final class DomainLockUtils {
private DomainLockUtils() {}
private static final int VERIFICATION_CODE_LENGTH = 32;
public static RegistryLock createRegistryLockRequest(
private final StringGenerator stringGenerator;
@Inject
public DomainLockUtils(@Named("base58StringGenerator") StringGenerator stringGenerator) {
this.stringGenerator = stringGenerator;
}
public RegistryLock createRegistryLockRequest(
String domainName,
String registrarId,
@Nullable String registrarPocId,
@@ -68,7 +77,7 @@ public final class DomainLockUtils {
RegistryLock lock =
new RegistryLock.Builder()
.setVerificationCode(UUID.randomUUID().toString())
.setVerificationCode(stringGenerator.createString(VERIFICATION_CODE_LENGTH))
.setDomainName(domainName)
.setRepoId(domainBase.getRepoId())
.setRegistrarId(registrarId)
@@ -78,7 +87,7 @@ public final class DomainLockUtils {
return RegistryLockDao.save(lock);
}
public static RegistryLock createRegistryUnlockRequest(
public RegistryLock createRegistryUnlockRequest(
String domainName, String registrarId, boolean isAdmin, Clock clock) {
DomainBase domainBase = getDomain(domainName, clock);
Optional<RegistryLock> lockOptional =
@@ -121,7 +130,7 @@ public final class DomainLockUtils {
}
RegistryLock newLock =
newLockBuilder
.setVerificationCode(UUID.randomUUID().toString())
.setVerificationCode(stringGenerator.createString(VERIFICATION_CODE_LENGTH))
.isSuperuser(isAdmin)
.setUnlockRequestTimestamp(clock.nowUtc())
.setRegistrarId(registrarId)
@@ -129,8 +138,7 @@ public final class DomainLockUtils {
return RegistryLockDao.save(newLock);
}
public static RegistryLock verifyAndApplyLock(
String verificationCode, boolean isAdmin, Clock clock) {
public RegistryLock verifyAndApplyLock(String verificationCode, boolean isAdmin, Clock clock) {
return jpaTm()
.transact(
() -> {
@@ -156,8 +164,7 @@ public final class DomainLockUtils {
});
}
public static RegistryLock verifyAndApplyUnlock(
String verificationCode, boolean isAdmin, Clock clock) {
public RegistryLock verifyAndApplyUnlock(String verificationCode, boolean isAdmin, Clock clock) {
return jpaTm()
.transact(
() -> {
@@ -60,11 +60,11 @@ public class LockDomainCommand extends LockOrUnlockDomainCommand {
@Override
protected RegistryLock createLock(String domain) {
return DomainLockUtils.createRegistryLockRequest(domain, clientId, null, true, clock);
return domainLockUtils.createRegistryLockRequest(domain, clientId, null, true, clock);
}
@Override
protected void finalizeLockOrUnlockRequest(RegistryLock lock) {
DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, clock);
domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, clock);
}
}
@@ -38,7 +38,7 @@ public abstract class LockOrUnlockDomainCommand extends ConfirmingCommand
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
static final ImmutableSet<StatusValue> REGISTRY_LOCK_STATUSES =
public static final ImmutableSet<StatusValue> REGISTRY_LOCK_STATUSES =
ImmutableSet.of(
SERVER_DELETE_PROHIBITED, SERVER_TRANSFER_PROHIBITED, SERVER_UPDATE_PROHIBITED);
@@ -57,6 +57,8 @@ public abstract class LockOrUnlockDomainCommand extends ConfirmingCommand
@Inject Clock clock;
@Inject DomainLockUtils domainLockUtils;
protected ImmutableSet<String> relevantDomains = ImmutableSet.of();
protected ImmutableSet<String> getDomains() {
@@ -60,11 +60,11 @@ public class UnlockDomainCommand extends LockOrUnlockDomainCommand {
@Override
protected RegistryLock createLock(String domain) {
return DomainLockUtils.createRegistryUnlockRequest(domain, clientId, true, clock);
return domainLockUtils.createRegistryUnlockRequest(domain, clientId, true, clock);
}
@Override
protected void finalizeLockOrUnlockRequest(RegistryLock lock) {
DomainLockUtils.verifyAndApplyUnlock(lock.getVerificationCode(), true, clock);
domainLockUtils.verifyAndApplyUnlock(lock.getVerificationCode(), true, clock);
}
}
@@ -50,11 +50,9 @@ final class UpdateReservedListCommand extends CreateOrUpdateReservedListCommand
.setLastUpdateTime(new SystemClock().nowUtc())
.setShouldPublish(shouldPublish);
stageEntityChange(existing.get(), updated.build());
if (alsoCloudSql) {
cloudSqlReservedList =
google.registry.schema.tld.ReservedList.create(
name, shouldPublish, parseToReservationsByLabels(allLines));
}
cloudSqlReservedList =
google.registry.schema.tld.ReservedList.create(
name, shouldPublish, parseToReservationsByLabels(allLines));
}
@Override
@@ -37,11 +37,6 @@ final class UploadClaimsListCommand extends ConfirmingCommand implements Command
@Parameter(description = "Claims list filename")
private List<String> mainParameters = new ArrayList<>();
@Parameter(
names = {"--also_cloud_sql"},
description = "Persist claims list to Cloud SQL in addition to Datastore; defaults to false.")
boolean alsoCloudSql;
private String claimsListFilename;
private ClaimsList claimsList;
@@ -64,9 +59,7 @@ final class UploadClaimsListCommand extends ConfirmingCommand implements Command
@Override
public String execute() {
ClaimsListShard.create(claimsList.getTmdbGenerationTime(), claimsList.getLabelsToKeys()).save();
if (alsoCloudSql) {
ClaimsListDao.trySave(claimsList);
}
ClaimsListDao.trySave(claimsList);
return String.format("Successfully uploaded claims list %s", claimsListFilename);
}
}
@@ -14,7 +14,7 @@
package google.registry.ui.server.registrar;
import static google.registry.request.RequestParameters.extractBooleanParameter;
import static google.registry.request.RequestParameters.extractOptionalIntParameter;
import static google.registry.request.RequestParameters.extractOptionalParameter;
import static google.registry.request.RequestParameters.extractRequiredParameter;
@@ -144,4 +144,16 @@ public final class RegistrarConsoleModule {
static Optional<String> provideOptionalPasscode(HttpServletRequest req) {
return extractOptionalParameter(req, "passcode");
}
@Provides
@Parameter("lockVerificationCode")
static String provideLockVerificationCode(HttpServletRequest req) {
return extractRequiredParameter(req, "lockVerificationCode");
}
@Provides
@Parameter("isLock")
static Boolean provideIsLock(HttpServletRequest req) {
return extractBooleanParameter(req, "isLock");
}
}
@@ -0,0 +1,216 @@
// Copyright 2020 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.ui.server.registrar;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.security.JsonResponseHelper.Status.ERROR;
import static google.registry.security.JsonResponseHelper.Status.SUCCESS;
import static google.registry.ui.server.registrar.RegistrarConsoleModule.PARAM_CLIENT_ID;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gson.Gson;
import google.registry.config.RegistryConfig;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.RegistrarContact;
import google.registry.request.Action;
import google.registry.request.Action.Method;
import google.registry.request.HttpException.ForbiddenException;
import google.registry.request.JsonActionRunner;
import google.registry.request.auth.Auth;
import google.registry.request.auth.AuthResult;
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException;
import google.registry.request.auth.UserAuthInfo;
import google.registry.schema.domain.RegistryLock;
import google.registry.security.JsonResponseHelper;
import google.registry.tools.DomainLockUtils;
import google.registry.util.Clock;
import google.registry.util.EmailMessage;
import google.registry.util.SendEmailService;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Map;
import java.util.Optional;
import javax.inject.Inject;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import org.apache.http.client.utils.URIBuilder;
/**
* UI action that allows for creating registry locks. Locks / unlocks must be verified separately
* before they are written permanently.
*
* <p>Note: at the moment we have no mechanism for JSON GET/POSTs in the same class or at the same
* URL, which is why this is distinct from the {@link RegistryLockGetAction}.
*/
@Action(
service = Action.Service.DEFAULT,
path = RegistryLockPostAction.PATH,
method = Method.POST,
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAction {
public static final String PATH = "/registry-lock-post";
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final Gson GSON = new Gson();
private static final URL URL_BASE = RegistryConfig.getDefaultServer();
private static final String VERIFICATION_EMAIL_TEMPLATE =
"Please click the link below to perform the lock / unlock action on domain %s. Note: "
+ "this code will expire in one hour.\n\n%s";
private final JsonActionRunner jsonActionRunner;
private final AuthResult authResult;
private final AuthenticatedRegistrarAccessor registrarAccessor;
private final SendEmailService sendEmailService;
private final Clock clock;
private final DomainLockUtils domainLockUtils;
private final InternetAddress gSuiteOutgoingEmailAddress;
@Inject
RegistryLockPostAction(
JsonActionRunner jsonActionRunner,
AuthResult authResult,
AuthenticatedRegistrarAccessor registrarAccessor,
SendEmailService sendEmailService,
Clock clock,
DomainLockUtils domainLockUtils,
@Config("gSuiteOutgoingEmailAddress") InternetAddress gSuiteOutgoingEmailAddress) {
this.jsonActionRunner = jsonActionRunner;
this.authResult = authResult;
this.registrarAccessor = registrarAccessor;
this.sendEmailService = sendEmailService;
this.clock = clock;
this.domainLockUtils = domainLockUtils;
this.gSuiteOutgoingEmailAddress = gSuiteOutgoingEmailAddress;
}
@Override
public void run() {
jsonActionRunner.run(this);
}
@Override
public Map<String, ?> handleJsonRequest(Map<String, ?> input) {
try {
checkArgumentNotNull(input, "Null JSON");
RegistryLockPostInput postInput =
GSON.fromJson(GSON.toJsonTree(input), RegistryLockPostInput.class);
checkArgument(
!Strings.isNullOrEmpty(postInput.clientId),
"Missing key for client: %s",
PARAM_CLIENT_ID);
checkArgument(
!Strings.isNullOrEmpty(postInput.fullyQualifiedDomainName),
"Missing key for fullyQualifiedDomainName");
checkNotNull(postInput.isLock, "Missing key for isLock");
UserAuthInfo userAuthInfo =
authResult
.userAuthInfo()
.orElseThrow(() -> new ForbiddenException("User is not logged in"));
boolean isAdmin = userAuthInfo.isUserAdmin();
String userEmail = userAuthInfo.user().getEmail();
if (!isAdmin) {
verifyRegistryLockPassword(postInput, userEmail);
}
jpaTm()
.transact(
() -> {
RegistryLock registryLock =
postInput.isLock
? domainLockUtils.createRegistryLockRequest(
postInput.fullyQualifiedDomainName,
postInput.clientId,
userEmail,
isAdmin,
clock)
: domainLockUtils.createRegistryUnlockRequest(
postInput.fullyQualifiedDomainName, postInput.clientId, isAdmin, clock);
sendVerificationEmail(registryLock, userEmail, postInput.isLock);
});
String action = postInput.isLock ? "lock" : "unlock";
return JsonResponseHelper.create(SUCCESS, String.format("Successful %s", action));
} catch (Throwable e) {
logger.atWarning().withCause(e).log("Failed to lock/unlock domain with input %s", input);
return JsonResponseHelper.create(
ERROR,
Optional.ofNullable(Throwables.getRootCause(e).getMessage()).orElse("Unspecified error"));
}
}
private void sendVerificationEmail(RegistryLock lock, String userEmail, boolean isLock) {
try {
String url =
new URIBuilder()
.setScheme("https")
.setHost(URL_BASE.getHost())
.setPath("registry-lock-verify")
.setParameter("lockVerificationCode", lock.getVerificationCode())
.setParameter("isLock", String.valueOf(isLock))
.build()
.toString();
String body = String.format(VERIFICATION_EMAIL_TEMPLATE, lock.getDomainName(), url);
ImmutableList<InternetAddress> recipients =
ImmutableList.of(new InternetAddress(userEmail, true));
String action = isLock ? "lock" : "unlock";
sendEmailService.sendEmail(
EmailMessage.newBuilder()
.setBody(body)
.setSubject(String.format("Registry %s verification", action))
.setRecipients(recipients)
.setFrom(gSuiteOutgoingEmailAddress)
.build());
} catch (AddressException | URISyntaxException e) {
throw new RuntimeException(e); // caught above -- this is so we can run in a transaction
}
}
private void verifyRegistryLockPassword(RegistryLockPostInput postInput, String userEmail)
throws RegistrarAccessDeniedException {
// Verify that the user can access the registrar and that the user has
// registry lock enabled and provided a correct password
Registrar registrar = registrarAccessor.getRegistrar(postInput.clientId);
checkArgument(
registrar.isRegistryLockAllowed(), "Registry lock not allowed for this registrar");
checkArgument(!Strings.isNullOrEmpty(postInput.password), "Missing key for password");
RegistrarContact registrarContact =
registrar.getContacts().stream()
.filter(contact -> contact.getEmailAddress().equals(userEmail))
.findFirst()
.orElseThrow(
() ->
new IllegalArgumentException(
String.format("Unknown user email %s", userEmail)));
checkArgument(
registrarContact.verifyRegistryLockPassword(postInput.password),
"Incorrect registry lock password for contact");
}
/** Value class that represents the expected input body from the UI request. */
private static class RegistryLockPostInput {
private String clientId;
private String fullyQualifiedDomainName;
private Boolean isLock;
private String password;
}
}
@@ -0,0 +1,100 @@
// Copyright 2020 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.ui.server.registrar;
import static google.registry.ui.server.SoyTemplateUtils.CSS_RENAMING_MAP_SUPPLIER;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.flogger.FluentLogger;
import com.google.template.soy.tofu.SoyTofu;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.schema.domain.RegistryLock;
import google.registry.tools.DomainLockUtils;
import google.registry.ui.server.SoyTemplateUtils;
import google.registry.ui.soy.registrar.RegistryLockVerificationSoyInfo;
import google.registry.util.Clock;
import java.util.HashMap;
import javax.inject.Inject;
/** Action that allows for verification of registry lock / unlock requests */
@Action(
service = Action.Service.DEFAULT,
path = RegistryLockVerifyAction.PATH,
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
public final class RegistryLockVerifyAction extends HtmlAction {
public static final String PATH = "/registry-lock-verify";
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final Supplier<SoyTofu> TOFU_SUPPLIER =
SoyTemplateUtils.createTofuSupplier(
google.registry.ui.soy.ConsoleSoyInfo.getInstance(),
google.registry.ui.soy.AnalyticsSoyInfo.getInstance(),
google.registry.ui.soy.registrar.RegistryLockVerificationSoyInfo.getInstance());
private final Clock clock;
private final DomainLockUtils domainLockUtils;
private final String lockVerificationCode;
private final Boolean isLock;
@Inject
public RegistryLockVerifyAction(
Clock clock,
DomainLockUtils domainLockUtils,
@Parameter("lockVerificationCode") String lockVerificationCode,
@Parameter("isLock") Boolean isLock) {
this.clock = clock;
this.domainLockUtils = domainLockUtils;
this.lockVerificationCode = lockVerificationCode;
this.isLock = isLock;
}
@Override
public void runAfterLogin(HashMap<String, Object> data) {
try {
boolean isAdmin = authResult.userAuthInfo().get().isUserAdmin();
final RegistryLock resultLock;
if (isLock) {
resultLock = domainLockUtils.verifyAndApplyLock(lockVerificationCode, isAdmin, clock);
} else {
resultLock = domainLockUtils.verifyAndApplyUnlock(lockVerificationCode, isAdmin, clock);
}
data.put("isLock", isLock);
data.put("success", true);
data.put("fullyQualifiedDomainName", resultLock.getDomainName());
} catch (Throwable t) {
logger.atWarning().withCause(t).log(
"Error when verifying verification code %s", lockVerificationCode);
data.put("success", false);
data.put("errorMessage", Throwables.getRootCause(t).getMessage());
}
response.setPayload(
TOFU_SUPPLIER
.get()
.newRenderer(RegistryLockVerificationSoyInfo.VERIFICATION_PAGE)
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
.setData(data)
.render());
}
@Override
public String getPath() {
return PATH;
}
}
@@ -20,6 +20,8 @@
* Use Hibernate's ServiceRegistry for bootstrapping (not JPA-compliant)
-->
<class>google.registry.model.domain.DomainBase</class>
<class>google.registry.model.registrar.Registrar</class>
<class>google.registry.model.registrar.RegistrarContact</class>
<class>google.registry.schema.domain.RegistryLock</class>
<class>google.registry.schema.tmch.ClaimsList</class>
<class>google.registry.schema.cursor.Cursor</class>
@@ -37,9 +39,14 @@
<!-- Customized type converters -->
<class>google.registry.persistence.BloomFilterConverter</class>
<class>google.registry.persistence.CidrAddressBlockListConverter</class>
<class>google.registry.persistence.CreateAutoTimestampConverter</class>
<class>google.registry.persistence.CurrencyUnitConverter</class>
<class>google.registry.persistence.DateTimeConverter</class>
<class>google.registry.persistence.RegistrarPocSetConverter</class>
<class>google.registry.persistence.StatusValueSetConverter</class>
<class>google.registry.persistence.StringListConverter</class>
<class>google.registry.persistence.StringSetConverter</class>
<class>google.registry.persistence.UpdateAutoTimestampConverter</class>
<class>google.registry.persistence.ZonedDateTimeConverter</class>
@@ -0,0 +1,71 @@
// 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.
{namespace registry.soy.registrar.registrylock.verification}
/**
* Results page for a registry lock/unlock verification.
*/
{template .verificationPage}
{@param username: string} /** Arbitrary username to display. */
{@param analyticsConfig: [googleAnalyticsId: string|null]}
{@param success: bool}
{@param? errorMessage: string}
{@param? isLock: bool}
{@param? fullyQualifiedDomainName: string}
{call registry.soy.console.header}
{param app: 'registrar' /}
{param subtitle: 'Verify Registry Lock' /}
{param analyticsConfig: $analyticsConfig /}
{/call}
{call registry.soy.console.googlebar data="all" /}
<div id="reg-content-and-footer">
<div id="reg-content">
<h1>Registry Lock Verification</h1>
{if $success}
{call .success data="all" /}
{else}
{call .failure data="all" /}
{/if}
<h3><a href="/registrar">Return to Registrar Console</a></h3>
</div>
{call registry.soy.console.footer /}
</div>
{/template}
/**
* Result page for failure, e.g. the UUID was invalid
*/
{template .failure}
{@param? errorMessage: string}
<h2 class="{css('kd-errormessage')}">Failed: {if isNonnull($errorMessage)}
{$errorMessage}
{else}
Undefined error message
{/if}
</h2>
{/template}
/**
* Result page for a successful lock / unlock.
*/
{template .success}
{@param? isLock: bool}
{@param? fullyQualifiedDomainName: string}
<h3>
Success: {if $isLock}lock{else}unlock{/if} has been applied to {$fullyQualifiedDomainName}
</h3>
{/template}
@@ -26,7 +26,9 @@ public class DevTool {
* any invocations in scripts (e.g. PDT, ICANN reporting).
*/
public static final ImmutableMap<String, Class<? extends Command>> COMMAND_MAP =
ImmutableMap.of("generate_sql_schema", GenerateSqlSchemaCommand.class);
ImmutableMap.of(
"dump_golden_schema", DumpGoldenSchemaCommand.class,
"generate_sql_schema", GenerateSqlSchemaCommand.class);
public static void main(String[] args) throws Exception {
RegistryToolEnvironment.parseFromArgs(args).setup();
@@ -0,0 +1,91 @@
// Copyright 2020 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.tools;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import org.flywaydb.core.Flyway;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.Container;
/**
* Generates a schema for JPA annotated classes using Hibernate.
*
* <p>Note that this isn't complete yet, as all of the persistent classes have not yet been
* converted. After converting a class, a call to "addAnnotatedClass()" for the new class must be
* added to the code below.
*/
@Parameters(separators = " =", commandDescription = "Dump golden schema.")
public class DumpGoldenSchemaCommand extends PostgresqlCommand {
// The mount point in the container.
private static final String CONTAINER_MOUNT_POINT = "/tmp/pg_dump.out";
@Parameter(
names = {"--output", "-o"},
description = "Output file",
required = true)
Path output;
@Override
void runCommand() throws IOException, InterruptedException {
Flyway flyway =
Flyway.configure()
.locations("sql/flyway")
.dataSource(
postgresContainer.getJdbcUrl(),
postgresContainer.getUsername(),
postgresContainer.getPassword())
.load();
flyway.migrate();
String userName = postgresContainer.getUsername();
String databaseName = postgresContainer.getDatabaseName();
Container.ExecResult result =
postgresContainer.execInContainer(getSchemaDumpCommand(userName, databaseName));
if (result.getExitCode() != 0) {
throw new RuntimeException(result.toString());
}
}
@Override
protected void onContainerCreate() throws IOException {
// open the output file for write so we can mount it.
new FileOutputStream(output.toFile()).close();
postgresContainer.withFileSystemBind(
output.toString(), CONTAINER_MOUNT_POINT, BindMode.READ_WRITE);
}
private static String[] getSchemaDumpCommand(String username, String dbName) {
return new String[] {
"pg_dump",
"-h",
"localhost",
"-U",
username,
"-f",
CONTAINER_MOUNT_POINT,
"--schema-only",
"--no-owner",
"--no-privileges",
"--exclude-table",
"flyway_schema_history",
dbName
};
}
}
@@ -0,0 +1,128 @@
// 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.tools;
import com.beust.jcommander.Parameter;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.flogger.FluentLogger;
import google.registry.persistence.NomulusPostgreSql;
import org.testcontainers.containers.PostgreSQLContainer;
/** Base class for commands that need a PostgreSQL database. */
public abstract class PostgresqlCommand implements Command {
static final FluentLogger logger = FluentLogger.forEnclosingClass();
protected static final String DB_NAME = "postgres";
protected static final String DB_USERNAME = "postgres";
protected static final String DB_PASSWORD = "domain-registry";
@VisibleForTesting
public static final String DB_OPTIONS_CLASH =
"Database host and port may not be specified along with the option to start a "
+ "PostgreSQL container.";
@VisibleForTesting public static final int POSTGRESQL_PORT = 5432;
protected PostgreSQLContainer postgresContainer = null;
@Parameter(
names = {"-s", "--start_postgresql"},
description = "If specified, start PostgreSQL in a Docker container.")
boolean startPostgresql = false;
@Parameter(
names = {"-a", "--db_host"},
description = "Database host name.")
String databaseHost;
@Parameter(
names = {"-p", "--db_port"},
description = "Database port number. This defaults to the PostgreSQL default port.")
Integer databasePort;
/**
* Starts the database if appropriate.
*
* <p>Returns true if the database was successfully initialized, false if not.
*/
private boolean initializeDatabase() {
// Start PostgreSQL if requested.
if (startPostgresql) {
// Complain if the user has also specified either --db_host or --db_port.
if (databaseHost != null || databasePort != null) {
System.err.println(DB_OPTIONS_CLASH);
// TODO: it would be nice to exit(1) here, but this breaks testability.
return false;
}
// Start the container and store the address information.
postgresContainer =
new PostgreSQLContainer(NomulusPostgreSql.getDockerTag())
.withDatabaseName(DB_NAME)
.withUsername(DB_USERNAME)
.withPassword(DB_PASSWORD);
try {
onContainerCreate();
} catch (Exception e) {
logger.atSevere().withCause(e).log("Error in container callback hook.");
return false;
}
postgresContainer.start();
databaseHost = postgresContainer.getContainerIpAddress();
databasePort = postgresContainer.getMappedPort(POSTGRESQL_PORT);
} else if (databaseHost == null) {
System.err.println(
"You must specify either --start_postgresql to start a PostgreSQL database in a\n"
+ "docker instance, or specify --db_host (and, optionally, --db_port) to identify\n"
+ "the location of a running instance. To start a long-lived instance (suitable\n"
+ "for running this command multiple times) run this:\n\n"
+ " docker run --rm --name some-postgres -e POSTGRES_PASSWORD=domain-registry \\\n"
+ " -d "
+ NomulusPostgreSql.getDockerTag()
+ "\n\nCopy the container id output from the command, then run:\n\n"
+ " docker inspect <container-id> | grep IPAddress\n\n"
+ "To obtain the value for --db-host.\n");
// TODO(mmuller): need exit(1), see above.
return false;
}
// use the default port if non has been defined.
if (databasePort == null) {
databasePort = POSTGRESQL_PORT;
}
return true;
}
@Override
public void run() throws Exception {
if (!initializeDatabase()) {
return;
}
try {
runCommand();
} finally {
if (postgresContainer != null) {
postgresContainer.stop();
}
}
}
/** Called after the container has been created but before it has been started. */
protected void onContainerCreate() throws Exception {}
/** Command to be run while the database is running. */
abstract void runCommand() throws Exception;
}
@@ -25,7 +25,6 @@ import google.registry.schema.domain.RegistryLock;
import google.registry.testing.AppEngineRule;
import google.registry.testing.FakeClock;
import java.util.Optional;
import java.util.UUID;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -201,7 +200,7 @@ public final class RegistryLockDaoTest {
.setRepoId("repoId")
.setDomainName("example.test")
.setRegistrarId("TheRegistrar")
.setVerificationCode(UUID.randomUUID().toString())
.setVerificationCode("123456789ABCDEFGHJKLMNPQRSTUVWXY")
.isSuperuser(true)
.build();
}
@@ -0,0 +1,69 @@
// Copyright 2020 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.persistence;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import com.google.common.collect.ImmutableList;
import google.registry.model.ImmutableObject;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule;
import google.registry.util.CidrAddressBlock;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link CidrAddressBlockListConverter}. */
@RunWith(JUnit4.class)
public class CidrAddressBlockListUserTypeTest {
@Rule
public final JpaUnitTestRule jpaRule =
new JpaTestRules.Builder().withEntityClass(TestEntity.class).buildUnitTestRule();
@Test
public void roundTripConversion_returnsSameCidrAddressBlock() {
List<CidrAddressBlock> addresses =
ImmutableList.of(
CidrAddressBlock.create("0.0.0.0/32"),
CidrAddressBlock.create("255.255.255.254/31"),
CidrAddressBlock.create("::"),
CidrAddressBlock.create("8000::/1"),
CidrAddressBlock.create("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
TestEntity testEntity = new TestEntity(addresses);
jpaTm().transact(() -> jpaTm().getEntityManager().persist(testEntity));
TestEntity persisted =
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "id"));
assertThat(persisted.addresses).isEqualTo(addresses);
}
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
private static class TestEntity extends ImmutableObject {
@Id String name = "id";
List<CidrAddressBlock> addresses;
private TestEntity() {}
private TestEntity(List<CidrAddressBlock> addresses) {
this.addresses = addresses;
}
}
}
@@ -0,0 +1,74 @@
// Copyright 2020 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.persistence;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import com.google.common.collect.ImmutableMap;
import google.registry.model.ImmutableObject;
import google.registry.model.registrar.Registrar.BillingAccountEntry;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule;
import java.util.Map;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.hibernate.annotations.Type;
import org.joda.money.CurrencyUnit;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link CurrencyToBillingMapUserType}. */
@RunWith(JUnit4.class)
public class CurrencyToBillingMapUserTypeTest {
@Rule
public final JpaUnitTestRule jpaRule =
new JpaTestRules.Builder()
.withInitScript("sql/flyway/V14__load_extension_for_hstore.sql")
.withEntityClass(TestEntity.class)
.buildUnitTestRule();
@Test
public void roundTripConversion_returnsSameCurrencyToBillingMap() {
ImmutableMap<CurrencyUnit, BillingAccountEntry> currencyToBilling =
ImmutableMap.of(
CurrencyUnit.of("USD"),
new BillingAccountEntry(CurrencyUnit.of("USD"), "accountId1"),
CurrencyUnit.of("CNY"),
new BillingAccountEntry(CurrencyUnit.of("CNY"), "accountId2"));
TestEntity testEntity = new TestEntity(currencyToBilling);
jpaTm().transact(() -> jpaTm().getEntityManager().persist(testEntity));
TestEntity persisted =
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "id"));
assertThat(persisted.currencyToBilling).containsExactlyEntriesIn(currencyToBilling);
}
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
private static class TestEntity extends ImmutableObject {
@Id String name = "id";
@Type(type = "google.registry.persistence.CurrencyToBillingMapUserType")
Map<CurrencyUnit, BillingAccountEntry> currencyToBilling;
private TestEntity() {}
private TestEntity(Map<CurrencyUnit, BillingAccountEntry> currencyToBilling) {
this.currencyToBilling = currencyToBilling;
}
}
}
@@ -18,29 +18,27 @@ import static com.google.common.truth.Truth.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import com.google.common.collect.ImmutableSet;
import google.registry.model.eppcommon.StatusValue;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.hibernate.annotations.Type;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link EnumSetUserType}. */
/** Unit tests for {@link StatusValueSetConverter}. */
@RunWith(JUnit4.class)
public class EnumSetUserTypeTest {
public class StatusValueSetConverterTest {
@Rule
public final JpaUnitTestRule jpaRule =
new JpaTestRules.Builder().withEntityClass(TestEntity.class).buildUnitTestRule();
public EnumSetUserTypeTest() {}
@Test
public void testRoundTrip() {
Set<TestEnum> enums = ImmutableSet.of(TestEnum.BAR, TestEnum.FOO);
Set<StatusValue> enums = ImmutableSet.of(StatusValue.INACTIVE, StatusValue.PENDING_DELETE);
TestEntity obj = new TestEntity("foo", enums);
jpaTm().transact(() -> jpaTm().getEntityManager().persist(obj));
@@ -49,29 +47,15 @@ public class EnumSetUserTypeTest {
assertThat(persisted.data).isEqualTo(enums);
}
enum TestEnum {
FOO,
BAR,
BAZ;
public static class TestEnumType extends EnumSetUserType<TestEnum> {
@Override
protected Object convertToElem(Object value) {
return TestEnum.valueOf((String) value);
}
}
}
@Entity(name = "TestEntity")
static class TestEntity {
@Id String name;
@Type(type = "google.registry.persistence.EnumSetUserTypeTest$TestEnum$TestEnumType")
Set<TestEnum> data;
Set<StatusValue> data;
TestEntity() {}
TestEntity(String name, Set<TestEnum> data) {
TestEntity(String name, Set<StatusValue> data) {
this.name = name;
this.data = data;
}
@@ -26,15 +26,14 @@ import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NoResultException;
import org.hibernate.annotations.Type;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link StringListUserType}. */
/** Unit tests for {@link StringListConverter}. */
@RunWith(JUnit4.class)
public class StringListUserTypeTest {
public class StringListConverterTest {
@Rule
public final JpaUnitTestRule jpaRule =
new JpaTestRules.Builder().withEntityClass(TestEntity.class).buildUnitTestRule();
@@ -123,7 +122,6 @@ public class StringListUserTypeTest {
@Id String name = "id";
@Type(type = "google.registry.persistence.StringListUserType")
List<String> tlds;
private TestEntity() {}
@@ -24,15 +24,14 @@ import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.hibernate.annotations.Type;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link StringSetUserType}. */
/** Unit tests for {@link StringSetConverter}. */
@RunWith(JUnit4.class)
public class StringSetUserTypeTest {
public class StringSetConverterTest {
@Rule
public final JpaUnitTestRule jpaRule =
new JpaTestRules.Builder().withEntityClass(TestEntity.class).buildUnitTestRule();
@@ -70,7 +69,6 @@ public class StringSetUserTypeTest {
@Id String name = "id";
@Type(type = "google.registry.persistence.StringSetUserType")
Set<String> tlds;
private TestEntity() {}
@@ -0,0 +1,80 @@
// Copyright 2020 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.persistence;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import google.registry.model.ImmutableObject;
import google.registry.model.registrar.Registrar.State;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link Enumerated} annotation. */
@RunWith(JUnit4.class)
public class StringValueEnumeratedTest {
@Rule
public final JpaUnitTestRule jpaRule =
new JpaTestRules.Builder().withEntityClass(TestEntity.class).buildUnitTestRule();
@Test
public void roundTripConversion_returnsSameEnum() {
TestEntity testEntity = new TestEntity(State.ACTIVE);
jpaTm().transact(() -> jpaTm().getEntityManager().persist(testEntity));
TestEntity persisted =
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "id"));
assertThat(persisted.state).isEqualTo(State.ACTIVE);
}
@Test
public void testNativeQuery_succeeds() {
TestEntity testEntity = new TestEntity(State.DISABLED);
jpaTm().transact(() -> jpaTm().getEntityManager().persist(testEntity));
assertThat(
jpaTm()
.transact(
() ->
jpaTm()
.getEntityManager()
.createNativeQuery("SELECT state FROM \"TestEntity\" WHERE name = 'id'")
.getSingleResult()))
.isEqualTo("DISABLED");
}
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
private static class TestEntity extends ImmutableObject {
@Id String name = "id";
@Enumerated(EnumType.STRING)
State state;
private TestEntity() {}
private TestEntity(State state) {
this.state = state;
}
}
}
@@ -30,6 +30,7 @@ import google.registry.tools.UpdateReservedListCommandTest;
import google.registry.tools.server.CreatePremiumListActionTest;
import google.registry.tools.server.UpdatePremiumListActionTest;
import google.registry.ui.server.registrar.RegistryLockGetActionTest;
import google.registry.ui.server.registrar.RegistryLockVerifyActionTest;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;
@@ -60,6 +61,7 @@ import org.junit.runners.Suite.SuiteClasses;
PremiumListDaoTest.class,
RegistryLockDaoTest.class,
RegistryLockGetActionTest.class,
RegistryLockVerifyActionTest.class,
ReservedListDaoTest.class,
UnlockDomainCommandTest.class,
UpdatePremiumListActionTest.class,
@@ -202,4 +202,38 @@ public class PremiumListDaoTest {
() -> PremiumListDao.getPremiumPrice("foobar", Registry.get("tld")));
assertThat(thrown).hasMessageThat().isEqualTo("Could not load premium list 'tld'");
}
@Test
public void testGetPremiumPrice_worksForJPY() {
persistResource(
newRegistry("foobar", "FOOBAR")
.asBuilder()
.setPremiumListKey(
Key.create(
getCrossTldKey(),
google.registry.model.registry.label.PremiumList.class,
"premlist"))
.build());
PremiumListDao.saveNew(
PremiumList.create(
"premlist",
JPY,
ImmutableMap.of(
"silver",
BigDecimal.valueOf(10.00),
"gold",
BigDecimal.valueOf(1000.0),
"palladium",
BigDecimal.valueOf(15000))));
assertThat(PremiumListDao.getPremiumPrice("silver", Registry.get("foobar")))
.hasValue(moneyOf(JPY, 10));
assertThat(PremiumListDao.getPremiumPrice("gold", Registry.get("foobar")))
.hasValue(moneyOf(JPY, 1000));
assertThat(PremiumListDao.getPremiumPrice("palladium", Registry.get("foobar")))
.hasValue(moneyOf(JPY, 15000));
}
private static Money moneyOf(CurrencyUnit unit, double amount) {
return Money.of(unit, BigDecimal.valueOf(amount).setScale(unit.getDecimalPlaces()));
}
}
@@ -83,7 +83,9 @@ public final class RegistryTestServer {
route("/registrar-ote-setup", FrontendServlet.class),
route("/registrar-ote-status", FrontendServlet.class),
route("/registrar-settings", FrontendServlet.class),
route("/registry-lock-get", FrontendServlet.class));
route("/registry-lock-get", FrontendServlet.class),
route("/registry-lock-post", FrontendServlet.class),
route("/registry-lock-verify", FrontendServlet.class));
private static final ImmutableList<Class<? extends Filter>> FILTERS = ImmutableList.of(
ObjectifyFilter.class,
@@ -178,8 +178,7 @@ public class CreateReservedListCommandTest extends
@Test
public void testSaveToCloudSql_succeeds() throws Exception {
runCommandForced(
"--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath, "--also_cloud_sql");
runCommandForced("--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath);
verifyXnq9jyb4cInDatastore();
verifyXnq9jyb4cInCloudSql();
}
@@ -193,8 +192,7 @@ public class CreateReservedListCommandTest extends
"xn--q9jyb4c_common-reserved",
true,
ImmutableMap.of("testdomain", ReservedEntry.create(FULLY_BLOCKED, ""))));
runCommandForced(
"--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath, "--also_cloud_sql");
runCommandForced("--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath);
verifyXnq9jyb4cInDatastore();
}
@@ -38,8 +38,10 @@ import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCo
import google.registry.schema.domain.RegistryLock;
import google.registry.testing.AppEngineRule;
import google.registry.testing.DatastoreHelper;
import google.registry.testing.DeterministicStringGenerator;
import google.registry.testing.FakeClock;
import google.registry.testing.UserInfo;
import google.registry.util.StringGenerator.Alphabets;
import java.util.Set;
import java.util.stream.Collectors;
import org.joda.time.Duration;
@@ -57,6 +59,8 @@ public final class DomainLockUtilsTest {
private static final String POC_ID = "marla.singer@example.com";
private final FakeClock clock = new FakeClock();
private final DomainLockUtils domainLockUtils =
new DomainLockUtils(new DeterministicStringGenerator(Alphabets.BASE_58));
@Rule
public final AppEngineRule appEngineRule =
@@ -80,39 +84,39 @@ public final class DomainLockUtilsTest {
@Test
public void testSuccess_createLock() {
DomainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
domainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
}
@Test
public void testSuccess_createUnlock() {
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(
domainLockUtils.createRegistryLockRequest(
DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock);
DomainLockUtils.createRegistryUnlockRequest(DOMAIN_NAME, "TheRegistrar", false, clock);
domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock);
domainLockUtils.createRegistryUnlockRequest(DOMAIN_NAME, "TheRegistrar", false, clock);
}
@Test
public void testSuccess_createUnlock_adminUnlockingAdmin() {
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", null, true, clock);
DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, clock);
DomainLockUtils.createRegistryUnlockRequest(DOMAIN_NAME, "TheRegistrar", true, clock);
domainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", null, true, clock);
domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, clock);
domainLockUtils.createRegistryUnlockRequest(DOMAIN_NAME, "TheRegistrar", true, clock);
}
@Test
public void testSuccess_createLock_previousLockExpired() {
DomainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
domainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
clock.advanceBy(Duration.standardDays(1));
DomainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
domainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
}
@Test
public void testSuccess_applyLockDomain() {
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(
domainLockUtils.createRegistryLockRequest(
DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock);
domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock);
assertThat(reloadDomain().getStatusValues()).containsExactlyElementsIn(REGISTRY_LOCK_STATUSES);
HistoryEntry historyEntry = getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_UPDATE);
assertThat(historyEntry.getRequestedByRegistrar()).isTrue();
@@ -125,12 +129,12 @@ public final class DomainLockUtilsTest {
@Test
public void testSuccess_applyUnlockDomain() {
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(
domainLockUtils.createRegistryLockRequest(
DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock);
domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock);
RegistryLock unlock =
DomainLockUtils.createRegistryUnlockRequest(DOMAIN_NAME, "TheRegistrar", false, clock);
DomainLockUtils.verifyAndApplyUnlock(unlock.getVerificationCode(), false, clock);
domainLockUtils.createRegistryUnlockRequest(DOMAIN_NAME, "TheRegistrar", false, clock);
domainLockUtils.verifyAndApplyUnlock(unlock.getVerificationCode(), false, clock);
assertThat(reloadDomain().getStatusValues()).containsNoneIn(REGISTRY_LOCK_STATUSES);
ImmutableList<HistoryEntry> historyEntries =
@@ -149,8 +153,8 @@ public final class DomainLockUtilsTest {
@Test
public void testSuccess_applyAdminLock_onlyHistoryEntry() {
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", null, true, clock);
DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, clock);
domainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", null, true, clock);
domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, clock);
HistoryEntry historyEntry = getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_UPDATE);
assertThat(historyEntry.getRequestedByRegistrar()).isFalse();
@@ -161,16 +165,16 @@ public final class DomainLockUtilsTest {
@Test
public void testFailure_createUnlock_alreadyPendingUnlock() {
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(
domainLockUtils.createRegistryLockRequest(
DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock);
DomainLockUtils.createRegistryUnlockRequest(DOMAIN_NAME, "TheRegistrar", false, clock);
domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock);
domainLockUtils.createRegistryUnlockRequest(DOMAIN_NAME, "TheRegistrar", false, clock);
assertThat(
assertThrows(
IllegalArgumentException.class,
() ->
DomainLockUtils.createRegistryUnlockRequest(
domainLockUtils.createRegistryUnlockRequest(
DOMAIN_NAME, "TheRegistrar", false, clock)))
.hasMessageThat()
.isEqualTo("A pending unlock action already exists for example.tld");
@@ -179,13 +183,13 @@ public final class DomainLockUtilsTest {
@Test
public void testFailure_createUnlock_nonAdminUnlockingAdmin() {
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", null, true, clock);
DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, clock);
domainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", null, true, clock);
domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, clock);
assertThat(
assertThrows(
IllegalArgumentException.class,
() ->
DomainLockUtils.createRegistryUnlockRequest(
domainLockUtils.createRegistryUnlockRequest(
DOMAIN_NAME, "TheRegistrar", false, clock)))
.hasMessageThat()
.isEqualTo("Non-admin user cannot unlock admin-locked domain example.tld");
@@ -197,7 +201,7 @@ public final class DomainLockUtilsTest {
assertThrows(
IllegalArgumentException.class,
() ->
DomainLockUtils.createRegistryLockRequest(
domainLockUtils.createRegistryLockRequest(
"asdf.tld", "TheRegistrar", POC_ID, false, clock)))
.hasMessageThat()
.isEqualTo("Unknown domain asdf.tld");
@@ -205,12 +209,12 @@ public final class DomainLockUtilsTest {
@Test
public void testFailure_createLock_alreadyPendingLock() {
DomainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
domainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
assertThat(
assertThrows(
IllegalArgumentException.class,
() ->
DomainLockUtils.createRegistryLockRequest(
domainLockUtils.createRegistryLockRequest(
DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock)))
.hasMessageThat()
.isEqualTo("A pending or completed lock action already exists for example.tld");
@@ -223,7 +227,7 @@ public final class DomainLockUtilsTest {
assertThrows(
IllegalArgumentException.class,
() ->
DomainLockUtils.createRegistryLockRequest(
domainLockUtils.createRegistryLockRequest(
DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock)))
.hasMessageThat()
.isEqualTo("Domain example.tld is already locked");
@@ -235,7 +239,7 @@ public final class DomainLockUtilsTest {
assertThrows(
IllegalArgumentException.class,
() ->
DomainLockUtils.createRegistryUnlockRequest(
domainLockUtils.createRegistryUnlockRequest(
DOMAIN_NAME, "TheRegistrar", false, clock)))
.hasMessageThat()
.isEqualTo("Domain example.tld is already unlocked");
@@ -244,14 +248,14 @@ public final class DomainLockUtilsTest {
@Test
public void testFailure_applyLock_alreadyApplied() {
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(
domainLockUtils.createRegistryLockRequest(
DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock);
domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock);
domain = reloadDomain();
assertThat(
assertThrows(
IllegalArgumentException.class,
() -> DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock)))
() -> domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock)))
.hasMessageThat()
.isEqualTo("Domain example.tld is already locked");
assertNoDomainChanges();
@@ -260,13 +264,13 @@ public final class DomainLockUtilsTest {
@Test
public void testFailure_applyLock_expired() {
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(
domainLockUtils.createRegistryLockRequest(
DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
clock.advanceBy(Duration.standardDays(1));
assertThat(
assertThrows(
IllegalArgumentException.class,
() -> DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, clock)))
() -> domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, clock)))
.hasMessageThat()
.isEqualTo("The pending lock has expired; please try again");
assertNoDomainChanges();
@@ -275,11 +279,11 @@ public final class DomainLockUtilsTest {
@Test
public void testFailure_applyLock_nonAdmin_applyAdminLock() {
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", null, true, clock);
domainLockUtils.createRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", null, true, clock);
assertThat(
assertThrows(
IllegalArgumentException.class,
() -> DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock)))
() -> domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock)))
.hasMessageThat()
.isEqualTo("Non-admin user cannot complete admin lock");
assertNoDomainChanges();
@@ -288,18 +292,18 @@ public final class DomainLockUtilsTest {
@Test
public void testFailure_applyUnlock_alreadyUnlocked() {
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(
domainLockUtils.createRegistryLockRequest(
DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock);
domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false, clock);
RegistryLock unlock =
DomainLockUtils.createRegistryUnlockRequest(DOMAIN_NAME, "TheRegistrar", false, clock);
DomainLockUtils.verifyAndApplyUnlock(unlock.getVerificationCode(), false, clock);
domainLockUtils.createRegistryUnlockRequest(DOMAIN_NAME, "TheRegistrar", false, clock);
domainLockUtils.verifyAndApplyUnlock(unlock.getVerificationCode(), false, clock);
assertThat(
assertThrows(
IllegalArgumentException.class,
() ->
DomainLockUtils.verifyAndApplyUnlock(
domainLockUtils.verifyAndApplyUnlock(
unlock.getVerificationCode(), false, clock)))
.hasMessageThat()
.isEqualTo("Domain example.tld is already unlocked");
@@ -309,7 +313,7 @@ public final class DomainLockUtilsTest {
@Test
public void testFailure_applyLock_alreadyLocked() {
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(
domainLockUtils.createRegistryLockRequest(
DOMAIN_NAME, "TheRegistrar", POC_ID, false, clock);
String verificationCode = lock.getVerificationCode();
// reload to pick up modification times, etc
@@ -318,7 +322,7 @@ public final class DomainLockUtilsTest {
assertThat(
assertThrows(
IllegalArgumentException.class,
() -> DomainLockUtils.verifyAndApplyLock(verificationCode, false, clock)))
() -> domainLockUtils.verifyAndApplyLock(verificationCode, false, clock)))
.hasMessageThat()
.isEqualTo("Domain example.tld is already locked");
@@ -0,0 +1,39 @@
// Copyright 2020 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.tools;
import static com.google.common.truth.Truth.assertThat;
import java.io.File;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class DumpGoldenSchemaCommandTest extends CommandTestCase<DumpGoldenSchemaCommand> {
@Rule public TemporaryFolder tmp = new TemporaryFolder();
public DumpGoldenSchemaCommandTest() {}
@Test
public void testSchemaGeneration() throws Exception {
runCommand(
"--output=" + tmp.getRoot() + File.separatorChar + "golden.sql", "--start_postgresql");
assertThat(new File(tmp.getRoot(), "golden.sql").length()).isGreaterThan(1);
}
}
@@ -30,7 +30,9 @@ import google.registry.model.registrar.Registrar.Type;
import google.registry.model.registry.RegistryLockDao;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule;
import google.registry.testing.DeterministicStringGenerator;
import google.registry.testing.FakeClock;
import google.registry.util.StringGenerator.Alphabets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -51,6 +53,8 @@ public class LockDomainCommandTest extends CommandTestCase<LockDomainCommand> {
createTld("tld");
command.registryAdminClientId = "adminreg";
command.clock = new FakeClock();
command.domainLockUtils =
new DomainLockUtils(new DeterministicStringGenerator(Alphabets.BASE_58));
}
@Test
@@ -33,7 +33,9 @@ import google.registry.model.registry.RegistryLockDao;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule;
import google.registry.schema.domain.RegistryLock;
import google.registry.testing.DeterministicStringGenerator;
import google.registry.testing.FakeClock;
import google.registry.util.StringGenerator.Alphabets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -54,14 +56,16 @@ public class UnlockDomainCommandTest extends CommandTestCase<UnlockDomainCommand
createTld("tld");
command.registryAdminClientId = "adminreg";
command.clock = new FakeClock();
command.domainLockUtils =
new DomainLockUtils(new DeterministicStringGenerator(Alphabets.BASE_58));
}
private DomainBase persistLockedDomain(String domainName, String registrarId) {
DomainBase domain = persistResource(newDomainBase(domainName));
RegistryLock lock =
DomainLockUtils.createRegistryLockRequest(
command.domainLockUtils.createRegistryLockRequest(
domainName, registrarId, null, true, command.clock);
DomainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, command.clock);
command.domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, command.clock);
return reloadResource(domain);
}
@@ -116,20 +116,18 @@ public class UpdateReservedListCommandTest extends
public void testSaveToCloudSql_succeeds() throws Exception {
populateInitialReservedListInDatastore(true);
populateInitialReservedListInCloudSql(true);
runCommandForced(
"--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath, "--also_cloud_sql");
runCommandForced("--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath);
verifyXnq9jyb4cInDatastore();
verifyXnq9jyb4cInCloudSql();
}
@Test
public void testSaveToCloudSql_succeedsEvenPreviousListNotExist() throws Exception {
// Note that, during the dual-write phase, we just always save the revered list to
// Cloud SQL (if --also_cloud_sql is set) without checking if there is a list with
// same name. This is to backfill the existing list in Datastore when we update it.
// Note that, during the dual-write phase, we always save the reserved list to Cloud SQL without
// checking if there is a list with same name. This is to backfill the existing list in Cloud
// Datastore when we update it.
populateInitialReservedListInDatastore(true);
runCommandForced(
"--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath, "--also_cloud_sql");
runCommandForced("--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath);
verifyXnq9jyb4cInDatastore();
assertThat(ReservedListDao.checkExists("xn--q9jyb4c_common-reserved")).isTrue();
}
@@ -43,7 +43,6 @@ import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Rule;
@@ -97,7 +96,7 @@ public final class RegistryLockGetActionTest {
.setRepoId("repoId")
.setDomainName("example.test")
.setRegistrarId("TheRegistrar")
.setVerificationCode(UUID.randomUUID().toString())
.setVerificationCode("123456789ABCDEFGHJKLMNPQRSTUVWXY")
.setRegistrarPocId("johndoe@theregistrar.com")
.setLockCompletionTimestamp(fakeClock.nowUtc())
.build();
@@ -107,7 +106,7 @@ public final class RegistryLockGetActionTest {
.setRepoId("repoId")
.setDomainName("adminexample.test")
.setRegistrarId("TheRegistrar")
.setVerificationCode(UUID.randomUUID().toString())
.setVerificationCode("122222222ABCDEFGHJKLMNPQRSTUVWXY")
.isSuperuser(true)
.setLockCompletionTimestamp(fakeClock.nowUtc())
.build();
@@ -116,7 +115,7 @@ public final class RegistryLockGetActionTest {
.setRepoId("repoId")
.setDomainName("incomplete.test")
.setRegistrarId("TheRegistrar")
.setVerificationCode(UUID.randomUUID().toString())
.setVerificationCode("111111111ABCDEFGHJKLMNPQRSTUVWXY")
.setRegistrarPocId("johndoe@theregistrar.com")
.build();
@@ -126,7 +125,7 @@ public final class RegistryLockGetActionTest {
.setDomainName("unlocked.test")
.setRegistrarId("TheRegistrar")
.setRegistrarPocId("johndoe@theregistrar.com")
.setVerificationCode(UUID.randomUUID().toString())
.setVerificationCode("123456789ABCDEFGHJKLMNPQRSTUUUUU")
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setUnlockCompletionTimestamp(fakeClock.nowUtc())
@@ -0,0 +1,407 @@
// Copyright 2020 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.ui.server.registrar;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.loadRegistrar;
import static google.registry.testing.DatastoreHelper.newDomainBase;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import com.google.appengine.api.users.User;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSetMultimap;
import google.registry.model.domain.DomainBase;
import google.registry.model.registry.RegistryLockDao;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule;
import google.registry.request.JsonActionRunner;
import google.registry.request.JsonResponse;
import google.registry.request.ResponseImpl;
import google.registry.request.auth.AuthLevel;
import google.registry.request.auth.AuthResult;
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
import google.registry.request.auth.AuthenticatedRegistrarAccessor.Role;
import google.registry.request.auth.UserAuthInfo;
import google.registry.schema.domain.RegistryLock;
import google.registry.testing.AppEngineRule;
import google.registry.testing.DeterministicStringGenerator;
import google.registry.testing.FakeClock;
import google.registry.tools.DomainLockUtils;
import google.registry.util.EmailMessage;
import google.registry.util.SendEmailService;
import google.registry.util.StringGenerator.Alphabets;
import java.util.Map;
import java.util.UUID;
import javax.mail.internet.InternetAddress;
import javax.servlet.http.HttpServletResponse;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@RunWith(JUnit4.class)
public final class RegistryLockPostActionTest {
private static final String EMAIL_MESSAGE_TEMPLATE =
"Please click the link below to perform the lock \\/ unlock action on domain example.tld. "
+ "Note: this code will expire in one hour.\n\n"
+ "https:\\/\\/localhost\\/registry-lock-verify\\?lockVerificationCode="
+ "[0-9a-zA-Z_\\-]+&isLock=(true|false)";
@Rule public final AppEngineRule appEngineRule = AppEngineRule.builder().withDatastore().build();
@Rule
public final JpaIntegrationTestRule jpaRule =
new JpaTestRules.Builder().buildIntegrationTestRule();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
private final User userWithoutPermission =
new User("johndoe@theregistrar.com", "gmail.com", "31337");
// Marla Singer has registry lock auth permissions
private final User userWithLockPermission =
new User("Marla.Singer@crr.com", "gmail.com", "31337");
private final FakeClock clock = new FakeClock();
private InternetAddress outgoingAddress;
private DomainBase domain;
private RegistryLockPostAction action;
@Mock SendEmailService emailService;
@Mock HttpServletResponse mockResponse;
@Before
public void setup() throws Exception {
createTld("tld");
domain = persistResource(newDomainBase("example.tld"));
outgoingAddress = new InternetAddress("domain-registry@example.com");
action =
createAction(
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithLockPermission, false)));
}
@Test
public void testSuccess_lock() throws Exception {
Map<String, ?> response = action.handleJsonRequest(lockRequest());
assertSuccess(response, "lock", "Marla.Singer@crr.com");
}
@Test
public void testSuccess_unlock() throws Exception {
RegistryLockDao.save(
createLock().asBuilder().setLockCompletionTimestamp(clock.nowUtc()).build());
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
Map<String, ?> response = action.handleJsonRequest(unlockRequest());
assertSuccess(response, "unlock", "Marla.Singer@crr.com");
}
@Test
public void testSuccess_unlock_adminUnlockingAdmin() throws Exception {
RegistryLockDao.save(
createLock()
.asBuilder()
.isSuperuser(true)
.setLockCompletionTimestamp(clock.nowUtc())
.build());
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
action =
createAction(
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, true)));
Map<String, ?> response = action.handleJsonRequest(unlockRequest());
// we should still email the admin user's email address
assertSuccess(response, "unlock", "johndoe@theregistrar.com");
}
@Test
public void testFailure_unlock_noLock() {
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
Map<String, ?> response = action.handleJsonRequest(unlockRequest());
assertFailureWithMessage(response, "No lock object for domain example.tld");
}
@Test
public void testFailure_unlock_alreadyUnlocked() {
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
RegistryLockDao.save(
createLock()
.asBuilder()
.setLockCompletionTimestamp(clock.nowUtc())
.setUnlockRequestTimestamp(clock.nowUtc())
.build());
Map<String, ?> response = action.handleJsonRequest(unlockRequest());
assertFailureWithMessage(response, "A pending unlock action already exists for example.tld");
}
@Test
public void testFailure_unlock_nonAdminUnlockingAdmin() {
RegistryLockDao.save(
createLock()
.asBuilder()
.isSuperuser(true)
.setLockCompletionTimestamp(clock.nowUtc())
.build());
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
Map<String, ?> response = action.handleJsonRequest(unlockRequest());
assertFailureWithMessage(
response, "Non-admin user cannot unlock admin-locked domain example.tld");
}
@Test
public void testSuccess_adminUser() throws Exception {
// Admin user should be able to lock/unlock regardless -- and we use the admin user's email
action =
createAction(
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, true)));
Map<String, ?> response = action.handleJsonRequest(lockRequest());
assertSuccess(response, "lock", "johndoe@theregistrar.com");
}
@Test
public void testSuccess_adminUser_doesNotRequirePassword() throws Exception {
action =
createAction(
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, true)));
Map<String, ?> response =
action.handleJsonRequest(
ImmutableMap.of(
"clientId", "TheRegistrar",
"fullyQualifiedDomainName", "example.tld",
"isLock", true));
assertSuccess(response, "lock", "johndoe@theregistrar.com");
}
@Test
public void testFailure_noInput() {
Map<String, ?> response = action.handleJsonRequest(null);
assertFailureWithMessage(response, "Null JSON");
}
@Test
public void testFailure_noClientId() {
Map<String, ?> response = action.handleJsonRequest(ImmutableMap.of());
assertFailureWithMessage(response, "Missing key for client: clientId");
}
@Test
public void testFailure_emptyClientId() {
Map<String, ?> response = action.handleJsonRequest(ImmutableMap.of("clientId", ""));
assertFailureWithMessage(response, "Missing key for client: clientId");
}
@Test
public void testFailure_noDomainName() {
Map<String, ?> response =
action.handleJsonRequest(
ImmutableMap.of("clientId", "TheRegistrar", "password", "hi", "isLock", true));
assertFailureWithMessage(response, "Missing key for fullyQualifiedDomainName");
}
@Test
public void testFailure_noLockParam() {
Map<String, ?> response =
action.handleJsonRequest(
ImmutableMap.of(
"clientId", "TheRegistrar",
"fullyQualifiedDomainName", "example.tld",
"password", "hi"));
assertFailureWithMessage(response, "Missing key for isLock");
}
@Test
public void testFailure_notAllowedOnRegistrar() {
persistResource(
loadRegistrar("TheRegistrar").asBuilder().setRegistryLockAllowed(false).build());
Map<String, ?> response = action.handleJsonRequest(lockRequest());
assertFailureWithMessage(response, "Registry lock not allowed for this registrar");
}
@Test
public void testFailure_noPassword() {
Map<String, ?> response =
action.handleJsonRequest(
ImmutableMap.of(
"clientId", "TheRegistrar",
"fullyQualifiedDomainName", "example.tld",
"isLock", true));
assertFailureWithMessage(response, "Missing key for password");
}
@Test
public void testFailure_notEnabledForRegistrarContact() {
action =
createAction(
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, false)));
Map<String, ?> response =
action.handleJsonRequest(
ImmutableMap.of(
"clientId", "TheRegistrar",
"fullyQualifiedDomainName", "example.tld",
"isLock", true,
"password", "hi"));
assertFailureWithMessage(response, "Incorrect registry lock password for contact");
}
@Test
public void testFailure_badPassword() {
Map<String, ?> response =
action.handleJsonRequest(
ImmutableMap.of(
"clientId", "TheRegistrar",
"fullyQualifiedDomainName", "example.tld",
"isLock", true,
"password", "badPassword"));
assertFailureWithMessage(response, "Incorrect registry lock password for contact");
}
@Test
public void testFailure_invalidDomain() {
Map<String, ?> response =
action.handleJsonRequest(
ImmutableMap.of(
"clientId", "TheRegistrar",
"fullyQualifiedDomainName", "bad.tld",
"isLock", true,
"password", "hi"));
assertFailureWithMessage(response, "Unknown domain bad.tld");
}
@Test
public void testSuccess_previousLockUnlocked() throws Exception {
RegistryLockDao.save(
createLock()
.asBuilder()
.setLockCompletionTimestamp(clock.nowUtc().minusMinutes(1))
.setUnlockRequestTimestamp(clock.nowUtc().minusMinutes(1))
.setUnlockCompletionTimestamp(clock.nowUtc().minusMinutes(1))
.build());
Map<String, ?> response = action.handleJsonRequest(lockRequest());
assertSuccess(response, "lock", "Marla.Singer@crr.com");
}
@Test
public void testSuccess_previousLockExpired() throws Exception {
RegistryLock previousLock = RegistryLockDao.save(createLock());
previousLock = RegistryLockDao.getByVerificationCode(previousLock.getVerificationCode()).get();
clock.setTo(previousLock.getLockRequestTimestamp().plusHours(2));
Map<String, ?> response = action.handleJsonRequest(lockRequest());
assertSuccess(response, "lock", "Marla.Singer@crr.com");
}
@Test
public void testFailure_alreadyPendingLock() {
RegistryLockDao.save(createLock());
Map<String, ?> response = action.handleJsonRequest(lockRequest());
assertFailureWithMessage(
response, "A pending or completed lock action already exists for example.tld");
}
@Test
public void testFailure_alreadyLocked() {
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
Map<String, ?> response = action.handleJsonRequest(lockRequest());
assertFailureWithMessage(response, "Domain example.tld is already locked");
}
@Test
public void testFailure_alreadyUnlocked() {
Map<String, ?> response = action.handleJsonRequest(unlockRequest());
assertFailureWithMessage(response, "Domain example.tld is already unlocked");
}
private ImmutableMap<String, Object> lockRequest() {
return fullRequest(true);
}
private ImmutableMap<String, Object> unlockRequest() {
return fullRequest(false);
}
private ImmutableMap<String, Object> fullRequest(boolean lock) {
return ImmutableMap.of(
"isLock", lock,
"clientId", "TheRegistrar",
"fullyQualifiedDomainName", "example.tld",
"password", "hi");
}
private RegistryLock createLock() {
DomainBase domain = loadByForeignKey(DomainBase.class, "example.tld", clock.nowUtc()).get();
return new RegistryLock.Builder()
.setDomainName("example.tld")
.isSuperuser(false)
.setVerificationCode(UUID.randomUUID().toString())
.setRegistrarId("TheRegistrar")
.setRepoId(domain.getRepoId())
.setRegistrarPocId("Marla.Singer@crr.com")
.build();
}
private void assertSuccess(Map<String, ?> response, String lockAction, String recipient)
throws Exception {
assertThat(response)
.containsExactly(
"status", "SUCCESS",
"results", ImmutableList.of(),
"message", String.format("Successful %s", lockAction));
verifyEmail(recipient);
}
private void assertFailureWithMessage(Map<String, ?> response, String message) {
assertThat(response)
.containsExactly("status", "ERROR", "results", ImmutableList.of(), "message", message);
verifyNoMoreInteractions(emailService);
}
private void verifyEmail(String recipient) throws Exception {
ArgumentCaptor<EmailMessage> emailCaptor = ArgumentCaptor.forClass(EmailMessage.class);
verify(emailService).sendEmail(emailCaptor.capture());
EmailMessage sentMessage = emailCaptor.getValue();
assertThat(sentMessage.subject()).matches("Registry (un)?lock verification");
assertThat(sentMessage.body()).matches(EMAIL_MESSAGE_TEMPLATE);
assertThat(sentMessage.from()).isEqualTo(new InternetAddress("domain-registry@example.com"));
assertThat(sentMessage.recipients()).containsExactly(new InternetAddress(recipient));
}
private RegistryLockPostAction createAction(AuthResult authResult) {
AuthenticatedRegistrarAccessor registrarAccessor =
AuthenticatedRegistrarAccessor.createForTesting(
ImmutableSetMultimap.of("TheRegistrar", Role.OWNER, "NewRegistrar", Role.OWNER));
JsonActionRunner jsonActionRunner =
new JsonActionRunner(ImmutableMap.of(), new JsonResponse(new ResponseImpl(mockResponse)));
DomainLockUtils domainLockUtils =
new DomainLockUtils(new DeterministicStringGenerator(Alphabets.BASE_58));
return new RegistryLockPostAction(
jsonActionRunner,
authResult,
registrarAccessor,
emailService,
clock,
domainLockUtils,
outgoingAddress);
}
}
@@ -0,0 +1,351 @@
// Copyright 2020 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.ui.server.registrar;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.testing.DatastoreHelper.createTlds;
import static google.registry.testing.DatastoreHelper.getOnlyHistoryEntryOfType;
import static google.registry.testing.DatastoreHelper.newDomainBase;
import static google.registry.testing.DatastoreHelper.persistActiveHost;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.common.collect.ImmutableMap;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainBase;
import google.registry.model.host.HostResource;
import google.registry.model.registry.Registry;
import google.registry.model.registry.RegistryLockDao;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule;
import google.registry.request.auth.AuthLevel;
import google.registry.request.auth.AuthResult;
import google.registry.request.auth.UserAuthInfo;
import google.registry.schema.domain.RegistryLock;
import google.registry.security.XsrfTokenManager;
import google.registry.testing.AppEngineRule;
import google.registry.testing.DatastoreHelper;
import google.registry.testing.DeterministicStringGenerator;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse;
import google.registry.testing.InjectRule;
import google.registry.testing.UserInfo;
import google.registry.tools.DomainLockUtils;
import google.registry.util.StringGenerator;
import google.registry.util.StringGenerator.Alphabets;
import javax.servlet.http.HttpServletRequest;
import org.joda.time.Duration;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public final class RegistryLockVerifyActionTest {
private final FakeClock fakeClock = new FakeClock();
@Rule
public final AppEngineRule appEngineRule =
AppEngineRule.builder()
.withDatastore()
.withUserService(UserInfo.create("marla.singer@example.com", "12345"))
.build();
@Rule
public final JpaIntegrationWithCoverageRule jpaRule =
new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageRule();
@Rule public final InjectRule inject = new InjectRule();
private final HttpServletRequest request = mock(HttpServletRequest.class);
private final UserService userService = UserServiceFactory.getUserService();
private final User user = new User("marla.singer@example.com", "gmail.com", "12345");
private final String lockId = "123456789ABCDEFGHJKLMNPQRSTUVWXY";
private final StringGenerator stringGenerator =
new DeterministicStringGenerator(Alphabets.BASE_58);
private FakeResponse response;
private DomainBase domain;
private AuthResult authResult;
private RegistryLockVerifyAction action;
@Before
public void setup() {
createTlds("tld", "net");
HostResource host = persistActiveHost("ns1.example.net");
domain = persistResource(newDomainBase("example.tld", host));
when(request.getRequestURI()).thenReturn("https://registry.example/registry-lock-verification");
action = createAction(lockId, true);
}
@Test
public void testSuccess_lockDomain() {
RegistryLockDao.save(createLock());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(reloadDomain().getStatusValues()).containsExactlyElementsIn(REGISTRY_LOCK_STATUSES);
assertThat(response.getPayload()).contains("Success: lock has been applied to example.tld");
HistoryEntry historyEntry = getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_UPDATE);
assertThat(historyEntry.getRequestedByRegistrar()).isTrue();
assertThat(historyEntry.getBySuperuser()).isFalse();
assertThat(historyEntry.getReason())
.isEqualTo("Lock or unlock of a domain through a RegistryLock operation");
assertBillingEvent(historyEntry);
}
@Test
public void testSuccess_unlockDomain() {
action = createAction(lockId, false);
domain = persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
RegistryLockDao.save(
createLock().asBuilder().setUnlockRequestTimestamp(fakeClock.nowUtc()).build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(response.getPayload()).contains("Success: unlock has been applied to example.tld");
assertThat(reloadDomain().getStatusValues()).containsNoneIn(REGISTRY_LOCK_STATUSES);
HistoryEntry historyEntry = getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_UPDATE);
assertThat(historyEntry.getRequestedByRegistrar()).isTrue();
assertThat(historyEntry.getBySuperuser()).isFalse();
assertThat(historyEntry.getReason())
.isEqualTo("Lock or unlock of a domain through a RegistryLock operation");
assertBillingEvent(historyEntry);
}
@Test
public void testSuccess_adminLock_createsOnlyHistoryEntry() {
action.authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, true));
RegistryLockDao.save(createLock().asBuilder().isSuperuser(true).build());
action.run();
HistoryEntry historyEntry = getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_UPDATE);
assertThat(historyEntry.getRequestedByRegistrar()).isFalse();
assertThat(historyEntry.getBySuperuser()).isTrue();
DatastoreHelper.assertNoBillingEvents();
}
@Test
public void testFailure_badVerificationCode() {
RegistryLockDao.save(
createLock().asBuilder().setVerificationCode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").build());
action.run();
assertThat(response.getPayload()).contains("Failed: Invalid verification code");
assertNoDomainChanges();
}
@Test
public void testFailure_alreadyVerified() {
RegistryLockDao.save(
createLock().asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already locked");
assertNoDomainChanges();
}
@Test
public void testFailure_expired() {
RegistryLockDao.save(createLock());
fakeClock.advanceBy(Duration.standardHours(2));
action.run();
assertThat(response.getPayload())
.contains("Failed: The pending lock has expired; please try again");
assertNoDomainChanges();
}
@Test
public void testFailure_nonAdmin_verifyingAdminLock() {
RegistryLockDao.save(createLock().asBuilder().isSuperuser(true).build());
action.run();
assertThat(response.getPayload()).contains("Failed: Non-admin user cannot complete admin lock");
assertNoDomainChanges();
}
@Test
public void testFailure_alreadyUnlocked() {
action = createAction(lockId, false);
RegistryLockDao.save(
createLock()
.asBuilder()
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setUnlockCompletionTimestamp(fakeClock.nowUtc())
.build());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already unlocked");
assertNoDomainChanges();
}
@Test
public void testFailure_alreadyLocked() {
RegistryLockDao.save(createLock());
domain = persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already locked");
assertNoDomainChanges();
}
@Test
public void testFailure_notLoggedIn() {
action.authResult = AuthResult.NOT_AUTHENTICATED;
action.run();
assertThat(response.getStatus()).isEqualTo(SC_MOVED_TEMPORARILY);
assertThat(response.getHeaders()).containsKey("Location");
assertNoDomainChanges();
}
@Test
public void testFailure_doesNotChangeLockObject() {
// A failure when performing Datastore actions means that no actions should be taken in the
// Cloud SQL RegistryLock object
RegistryLock lock = createLock();
RegistryLockDao.save(lock);
// reload the lock to pick up creation time
lock = RegistryLockDao.getByVerificationCode(lock.getVerificationCode()).get();
fakeClock.advanceOneMilli();
domain = persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
action.run();
// we would have failed during the Datastore segment of the action
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already locked");
// verify that the changes to the SQL object were rolled back
RegistryLock afterAction =
RegistryLockDao.getByVerificationCode(lock.getVerificationCode()).get();
assertThat(afterAction).isEqualTo(lock);
}
@Test
public void testFailure_isLockTrue_shouldBeFalse() {
domain = persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
RegistryLockDao.save(
createLock()
.asBuilder()
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.build());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already locked");
}
@Test
public void testFailure_isLockFalse_shouldBeTrue() {
action = createAction(lockId, false);
RegistryLockDao.save(createLock());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already unlocked");
}
@Test
public void testFailure_lock_unlock_lockAgain() {
RegistryLock lock = RegistryLockDao.save(createLock());
action.run();
assertThat(response.getPayload()).contains("Success: lock has been applied to example.tld");
String unlockVerificationCode = "some-unlock-code";
RegistryLockDao.save(
lock.asBuilder()
.setVerificationCode(unlockVerificationCode)
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.build());
action = createAction(unlockVerificationCode, false);
action.run();
assertThat(response.getPayload()).contains("Success: unlock has been applied to example.tld");
action = createAction(lockId, true);
action.run();
assertThat(response.getPayload()).contains("Failed: Invalid verification code");
}
@Test
public void testFailure_lock_lockAgain() {
RegistryLockDao.save(createLock());
action.run();
assertThat(response.getPayload()).contains("Success: lock has been applied to example.tld");
action = createAction(lockId, true);
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already locked");
}
@Test
public void testFailure_unlock_unlockAgain() {
action = createAction(lockId, false);
domain = persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
RegistryLockDao.save(
createLock().asBuilder().setUnlockRequestTimestamp(fakeClock.nowUtc()).build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(response.getPayload()).contains("Success: unlock has been applied to example.tld");
action = createAction(lockId, false);
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already unlocked");
}
private RegistryLock createLock() {
return new RegistryLock.Builder()
.setDomainName("example.tld")
.setRegistrarId("TheRegistrar")
.setRepoId("repoId")
.setRegistrarPocId("marla.singer@example.com")
.isSuperuser(false)
.setVerificationCode(lockId)
.build();
}
private DomainBase reloadDomain() {
return ofy().load().entity(domain).now();
}
private void assertNoDomainChanges() {
assertThat(reloadDomain()).isEqualTo(domain);
}
private void assertBillingEvent(HistoryEntry historyEntry) {
DatastoreHelper.assertBillingEvents(
new BillingEvent.OneTime.Builder()
.setReason(Reason.SERVER_STATUS)
.setTargetId(domain.getForeignKey())
.setClientId(domain.getCurrentSponsorClientId())
.setCost(Registry.get(domain.getTld()).getServerStatusChangeCost())
.setEventTime(fakeClock.nowUtc())
.setBillingTime(fakeClock.nowUtc())
.setParent(historyEntry)
.build());
}
private RegistryLockVerifyAction createAction(String lockVerificationCode, Boolean isLock) {
response = new FakeResponse();
RegistryLockVerifyAction action =
new RegistryLockVerifyAction(
fakeClock, new DomainLockUtils(stringGenerator), lockVerificationCode, isLock);
authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
action.req = request;
action.response = response;
action.authResult = authResult;
action.userService = userService;
action.logoFilename = "logo.png";
action.productName = "Nomulus";
action.analyticsConfig = ImmutableMap.of("googleAnalyticsId", "sampleId");
action.xsrfTokenManager = new XsrfTokenManager(new FakeClock(), action.userService);
return action;
}
}
@@ -18,7 +18,9 @@ import static google.registry.server.Fixture.BASIC;
import static google.registry.server.Route.route;
import static google.registry.testing.AppEngineRule.makeRegistrar2;
import static google.registry.testing.AppEngineRule.makeRegistrarContact2;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.loadRegistrar;
import static google.registry.testing.DatastoreHelper.newDomainBase;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
@@ -26,7 +28,9 @@ import com.google.common.collect.ImmutableMap;
import com.googlecode.objectify.ObjectifyFilter;
import google.registry.model.ofy.OfyFilter;
import google.registry.model.registrar.Registrar.State;
import google.registry.model.registry.RegistryLockDao;
import google.registry.module.frontend.FrontendServlet;
import google.registry.schema.domain.RegistryLock;
import google.registry.server.RegistryTestServer;
import google.registry.testing.CertificateSamples;
import org.junit.Rule;
@@ -46,7 +50,8 @@ public class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
.setRoutes(
route("/registrar", FrontendServlet.class),
route("/registrar-ote-status", FrontendServlet.class),
route("/registrar-settings", FrontendServlet.class))
route("/registrar-settings", FrontendServlet.class),
route("/registry-lock-verify", FrontendServlet.class))
.setFilters(ObjectifyFilter.class, OfyFilter.class)
.setFixtures(BASIC)
.setEmail("Marla.Singer@google.com")
@@ -370,4 +375,36 @@ public class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
Thread.sleep(500);
driver.diffPage("page");
}
@Test
public void registryLockVerify_success() throws Throwable {
String lockVerificationCode = "f1be78a2-2d61-458c-80f0-9dd8f2f8625f";
server.runInAppEngineEnvironment(
() -> {
createTld("tld");
persistResource(newDomainBase("example.tld"));
RegistryLockDao.save(
new RegistryLock.Builder()
.setRegistrarPocId("johndoe@theregistrar.com")
.setRepoId("repoId")
.setRegistrarId("TheRegistrar")
.setVerificationCode("f1be78a2-2d61-458c-80f0-9dd8f2f8625f")
.isSuperuser(false)
.setDomainName("example.tld")
.build());
return null;
});
driver.get(
server.getUrl(
"/registry-lock-verify?isLock=true&lockVerificationCode=" + lockVerificationCode));
driver.waitForElement(By.id("reg-content"));
driver.diffPage("page");
}
@Test
public void registryLockVerify_unknownLock() throws Throwable {
driver.get(server.getUrl("/registry-lock-verify?isLock=true&lockVerificationCode=asdfasdf"));
driver.waitForElement(By.id("reg-content"));
driver.diffPage("page");
}
}
@@ -6,3 +6,5 @@ PATH CLASS METHODS OK AUTH_METHODS
/registrar-ote-status OteStatusAction POST n API,LEGACY USER PUBLIC
/registrar-settings RegistrarSettingsAction POST n API,LEGACY USER PUBLIC
/registry-lock-get RegistryLockGetAction GET n API,LEGACY USER PUBLIC
/registry-lock-post RegistryLockPostAction POST n API,LEGACY USER PUBLIC
/registry-lock-verify RegistryLockVerifyAction GET n API,LEGACY USER PUBLIC
@@ -0,0 +1,65 @@
-- Copyright 2020 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.
create table "Registrar" (
client_id text not null,
allowed_tlds text[],
billing_account_map hstore,
billing_identifier int8,
block_premium_names boolean not null,
client_certificate text,
client_certificate_hash text,
contacts_require_syncing boolean not null,
creation_time timestamptz,
drive_folder_id text,
email_address text,
failover_client_certificate text,
failover_client_certificate_hash text,
fax_number text,
iana_identifier int8,
icann_referral_email text,
i18n_address_city text,
i18n_address_country_code text,
i18n_address_state text,
i18n_address_street_line1 text,
i18n_address_street_line2 text,
i18n_address_street_line3 text,
i18n_address_zip text,
ip_address_whitelist text[],
last_certificate_update_time timestamptz,
last_update_time timestamptz,
localized_address_city text,
localized_address_country_code text,
localized_address_state text,
localized_address_street_line1 text,
localized_address_street_line2 text,
localized_address_street_line3 text,
localized_address_zip text,
password_hash text,
phone_number text,
phone_passcode text,
po_number text,
rdap_base_urls text[],
registrar_name text not null,
registry_lock_allowed boolean not null,
password_salt text,
state text,
type text not null,
url text,
whois_server text,
primary key (client_id)
);
create index registrar_name_idx on "Registrar" (registrar_name);
create index registrar_iana_identifier_idx on "Registrar" (iana_identifier);
@@ -0,0 +1,31 @@
-- Copyright 2020 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.
create table "RegistrarPoc" (
email_address text not null,
allowed_to_set_registry_lock_password boolean not null,
fax_number text,
gae_user_id text,
name text,
phone_number text,
registry_lock_password_hash text,
registry_lock_password_salt text,
types text[],
visible_in_domain_whois_as_abuse boolean not null,
visible_in_whois_as_admin boolean not null,
visible_in_whois_as_tech boolean not null,
primary key (email_address)
);
create index registrarpoc_gae_user_id_idx on "RegistrarPoc" (gae_user_id);
@@ -93,6 +93,71 @@
primary key (revision_id)
);
create table "Registrar" (
client_id text not null,
allowed_tlds text[],
billing_account_map hstore,
billing_identifier int8,
block_premium_names boolean not null,
client_certificate text,
client_certificate_hash text,
contacts_require_syncing boolean not null,
creation_time timestamptz,
drive_folder_id text,
email_address text,
failover_client_certificate text,
failover_client_certificate_hash text,
fax_number text,
iana_identifier int8,
icann_referral_email text,
i18n_address_city text,
i18n_address_country_code text,
i18n_address_state text,
i18n_address_street_line1 text,
i18n_address_street_line2 text,
i18n_address_street_line3 text,
i18n_address_zip text,
ip_address_whitelist text[],
last_certificate_update_time timestamptz,
last_update_time timestamptz,
localized_address_city text,
localized_address_country_code text,
localized_address_state text,
localized_address_street_line1 text,
localized_address_street_line2 text,
localized_address_street_line3 text,
localized_address_zip text,
password_hash text,
phone_number text,
phone_passcode text,
po_number text,
rdap_base_urls text[],
registrar_name text not null,
registry_lock_allowed boolean not null,
password_salt text,
state text,
type text not null,
url text,
whois_server text,
primary key (client_id)
);
create table "RegistrarPoc" (
email_address text not null,
allowed_to_set_registry_lock_password boolean not null,
fax_number text,
gae_user_id text,
name text,
phone_number text,
registry_lock_password_hash text,
registry_lock_password_salt text,
types text[],
visible_in_domain_whois_as_abuse boolean not null,
visible_in_whois_as_admin boolean not null,
visible_in_whois_as_tech boolean not null,
primary key (email_address)
);
create table "RegistryLock" (
revision_id bigserial not null,
domain_name text not null,
@@ -130,6 +195,9 @@ create index IDX5mnf0wn20tno4b9do88j61klr on "Domain" (deletion_time);
create index IDX1rcgkdd777bpvj0r94sltwd5y on "Domain" (fully_qualified_domain_name);
create index IDXrwl38wwkli1j7gkvtywi9jokq on "Domain" (tld);
create index premiumlist_name_idx on "PremiumList" (name);
create index registrar_name_idx on "Registrar" (registrar_name);
create index registrar_iana_identifier_idx on "Registrar" (iana_identifier);
create index registrarpoc_gae_user_id_idx on "RegistrarPoc" (gae_user_id);
create index idx_registry_lock_verification_code on "RegistryLock" (verification_code);
create index idx_registry_lock_registrar_id on "RegistryLock" (registrar_id);
@@ -159,6 +159,79 @@ CREATE SEQUENCE public."PremiumList_revision_id_seq"
ALTER SEQUENCE public."PremiumList_revision_id_seq" OWNED BY public."PremiumList".revision_id;
--
-- Name: Registrar; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public."Registrar" (
client_id text NOT NULL,
allowed_tlds text[],
billing_account_map public.hstore,
billing_identifier bigint,
block_premium_names boolean NOT NULL,
client_certificate text,
client_certificate_hash text,
contacts_require_syncing boolean NOT NULL,
creation_time timestamp with time zone,
drive_folder_id text,
email_address text,
failover_client_certificate text,
failover_client_certificate_hash text,
fax_number text,
iana_identifier bigint,
icann_referral_email text,
i18n_address_city text,
i18n_address_country_code text,
i18n_address_state text,
i18n_address_street_line1 text,
i18n_address_street_line2 text,
i18n_address_street_line3 text,
i18n_address_zip text,
ip_address_whitelist text[],
last_certificate_update_time timestamp with time zone,
last_update_time timestamp with time zone,
localized_address_city text,
localized_address_country_code text,
localized_address_state text,
localized_address_street_line1 text,
localized_address_street_line2 text,
localized_address_street_line3 text,
localized_address_zip text,
password_hash text,
phone_number text,
phone_passcode text,
po_number text,
rdap_base_urls text[],
registrar_name text NOT NULL,
registry_lock_allowed boolean NOT NULL,
password_salt text,
state text,
type text NOT NULL,
url text,
whois_server text
);
--
-- Name: RegistrarPoc; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public."RegistrarPoc" (
email_address text NOT NULL,
allowed_to_set_registry_lock_password boolean NOT NULL,
fax_number text,
gae_user_id text,
name text,
phone_number text,
registry_lock_password_hash text,
registry_lock_password_salt text,
types text[],
visible_in_domain_whois_as_abuse boolean NOT NULL,
visible_in_whois_as_admin boolean NOT NULL,
visible_in_whois_as_tech boolean NOT NULL
);
--
-- Name: RegistryLock; Type: TABLE; Schema: public; Owner: -
--
@@ -317,6 +390,22 @@ ALTER TABLE ONLY public."PremiumList"
ADD CONSTRAINT "PremiumList_pkey" PRIMARY KEY (revision_id);
--
-- Name: RegistrarPoc RegistrarPoc_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."RegistrarPoc"
ADD CONSTRAINT "RegistrarPoc_pkey" PRIMARY KEY (email_address);
--
-- Name: Registrar Registrar_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."Registrar"
ADD CONSTRAINT "Registrar_pkey" PRIMARY KEY (client_id);
--
-- Name: RegistryLock RegistryLock_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@@ -405,6 +494,27 @@ CREATE INDEX idxrwl38wwkli1j7gkvtywi9jokq ON public."Domain" USING btree (tld);
CREATE INDEX premiumlist_name_idx ON public."PremiumList" USING btree (name);
--
-- Name: registrar_iana_identifier_idx; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX registrar_iana_identifier_idx ON public."Registrar" USING btree (iana_identifier);
--
-- Name: registrar_name_idx; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX registrar_name_idx ON public."Registrar" USING btree (registrar_name);
--
-- Name: registrarpoc_gae_user_id_idx; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX registrarpoc_gae_user_id_idx ON public."RegistrarPoc" USING btree (gae_user_id);
--
-- Name: reservedlist_name_idx; Type: INDEX; Schema: public; Owner: -
--
+1
View File
@@ -115,6 +115,7 @@ spotless {
format 'misc', {
clearSteps()
target '**/*.gradle'
targetExclude '**/cloudbuild-caches/**'
trimTrailingWhitespace()
indentWithSpaces(2)
endWithNewline()
@@ -25,7 +25,7 @@ import com.google.common.collect.ImmutableList;
import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import google.registry.networking.util.SelfSignedCaCertificate;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -163,9 +163,9 @@ public final class CertificateSupplierModule {
@Singleton
@Provides
static SelfSignedCertificate provideSelfSignedCertificate() {
static SelfSignedCaCertificate provideSelfSignedCertificate() {
try {
return new SelfSignedCertificate();
return SelfSignedCaCertificate.create();
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -174,7 +174,7 @@ public final class CertificateSupplierModule {
@Singleton
@Provides
@SelfSigned
static Supplier<PrivateKey> provideSelfSignedPrivateKeySupplier(SelfSignedCertificate ssc) {
static Supplier<PrivateKey> provideSelfSignedPrivateKeySupplier(SelfSignedCaCertificate ssc) {
return Suppliers.ofInstance(ssc.key());
}
@@ -182,7 +182,7 @@ public final class CertificateSupplierModule {
@Provides
@SelfSigned
static Supplier<ImmutableList<X509Certificate>> provideSelfSignedCertificatesSupplier(
SelfSignedCertificate ssc) {
SelfSignedCaCertificate ssc) {
return Suppliers.ofInstance(ImmutableList.of(ssc.cert()));
}
@@ -0,0 +1,112 @@
// Copyright 2020 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.networking.util;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.Random;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
/** A self-signed certificate authority (CA) cert for use in tests. */
// TODO(weiminyu): make this class test-only. Requires refactor in proxy and prober.
public class SelfSignedCaCertificate {
private static final String DEFAULT_ISSUER_FQDN = "registry-test";
private static final Date DEFAULT_NOT_BEFORE =
Date.from(Instant.now().minus(Duration.ofHours(1)));
private static final Date DEFAULT_NOT_AFTER = Date.from(Instant.now().plus(Duration.ofDays(1)));
private static final Random RANDOM = new Random();
private static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider();
private static final KeyPairGenerator keyGen = createKeyPairGenerator();
private final PrivateKey privateKey;
private final X509Certificate cert;
public SelfSignedCaCertificate(PrivateKey privateKey, X509Certificate cert) {
this.privateKey = privateKey;
this.cert = cert;
}
public PrivateKey key() {
return privateKey;
}
public X509Certificate cert() {
return cert;
}
public static SelfSignedCaCertificate create() throws Exception {
return create(
keyGen.generateKeyPair(), DEFAULT_ISSUER_FQDN, DEFAULT_NOT_BEFORE, DEFAULT_NOT_AFTER);
}
public static SelfSignedCaCertificate create(String fqdn) throws Exception {
return create(fqdn, DEFAULT_NOT_BEFORE, DEFAULT_NOT_AFTER);
}
public static SelfSignedCaCertificate create(String fqdn, Date from, Date to) throws Exception {
return create(keyGen.generateKeyPair(), fqdn, from, to);
}
public static SelfSignedCaCertificate create(KeyPair keyPair, String fqdn, Date from, Date to)
throws Exception {
return new SelfSignedCaCertificate(keyPair.getPrivate(), createCaCert(keyPair, fqdn, from, to));
}
static KeyPairGenerator createKeyPairGenerator() {
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", PROVIDER);
keyGen.initialize(2048, new SecureRandom());
return keyGen;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/** Returns a self-signed Certificate Authority (CA) certificate. */
static X509Certificate createCaCert(KeyPair keyPair, String fqdn, Date from, Date to)
throws Exception {
X500Name owner = new X500Name("CN=" + fqdn);
ContentSigner signer =
new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(keyPair.getPrivate());
X509v3CertificateBuilder builder =
new JcaX509v3CertificateBuilder(
owner, new BigInteger(64, RANDOM), from, to, owner, keyPair.getPublic());
// Mark cert as CA by adding basicConstraint with cA=true to the builder
BasicConstraints basicConstraints = new BasicConstraints(true);
builder.addExtension(new ASN1ObjectIdentifier("2.5.29.19"), true, basicConstraints);
X509CertificateHolder certHolder = builder.build(signer);
return new JcaX509CertificateConverter().setProvider(PROVIDER).getCertificate(certHolder);
}
}
@@ -21,6 +21,7 @@ import static google.registry.networking.handler.SslInitializerTestUtils.signKey
import static google.registry.networking.handler.SslInitializerTestUtils.verifySslExcpetion;
import com.google.common.collect.ImmutableList;
import google.registry.networking.util.SelfSignedCaCertificate;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
@@ -35,7 +36,6 @@ import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.ssl.SslProvider;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.cert.CertPathBuilderException;
@@ -153,7 +153,7 @@ public class SslClientInitializerTest {
@Test
public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Exception {
SelfSignedCertificate ssc = new SelfSignedCertificate(SSL_HOST);
SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create(SSL_HOST);
LocalAddress localAddress =
new LocalAddress("DEFAULT_TRUST_MANAGER_REJECT_SELF_SIGNED_CERT_" + sslProvider);
nettyRule.setUpServer(localAddress, getServerHandler(false, ssc.key(), ssc.cert()));
@@ -177,7 +177,7 @@ public class SslClientInitializerTest {
KeyPair keyPair = getKeyPair();
// Generate a self signed certificate, and use it to sign the key pair.
SelfSignedCertificate ssc = new SelfSignedCertificate();
SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create();
X509Certificate cert = signKeyPair(ssc, keyPair, SSL_HOST);
// Set up the server to use the signed cert and private key to perform handshake;
@@ -206,7 +206,7 @@ public class SslClientInitializerTest {
KeyPair keyPair = getKeyPair();
// Generate a self signed certificate, and use it to sign the key pair.
SelfSignedCertificate ssc = new SelfSignedCertificate();
SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create();
X509Certificate cert =
signKeyPair(
ssc,
@@ -240,7 +240,7 @@ public class SslClientInitializerTest {
KeyPair keyPair = getKeyPair();
// Generate a self signed certificate, and use it to sign the key pair.
SelfSignedCertificate ssc = new SelfSignedCertificate();
SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create();
X509Certificate cert =
signKeyPair(
ssc,
@@ -272,8 +272,8 @@ public class SslClientInitializerTest {
new LocalAddress(
"CUSTOM_TRUST_MANAGER_ACCEPT_SELF_SIGNED_CERT_CLIENT_CERT_REQUIRED_" + sslProvider);
SelfSignedCertificate serverSsc = new SelfSignedCertificate(SSL_HOST);
SelfSignedCertificate clientSsc = new SelfSignedCertificate();
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate.create();
// Set up the server to require client certificate.
nettyRule.setUpServer(localAddress, getServerHandler(true, serverSsc.key(), serverSsc.cert()));
@@ -311,7 +311,7 @@ public class SslClientInitializerTest {
KeyPair keyPair = getKeyPair();
// Generate a self signed certificate, and use it to sign the key pair.
SelfSignedCertificate ssc = new SelfSignedCertificate();
SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create();
X509Certificate cert = signKeyPair(ssc, keyPair, "wrong.com");
// Set up the server to use the signed cert and private key to perform handshake;
@@ -18,15 +18,14 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import com.google.common.base.Throwables;
import google.registry.networking.util.SelfSignedCaCertificate;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
@@ -34,17 +33,13 @@ import java.util.Date;
import java.util.concurrent.ExecutionException;
import javax.net.ssl.SSLSession;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
/**
* Utility class that provides methods used by {@link SslClientInitializerTest} and {@link
@@ -52,16 +47,23 @@ import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
*/
public final class SslInitializerTestUtils {
static {
Security.addProvider(new BouncyCastleProvider());
}
private static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider();
private static final KeyPairGenerator KEY_PAIR_GENERATOR = getKeyPairGenerator();
private SslInitializerTestUtils() {}
private static KeyPairGenerator getKeyPairGenerator() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", PROVIDER);
keyPairGenerator.initialize(2048, new SecureRandom());
return keyPairGenerator;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static KeyPair getKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
keyPairGenerator.initialize(2048, new SecureRandom());
return keyPairGenerator.generateKeyPair();
return KEY_PAIR_GENERATOR.generateKeyPair();
}
/**
@@ -71,26 +73,20 @@ public final class SslInitializerTestUtils {
* @return signed public key (of the key pair) certificate
*/
public static X509Certificate signKeyPair(
SelfSignedCertificate ssc, KeyPair keyPair, String hostname, Date from, Date to)
SelfSignedCaCertificate ssc, KeyPair keyPair, String hostname, Date from, Date to)
throws Exception {
X500Name subjectDnName = new X500Name("CN=" + hostname);
BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
X500Name issuerDnName = new X500Name(ssc.cert().getIssuerDN().getName());
SubjectPublicKeyInfo subPubKeyInfo =
SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
AlgorithmIdentifier sigAlgId =
new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSAEncryption");
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
ContentSigner sigGen =
new BcRSAContentSignerBuilder(sigAlgId, digAlgId)
.build(PrivateKeyFactory.createKey(ssc.key().getEncoded()));
ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(ssc.key());
X509v3CertificateBuilder v3CertGen =
new X509v3CertificateBuilder(
issuerDnName, serialNumber, from, to, subjectDnName, subPubKeyInfo);
new JcaX509v3CertificateBuilder(
issuerDnName, serialNumber, from, to, subjectDnName, keyPair.getPublic());
X509CertificateHolder certificateHolder = v3CertGen.build(sigGen);
return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certificateHolder);
return new JcaX509CertificateConverter()
.setProvider(PROVIDER)
.getCertificate(certificateHolder);
}
/**
@@ -100,7 +96,7 @@ public final class SslInitializerTestUtils {
* @return signed public key (of the key pair) certificate
*/
public static X509Certificate signKeyPair(
SelfSignedCertificate ssc, KeyPair keyPair, String hostname) throws Exception {
SelfSignedCaCertificate ssc, KeyPair keyPair, String hostname) throws Exception {
return signKeyPair(
ssc,
keyPair,
@@ -23,6 +23,7 @@ import static google.registry.networking.handler.SslServerInitializer.CLIENT_CER
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import google.registry.networking.util.SelfSignedCaCertificate;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
@@ -33,7 +34,6 @@ import io.netty.handler.ssl.OpenSsl;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.ssl.SslProvider;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
@@ -127,7 +127,7 @@ public class SslServerInitializerTest {
@Test
public void testSuccess_swappedInitializerWithSslHandler() throws Exception {
SelfSignedCertificate ssc = new SelfSignedCertificate(SSL_HOST);
SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create(SSL_HOST);
SslServerInitializer<EmbeddedChannel> sslServerInitializer =
new SslServerInitializer<>(
true,
@@ -147,12 +147,12 @@ public class SslServerInitializerTest {
@Test
public void testSuccess_trustAnyClientCert() throws Exception {
SelfSignedCertificate serverSsc = new SelfSignedCertificate(SSL_HOST);
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
LocalAddress localAddress = new LocalAddress("TRUST_ANY_CLIENT_CERT_" + sslProvider);
nettyRule.setUpServer(
localAddress, getServerHandler(true, false, serverSsc.key(), serverSsc.cert()));
SelfSignedCertificate clientSsc = new SelfSignedCertificate();
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate.create();
nettyRule.setUpClient(
localAddress, getClientHandler(serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
@@ -168,13 +168,13 @@ public class SslServerInitializerTest {
@Test
public void testFailure_clientCertExpired() throws Exception {
SelfSignedCertificate serverSsc = new SelfSignedCertificate(SSL_HOST);
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
LocalAddress localAddress = new LocalAddress("CLIENT_CERT_EXPIRED_" + sslProvider);
nettyRule.setUpServer(
localAddress, getServerHandler(true, true, serverSsc.key(), serverSsc.cert()));
SelfSignedCertificate clientSsc =
new SelfSignedCertificate(
SelfSignedCaCertificate clientSsc =
SelfSignedCaCertificate.create(
"CLIENT",
Date.from(Instant.now().minus(Duration.ofDays(2))),
Date.from(Instant.now().minus(Duration.ofDays(1))));
@@ -189,13 +189,13 @@ public class SslServerInitializerTest {
@Test
public void testFailure_clientCertNotYetValid() throws Exception {
SelfSignedCertificate serverSsc = new SelfSignedCertificate(SSL_HOST);
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
LocalAddress localAddress = new LocalAddress("CLIENT_CERT_EXPIRED_" + sslProvider);
nettyRule.setUpServer(
localAddress, getServerHandler(true, true, serverSsc.key(), serverSsc.cert()));
SelfSignedCertificate clientSsc =
new SelfSignedCertificate(
SelfSignedCaCertificate clientSsc =
SelfSignedCaCertificate.create(
"CLIENT",
Date.from(Instant.now().plus(Duration.ofDays(1))),
Date.from(Instant.now().plus(Duration.ofDays(2))));
@@ -210,7 +210,7 @@ public class SslServerInitializerTest {
@Test
public void testSuccess_doesNotRequireClientCert() throws Exception {
SelfSignedCertificate serverSsc = new SelfSignedCertificate(SSL_HOST);
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
LocalAddress localAddress = new LocalAddress("DOES_NOT_REQUIRE_CLIENT_CERT_" + sslProvider);
nettyRule.setUpServer(
@@ -230,7 +230,7 @@ public class SslServerInitializerTest {
@Test
public void testSuccess_CertSignedByOtherCA() throws Exception {
// The self-signed cert of the CA.
SelfSignedCertificate caSsc = new SelfSignedCertificate();
SelfSignedCaCertificate caSsc = SelfSignedCaCertificate.create();
KeyPair keyPair = getKeyPair();
X509Certificate serverCert = signKeyPair(caSsc, keyPair, SSL_HOST);
LocalAddress localAddress = new LocalAddress("CERT_SIGNED_BY_OTHER_CA_" + sslProvider);
@@ -244,7 +244,7 @@ public class SslServerInitializerTest {
// Serving both the server cert, and the CA cert
serverCert,
caSsc.cert()));
SelfSignedCertificate clientSsc = new SelfSignedCertificate();
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate.create();
nettyRule.setUpClient(
localAddress,
getClientHandler(
@@ -263,7 +263,7 @@ public class SslServerInitializerTest {
@Test
public void testFailure_requireClientCertificate() throws Exception {
SelfSignedCertificate serverSsc = new SelfSignedCertificate(SSL_HOST);
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
LocalAddress localAddress = new LocalAddress("REQUIRE_CLIENT_CERT_" + sslProvider);
nettyRule.setUpServer(
@@ -285,12 +285,12 @@ public class SslServerInitializerTest {
@Test
public void testFailure_wrongHostnameInCertificate() throws Exception {
SelfSignedCertificate serverSsc = new SelfSignedCertificate("wrong.com");
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create("wrong.com");
LocalAddress localAddress = new LocalAddress("WRONG_HOSTNAME_" + sslProvider);
nettyRule.setUpServer(
localAddress, getServerHandler(true, false, serverSsc.key(), serverSsc.cert()));
SelfSignedCertificate clientSsc = new SelfSignedCertificate();
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate.create();
nettyRule.setUpClient(
localAddress, getClientHandler(serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
@@ -26,7 +26,7 @@ import dagger.Component;
import dagger.Module;
import dagger.Provides;
import google.registry.networking.module.CertificateSupplierModule.Mode;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import google.registry.networking.util.SelfSignedCaCertificate;
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import java.security.KeyPair;
@@ -47,7 +47,7 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class CertificateSupplierModuleTest {
private SelfSignedCertificate ssc;
private SelfSignedCaCertificate ssc;
private PrivateKey key;
private Certificate cert;
private TestComponent component;
@@ -62,7 +62,7 @@ public class CertificateSupplierModuleTest {
@Before
public void setUp() throws Exception {
ssc = new SelfSignedCertificate();
ssc = SelfSignedCaCertificate.create();
KeyPair keyPair = getKeyPair();
key = keyPair.getPrivate();
cert = signKeyPair(ssc, keyPair, "example.tld");
@@ -23,6 +23,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertThrows;
import com.google.common.base.Throwables;
import google.registry.networking.util.SelfSignedCaCertificate;
import google.registry.proxy.handler.HttpsRelayServiceHandler.NonOkHttpResponseException;
import google.registry.testing.FakeClock;
import io.netty.buffer.ByteBuf;
@@ -34,7 +35,6 @@ import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.cookie.Cookie;
import io.netty.handler.codec.http.cookie.DefaultCookie;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.util.concurrent.Promise;
import java.security.cert.X509Certificate;
import org.junit.Before;
@@ -123,7 +123,7 @@ public class EppProtocolModuleTest extends ProtocolModuleTest {
@Before
public void setUp() throws Exception {
testComponent = makeTestComponent(new FakeClock());
certificate = new SelfSignedCertificate().cert();
certificate = SelfSignedCaCertificate.create().cert();
initializeChannel(
ch -> {
ch.attr(REMOTE_ADDRESS_KEY).set(CLIENT_ADDRESS);
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import com.google.common.base.Throwables;
import google.registry.networking.util.SelfSignedCaCertificate;
import google.registry.proxy.TestUtils;
import google.registry.proxy.handler.HttpsRelayServiceHandler.NonOkHttpResponseException;
import google.registry.proxy.metric.FrontendMetrics;
@@ -41,7 +42,6 @@ import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.cookie.Cookie;
import io.netty.handler.codec.http.cookie.DefaultCookie;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.util.concurrent.Promise;
import java.security.cert.X509Certificate;
import org.junit.Before;
@@ -114,7 +114,7 @@ public class EppServiceHandlerTest {
@Before
public void setUp() throws Exception {
clientCertificate = new SelfSignedCertificate().cert();
clientCertificate = SelfSignedCaCertificate.create().cert();
channel = setUpNewChannel(eppServiceHandler);
}
@@ -179,7 +179,7 @@ public class EppServiceHandlerTest {
HELLO.getBytes(UTF_8),
metrics);
EmbeddedChannel channel2 = setUpNewChannel(eppServiceHandler2);
X509Certificate clientCertificate2 = new SelfSignedCertificate().cert();
X509Certificate clientCertificate2 = SelfSignedCaCertificate.create().cert();
setHandshakeSuccess(channel2, clientCertificate2);
String certHash2 = getCertificateHash(clientCertificate2);
+8
View File
@@ -29,6 +29,14 @@ environment="$1"
dest="$2"
gcs_prefix="storage.googleapis.com/domain-registry-maven-repository"
# Let Gradle put its caches (dependency cache and build cache) in the source
# tree. This allows sharing of the caches between steps in a Cloud Build
# task. (See ./cloudbuild-nomulus.yaml, which calls this script in several
# steps). If left at their default location, the caches will be lost after
# each step.
# Note: must be consistent with value in ./cloudbuild-nomulus.yaml
export GRADLE_USER_HOME="./cloudbuild-caches"
if [ "${environment}" == tool ]
then
mkdir -p "${dest}"
+18 -11
View File
@@ -12,16 +12,23 @@
#
# To trigger a build automatically, follow the instructions below and add a trigger:
# https://cloud.google.com/cloud-build/docs/running-builds/automate-builds
#
# Note: to work around issue in Spinnaker's 'Deployment Manifest' stage,
# variable references must avoid the ${var} format. Valid formats include
# $var or ${"${var}"}. This file use the former. Since TAG_NAME and _ENV are
# expanded in the copies sent to Spinnaker, we preserve the brackets around
# them for safe pattern matching during release.
# See https://github.com/spinnaker/spinnaker/issues/3028 for more information.
steps:
# Pull the credential for nomulus tool.
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
- name: 'gcr.io/$PROJECT_ID/builder:latest'
args:
- gsutil
- cp
- gs://${PROJECT_ID}-deploy/secrets/tool-credential.json.enc
- gs://$PROJECT_ID-deploy/secrets/tool-credential.json.enc
- .
# Decrypt the credential.
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
- name: 'gcr.io/$PROJECT_ID/builder:latest'
entrypoint: /bin/bash
args:
- -c
@@ -31,7 +38,7 @@ steps:
--ciphertext-file=- --plaintext-file=tool-credential.json \
--location=global --keyring=nomulus-tool-keyring --key=nomulus-tool-key
# Deploy the Spec11 pipeline to GCS.
- name: 'gcr.io/${PROJECT_ID}/nomulus-tool:latest'
- name: 'gcr.io/$PROJECT_ID/nomulus-tool:latest'
args:
- -e
- ${_ENV}
@@ -39,7 +46,7 @@ steps:
- tool-credential.json
- deploy_spec11_pipeline
# Deploy the invoicing pipeline to GCS.
- name: 'gcr.io/${PROJECT_ID}/nomulus-tool:latest'
- name: 'gcr.io/$PROJECT_ID/nomulus-tool:latest'
args:
- -e
- ${_ENV}
@@ -49,18 +56,18 @@ steps:
# Save the deployed tag for the current environment on GCS. Because of b/137891685
# which causes the for-loop in the next step to fail, this may not be the last step.
# TODO(weiminyu): do this in last step.
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
- name: 'gcr.io/$PROJECT_ID/builder:latest'
entrypoint: /bin/bash
args:
- -c
- |
set -e
echo ${TAG_NAME} | \
gsutil cp - gs://${PROJECT_ID}-deployed-tags/nomulus.${_ENV}.tag
gsutil cp - gs://$PROJECT_ID-deployed-tags/nomulus.${_ENV}.tag
# Deploy the GAE config files.
# First authorize the gcloud tool to use the credential json file, then
# download and unzip the tarball that contains the relevant config files
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
- name: 'gcr.io/$PROJECT_ID/builder:latest'
entrypoint: /bin/bash
args:
- -c
@@ -72,13 +79,13 @@ steps:
else
project_id="domain-registry-${_ENV}"
fi
gsutil cp gs://${PROJECT_ID}-deploy/${TAG_NAME}/${_ENV}.tar .
gsutil cp gs://$PROJECT_ID-deploy/${TAG_NAME}/${_ENV}.tar .
tar -xvf ${_ENV}.tar
# Note that this currently does not work for google.com projects that
# we use due to b/137891685. External projects are likely to work.
for filename in cron dispatch dos index queue; do
gcloud -q --project ${project_id} app deploy \
default/WEB-INF/appengine-generated/${filename}.yaml
gcloud -q --project $project_id app deploy \
default/WEB-INF/appengine-generated/$filename.yaml
done
timeout: 3600s
+12 -1
View File
@@ -21,7 +21,15 @@ steps:
args: ['mkdir', 'nomulus']
# Run tests
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
args: ['./gradlew', 'test', '-PskipDockerIncompatibleTests=true']
# Set home for Gradle caches. Must be consistent with last step below
# and ./build_nomulus_for_env.sh
env: [ 'GRADLE_USER_HOME=./cloudbuild-caches' ]
args: ['./gradlew',
'test',
'-PskipDockerIncompatibleTests=true',
'-PmavenUrl=https://storage.googleapis.com/domain-registry-maven-repository/maven',
'-PpluginsUrl=https://storage.googleapis.com/domain-registry-maven-repository/plugins'
]
# Build the tool binary and image.
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
args: ['release/build_nomulus_for_env.sh', 'tool', 'output']
@@ -70,6 +78,9 @@ steps:
# server/schema compatibility tests.
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
entrypoint: /bin/bash
# Set home for Gradle caches. Must be consistent with second step above
# and ./build_nomulus_for_env.sh
env: [ 'GRADLE_USER_HOME=./cloudbuild-caches' ]
args:
- -c
- |
+17 -9
View File
@@ -15,14 +15,22 @@
#
# Note that the release process hardens the tags and variables in this file:
# - The 'latest' tag on docker images will be replaced by their image digests.
# - The ${TAG_NAME} pattern will be replaced by the acutal release tag.
# - The ${TAG_NAME} pattern will be replaced by the actual release tag.
# - The ${_ENV} pattern will be replaced by the actual environment name.
# Please refer to ./cloudbuild-release.yaml for more details.
# Note 2: to work around issue in Spinnaker's 'Deployment Manifest' stage,
# variable references must avoid the ${var} format. Valid formats include
# $var or ${"${var}"}. This file use the former. Since TAG_NAME and _ENV are
# expanded in the copies sent to Spinnaker, we preserve the brackets around
# them for safe pattern matching during release.
# See https://github.com/spinnaker/spinnaker/issues/3028 for more information.
steps:
# Download and decrypt the nomulus tool credential, which has the privilege to
# start Cloud SQL proxy to all environments.
# Also download and decrypt the admin_credential file, which has the cloud
# instance name and database login name and password.
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
- name: 'gcr.io/$PROJECT_ID/builder:latest'
volumes:
- name: 'secrets'
path: '/secrets'
@@ -31,13 +39,13 @@ steps:
- -c
- |
set -e
gsutil cp gs://${PROJECT_ID}-deploy/secrets/tool-credential.json.enc - \
gsutil cp gs://$PROJECT_ID-deploy/secrets/tool-credential.json.enc - \
| base64 -d \
| gcloud kms decrypt \
--ciphertext-file=- \
--plaintext-file=/secrets/cloud_sql_credential.json \
--location=global --keyring=nomulus-tool-keyring --key=nomulus-tool-key
gsutil cp gs://${PROJECT_ID}-deploy/cloudsql-credentials/${_ENV}/admin_credential.enc - \
gsutil cp gs://$PROJECT_ID-deploy/cloudsql-credentials/${_ENV}/admin_credential.enc - \
| base64 -d \
| gcloud kms decrypt \
--ciphertext-file=- \
@@ -45,7 +53,7 @@ steps:
--location global --keyring=nomulus-tool-keyring \
--key=nomulus-tool-key
# Download the schema jar to be deployed.
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
- name: 'gcr.io/$PROJECT_ID/builder:latest'
volumes:
- name: 'flyway'
path: '/flyway/jars'
@@ -54,10 +62,10 @@ steps:
- -c
- |
set -e
gsutil cp gs://domain-registry-dev-deploy/${TAG_NAME}/schema.jar \
gsutil cp gs://$PROJECT_ID-deploy/${TAG_NAME}/schema.jar \
/flyway/jars
# Deploy SQL schema
- name: 'gcr.io/${PROJECT_ID}/schema_deployer:latest'
- name: 'gcr.io/$PROJECT_ID/schema_deployer:latest'
volumes:
- name: 'secrets'
path: '/secrets'
@@ -68,14 +76,14 @@ steps:
# location. Do not use the 'artifacts' section for this since it will
# upload an extra metadata file every time and pollute the folder.
# TODO(weiminyu): modify this step so that TAG_NAME may be 'live'.
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
- name: 'gcr.io/$PROJECT_ID/builder:latest'
entrypoint: /bin/bash
args:
- -c
- |
set -e
echo ${TAG_NAME} | \
gsutil cp - gs://${PROJECT_ID}-deployed-tags/sql.${_ENV}.tag\
gsutil cp - gs://$PROJECT_ID-deployed-tags/sql.${_ENV}.tag\
timeout: 3600s
options:
machineType: 'N1_HIGHCPU_8'
+10 -3
View File
@@ -9,16 +9,23 @@
#
# To trigger a build automatically, follow the instructions below and add a trigger:
# https://cloud.google.com/cloud-build/docs/running-builds/automate-builds
#
# Note: to work around issue in Spinnaker's 'Deployment Manifest' stage,
# variable references must avoid the ${var} format. Valid formats include
# $var or ${"${var}"}. This file use the former. Since TAG_NAME is
# expanded in the copies sent to Spinnaker, we preserve the brackets around
# them for safe pattern matching during release.
# See https://github.com/spinnaker/spinnaker/issues/3028 for more information.
steps:
# Rsync the folder.
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
- name: 'gcr.io/$PROJECT_ID/builder:latest'
args:
- gsutil
- -m
- rsync
- -d
- gs://${PROJECT_ID}-deploy/${TAG_NAME}
- gs://${PROJECT_ID}-deploy/live
- gs://$PROJECT_ID-deploy/${TAG_NAME}
- gs://$PROJECT_ID-deploy/live
timeout: 3600s
options:
machineType: 'N1_HIGHCPU_8'
+10 -3
View File
@@ -11,15 +11,22 @@
#
# To trigger a build automatically, follow the instructions below and add a trigger:
# https://cloud.google.com/cloud-build/docs/running-builds/automate-builds
#
# Note: to work around issue in Spinnaker's 'Deployment Manifest' stage,
# variable references must avoid the ${var} format. Valid formats include
# $var or ${"${var}"}. This file use the former. Since TAG_NAME is
# expanded in the copies sent to Spinnaker, we preserve the brackets around
# them for safe pattern matching during release.
# See https://github.com/spinnaker/spinnaker/issues/3028 for more information.
steps:
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
- name: 'gcr.io/$PROJECT_ID/builder:latest'
args:
- gcloud
- container
- images
- add-tag
- gcr.io/${PROJECT_ID}/${_IMAGE}:${TAG_NAME}
- gcr.io/${PROJECT_ID}/${_IMAGE}:live
- gcr.io/$PROJECT_ID/${_IMAGE}:${TAG_NAME}
- gcr.io/$PROJECT_ID/${_IMAGE}:live
timeout: 3600s
options:
machineType: 'N1_HIGHCPU_8'
@@ -18,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -95,22 +95,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -135,7 +135,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -157,10 +157,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -193,8 +193,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -203,6 +203,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hibernate.common:hibernate-commons-annotations:5.1.0.Final
@@ -18,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -95,22 +95,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -135,7 +135,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
io.grpc:grpc-netty:1.17.1
@@ -156,10 +156,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -192,8 +192,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -202,6 +202,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hibernate.common:hibernate-commons-annotations:5.1.0.Final
@@ -18,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-appengine:1.30.7
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.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api-client:google-api-client-servlet:1.30.7
com.google.api-client:google-api-client:1.30.7
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.38.0
@@ -95,22 +95,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.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-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-appengine:1.34.0
com.google.http-client:google-http-client-jackson2:1.32.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.30.1
com.google.http-client:google-http-client:1.34.0
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-appengine:1.30.5
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.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
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
@@ -135,7 +135,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.19.0
io.grpc:grpc-context:1.22.1
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -157,10 +157,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.21.0
io.opencensus:opencensus-api:0.24.0
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.21.0
io.opencensus:opencensus-contrib-http-util:0.24.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -193,8 +193,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.httpcomponents:httpclient:4.5.10
org.apache.httpcomponents:httpcore:4.4.12
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.8.1
@@ -203,6 +203,7 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13
org.codehaus.mojo:animal-sniffer-annotations:1.18
org.dom4j:dom4j:2.1.1
org.easymock:easymock:3.0
org.flywaydb:flyway-core:5.2.4
org.glassfish.jaxb:jaxb-runtime:2.3.1
org.glassfish.jaxb:txw2:2.3.1
org.hibernate.common:hibernate-commons-annotations:5.1.0.Final

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