mirror of
https://github.com/google/nomulus
synced 2026-08-05 14:56:11 +00:00
Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b75eb0ad95 | ||
|
|
63f8fcef18 | ||
|
|
8d563c4516 | ||
|
|
a58c4a6492 | ||
|
|
e59475a5f6 | ||
|
|
c35f92f54b | ||
|
|
cd415fe846 | ||
|
|
4ca2c11b20 | ||
|
|
4e44a98139 | ||
|
|
d4371a880e | ||
|
|
7312bc9e60 | ||
|
|
83ca9d82df | ||
|
|
8724ef6c70 |
+2
-2
@@ -121,7 +121,7 @@ task stage {
|
||||
// App-engine environment configuration. We set up all of the variables in
|
||||
// the root project.
|
||||
|
||||
def environments = ['production', 'sandbox', 'alpha', 'crash']
|
||||
def environments = ['production', 'sandbox', 'alpha', 'crash', 'qa']
|
||||
|
||||
def gcpProject = null
|
||||
|
||||
@@ -155,7 +155,7 @@ def verifyDeploymentParams() {
|
||||
System.err.println('-----------------------------------------------------------------')
|
||||
throw new GradleException('Aborting. See prominent error above.')
|
||||
} else if (gcpProject == null) {
|
||||
def error = 'You must specify -P environment={alpha,crash}'
|
||||
def error = 'You must specify -P environment={alpha,crash,qa}'
|
||||
System.err.println("\033[33;1m${error}\033[0m")
|
||||
throw GradleException("Aborting: ${error}")
|
||||
}
|
||||
|
||||
@@ -71,12 +71,13 @@ dependencies {
|
||||
def deps = dependencyMap
|
||||
compile deps['com.google.auth:google-auth-library-credentials']
|
||||
compile deps['com.google.auth:google-auth-library-oauth2-http']
|
||||
compile deps['com.google.cloud:google-cloud-core']
|
||||
compile deps['com.google.guava:guava']
|
||||
compile deps['com.google.auto.value:auto-value-annotations']
|
||||
compile deps['com.google.cloud:google-cloud-core']
|
||||
compile deps['com.google.cloud:google-cloud-storage']
|
||||
compile deps['org.apache.commons:commons-text']
|
||||
compile deps['com.google.guava:guava']
|
||||
compile deps['com.google.protobuf:protobuf-java']
|
||||
compile deps['com.google.template:soy']
|
||||
compile deps['org.apache.commons:commons-text']
|
||||
annotationProcessor deps['com.google.auto.value:auto-value']
|
||||
testCompile deps['com.google.truth:truth']
|
||||
testCompile deps['com.google.truth.extensions:truth-java8-extension']
|
||||
|
||||
@@ -33,7 +33,7 @@ com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.13.0
|
||||
com.google.template:soy:2018-03-14
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
|
||||
@@ -33,7 +33,7 @@ com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.13.0
|
||||
com.google.template:soy:2018-03-14
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
|
||||
@@ -33,7 +33,7 @@ com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.13.0
|
||||
com.google.template:soy:2018-03-14
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
|
||||
@@ -33,7 +33,7 @@ com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.13.0
|
||||
com.google.template:soy:2018-03-14
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
|
||||
@@ -33,7 +33,7 @@ com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.13.0
|
||||
com.google.template:soy:2018-03-14
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
|
||||
@@ -33,7 +33,7 @@ com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.13.0
|
||||
com.google.template:soy:2018-03-14
|
||||
com.google.truth.extensions:truth-java8-extension:1.0
|
||||
com.google.truth:truth:1.0
|
||||
@@ -50,8 +50,8 @@ javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
@@ -66,8 +66,8 @@ org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
|
||||
@@ -33,7 +33,7 @@ com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.13.0
|
||||
com.google.template:soy:2018-03-14
|
||||
com.google.truth.extensions:truth-java8-extension:1.0
|
||||
com.google.truth:truth:1.0
|
||||
@@ -50,8 +50,8 @@ javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
@@ -66,8 +66,8 @@ org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
|
||||
@@ -33,7 +33,7 @@ com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.13.0
|
||||
com.google.template:soy:2018-03-14
|
||||
com.google.truth.extensions:truth-java8-extension:1.0
|
||||
com.google.truth:truth:1.0
|
||||
@@ -50,8 +50,8 @@ javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
@@ -66,8 +66,8 @@ org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
|
||||
@@ -33,7 +33,7 @@ com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.13.0
|
||||
com.google.template:soy:2018-03-14
|
||||
com.google.truth.extensions:truth-java8-extension:1.0
|
||||
com.google.truth:truth:1.0
|
||||
@@ -50,8 +50,8 @@ javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
@@ -66,8 +66,8 @@ org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
mock-maker-inline
|
||||
+2
-2
@@ -111,8 +111,8 @@ PROPERTIES = [
|
||||
|
||||
# Cloud SQL properties
|
||||
Property('dbServer',
|
||||
'A registry environment name (e.g., "alpha") or a host[:port] '
|
||||
'string'),
|
||||
'The host[:port] of a database that accepts direct IP access. '
|
||||
'This is typically used with a testing database.'),
|
||||
Property('dbName',
|
||||
'Database name to use in connection.',
|
||||
'postgres'),
|
||||
|
||||
@@ -207,6 +207,9 @@ PRESUBMITS = {
|
||||
"ForeignKeyIndex.java",
|
||||
"HistoryEntryDao.java",
|
||||
"JpaTransactionManagerImpl.java",
|
||||
# CriteriaQueryBuilder is a false positive
|
||||
"CriteriaQueryBuilder.java",
|
||||
"RdapSearchActionBase.java",
|
||||
},
|
||||
):
|
||||
"The first String parameter to EntityManager.create(Native)Query "
|
||||
|
||||
@@ -344,6 +344,8 @@ dependencies {
|
||||
jaxb deps['com.sun.xml.bind:jaxb-osgi']
|
||||
|
||||
// Dependency needed for soy to java compilation.
|
||||
soy deps['com.google.inject:guice']
|
||||
soy deps['com.google.protobuf:protobuf-java']
|
||||
soy deps['com.google.template:soy']
|
||||
|
||||
// Dependencies needed for compiling stylesheets to javascript
|
||||
|
||||
@@ -3,19 +3,24 @@
|
||||
# This file is expected to be part of source control.
|
||||
aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.0.23
|
||||
com.google.code.findbugs:jsr305:2.0.3
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.7
|
||||
com.google.common.html.types:types:1.0.4
|
||||
com.google.guava:guava:21.0
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:30.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.8.0-beta1
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.protobuf:protobuf-java:3.3.0
|
||||
com.google.inject:guice:5.0.1
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.protobuf:protobuf-java:3.13.0
|
||||
com.google.template:soy:2018-03-14
|
||||
com.ibm.icu:icu4j:57.1
|
||||
javax.annotation:jsr250-api:1.0
|
||||
javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
org.checkerframework:checker-qual:3.5.0
|
||||
org.json:json:20160212
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
|
||||
@@ -198,8 +198,8 @@ javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.10.5
|
||||
junit:junit:4.13.1
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.17
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
net.java.dev.jna:jna:5.5.0
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-fn-execution:2.27.0
|
||||
@@ -273,11 +273,11 @@ org.junit.platform:junit-platform-runner:1.7.0
|
||||
org.junit.platform:junit-platform-suite-api:1.7.0
|
||||
org.junit:junit-bom:5.7.0
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.mockito:mockito-junit-jupiter:3.3.3
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.mockito:mockito-junit-jupiter:3.7.7
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
org.objenesis:objenesis:2.6
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.ow2.asm:asm-analysis:8.0.1
|
||||
org.ow2.asm:asm-commons:7.1
|
||||
|
||||
@@ -193,8 +193,8 @@ javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.10.5
|
||||
junit:junit:4.13.1
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.17
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
net.java.dev.jna:jna:5.5.0
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-fn-execution:2.27.0
|
||||
@@ -267,11 +267,11 @@ org.junit.platform:junit-platform-runner:1.7.0
|
||||
org.junit.platform:junit-platform-suite-api:1.7.0
|
||||
org.junit:junit-bom:5.7.0
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.mockito:mockito-junit-jupiter:3.3.3
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.mockito:mockito-junit-jupiter:3.7.7
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
org.objenesis:objenesis:2.6
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.ow2.asm:asm-analysis:8.0.1
|
||||
org.ow2.asm:asm-commons:7.1
|
||||
|
||||
@@ -208,8 +208,8 @@ jline:jline:1.0
|
||||
joda-time:joda-time:2.10.5
|
||||
junit:junit:4.13.1
|
||||
net.arnx:nashorn-promise:0.1.1
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.17
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
net.java.dev.jna:jna:5.5.0
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-fn-execution:2.27.0
|
||||
@@ -285,11 +285,11 @@ org.junit.platform:junit-platform-runner:1.7.0
|
||||
org.junit.platform:junit-platform-suite-api:1.7.0
|
||||
org.junit:junit-bom:5.7.0
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.mockito:mockito-junit-jupiter:3.3.3
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.mockito:mockito-junit-jupiter:3.7.7
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
org.objenesis:objenesis:2.6
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.ow2.asm:asm-analysis:8.0.1
|
||||
org.ow2.asm:asm-commons:7.1
|
||||
|
||||
@@ -208,8 +208,8 @@ jline:jline:1.0
|
||||
joda-time:joda-time:2.10.5
|
||||
junit:junit:4.13.1
|
||||
net.arnx:nashorn-promise:0.1.1
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.17
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
net.java.dev.jna:jna:5.5.0
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-fn-execution:2.27.0
|
||||
@@ -285,11 +285,11 @@ org.junit.platform:junit-platform-runner:1.7.0
|
||||
org.junit.platform:junit-platform-suite-api:1.7.0
|
||||
org.junit:junit-bom:5.7.0
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.mockito:mockito-junit-jupiter:3.3.3
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.mockito:mockito-junit-jupiter:3.7.7
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
org.objenesis:objenesis:2.6
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.ow2.asm:asm-analysis:8.0.1
|
||||
org.ow2.asm:asm-commons:7.1
|
||||
|
||||
@@ -104,8 +104,9 @@ public class DeleteExpiredDomainsAction implements Runnable {
|
||||
runLocked();
|
||||
response.setStatus(SC_OK);
|
||||
} catch (Exception e) {
|
||||
logger.atSevere().withCause(e).log("Errored out during execution.");
|
||||
response.setStatus(SC_INTERNAL_SERVER_ERROR);
|
||||
response.setPayload("Encountered error; see GCP logs for full details.");
|
||||
response.setPayload(String.format("Errored out with cause: %s", e));
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -280,7 +280,7 @@
|
||||
</cron>
|
||||
|
||||
<cron>
|
||||
<url><![CDATA[/_dr/task/icannReportingUpload]]></url>
|
||||
<url><![CDATA[/_dr/cron/fanout?queue=retryable-cron-tasks&endpoint=/_dr/task/icannReportingUpload&runInEmpty]]></url>
|
||||
<description>
|
||||
Checks if the monthly ICANN reports have been successfully uploaded. If they have not, attempts to upload them again.
|
||||
Most of the time, this job should not do anything since the uploads are triggered when the reports are staged.
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.label.PremiumList.PremiumListEntry;
|
||||
import google.registry.model.registry.label.PremiumListDualDao;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Parameter;
|
||||
@@ -141,7 +142,7 @@ public class ExportPremiumTermsAction implements Runnable {
|
||||
PremiumListDualDao.exists(premiumListName), "Could not load premium list for " + tld);
|
||||
SortedSet<String> premiumTerms =
|
||||
Streams.stream(PremiumListDualDao.loadAllPremiumListEntries(premiumListName))
|
||||
.map(entry -> Joiner.on(",").join(entry.getLabel(), entry.getValue()))
|
||||
.map(PremiumListEntry::toString)
|
||||
.collect(ImmutableSortedSet.toImmutableSortedSet(String::compareTo));
|
||||
|
||||
return Joiner.on("\n")
|
||||
|
||||
@@ -52,6 +52,7 @@ import google.registry.model.tmch.ClaimsListShard;
|
||||
import google.registry.model.tmch.ClaimsListShard.ClaimsListRevision;
|
||||
import google.registry.model.tmch.ClaimsListShard.ClaimsListSingleton;
|
||||
import google.registry.model.tmch.TmchCrl;
|
||||
import google.registry.schema.replay.LastSqlTransaction;
|
||||
|
||||
/** Sets of classes of the Objectify-registered entities in use throughout the model. */
|
||||
public final class EntityClasses {
|
||||
@@ -90,6 +91,7 @@ public final class EntityClasses {
|
||||
HostResource.class,
|
||||
KmsSecret.class,
|
||||
KmsSecretRevision.class,
|
||||
LastSqlTransaction.class,
|
||||
Lock.class,
|
||||
PollMessage.class,
|
||||
PollMessage.Autorenew.class,
|
||||
|
||||
@@ -62,6 +62,8 @@ public class DatabaseTransitionSchedule extends ImmutableObject implements Datas
|
||||
DOMAIN_LABEL_LISTS,
|
||||
/** The schedule for the migration of the {@link SignedMarkRevocationList} entity. */
|
||||
SIGNED_MARK_REVOCATION_LIST,
|
||||
/** The schedule for all asynchronously-replayed entities, ones not dually-written. */
|
||||
REPLAYED_ENTITIES,
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,9 +41,9 @@ public class EntityWritePriorities {
|
||||
*/
|
||||
static final ImmutableMap<String, Integer> CLASS_PRIORITIES =
|
||||
ImmutableMap.of(
|
||||
"ContactResource", -15,
|
||||
"HistoryEntry", -10,
|
||||
"AllocationToken", -9,
|
||||
"ContactResource", 5,
|
||||
"DomainBase", 10);
|
||||
|
||||
// The beginning of the range of priority numbers reserved for delete. This must be greater than
|
||||
|
||||
@@ -116,7 +116,7 @@ public class Ofy {
|
||||
return ofy().getTransaction() != null;
|
||||
}
|
||||
|
||||
void assertInTransaction() {
|
||||
public void assertInTransaction() {
|
||||
checkState(inTransaction(), "Must be called in a transaction");
|
||||
}
|
||||
|
||||
|
||||
@@ -208,6 +208,12 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
|
||||
return price;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// Don't include the comment so that we can use this when exporting the premium list
|
||||
return String.format("%s,%s", label, price);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
return new Builder(clone(this));
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright 2021 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 static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.Collection;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Order;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
/**
|
||||
* An extension of {@link CriteriaQuery} that uses a Builder-style pattern when adding "WHERE"
|
||||
* and/or "ORDER BY" clauses.
|
||||
*
|
||||
* <p>{@link CriteriaQuery}, as is, requires that all clauses must be passed in at once -- if one
|
||||
* calls "WHERE" multiple times, the later call overwrites the earlier call.
|
||||
*/
|
||||
public class CriteriaQueryBuilder<T> {
|
||||
|
||||
/** Functional interface that defines the 'where' operator, e.g. {@link CriteriaBuilder#equal}. */
|
||||
public interface WhereClause<U> {
|
||||
Predicate predicate(Expression<U> expression, U object);
|
||||
}
|
||||
|
||||
/** Functional interface that defines the order-by operator, e.g. {@link CriteriaBuilder#asc}. */
|
||||
public interface OrderByClause<U> {
|
||||
Order order(Expression<U> expression);
|
||||
}
|
||||
|
||||
private final CriteriaQuery<T> query;
|
||||
private final Root<T> root;
|
||||
private final ImmutableList.Builder<Predicate> predicates = new ImmutableList.Builder<>();
|
||||
private final ImmutableList.Builder<Order> orders = new ImmutableList.Builder<>();
|
||||
|
||||
private CriteriaQueryBuilder(CriteriaQuery<T> query, Root<T> root) {
|
||||
this.query = query;
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
/** Adds a WHERE clause to the query, given the specified operation, field, and value. */
|
||||
public <V> CriteriaQueryBuilder<T> where(WhereClause<V> whereClause, String fieldName, V value) {
|
||||
Expression<V> expression = root.get(fieldName);
|
||||
return where(whereClause.predicate(expression, value));
|
||||
}
|
||||
|
||||
/** Adds a WHERE clause to the query specifying that a value must be in the given collection. */
|
||||
public CriteriaQueryBuilder<T> whereFieldIsIn(String fieldName, Collection<?> values) {
|
||||
return where(root.get(fieldName).in(values));
|
||||
}
|
||||
|
||||
/** Orders the result by the given operation applied to the given field. */
|
||||
public <U> CriteriaQueryBuilder<T> orderBy(OrderByClause<U> orderByClause, String fieldName) {
|
||||
Expression<U> expression = root.get(fieldName);
|
||||
return orderBy(orderByClause.order(expression));
|
||||
}
|
||||
|
||||
/** Builds and returns the query, applying all WHERE and ORDER BY clauses at once. */
|
||||
public CriteriaQuery<T> build() {
|
||||
Predicate[] predicateArray = predicates.build().toArray(new Predicate[0]);
|
||||
return query.where(predicateArray).orderBy(orders.build());
|
||||
}
|
||||
|
||||
private CriteriaQueryBuilder<T> where(Predicate predicate) {
|
||||
predicates.add(predicate);
|
||||
return this;
|
||||
}
|
||||
|
||||
private CriteriaQueryBuilder<T> orderBy(Order order) {
|
||||
orders.add(order);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Creates a query builder that will SELECT from the given class. */
|
||||
public static <T> CriteriaQueryBuilder<T> create(Class<T> clazz) {
|
||||
CriteriaQuery<T> query = jpaTm().getEntityManager().getCriteriaBuilder().createQuery(clazz);
|
||||
Root<T> root = query.from(clazz);
|
||||
query = query.select(root);
|
||||
return new CriteriaQueryBuilder<>(query, root);
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public class Transaction extends ImmutableObject implements Buildable {
|
||||
}
|
||||
}
|
||||
|
||||
static Transaction deserialize(byte[] serializedTransaction) throws IOException {
|
||||
public static Transaction deserialize(byte[] serializedTransaction) throws IOException {
|
||||
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(serializedTransaction));
|
||||
|
||||
// Verify that the data is what we expect.
|
||||
|
||||
@@ -34,9 +34,9 @@ public class TransactionEntity implements SqlEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
long id;
|
||||
private long id;
|
||||
|
||||
byte[] contents;
|
||||
private byte[] contents;
|
||||
|
||||
TransactionEntity() {}
|
||||
|
||||
@@ -48,4 +48,12 @@ public class TransactionEntity implements SqlEntity {
|
||||
public Optional<DatastoreEntity> toDatastoreEntity() {
|
||||
return Optional.empty(); // Not persisted in Datastore per se
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public byte[] getContents() {
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package google.registry.rdap;
|
||||
import static com.google.common.base.Charsets.UTF_8;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Actions.getPathForAction;
|
||||
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
@@ -28,7 +29,10 @@ import com.google.common.net.MediaType;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.DatabaseMigrationUtils;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.PrimaryDatabase;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.TransitionId;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.rdap.RdapMetrics.EndpointType;
|
||||
import google.registry.rdap.RdapObjectClasses.ErrorResponse;
|
||||
@@ -256,4 +260,11 @@ public abstract class RdapActionBase implements Runnable {
|
||||
DateTime getRequestTime() {
|
||||
return rdapJsonFormatter.getRequestTime();
|
||||
}
|
||||
|
||||
static boolean isDatastore() {
|
||||
return tm().transact(
|
||||
() ->
|
||||
DatabaseMigrationUtils.getPrimaryDatabase(TransitionId.REPLAYED_ENTITIES)
|
||||
.equals(PrimaryDatabase.DATASTORE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
package google.registry.rdap;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
|
||||
import static google.registry.rdap.RdapUtils.getRegistrarByIanaIdentifier;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.HEAD;
|
||||
@@ -29,6 +31,9 @@ import com.google.common.primitives.Longs;
|
||||
import com.googlecode.objectify.cmd.Query;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.CriteriaQueryBuilder;
|
||||
import google.registry.rdap.RdapAuthorization.Role;
|
||||
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
|
||||
import google.registry.rdap.RdapMetrics.EndpointType;
|
||||
import google.registry.rdap.RdapMetrics.SearchType;
|
||||
@@ -112,7 +117,6 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
/** Parses the parameters and calls the appropriate search function. */
|
||||
@Override
|
||||
public EntitySearchResponse getSearchResponse(boolean isHeadRequest) {
|
||||
|
||||
// RDAP syntax example: /rdap/entities?fn=Bobby%20Joe*.
|
||||
if (Booleans.countTrue(fnParam.isPresent(), handleParam.isPresent()) != 1) {
|
||||
throw new BadRequestException("You must specify either fn=XXXX or handle=YYYY");
|
||||
@@ -214,9 +218,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
// Don't allow wildcard suffixes when searching for entities.
|
||||
if (partialStringQuery.getHasWildcard() && (partialStringQuery.getSuffix() != null)) {
|
||||
throw new UnprocessableEntityException(
|
||||
partialStringQuery.getHasWildcard()
|
||||
? "Suffixes not allowed in wildcard entity name searches"
|
||||
: "Suffixes not allowed when searching for deleted entities");
|
||||
"Suffixes not allowed in wildcard entity name searches");
|
||||
}
|
||||
// For wildcards, make sure the initial string is long enough, except in the special case of
|
||||
// searching for all registrars, where we aren't worried about inefficient searches.
|
||||
@@ -225,9 +227,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
&& (partialStringQuery.getInitialString().length()
|
||||
< RdapSearchPattern.MIN_INITIAL_STRING_LENGTH)) {
|
||||
throw new UnprocessableEntityException(
|
||||
partialStringQuery.getHasWildcard()
|
||||
? "Initial search string required in wildcard entity name searches"
|
||||
: "Initial search string required when searching for deleted entities");
|
||||
"Initial search string required in wildcard entity name searches");
|
||||
}
|
||||
// Get the registrar matches. If we have a registrar cursor, weed out registrars up to and
|
||||
// including the one we ended with last time. We can skip registrars if subtype is CONTACTS.
|
||||
@@ -262,18 +262,39 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
|| (cursorType == CursorType.REGISTRAR)) {
|
||||
resultSet = RdapResultSet.create(ImmutableList.of());
|
||||
} else {
|
||||
Query<ContactResource> query =
|
||||
queryItems(
|
||||
ContactResource.class,
|
||||
"searchName",
|
||||
partialStringQuery,
|
||||
cursorQueryString, // if we get this far, and there's a cursor, it must be a contact
|
||||
DeletedItemHandling.EXCLUDE,
|
||||
rdapResultSetMaxSize + 1);
|
||||
if (rdapAuthorization.role() != RdapAuthorization.Role.ADMINISTRATOR) {
|
||||
query = query.filter("currentSponsorClientId in", rdapAuthorization.clientIds());
|
||||
if (isDatastore()) {
|
||||
Query<ContactResource> query =
|
||||
queryItems(
|
||||
ContactResource.class,
|
||||
"searchName",
|
||||
partialStringQuery,
|
||||
cursorQueryString, // if we get here and there's a cursor, it must be a contact
|
||||
DeletedItemHandling.EXCLUDE,
|
||||
rdapResultSetMaxSize + 1);
|
||||
if (!rdapAuthorization.role().equals(Role.ADMINISTRATOR)) {
|
||||
query = query.filter("currentSponsorClientId in", rdapAuthorization.clientIds());
|
||||
}
|
||||
resultSet = getMatchingResources(query, false, rdapResultSetMaxSize + 1);
|
||||
} else {
|
||||
resultSet =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
CriteriaQueryBuilder<ContactResource> builder =
|
||||
queryItemsSql(
|
||||
ContactResource.class,
|
||||
"searchName",
|
||||
partialStringQuery,
|
||||
cursorQueryString,
|
||||
DeletedItemHandling.EXCLUDE);
|
||||
if (!rdapAuthorization.role().equals(Role.ADMINISTRATOR)) {
|
||||
builder =
|
||||
builder.whereFieldIsIn(
|
||||
"currentSponsorClientId", rdapAuthorization.clientIds());
|
||||
}
|
||||
return getMatchingResourcesSql(builder, false, rdapResultSetMaxSize + 1);
|
||||
});
|
||||
}
|
||||
resultSet = getMatchingResources(query, false, rdapResultSetMaxSize + 1);
|
||||
}
|
||||
}
|
||||
return makeSearchResults(resultSet, registrars, QueryType.FULL_NAME);
|
||||
@@ -303,15 +324,15 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
if (subtype == Subtype.REGISTRARS) {
|
||||
contactResourceList = ImmutableList.of();
|
||||
} else {
|
||||
ContactResource contactResource =
|
||||
ofy()
|
||||
.load()
|
||||
.type(ContactResource.class)
|
||||
.id(partialStringQuery.getInitialString())
|
||||
.now();
|
||||
Optional<ContactResource> contactResource =
|
||||
transactIfJpaTm(
|
||||
() ->
|
||||
tm().loadByKeyIfPresent(
|
||||
VKey.create(
|
||||
ContactResource.class, partialStringQuery.getInitialString())));
|
||||
contactResourceList =
|
||||
((contactResource != null) && shouldBeVisible(contactResource))
|
||||
? ImmutableList.of(contactResource)
|
||||
(contactResource.isPresent() && shouldBeVisible(contactResource.get()))
|
||||
? ImmutableList.of(contactResource.get())
|
||||
: ImmutableList.of();
|
||||
}
|
||||
ImmutableList<Registrar> registrarList;
|
||||
@@ -365,16 +386,31 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
if (subtype == Subtype.REGISTRARS) {
|
||||
contactResultSet = RdapResultSet.create(ImmutableList.of());
|
||||
} else {
|
||||
contactResultSet =
|
||||
getMatchingResources(
|
||||
queryItemsByKey(
|
||||
ContactResource.class,
|
||||
partialStringQuery,
|
||||
cursorQueryString,
|
||||
getDeletedItemHandling(),
|
||||
querySizeLimit),
|
||||
shouldIncludeDeleted(),
|
||||
querySizeLimit);
|
||||
if (isDatastore()) {
|
||||
contactResultSet =
|
||||
getMatchingResources(
|
||||
queryItemsByKey(
|
||||
ContactResource.class,
|
||||
partialStringQuery,
|
||||
cursorQueryString,
|
||||
getDeletedItemHandling(),
|
||||
querySizeLimit),
|
||||
shouldIncludeDeleted(),
|
||||
querySizeLimit);
|
||||
} else {
|
||||
contactResultSet =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
getMatchingResourcesSql(
|
||||
queryItemsByKeySql(
|
||||
ContactResource.class,
|
||||
partialStringQuery,
|
||||
cursorQueryString,
|
||||
getDeletedItemHandling()),
|
||||
shouldIncludeDeleted(),
|
||||
querySizeLimit));
|
||||
}
|
||||
}
|
||||
return makeSearchResults(contactResultSet, registrars, QueryType.HANDLE);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.rdap;
|
||||
|
||||
import static com.google.common.base.Charsets.UTF_8;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -24,6 +25,7 @@ import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.cmd.Query;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.persistence.transaction.CriteriaQueryBuilder;
|
||||
import google.registry.rdap.RdapMetrics.EndpointType;
|
||||
import google.registry.rdap.RdapMetrics.WildcardType;
|
||||
import google.registry.rdap.RdapSearchResults.BaseSearchResponse;
|
||||
@@ -40,8 +42,10 @@ import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
|
||||
/**
|
||||
* Base RDAP (new WHOIS) action for domain, nameserver and entity search requests.
|
||||
@@ -161,14 +165,63 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
|
||||
if (desiredRegistrar.isPresent()) {
|
||||
query = query.filter("currentSponsorClientId", desiredRegistrar.get());
|
||||
}
|
||||
if (!checkForVisibility) {
|
||||
return RdapResultSet.create(query.list());
|
||||
List<T> queryResult = query.list();
|
||||
if (checkForVisibility) {
|
||||
return filterResourcesByVisibility(queryResult, querySizeLimit);
|
||||
} else {
|
||||
return RdapResultSet.create(queryResult);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In Cloud SQL, builds and runs the given query, and checks for permissioning if necessary.
|
||||
*
|
||||
* @param builder a query builder that represents the various SELECT FROM, WHERE, ORDER BY and
|
||||
* (etc) clauses that make up this SQL query
|
||||
* @param checkForVisibility true if the results should be checked to make sure they are visible;
|
||||
* normally this should be equal to the shouldIncludeDeleted setting, but in cases where the
|
||||
* query could not check deletion status (due to Datastore limitations such as the limit of
|
||||
* one field queried for inequality, for instance), it may need to be set to true even when
|
||||
* not including deleted records
|
||||
* @param querySizeLimit the maximum number of items the query is expected to return, usually
|
||||
* because the limit has been set
|
||||
* @return an {@link RdapResultSet} object containing the list of resources and an incompleteness
|
||||
* warning flag, which is set to MIGHT_BE_INCOMPLETE iff any resources were excluded due to
|
||||
* lack of visibility, and the resulting list of resources is less than the maximum allowable,
|
||||
* and the number of items returned by the query is greater than or equal to the maximum
|
||||
* number we might have expected
|
||||
*/
|
||||
<T extends EppResource> RdapResultSet<T> getMatchingResourcesSql(
|
||||
CriteriaQueryBuilder<T> builder, boolean checkForVisibility, int querySizeLimit) {
|
||||
jpaTm().assertInTransaction();
|
||||
Optional<String> desiredRegistrar = getDesiredRegistrar();
|
||||
if (desiredRegistrar.isPresent()) {
|
||||
builder =
|
||||
builder.where(
|
||||
jpaTm().getEntityManager().getCriteriaBuilder()::equal,
|
||||
"currentSponsorClientId",
|
||||
desiredRegistrar.get());
|
||||
}
|
||||
List<T> queryResult =
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createQuery(builder.build())
|
||||
.setMaxResults(querySizeLimit)
|
||||
.getResultList();
|
||||
if (checkForVisibility) {
|
||||
return filterResourcesByVisibility(queryResult, querySizeLimit);
|
||||
} else {
|
||||
return RdapResultSet.create(queryResult);
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends EppResource> RdapResultSet<T> filterResourcesByVisibility(
|
||||
List<T> queryResult, int querySizeLimit) {
|
||||
// If we are including deleted resources, we need to check that we're authorized for each one.
|
||||
List<T> resources = new ArrayList<>();
|
||||
int numResourcesQueried = 0;
|
||||
boolean someExcluded = false;
|
||||
for (T resource : query) {
|
||||
for (T resource : queryResult) {
|
||||
if (shouldBeVisible(resource)) {
|
||||
resources.add(resource);
|
||||
} else {
|
||||
@@ -268,8 +321,8 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
|
||||
// to be (more) sure we got everything.
|
||||
int getStandardQuerySizeLimit() {
|
||||
return shouldIncludeDeleted()
|
||||
? (RESULT_SET_SIZE_SCALING_FACTOR * (rdapResultSetMaxSize + 1))
|
||||
: (rdapResultSetMaxSize + 1);
|
||||
? (RESULT_SET_SIZE_SCALING_FACTOR * (rdapResultSetMaxSize + 1))
|
||||
: (rdapResultSetMaxSize + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,9 +364,10 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
|
||||
query = query.filter(filterField, partialStringQuery.getInitialString());
|
||||
} else {
|
||||
// Ignore the suffix; the caller will need to filter on the suffix, if any.
|
||||
query = query
|
||||
.filter(filterField + " >=", partialStringQuery.getInitialString())
|
||||
.filter(filterField + " <", partialStringQuery.getNextInitialString());
|
||||
query =
|
||||
query
|
||||
.filter(filterField + " >=", partialStringQuery.getInitialString())
|
||||
.filter(filterField + " <", partialStringQuery.getNextInitialString());
|
||||
}
|
||||
if (cursorString.isPresent()) {
|
||||
query = query.filter(filterField + " >", cursorString.get());
|
||||
@@ -321,6 +375,59 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
|
||||
return setOtherQueryAttributes(query, deletedItemHandling, resultSetMaxSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* In Cloud SQL, handles prefix searches in cases where, if we need to filter out deleted items,
|
||||
* there are no pending deletes.
|
||||
*
|
||||
* <p>In such cases, it is sufficient to check whether {@code deletionTime} is equal to {@code
|
||||
* END_OF_TIME}, because any other value means it has already been deleted. This allows us to use
|
||||
* an equality query for the deletion time.
|
||||
*
|
||||
* @param clazz the type of resource to be queried
|
||||
* @param filterField the database field of interest
|
||||
* @param partialStringQuery the details of the search string; if there is no wildcard, an
|
||||
* equality query is used; if there is a wildcard, a range query is used instead; the initial
|
||||
* string should not be empty, and any search suffix will be ignored, so the caller must
|
||||
* filter the results if a suffix is specified
|
||||
* @param cursorString if a cursor is present, this parameter should specify the cursor string, to
|
||||
* skip any results up to and including the string; empty() if there is no cursor
|
||||
* @param deletedItemHandling whether to include or exclude deleted items
|
||||
* @return a {@link CriteriaQueryBuilder} object representing the query so far
|
||||
*/
|
||||
static <T extends EppResource> CriteriaQueryBuilder<T> queryItemsSql(
|
||||
Class<T> clazz,
|
||||
String filterField,
|
||||
RdapSearchPattern partialStringQuery,
|
||||
Optional<String> cursorString,
|
||||
DeletedItemHandling deletedItemHandling) {
|
||||
jpaTm().assertInTransaction();
|
||||
if (partialStringQuery.getInitialString().length()
|
||||
< RdapSearchPattern.MIN_INITIAL_STRING_LENGTH) {
|
||||
throw new UnprocessableEntityException(
|
||||
String.format(
|
||||
"Initial search string must be at least %d characters",
|
||||
RdapSearchPattern.MIN_INITIAL_STRING_LENGTH));
|
||||
}
|
||||
CriteriaBuilder criteriaBuilder = jpaTm().getEntityManager().getCriteriaBuilder();
|
||||
CriteriaQueryBuilder<T> builder = CriteriaQueryBuilder.create(clazz);
|
||||
if (partialStringQuery.getHasWildcard()) {
|
||||
builder =
|
||||
builder.where(
|
||||
criteriaBuilder::like,
|
||||
filterField,
|
||||
String.format("%s%%", partialStringQuery.getInitialString()));
|
||||
} else {
|
||||
// no wildcard means we use a standard equals query
|
||||
builder =
|
||||
builder.where(criteriaBuilder::equal, filterField, partialStringQuery.getInitialString());
|
||||
}
|
||||
if (cursorString.isPresent()) {
|
||||
builder = builder.where(criteriaBuilder::greaterThan, filterField, cursorString.get());
|
||||
}
|
||||
builder = builder.orderBy(criteriaBuilder::asc, filterField);
|
||||
return setDeletedItemHandlingSql(builder, deletedItemHandling);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles searches using a simple string rather than an {@link RdapSearchPattern}.
|
||||
*
|
||||
@@ -331,9 +438,9 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
|
||||
* @param filterField the database field of interest
|
||||
* @param queryString the search string
|
||||
* @param cursorField the field which should be compared to the cursor string, or empty() if the
|
||||
* key should be compared to a key created from the cursor string
|
||||
* key should be compared to a key created from the cursor string
|
||||
* @param cursorString if a cursor is present, this parameter should specify the cursor string, to
|
||||
* skip any results up to and including the string; empty() if there is no cursor
|
||||
* skip any results up to and including the string; empty() if there is no cursor
|
||||
* @param deletedItemHandling whether to include or exclude deleted items
|
||||
* @param resultSetMaxSize the maximum number of results to return
|
||||
* @return the query object
|
||||
@@ -363,6 +470,50 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
|
||||
return setOtherQueryAttributes(query, deletedItemHandling, resultSetMaxSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* In Cloud SQL, handles searches using a simple string rather than an {@link RdapSearchPattern}.
|
||||
*
|
||||
* <p>Since the filter is not an inequality, we can support also checking a cursor string against
|
||||
* a different field (which involves an inequality on that field).
|
||||
*
|
||||
* @param clazz the type of resource to be queried
|
||||
* @param filterField the database field of interest
|
||||
* @param queryString the search string
|
||||
* @param cursorField the field which should be compared to the cursor string, or empty() if the
|
||||
* key should be compared to a key created from the cursor string
|
||||
* @param cursorString if a cursor is present, this parameter should specify the cursor string, to
|
||||
* skip any results up to and including the string; empty() if there is no cursor
|
||||
* @param deletedItemHandling whether to include or exclude deleted items
|
||||
* @return a {@link CriteriaQueryBuilder} object representing the query so far
|
||||
*/
|
||||
static <T extends EppResource> CriteriaQueryBuilder<T> queryItemsSql(
|
||||
Class<T> clazz,
|
||||
String filterField,
|
||||
String queryString,
|
||||
Optional<String> cursorField,
|
||||
Optional<String> cursorString,
|
||||
DeletedItemHandling deletedItemHandling) {
|
||||
if (queryString.length() < RdapSearchPattern.MIN_INITIAL_STRING_LENGTH) {
|
||||
throw new UnprocessableEntityException(
|
||||
String.format(
|
||||
"Initial search string must be at least %d characters",
|
||||
RdapSearchPattern.MIN_INITIAL_STRING_LENGTH));
|
||||
}
|
||||
jpaTm().assertInTransaction();
|
||||
CriteriaQueryBuilder<T> builder = CriteriaQueryBuilder.create(clazz);
|
||||
CriteriaBuilder criteriaBuilder = jpaTm().getEntityManager().getCriteriaBuilder();
|
||||
builder = builder.where(criteriaBuilder::equal, filterField, queryString);
|
||||
if (cursorString.isPresent()) {
|
||||
if (cursorField.isPresent()) {
|
||||
builder =
|
||||
builder.where(criteriaBuilder::greaterThan, cursorField.get(), cursorString.get());
|
||||
} else {
|
||||
builder = builder.where(criteriaBuilder::greaterThan, "repoId", cursorString.get());
|
||||
}
|
||||
}
|
||||
return setDeletedItemHandlingSql(builder, deletedItemHandling);
|
||||
}
|
||||
|
||||
/** Handles searches where the field to be searched is the key. */
|
||||
static <T extends EppResource> Query<T> queryItemsByKey(
|
||||
Class<T> clazz,
|
||||
@@ -382,9 +533,10 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
|
||||
query = query.filterKey("=", Key.create(clazz, partialStringQuery.getInitialString()));
|
||||
} else {
|
||||
// Ignore the suffix; the caller will need to filter on the suffix, if any.
|
||||
query = query
|
||||
.filterKey(">=", Key.create(clazz, partialStringQuery.getInitialString()))
|
||||
.filterKey("<", Key.create(clazz, partialStringQuery.getNextInitialString()));
|
||||
query =
|
||||
query
|
||||
.filterKey(">=", Key.create(clazz, partialStringQuery.getInitialString()))
|
||||
.filterKey("<", Key.create(clazz, partialStringQuery.getNextInitialString()));
|
||||
}
|
||||
if (cursorString.isPresent()) {
|
||||
query = query.filterKey(">", Key.create(clazz, cursorString.get()));
|
||||
@@ -392,6 +544,26 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
|
||||
return setOtherQueryAttributes(query, deletedItemHandling, resultSetMaxSize);
|
||||
}
|
||||
|
||||
/** In Cloud SQL, handles searches where the field to be searched is the key. */
|
||||
static <T extends EppResource> CriteriaQueryBuilder<T> queryItemsByKeySql(
|
||||
Class<T> clazz,
|
||||
RdapSearchPattern partialStringQuery,
|
||||
Optional<String> cursorString,
|
||||
DeletedItemHandling deletedItemHandling) {
|
||||
jpaTm().assertInTransaction();
|
||||
return queryItemsSql(clazz, "repoId", partialStringQuery, cursorString, deletedItemHandling);
|
||||
}
|
||||
|
||||
static <T extends EppResource> CriteriaQueryBuilder<T> setDeletedItemHandlingSql(
|
||||
CriteriaQueryBuilder<T> builder, DeletedItemHandling deletedItemHandling) {
|
||||
if (!Objects.equals(deletedItemHandling, DeletedItemHandling.INCLUDE)) {
|
||||
builder =
|
||||
builder.where(
|
||||
jpaTm().getEntityManager().getCriteriaBuilder()::equal, "deletionTime", END_OF_TIME);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
static <T extends EppResource> Query<T> setOtherQueryAttributes(
|
||||
Query<T> query, DeletedItemHandling deletedItemHandling, int resultSetMaxSize) {
|
||||
if (deletedItemHandling != DeletedItemHandling.INCLUDE) {
|
||||
|
||||
@@ -135,7 +135,7 @@ public class RequestHandler<C> {
|
||||
return;
|
||||
}
|
||||
if (!route.get().isMethodAllowed(method)) {
|
||||
logger.atInfo().log("Method %s not allowed for: %s", method, path);
|
||||
logger.atWarning().log("Method %s not allowed for: %s", method, path);
|
||||
rsp.sendError(SC_METHOD_NOT_ALLOWED);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright 2021 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.schema.replay;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.ImmutableObject;
|
||||
|
||||
/** Datastore entity to keep track of the last SQL transaction imported into the datastore. */
|
||||
@Entity
|
||||
public class LastSqlTransaction extends ImmutableObject implements DatastoreOnlyEntity {
|
||||
|
||||
/** The key for this singleton. */
|
||||
public static final Key<LastSqlTransaction> KEY = Key.create(LastSqlTransaction.class, 1);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Id
|
||||
private long id = 1;
|
||||
|
||||
private long transactionId;
|
||||
|
||||
LastSqlTransaction() {}
|
||||
|
||||
@VisibleForTesting
|
||||
LastSqlTransaction(long newTransactionId) {
|
||||
transactionId = newTransactionId;
|
||||
}
|
||||
|
||||
LastSqlTransaction cloneWithNewTransactionId(long transactionId) {
|
||||
checkArgument(
|
||||
transactionId > this.transactionId,
|
||||
"New transaction id (%s) must be greater than the current transaction id (%s)",
|
||||
transactionId,
|
||||
this.transactionId);
|
||||
return new LastSqlTransaction(transactionId);
|
||||
}
|
||||
|
||||
long getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the instance.
|
||||
*
|
||||
* <p>Must be called within an Ofy transaction.
|
||||
*
|
||||
* <p>Creates a new instance of the singleton if it is not already present in Cloud Datastore,
|
||||
*/
|
||||
static LastSqlTransaction load() {
|
||||
ofy().assertInTransaction();
|
||||
LastSqlTransaction result = ofy().load().key(KEY).now();
|
||||
return result == null ? new LastSqlTransaction() : result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
// Copyright 2021 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.schema.replay;
|
||||
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.persistence.transaction.Transaction;
|
||||
import google.registry.persistence.transaction.TransactionEntity;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.auth.Auth;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.persistence.NoResultException;
|
||||
|
||||
/** Cron task to replicate from Cloud SQL to datastore. */
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
path = ReplicateToDatastoreAction.PATH,
|
||||
method = GET,
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_INTERNAL_OR_ADMIN)
|
||||
class ReplicateToDatastoreAction implements Runnable {
|
||||
public static final String PATH = "/_dr/cron/replicateToDatastore";
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
/**
|
||||
* Number of transactions to fetch from SQL. The rationale for 200 is that we're processing these
|
||||
* every minute and our production instance currently does about 2 mutations per second, so this
|
||||
* should generally be enough to scoop up all of the transactions for the past minute.
|
||||
*/
|
||||
public static final int BATCH_SIZE = 200;
|
||||
|
||||
@VisibleForTesting
|
||||
List<TransactionEntity> getTransactionBatch() {
|
||||
// Get the next batch of transactions that we haven't replicated.
|
||||
LastSqlTransaction lastSqlTxnBeforeBatch = ofyTm().transact(() -> LastSqlTransaction.load());
|
||||
try {
|
||||
return jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createQuery(
|
||||
"SELECT txn FROM TransactionEntity txn WHERE id >"
|
||||
+ " :lastId ORDER BY id")
|
||||
.setParameter("lastId", lastSqlTxnBeforeBatch.getTransactionId())
|
||||
.setMaxResults(BATCH_SIZE)
|
||||
.getResultList());
|
||||
} catch (NoResultException e) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a transaction to datastore, returns true if there was a fatal error and the batch should
|
||||
* be aborted.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean applyTransaction(TransactionEntity txnEntity) {
|
||||
logger.atInfo().log("Applying a single transaction Cloud SQL -> Cloud Datastore");
|
||||
return ofyTm()
|
||||
.transact(
|
||||
() -> {
|
||||
// Reload the last transaction id, which could possibly have changed.
|
||||
LastSqlTransaction lastSqlTxn = LastSqlTransaction.load();
|
||||
long nextTxnId = lastSqlTxn.getTransactionId() + 1;
|
||||
if (nextTxnId < txnEntity.getId()) {
|
||||
// We're missing a transaction. This is bad. Transaction ids are supposed to
|
||||
// increase monotonically, so we abort rather than applying anything out of
|
||||
// order.
|
||||
logger.atSevere().log(
|
||||
"Missing transaction: last transaction id = %s, next available transaction "
|
||||
+ "= %s",
|
||||
nextTxnId - 1, txnEntity.getId());
|
||||
return true;
|
||||
} else if (nextTxnId > txnEntity.getId()) {
|
||||
// We've already replayed this transaction. This shouldn't happen, as GAE cron
|
||||
// is supposed to avoid overruns and this action shouldn't be executed from any
|
||||
// other context, but it's not harmful as we can just ignore the transaction. Log
|
||||
// it so that we know about it and move on.
|
||||
logger.atWarning().log(
|
||||
"Ignoring transaction %s, which appears to have already been applied.",
|
||||
txnEntity.getId());
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.atInfo().log("Applying transaction %s to Cloud Datastore", txnEntity.getId());
|
||||
|
||||
// At this point, we know txnEntity is the correct next transaction, so write it
|
||||
// to datastore.
|
||||
try {
|
||||
Transaction.deserialize(txnEntity.getContents()).writeToDatastore();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error during transaction deserialization.", e);
|
||||
}
|
||||
|
||||
// Write the updated last transaction id to datastore as part of this datastore
|
||||
// transaction.
|
||||
ofy().save().entity(lastSqlTxn.cloneWithNewTransactionId(nextTxnId));
|
||||
logger.atInfo().log(
|
||||
"Finished applying single transaction Cloud SQL -> Cloud Datastore");
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// TODO(b/181758163): Deal with objects that don't exist in Cloud SQL, e.g. ForeignKeyIndex,
|
||||
// EppResourceIndex.
|
||||
logger.atInfo().log("Processing transaction replay batch Cloud SQL -> Cloud Datastore");
|
||||
for (TransactionEntity txnEntity : getTransactionBatch()) {
|
||||
if (applyTransaction(txnEntity)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
logger.atInfo().log("Done processing transaction replay batch Cloud SQL -> Cloud Datastore");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2021 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 com.google.common.collect.Streams;
|
||||
import google.registry.model.registry.label.PremiumList.PremiumListEntry;
|
||||
import google.registry.model.registry.label.PremiumListDualDao;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/** Retrieves and prints one or more premium lists. */
|
||||
@Parameters(separators = " =", commandDescription = "Show one or more premium lists")
|
||||
public class GetPremiumListCommand implements CommandWithRemoteApi {
|
||||
|
||||
@Parameter(description = "Name(s) of the premium list(s) to retrieve", required = true)
|
||||
private List<String> mainParameters;
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
for (String premiumListName : mainParameters) {
|
||||
if (PremiumListDualDao.exists(premiumListName)) {
|
||||
System.out.printf(
|
||||
"%s:\n%s\n",
|
||||
premiumListName,
|
||||
Streams.stream(PremiumListDualDao.loadAllPremiumListEntries(premiumListName))
|
||||
.sorted(Comparator.comparing(PremiumListEntry::getLabel))
|
||||
.map(PremiumListEntry::toString)
|
||||
.collect(Collectors.joining("\n")));
|
||||
} else {
|
||||
System.out.println(String.format("No list found with name %s.", premiumListName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,7 @@ public final class RegistryTool {
|
||||
.put("get_host", GetHostCommand.class)
|
||||
.put("get_keyring_secret", GetKeyringSecretCommand.class)
|
||||
.put("get_operation_status", GetOperationStatusCommand.class)
|
||||
.put("get_premium_list", GetPremiumListCommand.class)
|
||||
.put("get_registrar", GetRegistrarCommand.class)
|
||||
.put("get_resource_by_key", GetResourceByKeyCommand.class)
|
||||
.put("get_routing_map", GetRoutingMapCommand.class)
|
||||
|
||||
@@ -25,12 +25,19 @@ import google.registry.flows.ResourceCheckFlowTestCase;
|
||||
import google.registry.flows.exceptions.TooManyResourceChecksException;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.ReplayExtension;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ContactCheckFlow}. */
|
||||
@DualDatabaseTest
|
||||
class ContactCheckFlowTest extends ResourceCheckFlowTestCase<ContactCheckFlow, ContactResource> {
|
||||
|
||||
@Order(value = Order.DEFAULT - 2)
|
||||
@RegisterExtension
|
||||
final ReplayExtension replayExtension = ReplayExtension.createWithCompare(clock);
|
||||
|
||||
ContactCheckFlowTest() {
|
||||
setEppInput("contact_check.xml");
|
||||
}
|
||||
|
||||
@@ -33,13 +33,20 @@ import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientExcept
|
||||
import google.registry.flows.exceptions.ResourceCreateContentionException;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.ReplayExtension;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ContactCreateFlow}. */
|
||||
@DualDatabaseTest
|
||||
class ContactCreateFlowTest extends ResourceFlowTestCase<ContactCreateFlow, ContactResource> {
|
||||
|
||||
@Order(value = Order.DEFAULT - 2)
|
||||
@RegisterExtension
|
||||
final ReplayExtension replayExtension = ReplayExtension.createWithCompare(clock);
|
||||
|
||||
ContactCreateFlowTest() {
|
||||
setEppInput("contact_create.xml");
|
||||
clock.setTo(DateTime.parse("1999-04-03T22:00:00.0Z"));
|
||||
|
||||
@@ -38,13 +38,20 @@ import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.ReplayExtension;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ContactDeleteFlow}. */
|
||||
@DualDatabaseTest
|
||||
class ContactDeleteFlowTest extends ResourceFlowTestCase<ContactDeleteFlow, ContactResource> {
|
||||
|
||||
@Order(value = Order.DEFAULT - 2)
|
||||
@RegisterExtension
|
||||
final ReplayExtension replayExtension = ReplayExtension.createWithCompare(clock);
|
||||
|
||||
@BeforeEach
|
||||
void initFlowTest() {
|
||||
setEppInput("contact_delete.xml");
|
||||
|
||||
@@ -39,13 +39,20 @@ import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.eppcommon.PresenceMarker;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.ReplayExtension;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ContactInfoFlow}. */
|
||||
@DualDatabaseTest
|
||||
class ContactInfoFlowTest extends ResourceFlowTestCase<ContactInfoFlow, ContactResource> {
|
||||
|
||||
@Order(value = Order.DEFAULT - 2)
|
||||
@RegisterExtension
|
||||
final ReplayExtension replayExtension = ReplayExtension.createWithCompare(clock);
|
||||
|
||||
ContactInfoFlowTest() {
|
||||
setEppInput("contact_info.xml");
|
||||
}
|
||||
|
||||
@@ -38,14 +38,21 @@ import google.registry.model.transfer.TransferData;
|
||||
import google.registry.model.transfer.TransferResponse;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.ReplayExtension;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ContactTransferCancelFlow}. */
|
||||
@DualDatabaseTest
|
||||
class ContactTransferCancelFlowTest
|
||||
extends ContactTransferFlowTestCase<ContactTransferCancelFlow, ContactResource> {
|
||||
|
||||
@Order(value = Order.DEFAULT - 2)
|
||||
@RegisterExtension
|
||||
final ReplayExtension replayExtension = ReplayExtension.createWithCompare(clock);
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.setEppInput("contact_transfer_cancel.xml");
|
||||
|
||||
@@ -40,14 +40,21 @@ import google.registry.model.transfer.TransferData;
|
||||
import google.registry.model.transfer.TransferResponse;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.ReplayExtension;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ContactTransferRejectFlow}. */
|
||||
@DualDatabaseTest
|
||||
class ContactTransferRejectFlowTest
|
||||
extends ContactTransferFlowTestCase<ContactTransferRejectFlow, ContactResource> {
|
||||
|
||||
@Order(value = Order.DEFAULT - 2)
|
||||
@RegisterExtension
|
||||
final ReplayExtension replayExtension = ReplayExtension.createWithCompare(clock);
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
setEppInput("contact_transfer_reject.xml");
|
||||
|
||||
@@ -52,15 +52,22 @@ import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.ContactTransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.ReplayExtension;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ContactTransferRequestFlow}. */
|
||||
@DualDatabaseTest
|
||||
class ContactTransferRequestFlowTest
|
||||
extends ContactTransferFlowTestCase<ContactTransferRequestFlow, ContactResource> {
|
||||
|
||||
@Order(value = Order.DEFAULT - 2)
|
||||
@RegisterExtension
|
||||
final ReplayExtension replayExtension = ReplayExtension.createWithCompare(clock);
|
||||
|
||||
ContactTransferRequestFlowTest() {
|
||||
// We need the transfer to happen at exactly this time in order for the response to match up.
|
||||
clock.setTo(DateTime.parse("2000-06-08T22:00:00.0Z"));
|
||||
|
||||
@@ -71,16 +71,29 @@ import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.Registry.TldState;
|
||||
import google.registry.model.registry.label.ReservedList;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.testing.ReplayExtension;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link DomainCheckFlow}. */
|
||||
class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, DomainBase> {
|
||||
|
||||
@Order(value = Order.DEFAULT - 3)
|
||||
@RegisterExtension
|
||||
final SetClockExtension setClockExtension = new SetClockExtension();
|
||||
|
||||
@Order(value = Order.DEFAULT - 2)
|
||||
@RegisterExtension
|
||||
final ReplayExtension replayExtension = ReplayExtension.createWithCompare(clock);
|
||||
|
||||
DomainCheckFlowTest() {
|
||||
setEppInput("domain_check_one_tld.xml");
|
||||
}
|
||||
@@ -1338,4 +1351,12 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE))
|
||||
.build());
|
||||
}
|
||||
|
||||
class SetClockExtension implements BeforeEachCallback {
|
||||
@Override
|
||||
public void beforeEach(ExtensionContext context) {
|
||||
// Kick the clock back to before the earliest date that we set the clock to.
|
||||
clock.setTo(DateTime.parse("2009-01-01T10:00:00Z"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,13 +36,20 @@ import google.registry.flows.exceptions.TooManyResourceChecksException;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.Registry.TldState;
|
||||
import google.registry.testing.ReplayExtension;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link DomainClaimsCheckFlow}. */
|
||||
public class DomainClaimsCheckFlowTest
|
||||
extends ResourceFlowTestCase<DomainClaimsCheckFlow, DomainBase> {
|
||||
|
||||
@Order(value = Order.DEFAULT - 2)
|
||||
@RegisterExtension
|
||||
final ReplayExtension replayExtension = ReplayExtension.createWithCompare(clock);
|
||||
|
||||
DomainClaimsCheckFlowTest() {
|
||||
setEppInput("domain_check_claims.xml");
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import static google.registry.testing.DatabaseHelper.persistActiveHost;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
|
||||
import static google.registry.testing.TestDataHelper.updateSubstitutions;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@@ -45,7 +46,8 @@ import google.registry.flows.domain.DomainFlowUtils.FeeChecksDontSupportPhasesEx
|
||||
import google.registry.flows.domain.DomainFlowUtils.RestoresAreAlwaysForOneYearException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.TransfersAreAlwaysForOneYearException;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Recurring;
|
||||
import google.registry.model.billing.BillingEvent.Flag;
|
||||
import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.contact.ContactAuthInfo;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
@@ -63,13 +65,26 @@ import google.registry.model.registry.Registry;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.ReplayExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link DomainInfoFlow}. */
|
||||
class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase> {
|
||||
|
||||
@Order(value = Order.DEFAULT - 3)
|
||||
@RegisterExtension
|
||||
final SetClockExtension setClockExtension = new SetClockExtension();
|
||||
|
||||
@Order(value = Order.DEFAULT - 2)
|
||||
@RegisterExtension
|
||||
final ReplayExtension replayExtension = ReplayExtension.createWithCompare(clock);
|
||||
|
||||
/**
|
||||
* The domain_info_fee.xml default substitutions common to most tests.
|
||||
*
|
||||
@@ -93,7 +108,6 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
void setup() {
|
||||
setEppInput("domain_info.xml");
|
||||
sessionMetadata.setClientId("NewRegistrar");
|
||||
clock.setTo(DateTime.parse("2005-03-03T22:00:00.000Z"));
|
||||
createTld("tld");
|
||||
persistResource(AppEngineExtension.makeRegistrar1().asBuilder().setClientId("ClientZ").build());
|
||||
}
|
||||
@@ -149,7 +163,10 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
}
|
||||
|
||||
private void doSuccessfulTest(
|
||||
String expectedXmlFilename, boolean inactive, ImmutableMap<String, String> substitutions)
|
||||
String expectedXmlFilename,
|
||||
boolean inactive,
|
||||
ImmutableMap<String, String> substitutions,
|
||||
boolean expectHistoryAndBilling)
|
||||
throws Exception {
|
||||
assertTransactionalFlow(false);
|
||||
String expected =
|
||||
@@ -158,12 +175,20 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
expected = expected.replaceAll("\"ok\"", "\"inactive\"");
|
||||
}
|
||||
runFlowAssertResponse(expected);
|
||||
assertNoHistory();
|
||||
assertNoBillingEvents();
|
||||
if (!expectHistoryAndBilling) {
|
||||
assertNoHistory();
|
||||
assertNoBillingEvents();
|
||||
}
|
||||
}
|
||||
|
||||
private void doSuccessfulTest(
|
||||
String expectedXmlFilename, boolean inactive, ImmutableMap<String, String> substitutions)
|
||||
throws Exception {
|
||||
doSuccessfulTest(expectedXmlFilename, inactive, substitutions, false);
|
||||
}
|
||||
|
||||
private void doSuccessfulTest(String expectedXmlFilename, boolean inactive) throws Exception {
|
||||
doSuccessfulTest(expectedXmlFilename, inactive, ImmutableMap.of());
|
||||
doSuccessfulTest(expectedXmlFilename, inactive, ImmutableMap.of(), false);
|
||||
}
|
||||
|
||||
private void doSuccessfulTest(String expectedXmlFilename) throws Exception {
|
||||
@@ -309,7 +334,11 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
.asBuilder()
|
||||
.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
gracePeriodStatus, domain.getRepoId(), clock.nowUtc().plusDays(1), "foo", null))
|
||||
gracePeriodStatus,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.setCreationClientId("NewRegistrar")
|
||||
.setCreationTimeForTest(DateTime.parse("2003-11-26T22:00:00.0Z"))
|
||||
.setRegistrationExpirationTime(DateTime.parse("2005-11-26T22:00:00.0Z"))
|
||||
@@ -328,10 +357,25 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
@Test
|
||||
void testSuccess_autoRenewGracePeriod() throws Exception {
|
||||
persistTestEntities(false);
|
||||
Key<HistoryEntry> historyEntry =
|
||||
Key.create(domain.createVKey().getOfyKey(), HistoryEntry.class, 67890);
|
||||
VKey<BillingEvent.Recurring> recurringVKey =
|
||||
VKey.from(Key.create(historyEntry, Recurring.class, 12345));
|
||||
HistoryEntry historyEntry =
|
||||
persistResource(
|
||||
new HistoryEntry.Builder()
|
||||
.setParent(domain)
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.setModificationTime(clock.nowUtc())
|
||||
.build());
|
||||
BillingEvent.Recurring renewEvent =
|
||||
persistResource(
|
||||
new BillingEvent.Recurring.Builder()
|
||||
.setReason(Reason.RENEW)
|
||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||
.setTargetId(getUniqueIdFromCommand())
|
||||
.setClientId("TheRegistrar")
|
||||
.setEventTime(clock.nowUtc())
|
||||
.setRecurrenceEndTime(END_OF_TIME)
|
||||
.setParent(historyEntry)
|
||||
.build());
|
||||
VKey<BillingEvent.Recurring> recurringVKey = renewEvent.createVKey();
|
||||
// Add an AUTO_RENEW grace period to the saved resource.
|
||||
persistResource(
|
||||
domain
|
||||
@@ -341,10 +385,10 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
GracePeriodStatus.AUTO_RENEW,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"foo",
|
||||
"TheRegistrar",
|
||||
recurringVKey))
|
||||
.build());
|
||||
doSuccessfulTest("domain_info_response_autorenewperiod.xml", false);
|
||||
doSuccessfulTest("domain_info_response_autorenewperiod.xml", false, ImmutableMap.of(), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -360,7 +404,7 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
GracePeriodStatus.REDEMPTION,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"foo",
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE))
|
||||
.build());
|
||||
@@ -379,7 +423,7 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
GracePeriodStatus.RENEW,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"foo",
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.build());
|
||||
doSuccessfulTest("domain_info_response_renewperiod.xml", false);
|
||||
@@ -397,14 +441,14 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
GracePeriodStatus.RENEW,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"foo",
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.RENEW,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(2),
|
||||
"foo",
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.build());
|
||||
doSuccessfulTest("domain_info_response_renewperiod.xml", false);
|
||||
@@ -422,7 +466,7 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
GracePeriodStatus.TRANSFER,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"foo",
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.build());
|
||||
doSuccessfulTest("domain_info_response_transferperiod.xml", false);
|
||||
@@ -450,14 +494,14 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
GracePeriodStatus.ADD,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"foo",
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.RENEW,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(2),
|
||||
"foo",
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.build());
|
||||
doSuccessfulTest("domain_info_response_stackedaddrenewperiod.xml", false);
|
||||
@@ -475,7 +519,7 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
GracePeriodStatus.ADD,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"foo",
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.setDsData(
|
||||
ImmutableSet.of(
|
||||
@@ -929,4 +973,12 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase
|
||||
assertIcannReportingActivityFieldLogged("srs-dom-info");
|
||||
assertTldsFieldLogged("tld");
|
||||
}
|
||||
|
||||
class SetClockExtension implements BeforeEachCallback {
|
||||
@Override
|
||||
public void beforeEach(ExtensionContext context) {
|
||||
// Kick the clock back to before the earliest date that we set the clock to.
|
||||
clock.setTo(DateTime.parse("2005-03-03T22:00:00.000Z"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,16 +70,23 @@ import google.registry.model.registry.Registry;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.testing.ReplayExtension;
|
||||
import java.util.Map;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link DomainRestoreRequestFlow}. */
|
||||
class DomainRestoreRequestFlowTest
|
||||
extends ResourceFlowTestCase<DomainRestoreRequestFlow, DomainBase> {
|
||||
|
||||
@Order(value = Order.DEFAULT - 2)
|
||||
@RegisterExtension
|
||||
final ReplayExtension replayExtension = ReplayExtension.createWithCompare(clock);
|
||||
|
||||
private static final ImmutableMap<String, String> FEE_06_MAP =
|
||||
ImmutableMap.of("FEE_VERSION", "0.6", "FEE_NS", "fee", "CURRENCY", "USD");
|
||||
private static final ImmutableMap<String, String> FEE_11_MAP =
|
||||
@@ -99,11 +106,12 @@ class DomainRestoreRequestFlowTest
|
||||
}
|
||||
|
||||
void persistPendingDeleteDomain(DateTime expirationTime) throws Exception {
|
||||
DomainBase domain = newDomainBase(getUniqueIdFromCommand());
|
||||
DomainBase domain = persistResource(newDomainBase(getUniqueIdFromCommand()));
|
||||
HistoryEntry historyEntry =
|
||||
persistResource(
|
||||
new HistoryEntry.Builder()
|
||||
.setType(HistoryEntry.Type.DOMAIN_DELETE)
|
||||
.setModificationTime(clock.nowUtc())
|
||||
.setParent(domain)
|
||||
.build());
|
||||
persistResource(
|
||||
@@ -116,7 +124,7 @@ class DomainRestoreRequestFlowTest
|
||||
GracePeriodStatus.REDEMPTION,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"foo",
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE))
|
||||
.setDeletePollMessage(
|
||||
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
// Copyright 2021 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 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.JpaUnitTestExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Tests for {@link CriteriaQueryBuilder}. */
|
||||
class CriteriaQueryBuilderTest {
|
||||
|
||||
private final FakeClock fakeClock = new FakeClock();
|
||||
|
||||
private CriteriaQueryBuilderTestEntity entity1 =
|
||||
new CriteriaQueryBuilderTestEntity("name1", "data");
|
||||
private CriteriaQueryBuilderTestEntity entity2 =
|
||||
new CriteriaQueryBuilderTestEntity("name2", "zztz");
|
||||
private CriteriaQueryBuilderTestEntity entity3 = new CriteriaQueryBuilderTestEntity("zzz", "aaa");
|
||||
|
||||
@RegisterExtension
|
||||
final JpaUnitTestExtension jpaExtension =
|
||||
new JpaTestRules.Builder()
|
||||
.withClock(fakeClock)
|
||||
.withEntityClass(CriteriaQueryBuilderTestEntity.class)
|
||||
.buildUnitTestRule();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
jpaTm().transact(() -> jpaTm().putAll(ImmutableList.of(entity1, entity2, entity3)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_noWhereClause() {
|
||||
assertThat(
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createQuery(
|
||||
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
|
||||
.build())
|
||||
.getResultList()))
|
||||
.containsExactly(entity1, entity2, entity3)
|
||||
.inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_where_exactlyOne() {
|
||||
List<CriteriaQueryBuilderTestEntity> result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
CriteriaQuery<CriteriaQueryBuilderTestEntity> query =
|
||||
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
|
||||
.where(
|
||||
jpaTm().getEntityManager().getCriteriaBuilder()::equal,
|
||||
"data",
|
||||
"zztz")
|
||||
.build();
|
||||
return jpaTm().getEntityManager().createQuery(query).getResultList();
|
||||
});
|
||||
assertThat(result).containsExactly(entity2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_where_like_oneResult() {
|
||||
List<CriteriaQueryBuilderTestEntity> result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
CriteriaQuery<CriteriaQueryBuilderTestEntity> query =
|
||||
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
|
||||
.where(
|
||||
jpaTm().getEntityManager().getCriteriaBuilder()::like, "data", "a%")
|
||||
.build();
|
||||
return jpaTm().getEntityManager().createQuery(query).getResultList();
|
||||
});
|
||||
assertThat(result).containsExactly(entity3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_where_like_twoResults() {
|
||||
List<CriteriaQueryBuilderTestEntity> result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
CriteriaQuery<CriteriaQueryBuilderTestEntity> query =
|
||||
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
|
||||
.where(
|
||||
jpaTm().getEntityManager().getCriteriaBuilder()::like, "data", "%a%")
|
||||
.build();
|
||||
return jpaTm().getEntityManager().createQuery(query).getResultList();
|
||||
});
|
||||
assertThat(result).containsExactly(entity1, entity3).inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_multipleWheres() {
|
||||
List<CriteriaQueryBuilderTestEntity> result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
CriteriaQuery<CriteriaQueryBuilderTestEntity> query =
|
||||
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
|
||||
// first "where" matches 1 and 3
|
||||
.where(
|
||||
jpaTm().getEntityManager().getCriteriaBuilder()::like, "data", "%a%")
|
||||
// second "where" matches 1 and 2
|
||||
.where(
|
||||
jpaTm().getEntityManager().getCriteriaBuilder()::like, "data", "%t%")
|
||||
.build();
|
||||
return jpaTm().getEntityManager().createQuery(query).getResultList();
|
||||
});
|
||||
assertThat(result).containsExactly(entity1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_where_in_oneResult() {
|
||||
List<CriteriaQueryBuilderTestEntity> result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
CriteriaQuery<CriteriaQueryBuilderTestEntity> query =
|
||||
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
|
||||
.whereFieldIsIn("data", ImmutableList.of("aaa", "bbb"))
|
||||
.build();
|
||||
return jpaTm().getEntityManager().createQuery(query).getResultList();
|
||||
});
|
||||
assertThat(result).containsExactly(entity3).inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_where_in_twoResults() {
|
||||
List<CriteriaQueryBuilderTestEntity> result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
CriteriaQuery<CriteriaQueryBuilderTestEntity> query =
|
||||
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
|
||||
.whereFieldIsIn("data", ImmutableList.of("aaa", "bbb", "data"))
|
||||
.build();
|
||||
return jpaTm().getEntityManager().createQuery(query).getResultList();
|
||||
});
|
||||
assertThat(result).containsExactly(entity1, entity3).inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_orderBy() {
|
||||
List<CriteriaQueryBuilderTestEntity> result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
CriteriaQuery<CriteriaQueryBuilderTestEntity> query =
|
||||
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
|
||||
.orderBy(jpaTm().getEntityManager().getCriteriaBuilder()::asc, "data")
|
||||
.where(
|
||||
jpaTm().getEntityManager().getCriteriaBuilder()::like, "data", "%a%")
|
||||
.build();
|
||||
return jpaTm().getEntityManager().createQuery(query).getResultList();
|
||||
});
|
||||
assertThat(result).containsExactly(entity3, entity1).inOrder();
|
||||
}
|
||||
|
||||
@Entity(name = "CriteriaQueryBuilderTestEntity")
|
||||
private static class CriteriaQueryBuilderTestEntity extends ImmutableObject {
|
||||
@Id private String name;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private String data;
|
||||
|
||||
private CriteriaQueryBuilderTestEntity() {}
|
||||
|
||||
private CriteriaQueryBuilderTestEntity(String name, String data) {
|
||||
this.name = name;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,7 @@ class TransactionTest {
|
||||
});
|
||||
TransactionEntity txnEnt =
|
||||
jpaTm().transact(() -> jpaTm().loadByKey(VKey.createSql(TransactionEntity.class, 1L)));
|
||||
Transaction txn = Transaction.deserialize(txnEnt.contents);
|
||||
Transaction txn = Transaction.deserialize(txnEnt.getContents());
|
||||
txn.writeToDatastore();
|
||||
ofyTm()
|
||||
.transact(
|
||||
|
||||
@@ -43,14 +43,16 @@ import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.rdap.RdapMetrics.EndpointType;
|
||||
import google.registry.rdap.RdapMetrics.SearchType;
|
||||
import google.registry.rdap.RdapSearchResults.IncompletenessWarningType;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link RdapEntitySearchAction}. */
|
||||
@DualDatabaseTest
|
||||
class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySearchAction> {
|
||||
|
||||
RdapEntitySearchActionTest() {
|
||||
@@ -209,9 +211,9 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
.asBuilder()
|
||||
.setRepoId(String.format("%04d-ROID", i))
|
||||
.build();
|
||||
resourcesBuilder.add(contact);
|
||||
resourcesBuilder.add(makeHistoryEntry(
|
||||
contact, HistoryEntry.Type.CONTACT_CREATE, null, "created", clock.nowUtc()));
|
||||
resourcesBuilder.add(contact);
|
||||
}
|
||||
persistResources(resourcesBuilder.build());
|
||||
for (int i = 1; i <= numRegistrars; i++) {
|
||||
@@ -386,7 +388,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testInvalidPath_rejected() {
|
||||
action.requestPath = actionPath + "/path";
|
||||
action.run();
|
||||
@@ -394,7 +396,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(Optional.empty(), 400);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testInvalidRequest_rejected() {
|
||||
action.run();
|
||||
assertThat(parseJsonObject(response.getPayload()))
|
||||
@@ -405,7 +407,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(Optional.empty(), 400);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatch_suffixRejected() {
|
||||
assertThat(generateActualJsonWithFullName("exam*ple"))
|
||||
.isEqualTo(
|
||||
@@ -417,7 +419,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(Optional.empty(), 422);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatch_suffixRejected() {
|
||||
assertThat(generateActualJsonWithHandle("exam*ple"))
|
||||
.isEqualTo(
|
||||
@@ -429,7 +431,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(Optional.empty(), 422);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testMultipleWildcards_rejected() {
|
||||
assertThat(generateActualJsonWithHandle("*.*"))
|
||||
.isEqualTo(
|
||||
@@ -441,7 +443,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(Optional.empty(), 422);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNoCharactersToMatch_rejected() {
|
||||
rememberWildcardType("*");
|
||||
assertThat(generateActualJsonWithHandle("*"))
|
||||
@@ -453,7 +455,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(Optional.empty(), 422);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testFewerThanTwoCharactersToMatch_rejected() {
|
||||
rememberWildcardType("a*");
|
||||
assertThat(generateActualJsonWithHandle("a*"))
|
||||
@@ -465,7 +467,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(Optional.empty(), 422);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testInvalidSubtype_rejected() {
|
||||
action.subtypeParam = Optional.of("Space Aliens");
|
||||
assertThat(generateActualJsonWithFullName("Blinky (赤ベイ)"))
|
||||
@@ -478,14 +480,14 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(Optional.empty(), 400);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_found() {
|
||||
login("2-RegistrarTest");
|
||||
runSuccessfulNameTestWithBlinky("Blinky (赤ベイ)", "rdap_contact.json");
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_found_subtypeAll() {
|
||||
login("2-RegistrarTest");
|
||||
action.subtypeParam = Optional.of("aLl");
|
||||
@@ -493,7 +495,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_found_subtypeContacts() {
|
||||
login("2-RegistrarTest");
|
||||
action.subtypeParam = Optional.of("cONTACTS");
|
||||
@@ -501,7 +503,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_notFound_subtypeRegistrars() {
|
||||
login("2-RegistrarTest");
|
||||
action.subtypeParam = Optional.of("Registrars");
|
||||
@@ -509,7 +511,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_found_specifyingSameRegistrar() {
|
||||
login("2-RegistrarTest");
|
||||
action.registrarParam = Optional.of("2-RegistrarTest");
|
||||
@@ -517,7 +519,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_notFound_specifyingOtherRegistrar() {
|
||||
login("2-RegistrarTest");
|
||||
action.registrarParam = Optional.of("2-RegistrarInact");
|
||||
@@ -525,7 +527,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_found_asAdministrator() {
|
||||
loginAsAdmin();
|
||||
rememberWildcardType("Blinky (赤ベイ)");
|
||||
@@ -533,27 +535,27 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_notFound_notLoggedIn() {
|
||||
runNotFoundNameTest("Blinky (赤ベイ)");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_notFound_loggedInAsOtherRegistrar() {
|
||||
login("2-Registrar");
|
||||
runNotFoundNameTest("Blinky (赤ベイ)");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_found_wildcard() {
|
||||
login("2-RegistrarTest");
|
||||
runSuccessfulNameTestWithBlinky("Blinky*", "rdap_contact.json");
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_found_wildcardSpecifyingSameRegistrar() {
|
||||
login("2-RegistrarTest");
|
||||
action.registrarParam = Optional.of("2-RegistrarTest");
|
||||
@@ -561,7 +563,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_notFound_wildcardSpecifyingOtherRegistrar() {
|
||||
login("2-RegistrarTest");
|
||||
action.registrarParam = Optional.of("2-RegistrarInact");
|
||||
@@ -569,7 +571,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_found_wildcardBoth() {
|
||||
login("2-RegistrarTest");
|
||||
rememberWildcardType("Blin*");
|
||||
@@ -579,14 +581,14 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_notFound_deleted() {
|
||||
login("2-RegistrarTest");
|
||||
runNotFoundNameTest("Cl*");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_notFound_deletedWhenLoggedInAsOtherRegistrar() {
|
||||
login("2-RegistrarTest");
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
@@ -594,7 +596,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_notFound_deletedWhenLoggedInAsSameRegistrar() {
|
||||
login("2-Registrar");
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
@@ -602,7 +604,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContact_notFound_deletedWhenLoggedInAsAdmin() {
|
||||
loginAsAdmin();
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
@@ -610,7 +612,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_found() {
|
||||
login("2-RegistrarTest");
|
||||
runSuccessfulNameTest(
|
||||
@@ -618,7 +620,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_found_subtypeAll() {
|
||||
login("2-RegistrarTest");
|
||||
action.subtypeParam = Optional.of("all");
|
||||
@@ -627,7 +629,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_found_subtypeRegistrars() {
|
||||
login("2-RegistrarTest");
|
||||
action.subtypeParam = Optional.of("REGISTRARS");
|
||||
@@ -636,7 +638,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_notFound_subtypeContacts() {
|
||||
login("2-RegistrarTest");
|
||||
action.subtypeParam = Optional.of("contacts");
|
||||
@@ -644,7 +646,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_found_specifyingSameRegistrar() {
|
||||
action.registrarParam = Optional.of("2-Registrar");
|
||||
runSuccessfulNameTest(
|
||||
@@ -652,25 +654,26 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_notFound_specifyingDifferentRegistrar() {
|
||||
action.registrarParam = Optional.of("2-RegistrarTest");
|
||||
runNotFoundNameTest("Yes Virginia <script>");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContacts_nonTruncated() {
|
||||
login("2-RegistrarTest");
|
||||
createManyContactsAndRegistrars(4, 0, registrarTest);
|
||||
rememberWildcardType("Entity *");
|
||||
// JsonObject foo = generateActualJsonWithFullName("Entity *");
|
||||
assertThat(generateActualJsonWithFullName("Entity *"))
|
||||
.isEqualTo(generateExpectedJson("rdap_nontruncated_contacts.json"));
|
||||
assertThat(response.getStatus()).isEqualTo(200);
|
||||
verifyMetrics(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContacts_truncated() {
|
||||
login("2-RegistrarTest");
|
||||
createManyContactsAndRegistrars(5, 0, registrarTest);
|
||||
@@ -683,7 +686,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(5, IncompletenessWarningType.TRUNCATED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContacts_reallyTruncated() {
|
||||
login("2-RegistrarTest");
|
||||
createManyContactsAndRegistrars(9, 0, registrarTest);
|
||||
@@ -697,7 +700,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(5, IncompletenessWarningType.TRUNCATED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchContacts_cursorNavigation() throws Exception {
|
||||
login("2-RegistrarTest");
|
||||
createManyContactsAndRegistrars(9, 0, registrarTest);
|
||||
@@ -716,7 +719,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
"Entity 9"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrars_nonTruncated() {
|
||||
createManyContactsAndRegistrars(0, 4, registrarTest);
|
||||
rememberWildcardType("Entity *");
|
||||
@@ -726,7 +729,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrars_truncated() {
|
||||
createManyContactsAndRegistrars(0, 5, registrarTest);
|
||||
rememberWildcardType("Entity *");
|
||||
@@ -738,7 +741,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0, IncompletenessWarningType.TRUNCATED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrars_reallyTruncated() {
|
||||
createManyContactsAndRegistrars(0, 9, registrarTest);
|
||||
rememberWildcardType("Entity *");
|
||||
@@ -750,7 +753,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0, IncompletenessWarningType.TRUNCATED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrars_cursorNavigation() throws Exception {
|
||||
createManyContactsAndRegistrars(0, 13, registrarTest);
|
||||
checkCursorNavigation(
|
||||
@@ -772,7 +775,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
"Entity 9"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrars_cursorNavigationThroughAll() throws Exception {
|
||||
createManyContactsAndRegistrars(0, 13, registrarTest);
|
||||
action.subtypeParam = Optional.of("registrars");
|
||||
@@ -798,7 +801,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
"Yes Virginia <script>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchMix_truncated() {
|
||||
login("2-RegistrarTest");
|
||||
createManyContactsAndRegistrars(3, 3, registrarTest);
|
||||
@@ -811,7 +814,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(3, IncompletenessWarningType.TRUNCATED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchMix_cursorNavigation() throws Exception {
|
||||
login("2-RegistrarTest");
|
||||
createManyContactsAndRegistrars(3, 3, registrarTest);
|
||||
@@ -827,7 +830,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
"Entity 6"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchMix_subtypeContacts() {
|
||||
login("2-RegistrarTest");
|
||||
action.subtypeParam = Optional.of("contacts");
|
||||
@@ -839,7 +842,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchMix_subtypeRegistrars() {
|
||||
login("2-RegistrarTest");
|
||||
action.subtypeParam = Optional.of("registrars");
|
||||
@@ -849,13 +852,13 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_notFound_inactive() {
|
||||
runNotFoundNameTest("No Way");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_notFound_inactiveAsDifferentRegistrar() {
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
login("2-Registrar");
|
||||
@@ -863,7 +866,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_found_inactiveAsSameRegistrar() {
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
login("2-RegistrarInact");
|
||||
@@ -871,7 +874,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_found_inactiveAsAdmin() {
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
loginAsAdmin();
|
||||
@@ -879,13 +882,13 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_notFound_test() {
|
||||
runNotFoundNameTest("Da Test Registrar");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_notFound_testAsDifferentRegistrar() {
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
login("2-Registrar");
|
||||
@@ -893,7 +896,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_found_testAsSameRegistrar() {
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
login("2-RegistrarTest");
|
||||
@@ -902,7 +905,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testNameMatchRegistrar_found_testAsAdmin() {
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
loginAsAdmin();
|
||||
@@ -911,14 +914,14 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_found() {
|
||||
login("2-RegistrarTest");
|
||||
runSuccessfulHandleTestWithBlinky("2-ROID", "rdap_contact.json");
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_found_subtypeAll() {
|
||||
login("2-RegistrarTest");
|
||||
action.subtypeParam = Optional.of("all");
|
||||
@@ -926,7 +929,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_found_subtypeContacts() {
|
||||
login("2-RegistrarTest");
|
||||
action.subtypeParam = Optional.of("contacts");
|
||||
@@ -934,7 +937,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_notFound_subtypeRegistrars() {
|
||||
login("2-RegistrarTest");
|
||||
action.subtypeParam = Optional.of("reGistrars");
|
||||
@@ -942,28 +945,28 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_found_specifyingSameRegistrar() {
|
||||
action.registrarParam = Optional.of("2-RegistrarTest");
|
||||
runSuccessfulHandleTestWithBlinky("2-ROID", "rdap_contact_no_personal_data_with_remark.json");
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_notFound_specifyingDifferentRegistrar() {
|
||||
action.registrarParam = Optional.of("2-Registrar");
|
||||
runNotFoundHandleTest("2-ROID");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_notFound_deleted() {
|
||||
login("2-RegistrarTest");
|
||||
runNotFoundHandleTest("6-ROID");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_notFound_deletedWhenLoggedInAsOtherRegistrar() {
|
||||
login("2-RegistrarTest");
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
@@ -971,7 +974,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_found_deletedWhenLoggedInAsSameRegistrar() {
|
||||
login("2-Registrar");
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
@@ -985,7 +988,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_found_deletedWhenLoggedInAsAdmin() {
|
||||
loginAsAdmin();
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
@@ -999,14 +1002,14 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_notFound_deletedWildcard() {
|
||||
login("2-RegistrarTest");
|
||||
runNotFoundHandleTest("6-ROI*");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_notFound_deletedWildcardWhenLoggedInAsOtherRegistrar() {
|
||||
login("2-RegistrarTest");
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
@@ -1014,7 +1017,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_found_deletedWildcardWhenLoggedInAsSameRegistrar() {
|
||||
login("2-Registrar");
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
@@ -1028,7 +1031,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_found_deletedWildcardWhenLoggedInAsAdmin() {
|
||||
loginAsAdmin();
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
@@ -1042,48 +1045,48 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchRegistrar_found() {
|
||||
runSuccessfulHandleTest("20", "20", "Yes Virginia <script>", "rdap_registrar.json");
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchRegistrar_found_subtypeAll() {
|
||||
action.subtypeParam = Optional.of("all");
|
||||
runSuccessfulHandleTest("20", "20", "Yes Virginia <script>", "rdap_registrar.json");
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchRegistrar_found_subtypeRegistrars() {
|
||||
action.subtypeParam = Optional.of("registrars");
|
||||
runSuccessfulHandleTest("20", "20", "Yes Virginia <script>", "rdap_registrar.json");
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchRegistrar_notFound_subtypeContacts() {
|
||||
action.subtypeParam = Optional.of("contacts");
|
||||
runNotFoundHandleTest("20");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchRegistrar_found_specifyingSameRegistrar() {
|
||||
action.registrarParam = Optional.of("2-Registrar");
|
||||
runSuccessfulHandleTest("20", "20", "Yes Virginia <script>", "rdap_registrar.json");
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchRegistrar_notFound_specifyingDifferentRegistrar() {
|
||||
action.registrarParam = Optional.of("2-RegistrarTest");
|
||||
runNotFoundHandleTest("20");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_found_wildcardWithResultSetSizeOne() {
|
||||
login("2-RegistrarTest");
|
||||
action.rdapResultSetMaxSize = 1;
|
||||
@@ -1091,14 +1094,14 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_found_wildcard() {
|
||||
login("2-RegistrarTest");
|
||||
runSuccessfulHandleTestWithBlinky("2-RO*", "rdap_contact.json");
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_found_wildcardSpecifyingSameRegistrar() {
|
||||
action.registrarParam = Optional.of("2-RegistrarTest");
|
||||
login("2-RegistrarTest");
|
||||
@@ -1106,7 +1109,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_notFound_wildcardSpecifyingDifferentRegistrar() {
|
||||
action.registrarParam = Optional.of("2-Registrar");
|
||||
login("2-RegistrarTest");
|
||||
@@ -1114,20 +1117,20 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_found_deleted() {
|
||||
login("2-RegistrarTest");
|
||||
runSuccessfulHandleTestWithBlinky("2-RO*", "rdap_contact.json");
|
||||
verifyMetrics(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_notFound_wildcard() {
|
||||
runNotFoundHandleTest("20*");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_cursorNavigationWithFullLastPage() throws Exception {
|
||||
login("2-RegistrarTest");
|
||||
createManyContactsAndRegistrars(12, 0, registrarTest);
|
||||
@@ -1150,7 +1153,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
"Entity 12"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchContact_cursorNavigationWithPartialLastPage() throws Exception {
|
||||
login("2-RegistrarTest");
|
||||
createManyContactsAndRegistrars(13, 0, registrarTest);
|
||||
@@ -1174,13 +1177,13 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
"Entity 13"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchRegistrar_notFound_wildcard() {
|
||||
runNotFoundHandleTest("3test*");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchRegistrars_cursorNavigationThroughAll() throws Exception {
|
||||
createManyContactsAndRegistrars(0, 13, registrarTest);
|
||||
action.subtypeParam = Optional.of("registrars");
|
||||
@@ -1206,7 +1209,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
"Yes Virginia <script>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchMix_found_truncated() {
|
||||
createManyContactsAndRegistrars(30, 0, registrarTest);
|
||||
rememberWildcardType("00*");
|
||||
@@ -1216,13 +1219,13 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(5, IncompletenessWarningType.TRUNCATED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchRegistrar_notFound_inactive() {
|
||||
runNotFoundHandleTest("21");
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchRegistrar_notFound_inactiveAsDifferentRegistrar() {
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
login("2-Registrar");
|
||||
@@ -1230,7 +1233,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchRegistrar_found_inactiveAsSameRegistrar() {
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
login("2-RegistrarInact");
|
||||
@@ -1238,7 +1241,7 @@ class RdapEntitySearchActionTest extends RdapSearchActionTestCase<RdapEntitySear
|
||||
verifyMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testHandleMatchRegistrar_found_inactiveAsAdmin() {
|
||||
action.includeDeletedParam = Optional.of(true);
|
||||
loginAsAdmin();
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
// Copyright 2021 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.schema.replay;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
||||
import static google.registry.testing.LogsSubject.assertAboutLogs;
|
||||
|
||||
import com.google.common.testing.TestLogHandler;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.TransactionEntity;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
public class ReplicateToDatastoreActionTest {
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withOfyTestEntities(TestEntity.class)
|
||||
.withJpaUnitTestEntities(TestEntity.class)
|
||||
.build();
|
||||
|
||||
ReplicateToDatastoreAction task = new ReplicateToDatastoreAction();
|
||||
|
||||
TestLogHandler logHandler;
|
||||
|
||||
public ReplicateToDatastoreActionTest() {}
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
RegistryConfig.overrideCloudSqlReplicateTransactions(true);
|
||||
logHandler = new TestLogHandler();
|
||||
Logger.getLogger(ReplicateToDatastoreAction.class.getCanonicalName()).addHandler(logHandler);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
RegistryConfig.overrideCloudSqlReplicateTransactions(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplication() {
|
||||
TestEntity foo = new TestEntity("foo");
|
||||
TestEntity bar = new TestEntity("bar");
|
||||
TestEntity baz = new TestEntity("baz");
|
||||
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
jpaTm().insert(foo);
|
||||
jpaTm().insert(bar);
|
||||
});
|
||||
task.run();
|
||||
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKey(foo.key()))).isEqualTo(foo);
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKey(bar.key()))).isEqualTo(bar);
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKeyIfPresent(baz.key())).isPresent()).isFalse();
|
||||
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
jpaTm().delete(bar.key());
|
||||
jpaTm().insert(baz);
|
||||
});
|
||||
task.run();
|
||||
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKeyIfPresent(bar.key()).isPresent())).isFalse();
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKey(baz.key()))).isEqualTo(baz);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplayFromLastTxn() {
|
||||
TestEntity foo = new TestEntity("foo");
|
||||
TestEntity bar = new TestEntity("bar");
|
||||
|
||||
// Write a transaction containing "foo".
|
||||
jpaTm().transact(() -> jpaTm().insert(foo));
|
||||
task.run();
|
||||
|
||||
// Verify that it propagated to datastore, then remove "foo" directly from datastore.
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKey(foo.key()))).isEqualTo(foo);
|
||||
ofyTm().transact(() -> ofyTm().delete(foo.key()));
|
||||
|
||||
// Write "bar"
|
||||
jpaTm().transact(() -> jpaTm().insert(bar));
|
||||
task.run();
|
||||
|
||||
// If we replayed only the most recent transaction, we should have "bar" but not "foo".
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKey(bar.key()))).isEqualTo(bar);
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKeyIfPresent(foo.key()).isPresent())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnintentionalConcurrency() {
|
||||
TestEntity foo = new TestEntity("foo");
|
||||
TestEntity bar = new TestEntity("bar");
|
||||
|
||||
// Write a transaction and run just the batch fetch.
|
||||
jpaTm().transact(() -> jpaTm().insert(foo));
|
||||
List<TransactionEntity> txns1 = task.getTransactionBatch();
|
||||
assertThat(txns1).hasSize(1);
|
||||
|
||||
// Write a second transaction and do another batch fetch.
|
||||
jpaTm().transact(() -> jpaTm().insert(bar));
|
||||
List<TransactionEntity> txns2 = task.getTransactionBatch();
|
||||
assertThat(txns2).hasSize(2);
|
||||
|
||||
// Apply the first batch.
|
||||
assertThat(task.applyTransaction(txns1.get(0))).isFalse();
|
||||
|
||||
// Remove the foo record so we can ensure that this transaction doesn't get doublle-played.
|
||||
ofyTm().transact(() -> ofyTm().delete(foo.key()));
|
||||
|
||||
// Apply the second batch.
|
||||
for (TransactionEntity txn : txns2) {
|
||||
assertThat(task.applyTransaction(txn)).isFalse();
|
||||
}
|
||||
|
||||
// Verify that the first transaction didn't get replayed but the second one did.
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKeyIfPresent(foo.key()).isPresent())).isFalse();
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKey(bar.key()))).isEqualTo(bar);
|
||||
assertAboutLogs()
|
||||
.that(logHandler)
|
||||
.hasLogAtLevelWithMessage(
|
||||
Level.WARNING, "Ignoring transaction 1, which appears to have already been applied.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingTransactions() {
|
||||
// Write a transaction (should have a transaction id of 1).
|
||||
TestEntity foo = new TestEntity("foo");
|
||||
jpaTm().transact(() -> jpaTm().insert(foo));
|
||||
|
||||
// Force the last transaction id back to -1 so that we look for transaction 0.
|
||||
ofyTm().transact(() -> ofyTm().insert(new LastSqlTransaction(-1)));
|
||||
|
||||
List<TransactionEntity> txns = task.getTransactionBatch();
|
||||
assertThat(txns).hasSize(1);
|
||||
assertThat(task.applyTransaction(txns.get(0))).isTrue();
|
||||
assertAboutLogs()
|
||||
.that(logHandler)
|
||||
.hasLogAtLevelWithMessage(
|
||||
Level.SEVERE,
|
||||
"Missing transaction: last transaction id = -1, next available transaction = 1");
|
||||
}
|
||||
|
||||
@Entity(name = "ReplicationTestEntity")
|
||||
@javax.persistence.Entity(name = "TestEntity")
|
||||
private static class TestEntity extends ImmutableObject {
|
||||
@Id @javax.persistence.Id private String name;
|
||||
|
||||
private TestEntity() {}
|
||||
|
||||
private TestEntity(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public VKey<TestEntity> key() {
|
||||
return VKey.create(TestEntity.class, name, Key.create(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,12 @@ package google.registry.testing;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.io.Files.asCharSink;
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.testing.DatabaseHelper.persistSimpleResources;
|
||||
import static google.registry.testing.DualDatabaseTestInvocationContextProvider.injectTmForDualDatabaseTest;
|
||||
import static google.registry.testing.DualDatabaseTestInvocationContextProvider.restoreTmAfterDualDatabaseTest;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
import static google.registry.util.ResourceUtils.readResourceUtf8;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
@@ -40,10 +42,16 @@ import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.io.Files;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.ObjectifyFilter;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.PrimaryDatabase;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.PrimaryDatabaseTransition;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.TransitionId;
|
||||
import google.registry.model.common.TimedTransitionProperty;
|
||||
import google.registry.model.ofy.ObjectifyService;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.State;
|
||||
@@ -390,6 +398,14 @@ public final class AppEngineExtension implements BeforeEachCallback, AfterEachCa
|
||||
loadInitialData();
|
||||
}
|
||||
} else {
|
||||
// If we're using SQL, set replayed entities to use SQL
|
||||
DatabaseTransitionSchedule schedule =
|
||||
DatabaseTransitionSchedule.create(
|
||||
TransitionId.REPLAYED_ENTITIES,
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, PrimaryDatabase.CLOUD_SQL),
|
||||
PrimaryDatabaseTransition.class));
|
||||
tm().transactNew(() -> ofy().saveWithoutBackup().entity(schedule).now());
|
||||
if (withCloudSql && !withJpaUnitTest && !withoutCannedData) {
|
||||
loadInitialData();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright 2021 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 google.registry.testing.DatabaseHelper.createTld;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
@DualDatabaseTest
|
||||
public class GetPremiumListCommandTest extends CommandTestCase<GetPremiumListCommand> {
|
||||
|
||||
private static final String BASE_LIST_CONTENTS =
|
||||
"tld:\n"
|
||||
+ "aluminum,USD 11.00\n"
|
||||
+ "brass,USD 20.00\n"
|
||||
+ "copper,USD 15.00\n"
|
||||
+ "diamond,USD 1000000.00\n"
|
||||
+ "gold,USD 24317.00\n"
|
||||
+ "iridium,USD 13117.00\n"
|
||||
+ "palladium,USD 877.00\n"
|
||||
+ "platinum,USD 87741.00\n"
|
||||
+ "rhodium,USD 88415.00\n"
|
||||
+ "rich,USD 100.00\n"
|
||||
+ "richer,USD 1000.00\n"
|
||||
+ "silver,USD 588.00\n";
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("tld");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSuccess_list() throws Exception {
|
||||
runCommand("tld");
|
||||
assertStdoutIs(BASE_LIST_CONTENTS);
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSuccess_onlyOneExists() throws Exception {
|
||||
runCommand("tld", "nonexistent");
|
||||
assertStdoutIs(BASE_LIST_CONTENTS + "No list found with name nonexistent.\n");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testFailure_nonexistent() throws Exception {
|
||||
runCommand("nonexistent", "othernonexistent");
|
||||
assertStdoutIs(
|
||||
"No list found with name nonexistent.\nNo list found with name othernonexistent.\n");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testFailure_noArgs() {
|
||||
assertThrows(ParameterException.class, this::runCommand);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ HistoryEntry
|
||||
HostResource
|
||||
KmsSecret
|
||||
KmsSecretRevision
|
||||
LastSqlTransaction
|
||||
Modification
|
||||
OneTime
|
||||
PollMessage
|
||||
|
||||
+3
-3
@@ -28,7 +28,7 @@
|
||||
<fee:command name="create">
|
||||
<fee:period unit="y">1</fee:period>
|
||||
<fee:fee description="create">13.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-03T10:00:00.000Z">50.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-03T10:00:00.002Z">50.00</fee:fee>
|
||||
<fee:date>2010-01-02T13:22:21Z</fee:date>
|
||||
<fee:notAfter>2010-01-03T10:00:00.000Z</fee:notAfter>
|
||||
</fee:command>
|
||||
@@ -40,7 +40,7 @@
|
||||
<fee:command name="create">
|
||||
<fee:period unit="y">1</fee:period>
|
||||
<fee:fee description="create">13.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-03T10:00:00.000Z">50.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-03T10:00:00.002Z">50.00</fee:fee>
|
||||
<fee:date>2010-01-02T13:22:21Z</fee:date>
|
||||
<fee:notAfter>2010-01-03T10:00:00.000Z</fee:notAfter>
|
||||
</fee:command>
|
||||
@@ -52,7 +52,7 @@
|
||||
<fee:command name="create">
|
||||
<fee:period unit="y">1</fee:period>
|
||||
<fee:fee description="create">13.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-03T10:00:00.000Z">50.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-03T10:00:00.002Z">50.00</fee:fee>
|
||||
<fee:date>2010-01-02T13:22:21Z</fee:date>
|
||||
<fee:notAfter>2010-01-03T10:00:00.000Z</fee:notAfter>
|
||||
</fee:command>
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@
|
||||
<fee:command>create</fee:command>
|
||||
<fee:period unit="y">1</fee:period>
|
||||
<fee:fee description="create">13.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.002Z">100.00</fee:fee>
|
||||
</fee:cd>
|
||||
<fee:cd xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
|
||||
<fee:name>example3.tld</fee:name>
|
||||
@@ -33,7 +33,7 @@
|
||||
<fee:command>create</fee:command>
|
||||
<fee:period unit="y">2</fee:period>
|
||||
<fee:fee description="create">26.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.002Z">100.00</fee:fee>
|
||||
</fee:cd>
|
||||
</fee:chkData>
|
||||
</extension>
|
||||
|
||||
+3
-3
@@ -28,7 +28,7 @@
|
||||
<fee:currency>USD</fee:currency>
|
||||
<fee:period unit="y">1</fee:period>
|
||||
<fee:fee description="create">13.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.002Z">100.00</fee:fee>
|
||||
</fee:cd>
|
||||
<fee:cd avail="1">
|
||||
<fee:object>
|
||||
@@ -38,7 +38,7 @@
|
||||
<fee:currency>USD</fee:currency>
|
||||
<fee:period unit="y">1</fee:period>
|
||||
<fee:fee description="create">13.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.002Z">100.00</fee:fee>
|
||||
</fee:cd>
|
||||
<fee:cd avail="1">
|
||||
<fee:object>
|
||||
@@ -48,7 +48,7 @@
|
||||
<fee:currency>USD</fee:currency>
|
||||
<fee:period unit="y">1</fee:period>
|
||||
<fee:fee description="create">13.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.002Z">100.00</fee:fee>
|
||||
</fee:cd>
|
||||
</fee:chkData>
|
||||
</extension>
|
||||
|
||||
+3
-3
@@ -28,7 +28,7 @@
|
||||
<fee:command name="create">
|
||||
<fee:period unit="y">1</fee:period>
|
||||
<fee:fee description="create">13.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.002Z">100.00</fee:fee>
|
||||
<fee:notAfter>2010-01-02T10:00:00.000Z</fee:notAfter>
|
||||
</fee:command>
|
||||
</fee:cd>
|
||||
@@ -39,7 +39,7 @@
|
||||
<fee:command name="create">
|
||||
<fee:period unit="y">1</fee:period>
|
||||
<fee:fee description="create">13.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.002Z">100.00</fee:fee>
|
||||
<fee:notAfter>2010-01-02T10:00:00.000Z</fee:notAfter>
|
||||
</fee:command>
|
||||
</fee:cd>
|
||||
@@ -50,7 +50,7 @@
|
||||
<fee:command name="create">
|
||||
<fee:period unit="y">1</fee:period>
|
||||
<fee:fee description="create">13.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.002Z">100.00</fee:fee>
|
||||
<fee:notAfter>2010-01-02T10:00:00.000Z</fee:notAfter>
|
||||
</fee:command>
|
||||
</fee:cd>
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
<fee:command>create</fee:command>
|
||||
<fee:period unit="y">1</fee:period>
|
||||
<fee:fee description="create">100.00</fee:fee>
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00
|
||||
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.002Z">100.00
|
||||
</fee:fee>
|
||||
<fee:class>premium</fee:class>
|
||||
</fee:cd>
|
||||
|
||||
@@ -916,3 +916,7 @@ class google.registry.persistence.DomainHistoryVKey {
|
||||
java.lang.Long historyRevisionId;
|
||||
java.lang.String repoId;
|
||||
}
|
||||
class google.registry.schema.replay.LastSqlTransaction {
|
||||
@Id long id;
|
||||
long transactionId;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
mock-maker-inline
|
||||
+13
-5
@@ -20,8 +20,6 @@ plugins {
|
||||
ext {
|
||||
Set restrictedDbEnv =
|
||||
[ 'sandbox', 'production' ].asUnmodifiable()
|
||||
Set allDbEnv =
|
||||
[ 'alpha', 'crash' ].plus(restrictedDbEnv).asUnmodifiable()
|
||||
|
||||
def dbServerProperty = 'dbServer'
|
||||
def dbNameProperty = 'dbName'
|
||||
@@ -57,12 +55,12 @@ ext {
|
||||
}
|
||||
|
||||
getJdbcAccessInfo = {
|
||||
if (allDbEnv.contains(dbServer)) {
|
||||
return getSocketFactoryAccessInfo(dbServer)
|
||||
if (rootProject.projects.keySet().contains(environment)) {
|
||||
return getSocketFactoryAccessInfo(environment)
|
||||
} else if (!dbServer.isEmpty()) {
|
||||
return getAccessInfoByHostPort(dbServer)
|
||||
} else {
|
||||
// Not connecting to a database. Return a dummy object for Flyway config.
|
||||
// Not running flyway tasks. Return a dummy object for Flyway config.
|
||||
return [ url: '', user: '', password: '' ]
|
||||
}
|
||||
}
|
||||
@@ -137,6 +135,16 @@ publishing {
|
||||
}
|
||||
}
|
||||
|
||||
// Adds flyway tasks such as: flywayInfo, flywayValidate, flywayMigrate (deploying the schema in
|
||||
// local repository), and flywayClean (dropping all data in the database). The latter two commands
|
||||
// are disallowed in environments listed in ext.restrictedDbEnv.
|
||||
//
|
||||
// Examples:
|
||||
// Get info in alpha: nom_build :db:flywayInfo --environment=alpha
|
||||
// Deploy schema to a local test instance and override the database name:
|
||||
// nom_build :db:flywayMigrate --dbServer=localhost:5432 --dbName=not-default \
|
||||
// --dbUser=... --dbPassword=...
|
||||
|
||||
flyway {
|
||||
def accessInfo = project.ext.getJdbcAccessInfo()
|
||||
|
||||
|
||||
+3
-2
@@ -73,6 +73,7 @@ ext {
|
||||
'com.google.http-client:google-http-client-appengine:1.34.1',
|
||||
'com.google.http-client:google-http-client-jackson2:1.34.1',
|
||||
'com.google.http-client:google-http-client:1.34.1',
|
||||
'com.google.inject:guice:5.0.1',
|
||||
'com.google.javascript:closure-compiler:v20190301',
|
||||
'com.google.monitoring-client:contrib:1.0.7',
|
||||
'com.google.monitoring-client:metrics:1.0.7',
|
||||
@@ -157,8 +158,8 @@ ext {
|
||||
'org.joda:joda-money:1.0.1',
|
||||
'org.json:json:20160810',
|
||||
'org.jsoup:jsoup:1.13.1',
|
||||
'org.mockito:mockito-core:3.3.3',
|
||||
'org.mockito:mockito-junit-jupiter:3.3.3',
|
||||
'org.mockito:mockito-core:3.7.7',
|
||||
'org.mockito:mockito-junit-jupiter:3.7.7',
|
||||
'org.mortbay.jetty:jetty:6.1.26',
|
||||
'org.postgresql:postgresql:42.2.18',
|
||||
'org.seleniumhq.selenium:selenium-api:3.141.59',
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -28,6 +28,7 @@ dependencies {
|
||||
compile deps['org.bouncycastle:bcpkix-jdk15on']
|
||||
compile deps['org.bouncycastle:bcprov-jdk15on']
|
||||
compile project(':util')
|
||||
compile project(':common')
|
||||
|
||||
runtime deps['com.google.flogger:flogger-system-backend']
|
||||
runtime deps['io.netty:netty-tcnative-boringssl-static']
|
||||
@@ -38,9 +39,11 @@ dependencies {
|
||||
testCompile deps['org.junit.jupiter:junit-jupiter-params']
|
||||
testCompile deps['org.bouncycastle:bcpkix-jdk15on']
|
||||
testCompile deps['org.bouncycastle:bcprov-jdk15on']
|
||||
testCompile project(path: ':common', configuration: 'testing')
|
||||
|
||||
annotationProcessor deps['com.google.dagger:dagger-compiler']
|
||||
testAnnotationProcessor deps['com.google.dagger:dagger-compiler']
|
||||
compile 'joda-time:joda-time:2.9.2'
|
||||
}
|
||||
|
||||
// Make testing artifacts available to be depended up on by other projects.
|
||||
|
||||
+49
-4
@@ -19,6 +19,7 @@ import static google.registry.util.X509Utils.getCertificateHash;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.util.Clock;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
@@ -29,6 +30,7 @@ import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.ssl.SslHandler;
|
||||
import io.netty.handler.ssl.SslProvider;
|
||||
import io.netty.handler.ssl.SupportedCipherSuiteFilter;
|
||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
import io.netty.util.AttributeKey;
|
||||
import io.netty.util.concurrent.Future;
|
||||
@@ -41,6 +43,7 @@ import java.security.cert.X509Certificate;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.function.Supplier;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* Adds a server side SSL handler to the channel pipeline.
|
||||
@@ -66,6 +69,29 @@ public class SslServerInitializer<C extends Channel> extends ChannelInitializer<
|
||||
public static final AttributeKey<Promise<X509Certificate>> CLIENT_CERTIFICATE_PROMISE_KEY =
|
||||
AttributeKey.valueOf("CLIENT_CERTIFICATE_PROMISE_KEY");
|
||||
|
||||
/**
|
||||
* The list of cipher suites that are currently acceptable to create a successful handshake.
|
||||
*
|
||||
* <p>This list includes all of the current TLS1.3 ciphers and a collection of TLS1.2 ciphers with
|
||||
* no known security vulnerabilities. Note that OpenSSL uses a separate nomenclature for the
|
||||
* ciphers internally but the IANA names listed here will be transparently translated by the
|
||||
* OpenSSL provider (if used), so there is no need to include the OpenSSL name variants here. More
|
||||
* information about these cipher suites and their OpenSSL names can be found at ciphersuite.info.
|
||||
*/
|
||||
private static final ImmutableList ALLOWED_TLS_CIPHERS =
|
||||
ImmutableList.of(
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_AES_128_GCM_SHA256",
|
||||
"TLS_AES_256_GCM_SHA384",
|
||||
"TLS_CHACHA20_POLY1305_SHA256",
|
||||
"TLS_AES_128_CCM_SHA256",
|
||||
"TLS_AES_128_CCM_8_SHA256");
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private final boolean requireClientCert;
|
||||
// TODO(jianglai): Always validate client certs (if required).
|
||||
@@ -76,13 +102,19 @@ public class SslServerInitializer<C extends Channel> extends ChannelInitializer<
|
||||
private final Supplier<PrivateKey> privateKeySupplier;
|
||||
private final Supplier<ImmutableList<X509Certificate>> certificatesSupplier;
|
||||
private final ImmutableList<String> supportedSslVersions;
|
||||
// TODO(sarahbot): Remove this variable and its check after enforcement start date has passed.
|
||||
private final ImmutableList<String> oldSupportedSslVersions;
|
||||
private final DateTime enforcementStartTime;
|
||||
private final Clock clock;
|
||||
|
||||
public SslServerInitializer(
|
||||
boolean requireClientCert,
|
||||
boolean validateClientCert,
|
||||
SslProvider sslProvider,
|
||||
Supplier<PrivateKey> privateKeySupplier,
|
||||
Supplier<ImmutableList<X509Certificate>> certificatesSupplier) {
|
||||
Supplier<ImmutableList<X509Certificate>> certificatesSupplier,
|
||||
DateTime enforcementStartTime,
|
||||
Clock clock) {
|
||||
logger.atInfo().log("Server SSL Provider: %s", sslProvider);
|
||||
checkArgument(
|
||||
requireClientCert || !validateClientCert,
|
||||
@@ -94,10 +126,16 @@ public class SslServerInitializer<C extends Channel> extends ChannelInitializer<
|
||||
this.certificatesSupplier = certificatesSupplier;
|
||||
this.supportedSslVersions =
|
||||
sslProvider == SslProvider.OPENSSL
|
||||
? ImmutableList.of("TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1")
|
||||
// JDK support for TLS 1.3 won't be available until 2020-07-14 at the earliest.
|
||||
? ImmutableList.of("TLSv1.3", "TLSv1.2")
|
||||
// JDK support for TLS 1.3 won't be available until 2021-04-20 at the earliest.
|
||||
// See: https://java.com/en/jre-jdk-cryptoroadmap.html
|
||||
: ImmutableList.of("TLSv1.2");
|
||||
this.oldSupportedSslVersions =
|
||||
sslProvider == SslProvider.OPENSSL
|
||||
? ImmutableList.of("TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1")
|
||||
: ImmutableList.of("TLSv1.2", "TLSv1.1", "TLSv1");
|
||||
this.enforcementStartTime = enforcementStartTime;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,8 +147,15 @@ public class SslServerInitializer<C extends Channel> extends ChannelInitializer<
|
||||
.sslProvider(sslProvider)
|
||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||
.clientAuth(requireClientCert ? ClientAuth.REQUIRE : ClientAuth.NONE)
|
||||
.protocols(supportedSslVersions)
|
||||
.protocols(
|
||||
enforcementStartTime.isBefore(clock.nowUtc())
|
||||
? supportedSslVersions
|
||||
: oldSupportedSslVersions)
|
||||
.ciphers(
|
||||
enforcementStartTime.isBefore(clock.nowUtc()) ? ALLOWED_TLS_CIPHERS : null,
|
||||
SupportedCipherSuiteFilter.INSTANCE)
|
||||
.build();
|
||||
|
||||
logger.atInfo().log("Available Cipher Suites: %s", sslContext.cipherSuites());
|
||||
SslHandler sslHandler = sslContext.newHandler(channel.alloc());
|
||||
if (requireClientCert) {
|
||||
|
||||
+196
-4
@@ -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.testing.FakeClock;
|
||||
import google.registry.util.SelfSignedCaCertificate;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
@@ -42,13 +43,16 @@ import java.security.cert.CertificateNotYetValidException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
@@ -97,19 +101,29 @@ class SslServerInitializerTest {
|
||||
validateClientCert,
|
||||
sslProvider,
|
||||
Suppliers.ofInstance(privateKey),
|
||||
Suppliers.ofInstance(ImmutableList.copyOf(certificates)));
|
||||
Suppliers.ofInstance(ImmutableList.copyOf(certificates)),
|
||||
DateTime.parse("2021-04-01T16:00:00Z"),
|
||||
new FakeClock(DateTime.parse("2021-05-01T16:00:00Z")));
|
||||
}
|
||||
|
||||
private ChannelHandler getClientHandler(
|
||||
SslProvider sslProvider,
|
||||
X509Certificate trustedCertificate,
|
||||
PrivateKey privateKey,
|
||||
X509Certificate certificate) {
|
||||
X509Certificate certificate,
|
||||
String protocol,
|
||||
List<String> cipher) {
|
||||
return new ChannelInitializer<LocalChannel>() {
|
||||
@Override
|
||||
protected void initChannel(LocalChannel ch) throws Exception {
|
||||
SslContextBuilder sslContextBuilder =
|
||||
SslContextBuilder.forClient().trustManager(trustedCertificate).sslProvider(sslProvider);
|
||||
SslContextBuilder.forClient()
|
||||
.trustManager(trustedCertificate)
|
||||
.sslProvider(sslProvider)
|
||||
.ciphers(cipher);
|
||||
if (protocol != null) {
|
||||
sslContextBuilder.protocols(protocol);
|
||||
}
|
||||
if (privateKey != null && certificate != null) {
|
||||
sslContextBuilder.keyManager(privateKey, certificate);
|
||||
}
|
||||
@@ -127,6 +141,14 @@ class SslServerInitializerTest {
|
||||
};
|
||||
}
|
||||
|
||||
private ChannelHandler getClientHandler(
|
||||
SslProvider sslProvider,
|
||||
X509Certificate trustedCertificate,
|
||||
PrivateKey privateKey,
|
||||
X509Certificate certificate) {
|
||||
return getClientHandler(sslProvider, trustedCertificate, privateKey, certificate, null, null);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_swappedInitializerWithSslHandler(SslProvider sslProvider) throws Exception {
|
||||
@@ -137,7 +159,9 @@ class SslServerInitializerTest {
|
||||
false,
|
||||
sslProvider,
|
||||
Suppliers.ofInstance(ssc.key()),
|
||||
Suppliers.ofInstance(ImmutableList.of(ssc.cert())));
|
||||
Suppliers.ofInstance(ImmutableList.of(ssc.cert())),
|
||||
DateTime.parse("2021-04-01T16:00:00Z"),
|
||||
new FakeClock(DateTime.parse("2021-05-01T16:00:00Z")));
|
||||
EmbeddedChannel channel = new EmbeddedChannel();
|
||||
ChannelPipeline pipeline = channel.pipeline();
|
||||
pipeline.addLast(sslServerInitializer);
|
||||
@@ -172,6 +196,174 @@ class SslServerInitializerTest {
|
||||
assertThat(sslSession.getPeerCertificates()).asList().containsExactly(serverSsc.cert());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testFailure_cipherNotAccepted(SslProvider sslProvider) throws Exception {
|
||||
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
|
||||
LocalAddress localAddress = new LocalAddress("CIPHER_NOT_ACCEPTED_" + sslProvider);
|
||||
|
||||
nettyExtension.setUpServer(
|
||||
localAddress, getServerHandler(true, true, sslProvider, serverSsc.key(), serverSsc.cert()));
|
||||
SelfSignedCaCertificate clientSsc =
|
||||
SelfSignedCaCertificate.create(
|
||||
"CLIENT",
|
||||
Date.from(Instant.now().minus(Duration.ofDays(2))),
|
||||
Date.from(Instant.now().plus(Duration.ofDays(1))));
|
||||
nettyExtension.setUpClient(
|
||||
localAddress,
|
||||
getClientHandler(
|
||||
sslProvider,
|
||||
serverSsc.cert(),
|
||||
clientSsc.key(),
|
||||
clientSsc.cert(),
|
||||
"TLSv1.2",
|
||||
Collections.singletonList("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA")));
|
||||
|
||||
verifySslException(
|
||||
nettyExtension.getServerChannel(),
|
||||
channel -> channel.attr(CLIENT_CERTIFICATE_PROMISE_KEY).get().get(),
|
||||
SSLHandshakeException.class);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_someCiphersNotAccepted(SslProvider sslProvider) throws Exception {
|
||||
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
|
||||
LocalAddress localAddress = new LocalAddress("SOME_CIPHERS_NOT_ACCEPTED_" + sslProvider);
|
||||
|
||||
nettyExtension.setUpServer(
|
||||
localAddress,
|
||||
new SslServerInitializer<LocalChannel>(
|
||||
true,
|
||||
true,
|
||||
sslProvider,
|
||||
Suppliers.ofInstance(serverSsc.key()),
|
||||
Suppliers.ofInstance(ImmutableList.of(serverSsc.cert())),
|
||||
DateTime.parse("2021-04-01T16:00:00Z"),
|
||||
new FakeClock(DateTime.parse("2021-05-01T16:00:00Z"))));
|
||||
SelfSignedCaCertificate clientSsc =
|
||||
SelfSignedCaCertificate.create(
|
||||
"CLIENT",
|
||||
Date.from(Instant.now().minus(Duration.ofDays(2))),
|
||||
Date.from(Instant.now().plus(Duration.ofDays(1))));
|
||||
nettyExtension.setUpClient(
|
||||
localAddress,
|
||||
getClientHandler(
|
||||
sslProvider,
|
||||
serverSsc.cert(),
|
||||
clientSsc.key(),
|
||||
clientSsc.cert(),
|
||||
"TLSv1.2",
|
||||
ImmutableList.of(
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", // Only accepted cipher
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA")));
|
||||
|
||||
SSLSession sslSession = setUpSslChannel(nettyExtension.getClientChannel(), serverSsc.cert());
|
||||
nettyExtension.assertThatMessagesWork();
|
||||
|
||||
assertThat(sslSession.getLocalCertificates()).asList().containsExactly(clientSsc.cert());
|
||||
assertThat(sslSession.getPeerCertificates()).asList().containsExactly(serverSsc.cert());
|
||||
assertThat(sslSession.getCipherSuite()).isEqualTo("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_cipherNotAccepted_beforeEnforcementDate(SslProvider sslProvider)
|
||||
throws Exception {
|
||||
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
|
||||
LocalAddress localAddress = new LocalAddress("CIPHER_ACCEPTED_BEFORE_DATE_" + sslProvider);
|
||||
|
||||
nettyExtension.setUpServer(
|
||||
localAddress,
|
||||
new SslServerInitializer<LocalChannel>(
|
||||
true,
|
||||
true,
|
||||
sslProvider,
|
||||
Suppliers.ofInstance(serverSsc.key()),
|
||||
Suppliers.ofInstance(ImmutableList.of(serverSsc.cert())),
|
||||
DateTime.parse("2021-04-01T16:00:00Z"),
|
||||
new FakeClock(DateTime.parse("2021-03-01T16:00:00Z"))));
|
||||
SelfSignedCaCertificate clientSsc =
|
||||
SelfSignedCaCertificate.create(
|
||||
"CLIENT",
|
||||
Date.from(Instant.now().minus(Duration.ofDays(2))),
|
||||
Date.from(Instant.now().plus(Duration.ofDays(1))));
|
||||
nettyExtension.setUpClient(
|
||||
localAddress,
|
||||
getClientHandler(
|
||||
sslProvider,
|
||||
serverSsc.cert(),
|
||||
clientSsc.key(),
|
||||
clientSsc.cert(),
|
||||
"TLSv1.2",
|
||||
Collections.singletonList("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA")));
|
||||
|
||||
SSLSession sslSession = setUpSslChannel(nettyExtension.getClientChannel(), serverSsc.cert());
|
||||
nettyExtension.assertThatMessagesWork();
|
||||
|
||||
assertThat(sslSession.getLocalCertificates()).asList().containsExactly(clientSsc.cert());
|
||||
assertThat(sslSession.getPeerCertificates()).asList().containsExactly(serverSsc.cert());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testFailure_protocolNotAccepted(SslProvider sslProvider) throws Exception {
|
||||
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
|
||||
LocalAddress localAddress = new LocalAddress("PROTOCOL_NOT_ACCEPTED_" + sslProvider);
|
||||
|
||||
nettyExtension.setUpServer(
|
||||
localAddress, getServerHandler(true, true, sslProvider, serverSsc.key(), serverSsc.cert()));
|
||||
SelfSignedCaCertificate clientSsc =
|
||||
SelfSignedCaCertificate.create(
|
||||
"CLIENT",
|
||||
Date.from(Instant.now().minus(Duration.ofDays(2))),
|
||||
Date.from(Instant.now().plus(Duration.ofDays(1))));
|
||||
nettyExtension.setUpClient(
|
||||
localAddress,
|
||||
getClientHandler(
|
||||
sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert(), "TLSv1.1", null));
|
||||
|
||||
verifySslException(
|
||||
nettyExtension.getServerChannel(),
|
||||
channel -> channel.attr(CLIENT_CERTIFICATE_PROMISE_KEY).get().get(),
|
||||
SSLHandshakeException.class);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_protocolNotAccepted_beforeEnforcementDate(SslProvider sslProvider)
|
||||
throws Exception {
|
||||
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
|
||||
LocalAddress localAddress = new LocalAddress("PROTOCOL_ACCEPTED_BEFORE_DATE_" + sslProvider);
|
||||
|
||||
nettyExtension.setUpServer(
|
||||
localAddress,
|
||||
new SslServerInitializer<LocalChannel>(
|
||||
true,
|
||||
true,
|
||||
sslProvider,
|
||||
Suppliers.ofInstance(serverSsc.key()),
|
||||
Suppliers.ofInstance(ImmutableList.of(serverSsc.cert())),
|
||||
DateTime.parse("2021-04-01T16:00:00Z"),
|
||||
new FakeClock(DateTime.parse("2021-03-01T16:00:00Z"))));
|
||||
SelfSignedCaCertificate clientSsc =
|
||||
SelfSignedCaCertificate.create(
|
||||
"CLIENT",
|
||||
Date.from(Instant.now().minus(Duration.ofDays(2))),
|
||||
Date.from(Instant.now().plus(Duration.ofDays(1))));
|
||||
nettyExtension.setUpClient(
|
||||
localAddress,
|
||||
getClientHandler(
|
||||
sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert(), "TLSv1.1", null));
|
||||
|
||||
SSLSession sslSession = setUpSslChannel(nettyExtension.getClientChannel(), serverSsc.cert());
|
||||
nettyExtension.assertThatMessagesWork();
|
||||
|
||||
assertThat(sslSession.getLocalCertificates()).asList().containsExactly(clientSsc.cert());
|
||||
assertThat(sslSession.getPeerCertificates()).asList().containsExactly(serverSsc.cert());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testFailure_clientCertExpired(SslProvider sslProvider) throws Exception {
|
||||
|
||||
@@ -48,8 +48,8 @@ javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
@@ -64,8 +64,8 @@ org.junit.jupiter:junit-jupiter-params:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
|
||||
@@ -48,8 +48,8 @@ javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
@@ -64,8 +64,8 @@ org.junit.jupiter:junit-jupiter-params:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
|
||||
@@ -48,8 +48,8 @@ javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
@@ -64,8 +64,8 @@ org.junit.jupiter:junit-jupiter-params:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
|
||||
@@ -48,8 +48,8 @@ javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
@@ -64,8 +64,8 @@ org.junit.jupiter:junit-jupiter-params:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
mock-maker-inline
|
||||
+2
-1
@@ -19,7 +19,8 @@
|
||||
rootProject.ext.projects = ['production': 'your-production-project',
|
||||
'sandbox' : 'your-sandbox-project',
|
||||
'alpha' : 'your-alpha-project',
|
||||
'crash' : 'your-crash-project']
|
||||
'crash' : 'your-crash-project',
|
||||
'qa' : 'your-qa-project']
|
||||
|
||||
// The project to host your development/deployment infrastructure. It hosts
|
||||
// things like release artifacts, CI/CD system, etc.
|
||||
|
||||
@@ -53,8 +53,8 @@ javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
@@ -69,7 +69,7 @@ org.junit.jupiter:junit-jupiter-params:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
|
||||
@@ -53,8 +53,8 @@ javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
@@ -69,7 +69,7 @@ org.junit.jupiter:junit-jupiter-params:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
|
||||
@@ -53,8 +53,8 @@ javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
@@ -69,7 +69,7 @@ org.junit.jupiter:junit-jupiter-params:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
|
||||
@@ -53,8 +53,8 @@ javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
@@ -69,7 +69,7 @@ org.junit.jupiter:junit-jupiter-params:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
|
||||
@@ -50,6 +50,7 @@ import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Qualifier;
|
||||
import javax.inject.Singleton;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** A module that provides the {@link FrontendProtocol} used for epp protocol. */
|
||||
@Module
|
||||
@@ -159,11 +160,19 @@ public final class EppProtocolModule {
|
||||
@Provides
|
||||
@EppProtocol
|
||||
static SslServerInitializer<NioSocketChannel> provideSslServerInitializer(
|
||||
ProxyConfig config,
|
||||
SslProvider sslProvider,
|
||||
Supplier<PrivateKey> privateKeySupplier,
|
||||
Supplier<ImmutableList<X509Certificate>> certificatesSupplier) {
|
||||
Supplier<ImmutableList<X509Certificate>> certificatesSupplier,
|
||||
Clock clock) {
|
||||
return new SslServerInitializer<>(
|
||||
true, false, sslProvider, privateKeySupplier, certificatesSupplier);
|
||||
true,
|
||||
false,
|
||||
sslProvider,
|
||||
privateKeySupplier,
|
||||
certificatesSupplier,
|
||||
DateTime.parse(config.tlsEnforcementStartTime),
|
||||
clock);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -48,6 +48,7 @@ public class ProxyConfig {
|
||||
public WebWhois webWhois;
|
||||
public HttpsRelay httpsRelay;
|
||||
public Metrics metrics;
|
||||
public String tlsEnforcementStartTime;
|
||||
|
||||
/** Configuration options that apply to GCS. */
|
||||
public static class Gcs {
|
||||
|
||||
@@ -21,6 +21,8 @@ import dagger.multibindings.IntoSet;
|
||||
import google.registry.networking.handler.SslServerInitializer;
|
||||
import google.registry.proxy.Protocol.FrontendProtocol;
|
||||
import google.registry.proxy.handler.WebWhoisRedirectHandler;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.DateTimeUtils;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.http.HttpServerCodec;
|
||||
@@ -133,8 +135,15 @@ public final class WebWhoisProtocolsModule {
|
||||
static SslServerInitializer<NioSocketChannel> provideSslServerInitializer(
|
||||
SslProvider sslProvider,
|
||||
Supplier<PrivateKey> privateKeySupplier,
|
||||
Supplier<ImmutableList<X509Certificate>> certificatesSupplier) {
|
||||
Supplier<ImmutableList<X509Certificate>> certificatesSupplier,
|
||||
Clock clock) {
|
||||
return new SslServerInitializer<>(
|
||||
false, false, sslProvider, privateKeySupplier, certificatesSupplier);
|
||||
false,
|
||||
false,
|
||||
sslProvider,
|
||||
privateKeySupplier,
|
||||
certificatesSupplier,
|
||||
DateTimeUtils.END_OF_TIME,
|
||||
clock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
# GCP project ID
|
||||
projectId: your-gcp-project-id
|
||||
|
||||
# Time to begin enforcement of TLS versions and cipher suites.
|
||||
tlsEnforcementStartTime: "2021-04-01T16:00:00Z"
|
||||
|
||||
# OAuth scope that the GoogleCredential will be constructed with. This list
|
||||
# should include all service scopes that the proxy depends on.
|
||||
gcpScopes:
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
# Add environment-specific proxy configuration here.
|
||||
|
||||
# Time to begin enforcement of TLS versions and cipher suites.
|
||||
tlsEnforcementStartTime: "1970-01-01T00:00:00Z"
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
# Add environment-specific proxy configuration here.
|
||||
|
||||
# Time to begin enforcement of TLS versions and cipher suites.
|
||||
tlsEnforcementStartTime: "1970-01-01T00:00:00Z"
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
# Add environment-specific proxy configuration here.
|
||||
|
||||
# Time to begin enforcement of TLS versions and cipher suites.
|
||||
tlsEnforcementStartTime: "1970-01-01T00:00:00Z"
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
# Add environment-specific proxy configuration here.
|
||||
|
||||
# Time to begin enforcement of TLS versions and cipher suites.
|
||||
tlsEnforcementStartTime: "1970-01-01T00:00:00Z"
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
# Add environment-specific proxy configuration here.
|
||||
|
||||
# Time to begin enforcement of TLS versions and cipher suites.
|
||||
tlsEnforcementStartTime: "1970-01-01T00:00:00Z"
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
# Add environment-specific proxy configuration here.
|
||||
|
||||
# Time to begin enforcement of TLS versions and cipher suites.
|
||||
tlsEnforcementStartTime: "1970-01-01T00:00:00Z"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
mock-maker-inline
|
||||
@@ -37,8 +37,8 @@ javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.13
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
@@ -48,13 +48,13 @@ org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:3.5.0
|
||||
org.hamcrest:hamcrest-core:2.2
|
||||
org.hamcrest:hamcrest:2.2
|
||||
org.junit.jupiter:junit-jupiter-api:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.mockito:mockito-junit-jupiter:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.junit.jupiter:junit-jupiter-api:5.7.0
|
||||
org.junit.jupiter:junit-jupiter-engine:5.7.0
|
||||
org.junit.platform:junit-platform-commons:1.7.0
|
||||
org.junit.platform:junit-platform-engine:1.7.0
|
||||
org.junit:junit-bom:5.7.0
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.mockito:mockito-junit-jupiter:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
|
||||
@@ -37,8 +37,8 @@ javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.13
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
@@ -53,8 +53,8 @@ org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.mockito:mockito-junit-jupiter:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.mockito:mockito-junit-jupiter:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
|
||||
@@ -39,8 +39,8 @@ javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.13
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
@@ -50,13 +50,13 @@ org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:3.5.0
|
||||
org.hamcrest:hamcrest-core:2.2
|
||||
org.hamcrest:hamcrest:2.2
|
||||
org.junit.jupiter:junit-jupiter-api:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.mockito:mockito-junit-jupiter:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.junit.jupiter:junit-jupiter-api:5.7.0
|
||||
org.junit.jupiter:junit-jupiter-engine:5.7.0
|
||||
org.junit.platform:junit-platform-commons:1.7.0
|
||||
org.junit.platform:junit-platform-engine:1.7.0
|
||||
org.junit:junit-bom:5.7.0
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.mockito:mockito-junit-jupiter:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
|
||||
@@ -39,8 +39,8 @@ javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.13
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.5
|
||||
net.bytebuddy:byte-buddy-agent:1.10.19
|
||||
net.bytebuddy:byte-buddy:1.10.19
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
@@ -50,13 +50,13 @@ org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:3.5.0
|
||||
org.hamcrest:hamcrest-core:2.2
|
||||
org.hamcrest:hamcrest:2.2
|
||||
org.junit.jupiter:junit-jupiter-api:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.mockito:mockito-core:3.3.3
|
||||
org.mockito:mockito-junit-jupiter:3.3.3
|
||||
org.objenesis:objenesis:2.6
|
||||
org.junit.jupiter:junit-jupiter-api:5.7.0
|
||||
org.junit.jupiter:junit-jupiter-engine:5.7.0
|
||||
org.junit.platform:junit-platform-commons:1.7.0
|
||||
org.junit.platform:junit-platform-engine:1.7.0
|
||||
org.junit:junit-bom:5.7.0
|
||||
org.mockito:mockito-core:3.7.7
|
||||
org.mockito:mockito-junit-jupiter:3.7.7
|
||||
org.objenesis:objenesis:3.1
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
mock-maker-inline
|
||||
Reference in New Issue
Block a user