1
0
mirror of https://github.com/google/nomulus synced 2026-07-14 20:12:19 +00:00

Compare commits

...

4 Commits

Author SHA1 Message Date
Shicong Huang d01f1f7604 Make jpaTm for nomulus tool use local credential (#515)
* Make jpaTm for nomulus tool use local credential

* Remove unused methods in RegistryToolEnvironment

* Fix order of annotations

* Remove unused method in PersistenceComponent

* Move the creation of credential to the module

* Move creadential creation to AuthModule

* Add a TODO
2020-03-17 20:16:42 -04:00
gbrodman e9610636e4 Add a relockDuration to the RegistryLock SQL object (#514)
* Add a relockDuration to the RegistryLock SQL object

This is the length of time after an unlock that we will re-lock the
domain in question.

* Sort by domain name for stability

Note: this is likely not the best solution for the UI but we can iterate
on this.

* Add nullable

* Add a converter for Duration
2020-03-16 17:44:25 -04:00
gbrodman d09fc7ee05 Match logged-in GAE user ID with registrar POC user ID (#511)
* Match logged-in GAE user ID with registrar POC user ID

The reasoning for this is thus:
We wish to have the users log in using Google-managed addresses--this is
so that we can manage enforcement of things like 2FA, as well as generic
account management. However, we wish for the registry-lock confirmation
emails to go to their standard non-Google email addresses--e.g.
johndoe@theregistrar.com, rather than johndoe@registry.google.

As a result, for registry lock, we will enable it on
the johndoe@registry.google account, but we will alter the email address
of the corresponding Registrar POC account to contain
johndoe@theregistrar.com. By doing this, the user will still be logging
in using the @registry.google account but we'll match to their actual
contact email.

* fix up comments and messages

* Error if >1 matching contact

* include email addresses

* set default optional

* fix tests
2020-03-16 11:38:05 -04:00
Shicong Huang 0545375eba Change cloud sql SDK to compile level dependency (#516) 2020-03-16 10:24:19 -04:00
39 changed files with 544 additions and 161 deletions
+2 -1
View File
@@ -197,7 +197,8 @@ dependencies {
compile deps['com.google.appengine:appengine-remote-api']
compile deps['com.google.auth:google-auth-library-credentials']
compile deps['com.google.auth:google-auth-library-oauth2-http']
runtimeOnly deps['com.google.cloud.sql:postgres-socket-factory']
compile deps['com.google.cloud.sql:jdbc-socket-factory-core']
compile deps['com.google.cloud.sql:postgres-socket-factory']
compile deps['com.google.code.gson:gson']
compile deps['com.google.auto.value:auto-value-annotations']
compile deps['com.google.code.findbugs:jsr305']
+15 -4
View File
@@ -10,6 +10,14 @@ 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.github.jnr:jffi:1.2.17
com.github.jnr:jnr-a64asm:1.0.0
com.github.jnr:jnr-constants:0.9.11
com.github.jnr:jnr-enxio:0.19
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-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
@@ -50,6 +58,7 @@ com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
com.google.apis:google-api-services-monitoring:v3-rev426-1.23.0
com.google.apis:google-api-services-pubsub:v1-rev20181105-1.27.0
com.google.apis:google-api-services-sheets:v4-rev483-1.22.0
com.google.apis:google-api-services-sqladmin:v1beta4-rev56-1.23.0
com.google.apis:google-api-services-storage:v1-rev20181109-1.27.0
com.google.appengine.tools:appengine-gcs-client:0.6
com.google.appengine.tools:appengine-mapreduce:0.9
@@ -65,6 +74,8 @@ com.google.cloud.bigdataoss:gcsio:1.9.16
com.google.cloud.bigdataoss:util:1.9.16
com.google.cloud.bigtable:bigtable-client-core:1.8.0
com.google.cloud.datastore:datastore-v1-proto-client:1.6.0
com.google.cloud.sql:jdbc-socket-factory-core:1.0.12
com.google.cloud.sql:postgres-socket-factory:1.0.12
com.google.cloud:google-cloud-bigquerystorage:0.79.0-alpha
com.google.cloud:google-cloud-bigtable-admin:0.73.0-alpha
com.google.cloud:google-cloud-bigtable:0.73.0-alpha
@@ -212,11 +223,11 @@ org.mockito:mockito-core:1.9.5
org.mortbay.jetty:jetty-util:6.1.26
org.mortbay.jetty:jetty:6.1.26
org.objenesis:objenesis:1.2
org.ow2.asm:asm-analysis:6.0
org.ow2.asm:asm-analysis:7.0
org.ow2.asm:asm-commons:6.0
org.ow2.asm:asm-tree:6.0
org.ow2.asm:asm-util:6.0
org.ow2.asm:asm:6.0
org.ow2.asm:asm-tree:7.0
org.ow2.asm:asm-util:7.0
org.ow2.asm:asm:7.0
org.rnorth.duct-tape:duct-tape:1.0.8
org.rnorth.visible-assertions:visible-assertions:2.1.2
org.rnorth:tcp-unix-socket-proxy:1.0.2
@@ -10,6 +10,14 @@ 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.github.jnr:jffi:1.2.17
com.github.jnr:jnr-a64asm:1.0.0
com.github.jnr:jnr-constants:0.9.11
com.github.jnr:jnr-enxio:0.19
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-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
@@ -50,6 +58,7 @@ com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
com.google.apis:google-api-services-monitoring:v3-rev426-1.23.0
com.google.apis:google-api-services-pubsub:v1-rev20181105-1.27.0
com.google.apis:google-api-services-sheets:v4-rev483-1.22.0
com.google.apis:google-api-services-sqladmin:v1beta4-rev56-1.23.0
com.google.apis:google-api-services-storage:v1-rev20181109-1.27.0
com.google.appengine.tools:appengine-gcs-client:0.6
com.google.appengine.tools:appengine-mapreduce:0.9
@@ -65,6 +74,8 @@ com.google.cloud.bigdataoss:gcsio:1.9.16
com.google.cloud.bigdataoss:util:1.9.16
com.google.cloud.bigtable:bigtable-client-core:1.8.0
com.google.cloud.datastore:datastore-v1-proto-client:1.6.0
com.google.cloud.sql:jdbc-socket-factory-core:1.0.12
com.google.cloud.sql:postgres-socket-factory:1.0.12
com.google.cloud:google-cloud-bigquerystorage:0.79.0-alpha
com.google.cloud:google-cloud-bigtable-admin:0.73.0-alpha
com.google.cloud:google-cloud-bigtable:0.73.0-alpha
@@ -207,11 +218,11 @@ org.jvnet.staxex:stax-ex:1.8
org.mortbay.jetty:jetty-util:6.1.26
org.mortbay.jetty:jetty:6.1.26
org.objenesis:objenesis:1.2
org.ow2.asm:asm-analysis:6.0
org.ow2.asm:asm-analysis:7.0
org.ow2.asm:asm-commons:6.0
org.ow2.asm:asm-tree:6.0
org.ow2.asm:asm-util:6.0
org.ow2.asm:asm:6.0
org.ow2.asm:asm-tree:7.0
org.ow2.asm:asm-util:7.0
org.ow2.asm:asm:7.0
org.rnorth.duct-tape:duct-tape:1.0.8
org.rnorth.visible-assertions:visible-assertions:2.1.2
org.rnorth:tcp-unix-socket-proxy:1.0.2
@@ -10,6 +10,14 @@ 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.github.jnr:jffi:1.2.17
com.github.jnr:jnr-a64asm:1.0.0
com.github.jnr:jnr-constants:0.9.11
com.github.jnr:jnr-enxio:0.19
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-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
@@ -50,6 +58,7 @@ com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
com.google.apis:google-api-services-monitoring:v3-rev426-1.23.0
com.google.apis:google-api-services-pubsub:v1-rev20181105-1.27.0
com.google.apis:google-api-services-sheets:v4-rev483-1.22.0
com.google.apis:google-api-services-sqladmin:v1beta4-rev56-1.23.0
com.google.apis:google-api-services-storage:v1-rev20181109-1.27.0
com.google.appengine.tools:appengine-gcs-client:0.6
com.google.appengine.tools:appengine-mapreduce:0.9
@@ -65,6 +74,8 @@ com.google.cloud.bigdataoss:gcsio:1.9.16
com.google.cloud.bigdataoss:util:1.9.16
com.google.cloud.bigtable:bigtable-client-core:1.8.0
com.google.cloud.datastore:datastore-v1-proto-client:1.6.0
com.google.cloud.sql:jdbc-socket-factory-core:1.0.12
com.google.cloud.sql:postgres-socket-factory:1.0.12
com.google.cloud:google-cloud-bigquerystorage:0.79.0-alpha
com.google.cloud:google-cloud-bigtable-admin:0.73.0-alpha
com.google.cloud:google-cloud-bigtable:0.73.0-alpha
@@ -212,11 +223,11 @@ org.mockito:mockito-core:1.9.5
org.mortbay.jetty:jetty-util:6.1.26
org.mortbay.jetty:jetty:6.1.26
org.objenesis:objenesis:1.2
org.ow2.asm:asm-analysis:6.0
org.ow2.asm:asm-analysis:7.0
org.ow2.asm:asm-commons:6.0
org.ow2.asm:asm-tree:6.0
org.ow2.asm:asm-util:6.0
org.ow2.asm:asm:6.0
org.ow2.asm:asm-tree:7.0
org.ow2.asm:asm-util:7.0
org.ow2.asm:asm:7.0
org.rnorth.duct-tape:duct-tape:1.0.8
org.rnorth.visible-assertions:visible-assertions:2.1.2
org.rnorth:tcp-unix-socket-proxy:1.0.2
@@ -10,6 +10,14 @@ 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.github.jnr:jffi:1.2.17
com.github.jnr:jnr-a64asm:1.0.0
com.github.jnr:jnr-constants:0.9.11
com.github.jnr:jnr-enxio:0.19
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-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
@@ -50,6 +58,7 @@ com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
com.google.apis:google-api-services-monitoring:v3-rev426-1.23.0
com.google.apis:google-api-services-pubsub:v1-rev20181105-1.27.0
com.google.apis:google-api-services-sheets:v4-rev483-1.22.0
com.google.apis:google-api-services-sqladmin:v1beta4-rev56-1.23.0
com.google.apis:google-api-services-storage:v1-rev20181109-1.27.0
com.google.appengine.tools:appengine-gcs-client:0.6
com.google.appengine.tools:appengine-mapreduce:0.9
@@ -65,6 +74,8 @@ com.google.cloud.bigdataoss:gcsio:1.9.16
com.google.cloud.bigdataoss:util:1.9.16
com.google.cloud.bigtable:bigtable-client-core:1.8.0
com.google.cloud.datastore:datastore-v1-proto-client:1.6.0
com.google.cloud.sql:jdbc-socket-factory-core:1.0.12
com.google.cloud.sql:postgres-socket-factory:1.0.12
com.google.cloud:google-cloud-bigquerystorage:0.79.0-alpha
com.google.cloud:google-cloud-bigtable-admin:0.73.0-alpha
com.google.cloud:google-cloud-bigtable:0.73.0-alpha
@@ -210,11 +221,11 @@ org.mockito:mockito-core:1.9.5
org.mortbay.jetty:jetty-util:6.1.26
org.mortbay.jetty:jetty:6.1.26
org.objenesis:objenesis:1.2
org.ow2.asm:asm-analysis:6.0
org.ow2.asm:asm-analysis:7.0
org.ow2.asm:asm-commons:6.0
org.ow2.asm:asm-tree:6.0
org.ow2.asm:asm-util:6.0
org.ow2.asm:asm:6.0
org.ow2.asm:asm-tree:7.0
org.ow2.asm:asm-util:7.0
org.ow2.asm:asm:7.0
org.rnorth.duct-tape:duct-tape:1.0.8
org.rnorth.visible-assertions:visible-assertions:2.1.2
org.rnorth:tcp-unix-socket-proxy:1.0.2
@@ -10,6 +10,14 @@ 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.github.jnr:jffi:1.2.17
com.github.jnr:jnr-a64asm:1.0.0
com.github.jnr:jnr-constants:0.9.11
com.github.jnr:jnr-enxio:0.19
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-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
@@ -50,6 +58,7 @@ com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
com.google.apis:google-api-services-monitoring:v3-rev426-1.23.0
com.google.apis:google-api-services-pubsub:v1-rev20181105-1.27.0
com.google.apis:google-api-services-sheets:v4-rev483-1.22.0
com.google.apis:google-api-services-sqladmin:v1beta4-rev56-1.23.0
com.google.apis:google-api-services-storage:v1-rev20181109-1.27.0
com.google.appengine.tools:appengine-gcs-client:0.6
com.google.appengine.tools:appengine-mapreduce:0.9
@@ -65,6 +74,8 @@ com.google.cloud.bigdataoss:gcsio:1.9.16
com.google.cloud.bigdataoss:util:1.9.16
com.google.cloud.bigtable:bigtable-client-core:1.8.0
com.google.cloud.datastore:datastore-v1-proto-client:1.6.0
com.google.cloud.sql:jdbc-socket-factory-core:1.0.12
com.google.cloud.sql:postgres-socket-factory:1.0.12
com.google.cloud:google-cloud-bigquerystorage:0.79.0-alpha
com.google.cloud:google-cloud-bigtable-admin:0.73.0-alpha
com.google.cloud:google-cloud-bigtable:0.73.0-alpha
@@ -212,11 +223,11 @@ org.mockito:mockito-core:1.9.5
org.mortbay.jetty:jetty-util:6.1.26
org.mortbay.jetty:jetty:6.1.26
org.objenesis:objenesis:1.2
org.ow2.asm:asm-analysis:6.0
org.ow2.asm:asm-analysis:7.0
org.ow2.asm:asm-commons:6.0
org.ow2.asm:asm-tree:6.0
org.ow2.asm:asm-util:6.0
org.ow2.asm:asm:6.0
org.ow2.asm:asm-tree:7.0
org.ow2.asm:asm-util:7.0
org.ow2.asm:asm:7.0
org.postgresql:postgresql:42.2.6
org.rnorth.duct-tape:duct-tape:1.0.8
org.rnorth.visible-assertions:visible-assertions:2.1.2
@@ -10,6 +10,14 @@ 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.github.jnr:jffi:1.2.17
com.github.jnr:jnr-a64asm:1.0.0
com.github.jnr:jnr-constants:0.9.11
com.github.jnr:jnr-enxio:0.19
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-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
@@ -50,6 +58,7 @@ com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
com.google.apis:google-api-services-monitoring:v3-rev426-1.23.0
com.google.apis:google-api-services-pubsub:v1-rev20181105-1.27.0
com.google.apis:google-api-services-sheets:v4-rev483-1.22.0
com.google.apis:google-api-services-sqladmin:v1beta4-rev56-1.23.0
com.google.apis:google-api-services-storage:v1-rev20181109-1.27.0
com.google.appengine.tools:appengine-gcs-client:0.6
com.google.appengine.tools:appengine-mapreduce:0.9
@@ -65,6 +74,8 @@ com.google.cloud.bigdataoss:gcsio:1.9.16
com.google.cloud.bigdataoss:util:1.9.16
com.google.cloud.bigtable:bigtable-client-core:1.8.0
com.google.cloud.datastore:datastore-v1-proto-client:1.6.0
com.google.cloud.sql:jdbc-socket-factory-core:1.0.12
com.google.cloud.sql:postgres-socket-factory:1.0.12
com.google.cloud:google-cloud-bigquerystorage:0.79.0-alpha
com.google.cloud:google-cloud-bigtable-admin:0.73.0-alpha
com.google.cloud:google-cloud-bigtable:0.73.0-alpha
@@ -212,11 +223,11 @@ org.mockito:mockito-core:1.9.5
org.mortbay.jetty:jetty-util:6.1.26
org.mortbay.jetty:jetty:6.1.26
org.objenesis:objenesis:1.2
org.ow2.asm:asm-analysis:6.0
org.ow2.asm:asm-analysis:7.0
org.ow2.asm:asm-commons:6.0
org.ow2.asm:asm-tree:6.0
org.ow2.asm:asm-util:6.0
org.ow2.asm:asm:6.0
org.ow2.asm:asm-tree:7.0
org.ow2.asm:asm-util:7.0
org.ow2.asm:asm:7.0
org.postgresql:postgresql:42.2.6
org.rnorth.duct-tape:duct-tape:1.0.8
org.rnorth.visible-assertions:visible-assertions:2.1.2
+15 -4
View File
@@ -10,6 +10,14 @@ 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.github.jnr:jffi:1.2.17
com.github.jnr:jnr-a64asm:1.0.0
com.github.jnr:jnr-constants:0.9.11
com.github.jnr:jnr-enxio:0.19
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-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
@@ -50,6 +58,7 @@ com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
com.google.apis:google-api-services-monitoring:v3-rev426-1.23.0
com.google.apis:google-api-services-pubsub:v1-rev20181105-1.27.0
com.google.apis:google-api-services-sheets:v4-rev483-1.22.0
com.google.apis:google-api-services-sqladmin:v1beta4-rev56-1.23.0
com.google.apis:google-api-services-storage:v1-rev20181109-1.27.0
com.google.appengine.tools:appengine-gcs-client:0.6
com.google.appengine.tools:appengine-mapreduce:0.9
@@ -65,6 +74,8 @@ com.google.cloud.bigdataoss:gcsio:1.9.16
com.google.cloud.bigdataoss:util:1.9.16
com.google.cloud.bigtable:bigtable-client-core:1.8.0
com.google.cloud.datastore:datastore-v1-proto-client:1.6.0
com.google.cloud.sql:jdbc-socket-factory-core:1.0.12
com.google.cloud.sql:postgres-socket-factory:1.0.12
com.google.cloud:google-cloud-bigquerystorage:0.79.0-alpha
com.google.cloud:google-cloud-bigtable-admin:0.73.0-alpha
com.google.cloud:google-cloud-bigtable:0.73.0-alpha
@@ -212,11 +223,11 @@ org.mockito:mockito-core:1.9.5
org.mortbay.jetty:jetty-util:6.1.26
org.mortbay.jetty:jetty:6.1.26
org.objenesis:objenesis:1.2
org.ow2.asm:asm-analysis:6.0
org.ow2.asm:asm-analysis:7.0
org.ow2.asm:asm-commons:6.0
org.ow2.asm:asm-tree:6.0
org.ow2.asm:asm-util:6.0
org.ow2.asm:asm:6.0
org.ow2.asm:asm-tree:7.0
org.ow2.asm:asm-util:7.0
org.ow2.asm:asm:7.0
org.postgresql:postgresql:42.2.6
org.rnorth.duct-tape:duct-tape:1.0.8
org.rnorth.visible-assertions:visible-assertions:2.1.2
@@ -10,6 +10,14 @@ 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.github.jnr:jffi:1.2.17
com.github.jnr:jnr-a64asm:1.0.0
com.github.jnr:jnr-constants:0.9.11
com.github.jnr:jnr-enxio:0.19
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-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
@@ -50,6 +58,7 @@ com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
com.google.apis:google-api-services-monitoring:v3-rev426-1.23.0
com.google.apis:google-api-services-pubsub:v1-rev20181105-1.27.0
com.google.apis:google-api-services-sheets:v4-rev483-1.22.0
com.google.apis:google-api-services-sqladmin:v1beta4-rev56-1.23.0
com.google.apis:google-api-services-storage:v1-rev20181109-1.27.0
com.google.appengine.tools:appengine-gcs-client:0.6
com.google.appengine.tools:appengine-mapreduce:0.9
@@ -66,6 +75,8 @@ com.google.cloud.bigdataoss:gcsio:1.9.16
com.google.cloud.bigdataoss:util:1.9.16
com.google.cloud.bigtable:bigtable-client-core:1.8.0
com.google.cloud.datastore:datastore-v1-proto-client:1.6.0
com.google.cloud.sql:jdbc-socket-factory-core:1.0.12
com.google.cloud.sql:postgres-socket-factory:1.0.12
com.google.cloud:google-cloud-bigquerystorage:0.79.0-alpha
com.google.cloud:google-cloud-bigtable-admin:0.73.0-alpha
com.google.cloud:google-cloud-bigtable:0.73.0-alpha
@@ -244,11 +255,11 @@ org.mortbay.jetty:jetty-util:6.1.26
org.mortbay.jetty:jetty:6.1.26
org.objenesis:objenesis:2.6
org.opentest4j:opentest4j:1.2.0
org.ow2.asm:asm-analysis:6.0
org.ow2.asm:asm-analysis:7.0
org.ow2.asm:asm-commons:6.0
org.ow2.asm:asm-tree:6.0
org.ow2.asm:asm-util:6.0
org.ow2.asm:asm:6.0
org.ow2.asm:asm-tree:7.0
org.ow2.asm:asm-util:7.0
org.ow2.asm:asm:7.0
org.rnorth.duct-tape:duct-tape:1.0.8
org.rnorth.visible-assertions:visible-assertions:2.1.2
org.rnorth:tcp-unix-socket-proxy:1.0.2
@@ -10,6 +10,14 @@ 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.github.jnr:jffi:1.2.17
com.github.jnr:jnr-a64asm:1.0.0
com.github.jnr:jnr-constants:0.9.11
com.github.jnr:jnr-enxio:0.19
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-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
@@ -50,6 +58,7 @@ com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
com.google.apis:google-api-services-monitoring:v3-rev426-1.23.0
com.google.apis:google-api-services-pubsub:v1-rev20181105-1.27.0
com.google.apis:google-api-services-sheets:v4-rev483-1.22.0
com.google.apis:google-api-services-sqladmin:v1beta4-rev56-1.23.0
com.google.apis:google-api-services-storage:v1-rev20181109-1.27.0
com.google.appengine.tools:appengine-gcs-client:0.6
com.google.appengine.tools:appengine-mapreduce:0.9
@@ -66,6 +75,8 @@ com.google.cloud.bigdataoss:gcsio:1.9.16
com.google.cloud.bigdataoss:util:1.9.16
com.google.cloud.bigtable:bigtable-client-core:1.8.0
com.google.cloud.datastore:datastore-v1-proto-client:1.6.0
com.google.cloud.sql:jdbc-socket-factory-core:1.0.12
com.google.cloud.sql:postgres-socket-factory:1.0.12
com.google.cloud:google-cloud-bigquerystorage:0.79.0-alpha
com.google.cloud:google-cloud-bigtable-admin:0.73.0-alpha
com.google.cloud:google-cloud-bigtable:0.73.0-alpha
@@ -242,11 +253,11 @@ org.mortbay.jetty:jetty-util:6.1.26
org.mortbay.jetty:jetty:6.1.26
org.objenesis:objenesis:2.6
org.opentest4j:opentest4j:1.2.0
org.ow2.asm:asm-analysis:6.0
org.ow2.asm:asm-analysis:7.0
org.ow2.asm:asm-commons:6.0
org.ow2.asm:asm-tree:6.0
org.ow2.asm:asm-util:6.0
org.ow2.asm:asm:6.0
org.ow2.asm:asm-tree:7.0
org.ow2.asm:asm-util:7.0
org.ow2.asm:asm:7.0
org.rnorth.duct-tape:duct-tape:1.0.8
org.rnorth.visible-assertions:visible-assertions:2.1.2
org.rnorth:tcp-unix-socket-proxy:1.0.2
@@ -52,8 +52,10 @@ public final class RegistryLockDao {
jpaTm()
.getEntityManager()
.createQuery(
"SELECT lock FROM RegistryLock lock WHERE lock.registrarId = :registrarId"
+ " AND lock.unlockCompletionTimestamp IS NULL",
"SELECT lock FROM RegistryLock lock"
+ " WHERE lock.registrarId = :registrarId"
+ " AND lock.unlockCompletionTimestamp IS NULL"
+ " ORDER BY lock.domainName ASC",
RegistryLock.class)
.setParameter("registrarId", registrarId)
.getResultList());
@@ -19,7 +19,6 @@ import google.registry.config.CredentialModule;
import google.registry.config.RegistryConfig.ConfigModule;
import google.registry.keyring.kms.KmsModule;
import google.registry.persistence.PersistenceModule.AppEngineJpaTm;
import google.registry.persistence.PersistenceModule.NomulusToolJpaTm;
import google.registry.persistence.transaction.JpaTransactionManager;
import google.registry.util.UtilsModule;
import javax.inject.Singleton;
@@ -39,7 +38,4 @@ public interface PersistenceComponent {
@AppEngineJpaTm
JpaTransactionManager appEngineJpaTransactionManager();
@NomulusToolJpaTm
JpaTransactionManager nomulusToolJpaTransactionManager();
}
@@ -22,6 +22,7 @@ import static google.registry.config.RegistryConfig.getHibernateHikariMaximumPoo
import static google.registry.config.RegistryConfig.getHibernateHikariMinimumIdle;
import static google.registry.config.RegistryConfig.getHibernateLogSqlQueries;
import com.google.api.client.auth.oauth2.Credential;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
@@ -29,8 +30,10 @@ import dagger.Module;
import dagger.Provides;
import google.registry.config.RegistryConfig.Config;
import google.registry.keyring.kms.KmsKeyring;
import google.registry.persistence.transaction.CloudSqlCredentialSupplier;
import google.registry.persistence.transaction.JpaTransactionManager;
import google.registry.persistence.transaction.JpaTransactionManagerImpl;
import google.registry.tools.AuthModule.CloudSqlClientCredential;
import google.registry.util.Clock;
import java.lang.annotation.Documented;
import java.util.HashMap;
@@ -118,7 +121,9 @@ public class PersistenceModule {
@Config("toolsCloudSqlUsername") String username,
KmsKeyring kmsKeyring,
@PartialCloudSqlConfigs ImmutableMap<String, String> cloudSqlConfigs,
@CloudSqlClientCredential Credential credential,
Clock clock) {
CloudSqlCredentialSupplier.setupCredentialSupplier(credential);
HashMap<String, String> overrides = Maps.newHashMap(cloudSqlConfigs);
overrides.put(Environment.USER, username);
overrides.put(Environment.PASS, kmsKeyring.getToolsCloudSqlPassword());
@@ -158,7 +163,7 @@ public class PersistenceModule {
/** Dagger qualifier for {@link JpaTransactionManager} used for Nomulus tool. */
@Qualifier
@Documented
@interface NomulusToolJpaTm {}
public @interface NomulusToolJpaTm {}
/** Dagger qualifier for the partial Cloud SQL configs. */
@Qualifier
@@ -0,0 +1,37 @@
// 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.converter;
import javax.annotation.Nullable;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import org.joda.time.Duration;
/** JPA converter to for storing/retrieving {@link org.joda.time.DateTime} objects. */
@Converter(autoApply = true)
public class DurationConverter implements AttributeConverter<Duration, Long> {
@Override
@Nullable
public Long convertToDatabaseColumn(@Nullable Duration duration) {
return duration == null ? null : duration.getMillis();
}
@Override
@Nullable
public Duration convertToEntityAttribute(@Nullable Long dbData) {
return dbData == null ? null : new Duration(dbData);
}
}
@@ -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.transaction;
import com.google.api.client.auth.oauth2.Credential;
import com.google.cloud.sql.CredentialFactory;
/** Supplier class to provide {@link Credential} for Cloud SQL library. */
public class CloudSqlCredentialSupplier implements CredentialFactory {
private static Credential credential;
/** Initialize the supplier with given credential json and scopes. */
public static void setupCredentialSupplier(Credential credential) {
System.setProperty(
CredentialFactory.CREDENTIAL_FACTORY_PROPERTY, CloudSqlCredentialSupplier.class.getName());
CloudSqlCredentialSupplier.credential = credential;
}
@Override
public Credential create() {
return credential;
}
}
@@ -16,11 +16,9 @@ package google.registry.persistence.transaction;
import com.google.appengine.api.utils.SystemProperty;
import com.google.appengine.api.utils.SystemProperty.Environment.Value;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Suppliers;
import google.registry.model.ofy.DatastoreTransactionManager;
import google.registry.persistence.DaggerPersistenceComponent;
import google.registry.tools.RegistryToolEnvironment;
import google.registry.util.NonFinalForTesting;
import java.util.function.Supplier;
@@ -38,11 +36,10 @@ public class TransactionManagerFactory {
private TransactionManagerFactory() {}
private static JpaTransactionManager createJpaTransactionManager() {
// If we are running a nomulus command, jpaTm will be injected in RegistryCli.java
// by calling setJpaTm().
if (isInAppEngine()) {
return DaggerPersistenceComponent.create().appEngineJpaTransactionManager();
} else if (RegistryToolEnvironment.isInRegistryTool()
&& RegistryToolEnvironment.isJpaTmEnabled()) {
return DaggerPersistenceComponent.create().nomulusToolJpaTransactionManager();
} else {
return DummyJpaTransactionManager.create();
}
@@ -78,8 +75,8 @@ public class TransactionManagerFactory {
return jpaTm.get();
}
@VisibleForTesting
static void setJpaTmForTesting(JpaTransactionManager newJpaTm) {
/** Sets the return of {@link #jpaTm()} to the given instance of {@link JpaTransactionManager}. */
public static void setJpaTm(JpaTransactionManager newJpaTm) {
jpaTm = Suppliers.ofInstance(newJpaTm);
}
}
@@ -26,6 +26,7 @@ import google.registry.model.UpdateAutoTimestamp;
import google.registry.util.DateTimeUtils;
import java.time.ZonedDateTime;
import java.util.Optional;
import javax.annotation.Nullable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -37,6 +38,7 @@ import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/**
* Represents a registry lock/unlock object, meaning that the domain is locked on the registry
@@ -131,6 +133,9 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
@JoinColumn(name = "relockRevisionId", referencedColumnName = "revisionId")
private RegistryLock relock;
/** The duration after which we will re-lock this domain after it is unlocked. */
private Duration relockDuration;
/** Time that this entity was last updated. */
private UpdateAutoTimestamp lastUpdateTimestamp;
@@ -197,6 +202,11 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
return relock;
}
/** The duration after which we will re-lock this domain after it is unlocked. */
public Optional<Duration> getRelockDuration() {
return Optional.ofNullable(relockDuration);
}
public boolean isLocked() {
return lockCompletionTimestamp != null && unlockCompletionTimestamp == null;
}
@@ -289,5 +299,10 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
getInstance().relock = relock;
return this;
}
public Builder setRelockDuration(@Nullable Duration relockDuration) {
getInstance().relockDuration = relockDuration;
return this;
}
}
}
@@ -20,6 +20,7 @@ import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets.Details;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.util.store.AbstractDataStoreFactory;
@@ -42,6 +43,7 @@ import google.registry.util.GoogleCredentialsBundle;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -92,6 +94,26 @@ public class AuthModule {
}
}
// TODO(b/138195359): Deprecate this credential once Cloud SQL socket library uses the new auth
// library.
@Provides
@CloudSqlClientCredential
public static Credential providesLocalCredentialForCloudSqlClient(
@LocalCredentialJson String credentialJson,
@Config("localCredentialOauthScopes") ImmutableList<String> credentialScopes) {
try {
GoogleCredential credential =
GoogleCredential.fromStream(new ByteArrayInputStream(credentialJson.getBytes(UTF_8)));
if (credential.createScopedRequired()) {
credential = credential.createScoped(credentialScopes);
}
return credential;
} catch (IOException e) {
throw new UncheckedIOException(
"Error occurred while creating a GoogleCredential for Cloud SQL client", e);
}
}
@Provides
public static GoogleAuthorizationCodeFlow provideAuthorizationCodeFlow(
JsonFactory jsonFactory,
@@ -184,6 +206,11 @@ public class AuthModule {
@Retention(RetentionPolicy.RUNTIME)
private @interface StoredCredential {}
/** Dagger qualifier for {@link Credential} used by the Cloud SQL client in the nomulus tool. */
@Qualifier
@Documented
public @interface CloudSqlClientCredential {}
/** Dagger qualifier for the credential qualifier consisting of client and scopes. */
@Qualifier
@Documented
@@ -31,6 +31,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import google.registry.config.RegistryConfig;
import google.registry.model.ofy.ObjectifyService;
import google.registry.persistence.transaction.TransactionManagerFactory;
import google.registry.tools.AuthModule.LoginRequiredException;
import google.registry.tools.params.ParameterFactory;
import java.io.ByteArrayInputStream;
@@ -237,7 +238,7 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
// Enable Cloud SQL for command that needs remote API as they will very likely use
// Cloud SQL after the database migration. Note that the DB password is stored in Datastore
// and it is already initialized above.
RegistryToolEnvironment.enableJpaTm();
TransactionManagerFactory.setJpaTm(component.nomulusToolJpaTransactionManager());
}
command.run();
@@ -27,6 +27,9 @@ import google.registry.keyring.KeyringModule;
import google.registry.keyring.api.DummyKeyringModule;
import google.registry.keyring.api.KeyModule;
import google.registry.keyring.kms.KmsModule;
import google.registry.persistence.PersistenceModule;
import google.registry.persistence.PersistenceModule.NomulusToolJpaTm;
import google.registry.persistence.transaction.JpaTransactionManager;
import google.registry.rde.RdeModule;
import google.registry.request.Modules.DatastoreServiceModule;
import google.registry.request.Modules.Jackson2Module;
@@ -63,6 +66,7 @@ import javax.inject.Singleton;
KeyringModule.class,
KmsModule.class,
LocalCredentialModule.class,
PersistenceModule.class,
RdeModule.class,
RequestFactoryModule.class,
URLFetchServiceModule.class,
@@ -70,7 +74,7 @@ import javax.inject.Singleton;
UserServiceModule.class,
UtilsModule.class,
VoidDnsWriterModule.class,
WhoisModule.class,
WhoisModule.class
})
interface RegistryToolComponent {
void inject(AckPollMessagesCommand command);
@@ -117,6 +121,9 @@ interface RegistryToolComponent {
@LocalCredentialJson
String googleCredentialJson();
@NomulusToolJpaTm
JpaTransactionManager nomulusToolJpaTransactionManager();
@Component.Builder
interface Builder {
@BindsInstance
@@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import google.registry.config.RegistryEnvironment;
import google.registry.config.SystemPropertySetter;
import google.registry.persistence.transaction.TransactionManagerFactory;
/** Enum of production environments, used for the {@code --environment} flag. */
public enum RegistryToolEnvironment {
@@ -40,7 +39,6 @@ public enum RegistryToolEnvironment {
private static final ImmutableList<String> FLAGS = ImmutableList.of("-e", "--environment");
private static RegistryToolEnvironment instance;
private static boolean isJpaTmEnabled = false;
private final RegistryEnvironment actualEnvironment;
private final ImmutableMap<String, String> extraProperties;
@@ -100,26 +98,6 @@ public enum RegistryToolEnvironment {
}
}
/** Returns true if the RegistryToolEnvironment is set up. */
public static boolean isInRegistryTool() {
return instance != null;
}
/**
* Sets the flag to indicate that the running command needs JpaTransactionManager to be enabled.
*/
public static void enableJpaTm() {
isJpaTmEnabled = true;
}
/**
* Returns true if the JpaTransactionManager is enabled. Note that JpaTm is actually enabled in
* {@link TransactionManagerFactory} by reading this flag.
*/
public static boolean isJpaTmEnabled() {
return isJpaTmEnabled;
}
/** Extracts value from command-line arguments associated with any {@code flags}. */
private static String getFlagValue(String[] args, Iterable<String> flags) {
for (String flag : flags) {
@@ -41,7 +41,6 @@ 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 java.util.Optional;
@@ -117,41 +116,61 @@ public final class RegistryLockGetAction implements JsonGetAction {
}
}
private ImmutableMap<String, ?> getLockedDomainsMap(String clientId)
throws RegistrarAccessDeniedException {
// Note: admins always have access to the locks page
checkArgument(authResult.userAuthInfo().isPresent(), "User auth info must be present");
UserAuthInfo userAuthInfo = authResult.userAuthInfo().get();
boolean isAdmin = registrarAccessor.isAdmin();
Registrar registrar = getRegistrarAndVerifyLockAccess(clientId, isAdmin);
User user = userAuthInfo.user();
boolean isRegistryLockAllowed =
isAdmin
|| registrar.getContacts().stream()
.filter(contact -> contact.getEmailAddress().equals(user.getEmail()))
.findFirst()
.map(RegistrarContact::isRegistryLockAllowed)
.orElse(false);
return ImmutableMap.of(
LOCK_ENABLED_FOR_CONTACT_PARAM,
isRegistryLockAllowed,
EMAIL_PARAM,
user.getEmail(),
PARAM_CLIENT_ID,
registrar.getClientId(),
LOCKS_PARAM,
getLockedDomains(clientId, isAdmin));
static Optional<RegistrarContact> getContactMatchingLogin(User user, Registrar registrar) {
ImmutableList<RegistrarContact> matchingContacts =
registrar.getContacts().stream()
.filter(contact -> contact.getGaeUserId().equals(user.getUserId()))
.collect(toImmutableList());
if (matchingContacts.size() > 1) {
ImmutableList<String> matchingEmails =
matchingContacts.stream()
.map(RegistrarContact::getEmailAddress)
.collect(toImmutableList());
throw new IllegalArgumentException(
String.format(
"User ID %s had multiple matching contacts with email addresses %s",
user.getUserId(), matchingEmails));
}
return matchingContacts.stream().findFirst();
}
private Registrar getRegistrarAndVerifyLockAccess(String clientId, boolean isAdmin)
static Registrar getRegistrarAndVerifyLockAccess(
AuthenticatedRegistrarAccessor registrarAccessor, String clientId, boolean isAdmin)
throws RegistrarAccessDeniedException {
Registrar registrar = registrarAccessor.getRegistrar(clientId);
checkArgument(
isAdmin || registrar.isRegistryLockAllowed(),
"Registry lock not allowed for this registrar");
"Registry lock not allowed for registrar %s",
clientId);
return registrar;
}
private ImmutableMap<String, ?> getLockedDomainsMap(String clientId)
throws RegistrarAccessDeniedException {
// Note: admins always have access to the locks page
checkArgument(authResult.userAuthInfo().isPresent(), "User auth info must be present");
boolean isAdmin = registrarAccessor.isAdmin();
Registrar registrar = getRegistrarAndVerifyLockAccess(registrarAccessor, clientId, isAdmin);
User user = authResult.userAuthInfo().get().user();
Optional<RegistrarContact> contactOptional = getContactMatchingLogin(user, registrar);
boolean isRegistryLockAllowed =
isAdmin || contactOptional.map(RegistrarContact::isRegistryLockAllowed).orElse(false);
// Use the contact email if it's present, else use the login email
String relevantEmail =
contactOptional.map(RegistrarContact::getEmailAddress).orElse(user.getEmail());
return ImmutableMap.of(
LOCK_ENABLED_FOR_CONTACT_PARAM,
isRegistryLockAllowed,
EMAIL_PARAM,
relevantEmail,
PARAM_CLIENT_ID,
registrar.getClientId(),
LOCKS_PARAM,
getLockedDomains(clientId, isAdmin));
}
private ImmutableList<ImmutableMap<String, ?>> getLockedDomains(
String clientId, boolean isAdmin) {
return jpaTm()
@@ -20,8 +20,11 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
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.ui.server.registrar.RegistryLockGetAction.getContactMatchingLogin;
import static google.registry.ui.server.registrar.RegistryLockGetAction.getRegistrarAndVerifyLockAccess;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.appengine.api.users.User;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
@@ -124,11 +127,7 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc
.userAuthInfo()
.orElseThrow(() -> new ForbiddenException("User is not logged in"));
boolean isAdmin = userAuthInfo.isUserAdmin();
String userEmail = userAuthInfo.user().getEmail();
if (!isAdmin) {
verifyRegistryLockPassword(postInput, userEmail);
}
String userEmail = verifyPasswordAndGetEmail(userAuthInfo, postInput);
jpaTm()
.transact(
() -> {
@@ -138,9 +137,11 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc
postInput.fullyQualifiedDomainName,
postInput.clientId,
userEmail,
isAdmin)
registrarAccessor.isAdmin())
: domainLockUtils.saveNewRegistryUnlockRequest(
postInput.fullyQualifiedDomainName, postInput.clientId, isAdmin);
postInput.fullyQualifiedDomainName,
postInput.clientId,
registrarAccessor.isAdmin());
sendVerificationEmail(registryLock, userEmail, postInput.isLock);
});
String action = postInput.isLock ? "lock" : "unlock";
@@ -180,25 +181,28 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc
}
}
private void verifyRegistryLockPassword(RegistryLockPostInput postInput, String userEmail)
private String verifyPasswordAndGetEmail(
UserAuthInfo userAuthInfo, RegistryLockPostInput postInput)
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");
User user = userAuthInfo.user();
if (registrarAccessor.isAdmin()) {
return user.getEmail();
}
// Verify that the user can access the registrar, that the user has
// registry lock enabled, and that the user providjed a correct password
Registrar registrar =
getRegistrarAndVerifyLockAccess(registrarAccessor, postInput.clientId, false);
RegistrarContact registrarContact =
registrar.getContacts().stream()
.filter(contact -> contact.getEmailAddress().equals(userEmail))
.findFirst()
getContactMatchingLogin(user, registrar)
.orElseThrow(
() ->
new IllegalArgumentException(
String.format("Unknown user email %s", userEmail)));
String.format(
"Cannot match user %s to registrar contact", user.getUserId())));
checkArgument(
registrarContact.verifyRegistryLockPassword(postInput.password),
"Incorrect registry lock password for contact");
return registrarContact.getEmailAddress();
}
/** Value class that represents the expected input body from the UI request. */
@@ -38,6 +38,7 @@
<class>google.registry.persistence.converter.CreateAutoTimestampConverter</class>
<class>google.registry.persistence.converter.CurrencyUnitConverter</class>
<class>google.registry.persistence.converter.DateTimeConverter</class>
<class>google.registry.persistence.converter.DurationConverter</class>
<class>google.registry.persistence.converter.RegistrarPocSetConverter</class>
<class>google.registry.persistence.converter.StatusValueSetConverter</class>
<class>google.registry.persistence.converter.StringListConverter</class>
@@ -30,6 +30,7 @@ import google.registry.schema.domain.RegistryLock;
import google.registry.testing.AppEngineRule;
import google.registry.testing.FakeClock;
import java.util.Optional;
import org.joda.time.Duration;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -88,12 +89,14 @@ public final class RegistryLockDaoTest {
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setUnlockCompletionTimestamp(fakeClock.nowUtc())
.setRelockDuration(Duration.standardHours(6))
.build());
RegistryLock fromDatabase = getRegistryLockByVerificationCode(lock.getVerificationCode()).get();
assertThat(fromDatabase.getUnlockRequestTimestamp()).isEqualTo(Optional.of(fakeClock.nowUtc()));
assertThat(fromDatabase.getUnlockCompletionTimestamp())
.isEqualTo(Optional.of(fakeClock.nowUtc()));
assertThat(fromDatabase.isLocked()).isFalse();
assertThat(fromDatabase.getRelockDuration().get()).isEqualTo(Duration.standardHours(6));
}
@Test
@@ -11,6 +11,7 @@
// 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.converter;
import static com.google.common.truth.Truth.assertThat;
@@ -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.converter;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import google.registry.model.ImmutableObject;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule;
import java.math.BigInteger;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.joda.time.Duration;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link DurationConverter}. */
@RunWith(JUnit4.class)
public class DurationConverterTest {
@Rule
public final JpaUnitTestRule jpaRule =
new JpaTestRules.Builder().withEntityClass(TestEntity.class).buildUnitTestRule();
private final DurationConverter converter = new DurationConverter();
@Test
public void testNulls() {
assertThat(converter.convertToDatabaseColumn(null)).isNull();
assertThat(converter.convertToEntityAttribute(null)).isNull();
}
@Test
public void testRoundTrip() {
TestEntity entity = new TestEntity(Duration.standardDays(6));
jpaTm().transact(() -> jpaTm().getEntityManager().persist(entity));
assertThat(
jpaTm()
.transact(
() ->
jpaTm()
.getEntityManager()
.createNativeQuery(
"SELECT duration FROM \"TestEntity\" WHERE name = 'id'")
.getResultList()))
.containsExactly(BigInteger.valueOf(Duration.standardDays(6).getMillis()));
TestEntity persisted =
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "id"));
assertThat(persisted.duration).isEqualTo(Duration.standardDays(6));
}
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
public static class TestEntity extends ImmutableObject {
@Id String name = "id";
Duration duration;
public TestEntity() {}
TestEntity(Duration duration) {
this.duration = duration;
}
}
}
@@ -133,12 +133,12 @@ abstract class JpaTransactionManagerRule extends ExternalResource {
extraEntityClasses);
JpaTransactionManagerImpl txnManager = new JpaTransactionManagerImpl(emf, clock);
cachedTm = TransactionManagerFactory.jpaTm();
TransactionManagerFactory.setJpaTmForTesting(txnManager);
TransactionManagerFactory.setJpaTm(txnManager);
}
@Override
public void after() {
TransactionManagerFactory.setJpaTmForTesting(cachedTm);
TransactionManagerFactory.setJpaTm(cachedTm);
if (emf != null) {
emf.close();
emf = null;
@@ -249,7 +249,7 @@ public final class AppEngineRule extends ExternalResource {
.setEmailAddress("Marla.Singer@crr.com")
.setPhoneNumber("+1.2128675309")
.setTypes(ImmutableSet.of(RegistrarContact.Type.TECH))
.setGaeUserId(THE_REGISTRAR_GAE_USER_ID)
.setGaeUserId("12345")
.setAllowedToSetRegistryLockPassword(true)
.setRegistryLockPassword("hi")
.build();
@@ -31,6 +31,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.gson.Gson;
import google.registry.model.registrar.RegistrarContact;
import google.registry.request.Action.Method;
import google.registry.request.auth.AuthLevel;
import google.registry.request.auth.AuthResult;
@@ -67,14 +68,15 @@ public final class RegistryLockGetActionTest {
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
private final FakeResponse response = new FakeResponse();
private final User user = new User("Marla.Singer@crr.com", "gmail.com", "12345");
private User user;
private AuthResult authResult;
private AuthenticatedRegistrarAccessor accessor;
private RegistryLockGetAction action;
@Before
public void setup() {
user = userFromRegistrarContact(AppEngineRule.makeRegistrarContact3());
fakeClock.setTo(DateTime.parse("2000-06-08T22:00:00.0Z"));
authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
accessor =
@@ -186,10 +188,10 @@ public final class RegistryLockGetActionTest {
"locks",
ImmutableList.of(
new ImmutableMap.Builder<>()
.put("fullyQualifiedDomainName", "expiredunlock.test")
.put("lockedTime", "2000-06-08T22:00:00.000Z")
.put("lockedBy", "johndoe@theregistrar.com")
.put("userCanUnlock", true)
.put("fullyQualifiedDomainName", "adminexample.test")
.put("lockedTime", "2000-06-09T22:00:00.001Z")
.put("lockedBy", "admin")
.put("userCanUnlock", false)
.put("isLockPending", false)
.put("isUnlockPending", false)
.build(),
@@ -202,19 +204,11 @@ public final class RegistryLockGetActionTest {
.put("isUnlockPending", false)
.build(),
new ImmutableMap.Builder<>()
.put("fullyQualifiedDomainName", "adminexample.test")
.put("lockedTime", "2000-06-09T22:00:00.001Z")
.put("lockedBy", "admin")
.put("userCanUnlock", false)
.put("isLockPending", false)
.put("isUnlockPending", false)
.build(),
new ImmutableMap.Builder<>()
.put("fullyQualifiedDomainName", "pending.test")
.put("lockedTime", "")
.put("fullyQualifiedDomainName", "expiredunlock.test")
.put("lockedTime", "2000-06-08T22:00:00.000Z")
.put("lockedBy", "johndoe@theregistrar.com")
.put("userCanUnlock", true)
.put("isLockPending", true)
.put("isLockPending", false)
.put("isUnlockPending", false)
.build(),
new ImmutableMap.Builder<>()
@@ -224,6 +218,14 @@ public final class RegistryLockGetActionTest {
.put("userCanUnlock", true)
.put("isLockPending", false)
.put("isUnlockPending", true)
.build(),
new ImmutableMap.Builder<>()
.put("fullyQualifiedDomainName", "pending.test")
.put("lockedTime", "")
.put("lockedBy", "johndoe@theregistrar.com")
.put("userCanUnlock", true)
.put("isLockPending", true)
.put("isUnlockPending", false)
.build()))));
}
@@ -309,6 +311,29 @@ public final class RegistryLockGetActionTest {
ImmutableList.of())));
}
@Test
public void testSuccess_linkedToContactEmail() {
// Even though the user is some.email@gmail.com the contact is still Marla Singer
user = new User("some.email@gmail.com", "gmail.com", user.getUserId());
authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
action =
new RegistryLockGetAction(
Method.GET, response, accessor, authResult, Optional.of("TheRegistrar"));
action.run();
assertThat(GSON.fromJson(response.getPayload(), Map.class).get("results"))
.isEqualTo(
ImmutableList.of(
ImmutableMap.of(
"lockEnabledForContact",
true,
"email",
"Marla.Singer@crr.com",
"clientId",
"TheRegistrar",
"locks",
ImmutableList.of())));
}
@Test
public void testFailure_lockNotAllowedForRegistrar() {
// The UI shouldn't be making requests where lock isn't enabled for this registrar
@@ -337,4 +362,9 @@ public final class RegistryLockGetActionTest {
action.run();
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
}
static User userFromRegistrarContact(RegistrarContact registrarContact) {
return new User(
registrarContact.getEmailAddress(), "gmail.com", registrarContact.getGaeUserId());
}
}
@@ -23,6 +23,7 @@ import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.SqlHelper.getRegistryLockByVerificationCode;
import static google.registry.testing.SqlHelper.saveRegistryLock;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static google.registry.ui.server.registrar.RegistryLockGetActionTest.userFromRegistrarContact;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -78,11 +79,8 @@ public final class RegistryLockPostActionTest {
@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 User userWithoutPermission;
private User userWithLockPermission;
private InternetAddress outgoingAddress;
private DomainBase domain;
@@ -93,6 +91,8 @@ public final class RegistryLockPostActionTest {
@Before
public void setup() throws Exception {
userWithLockPermission = userFromRegistrarContact(AppEngineRule.makeRegistrarContact3());
userWithoutPermission = userFromRegistrarContact(AppEngineRule.makeRegistrarContact2());
createTld("tld");
domain = persistResource(newDomainBase("example.tld"));
outgoingAddress = new InternetAddress("domain-registry@example.com");
@@ -133,6 +133,18 @@ public final class RegistryLockPostActionTest {
assertSuccess(response, "unlock", "johndoe@theregistrar.com");
}
@Test
public void testSuccess_linkedToContactEmail() throws Exception {
// Even though the user is some.email@gmail.com the contact is still Marla Singer
userWithLockPermission =
new User("some.email@gmail.com", "gmail.com", userWithLockPermission.getUserId());
action =
createAction(
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithLockPermission, false)));
Map<String, ?> response = action.handleJsonRequest(lockRequest());
assertSuccess(response, "lock", "Marla.Singer@crr.com");
}
@Test
public void testFailure_unlock_noLock() {
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
@@ -233,7 +245,7 @@ public final class RegistryLockPostActionTest {
persistResource(
loadRegistrar("TheRegistrar").asBuilder().setRegistryLockAllowed(false).build());
Map<String, ?> response = action.handleJsonRequest(lockRequest());
assertFailureWithMessage(response, "Registry lock not allowed for this registrar");
assertFailureWithMessage(response, "Registry lock not allowed for registrar TheRegistrar");
}
@Test
@@ -244,7 +256,7 @@ public final class RegistryLockPostActionTest {
"clientId", "TheRegistrar",
"fullyQualifiedDomainName", "example.tld",
"isLock", true));
assertFailureWithMessage(response, "Missing key for password");
assertFailureWithMessage(response, "Incorrect registry lock password for contact");
}
@Test
@@ -386,9 +398,10 @@ public final class RegistryLockPostActionTest {
}
private RegistryLockPostAction createAction(AuthResult authResult) {
Role role = authResult.userAuthInfo().get().isUserAdmin() ? Role.ADMIN : Role.OWNER;
AuthenticatedRegistrarAccessor registrarAccessor =
AuthenticatedRegistrarAccessor.createForTesting(
ImmutableSetMultimap.of("TheRegistrar", Role.OWNER, "NewRegistrar", Role.OWNER));
ImmutableSetMultimap.of("TheRegistrar", role, "NewRegistrar", role));
JsonActionRunner jsonActionRunner =
new JsonActionRunner(ImmutableMap.of(), new JsonResponse(new ResponseImpl(mockResponse)));
DomainLockUtils domainLockUtils =
@@ -60,7 +60,8 @@ public class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
route("/registry-lock-verify", FrontendServlet.class))
.setFilters(ObjectifyFilter.class, OfyFilter.class)
.setFixtures(BASIC)
.setEmail("Marla.Singer@crr.com")
.setEmail("Marla.Singer@crr.com") // from AppEngineRule.makeRegistrarContact3
.setGaeUserId("12345") // from AppEngineRule.makeRegistrarContact3
.build();
@Test
@@ -452,11 +453,12 @@ public class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
createTld("tld");
// expired unlock request
DomainBase expiredUnlockRequestDomain = persistActiveDomain("expiredunlock.tld");
saveRegistryLock(createRegistryLock(expiredUnlockRequestDomain)
.asBuilder()
.setLockCompletionTimestamp(START_OF_TIME.minusDays(1))
.setUnlockRequestTimestamp(START_OF_TIME.minusDays(1))
.build());
saveRegistryLock(
createRegistryLock(expiredUnlockRequestDomain)
.asBuilder()
.setLockCompletionTimestamp(START_OF_TIME.minusDays(1))
.setUnlockRequestTimestamp(START_OF_TIME.minusDays(1))
.build());
DomainBase domain = persistActiveDomain("example.tld");
saveRegistryLock(createRegistryLock(domain).asBuilder().isSuperuser(true).build());
DomainBase otherDomain = persistActiveDomain("otherexample.tld");
@@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.testing.AppEngineRule.THE_REGISTRAR_GAE_USER_ID;
import static google.registry.util.NetworkUtils.getExternalAddressOfLocalSystem;
import static google.registry.util.NetworkUtils.pickUnusedPort;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -32,6 +33,7 @@ import google.registry.testing.UserInfo;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
@@ -66,7 +68,8 @@ public final class TestServerRule extends ExternalResource {
ImmutableList<Route> routes,
ImmutableList<Class<? extends Filter>> filters,
ImmutableList<Fixture> fixtures,
String email) {
String email,
Optional<String> gaeUserId) {
this.runfiles = runfiles;
this.routes = routes;
this.filters = filters;
@@ -79,7 +82,8 @@ public final class TestServerRule extends ExternalResource {
.withLocalModules()
.withUrlFetch()
.withTaskQueue()
.withUserService(UserInfo.createAdmin(email, THE_REGISTRAR_GAE_USER_ID))
.withUserService(
UserInfo.createAdmin(email, gaeUserId.orElse(THE_REGISTRAR_GAE_USER_ID)))
.build();
}
@@ -149,8 +153,8 @@ public final class TestServerRule extends ExternalResource {
/**
* Runs arbitrary code inside server event loop thread.
*
* <p>You should use this method when you want to do things like change Datastore, because the
* App Engine testing environment is thread-local.
* <p>You should use this method when you want to do things like change Datastore, because the App
* Engine testing environment is thread-local.
*/
public <T> T runInAppEngineEnvironment(Callable<T> callback) throws Throwable {
FutureTask<T> job = new FutureTask<>(callback);
@@ -211,7 +215,6 @@ public final class TestServerRule extends ExternalResource {
*
* <p>This builder has three required fields: {@link #setRunfiles}, {@link #setRoutes}, and {@link
* #setFilters}.
*
*/
public static final class Builder {
private ImmutableMap<String, Path> runfiles;
@@ -219,6 +222,7 @@ public final class TestServerRule extends ExternalResource {
ImmutableList<Class<? extends Filter>> filters;
private ImmutableList<Fixture> fixtures = ImmutableList.of();
private String email;
private Optional<String> gaeUserId = Optional.empty();
/** Sets the directories containing the static files for {@link TestServer}. */
public Builder setRunfiles(ImmutableMap<String, Path> runfiles) {
@@ -256,6 +260,13 @@ public final class TestServerRule extends ExternalResource {
return this;
}
/** Optionally, sets the GAE user ID for the logged in user. */
public Builder setGaeUserId(String gaeUserId) {
this.gaeUserId =
Optional.of(checkArgumentNotNull(gaeUserId, "Must specify a non-null GAE user ID"));
return this;
}
/** Returns a new {@link TestServerRule} instance. */
public TestServerRule build() {
return new TestServerRule(
@@ -263,7 +274,8 @@ public final class TestServerRule extends ExternalResource {
checkNotNull(this.routes),
checkNotNull(this.filters),
checkNotNull(this.fixtures),
checkNotNull(this.email));
checkNotNull(this.email),
this.gaeUserId);
}
}
}
@@ -13,7 +13,7 @@ contacts:
ADDED:
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=Extra Terrestrial, emailAddress=etphonehome@example.com, phoneNumber=+1.2345678901, faxNumber=null, types=[ADMIN, BILLING, TECH, WHOIS], gaeUserId=null, visibleInWhoisAsAdmin=true, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false}
REMOVED:
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=Marla Singer, emailAddress=Marla.Singer@crr.com, phoneNumber=+1.2128675309, faxNumber=null, types=[TECH], gaeUserId=31337, visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false},
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=Marla Singer, emailAddress=Marla.Singer@crr.com, phoneNumber=+1.2128675309, faxNumber=null, types=[TECH], gaeUserId=12345, visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false},
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=John Doe, emailAddress=johndoe@theregistrar.com, phoneNumber=+1.1234567890, faxNumber=null, types=[ADMIN], gaeUserId=31337, visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false},
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=Jian-Yang, emailAddress=jyang@bachman.accelerator, phoneNumber=+1.1234567890, faxNumber=null, types=[TECH], gaeUserId=null, visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false}
FINAL CONTENTS:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

@@ -0,0 +1,15 @@
-- 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.
ALTER TABLE "RegistryLock" ADD COLUMN relock_duration bigint;
@@ -176,6 +176,7 @@
lock_request_timestamp timestamptz not null,
registrar_id text not null,
registrar_poc_id text,
relock_duration int8,
repo_id text not null,
unlock_completion_timestamp timestamptz,
unlock_request_timestamp timestamptz,
@@ -262,7 +262,8 @@ CREATE TABLE public."RegistryLock" (
unlock_request_timestamp timestamp with time zone,
unlock_completion_timestamp timestamp with time zone,
last_update_timestamp timestamp with time zone,
relock_revision_id bigint
relock_revision_id bigint,
relock_duration bigint
);
+1
View File
@@ -43,6 +43,7 @@ ext {
'com.google.auto.value:auto-value-annotations:1.6.3',
'com.google.auto.value:auto-value:1.6.3',
'com.google.closure-stylesheets:closure-stylesheets:1.5.0',
'com.google.cloud.sql:jdbc-socket-factory-core:1.0.12',
'com.google.cloud.sql:postgres-socket-factory:1.0.12',
'com.google.cloud:google-cloud-core:1.59.0',
'com.google.cloud:google-cloud-storage:1.59.0',