mirror of
https://github.com/google/nomulus
synced 2026-02-05 12:31:15 +00:00
Compare commits
30 Commits
nomulus-20
...
nomulus-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e3151ca02 | ||
|
|
292bc788fb | ||
|
|
b1ee1e8441 | ||
|
|
f3f00d0ae0 | ||
|
|
ca213aa8d7 | ||
|
|
592dadd12e | ||
|
|
9d7e3cdf79 | ||
|
|
cf0560607e | ||
|
|
78ca14e426 | ||
|
|
72da4cc493 | ||
|
|
961f9e7844 | ||
|
|
d2b9ebafc8 | ||
|
|
9546408a3a | ||
|
|
0ee15b3a59 | ||
|
|
01464e8e05 | ||
|
|
52b0574c73 | ||
|
|
a0f177b71f | ||
|
|
e01448b52e | ||
|
|
4da474e094 | ||
|
|
e273a18b4a | ||
|
|
8275bc45b9 | ||
|
|
0b6805531a | ||
|
|
592454d97d | ||
|
|
671e42474c | ||
|
|
1c90a6648e | ||
|
|
3f68ad5ea3 | ||
|
|
9c6c210e21 | ||
|
|
ca60ca159f | ||
|
|
82092b3516 | ||
|
|
0746d28e0c |
@@ -4,28 +4,35 @@
|
||||
antlr:antlr:2.7.7=checkstyle
|
||||
aopalliance:aopalliance:1.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
args4j:args4j:2.0.23=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.13.3=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.13.3=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.13.4=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.13.4=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0=annotationProcessor,testAnnotationProcessor
|
||||
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,testAnnotationProcessor
|
||||
com.google.api-client:google-api-client:1.35.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.9.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.4.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.android:annotations:4.1.1.4=testRuntimeClasspath
|
||||
com.google.api-client:google-api-client:2.0.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.14.0-alpha=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.14.0-alpha=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-iam-v1:1.6.4=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.14.0-alpha=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.9.6=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.6.4=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:api-common:2.2.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:0.103.2=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.18.2=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20220705-1.32.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.7.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.7.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.9=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value:1.9=annotationProcessor
|
||||
com.google.api:gax-grpc:2.19.4=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:0.104.4=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.19.4=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20220705-2.0.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.12.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.12.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.10=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value:1.10=annotationProcessor
|
||||
com.google.auto:auto-common:0.10=annotationProcessor,testAnnotationProcessor
|
||||
com.google.cloud:google-cloud-core-http:2.8.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.8.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.10.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.8.22=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.8.22=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.8.22=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.14.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.findbugs:jFormatString:3.0.0=annotationProcessor,testAnnotationProcessor
|
||||
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.gson:gson:2.9.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.gson:gson:2.9.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.common.html.types:types:1.0.6=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotation:2.3.4=annotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.11.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -39,20 +46,21 @@ com.google.guava:guava:27.0.1-jre=annotationProcessor,testAnnotationProcessor
|
||||
com.google.guava:guava:29.0-jre=checkstyle
|
||||
com.google.guava:guava:31.1-jre=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.42.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.42.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-gson:1.42.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.42.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client:1.42.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.42.2=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.42.2=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-gson:1.42.2=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.42.2=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client:1.42.2=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.inject:guice:4.1.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.j2objc:j2objc-annotations:1.1=annotationProcessor,testAnnotationProcessor
|
||||
com.google.j2objc:j2objc-annotations:1.3=checkstyle,compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.jsinterop:jsinterop-annotations:1.0.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client:1.34.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java-util:3.21.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java:3.21.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java-util:3.21.8=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java:3.21.8=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java:3.4.0=annotationProcessor,testAnnotationProcessor
|
||||
com.google.re2j:re2j:1.6=testRuntimeClasspath
|
||||
com.google.template:soy:2021-02-01=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.truth.extensions:truth-java8-extension:1.1.3=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.truth:truth:1.1.3=testCompileClasspath,testRuntimeClasspath
|
||||
@@ -64,28 +72,44 @@ commons-codec:commons-codec:1.11=compileClasspath,testCompileClasspath,testRunti
|
||||
commons-collections:commons-collections:3.2.2=checkstyle
|
||||
commons-logging:commons-logging:1.2=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
info.picocli:picocli:4.5.2=checkstyle
|
||||
io.grpc:grpc-context:1.47.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-alts:1.50.1=testRuntimeClasspath
|
||||
io.grpc:grpc-api:1.50.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-auth:1.50.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-context:1.50.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-core:1.50.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-googleapis:1.50.1=testRuntimeClasspath
|
||||
io.grpc:grpc-grpclb:1.50.1=testRuntimeClasspath
|
||||
io.grpc:grpc-netty-shaded:1.50.1=testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf-lite:1.50.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf:1.50.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-services:1.50.1=testRuntimeClasspath
|
||||
io.grpc:grpc-stub:1.50.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-xds:1.50.1=testRuntimeClasspath
|
||||
io.opencensus:opencensus-api:0.31.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-http-util:0.31.1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-proto:0.2.0=testRuntimeClasspath
|
||||
io.perfmark:perfmark-api:0.25.0=testRuntimeClasspath
|
||||
javax.annotation:javax.annotation-api:1.3.2=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.annotation:jsr250-api:1.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.inject:javax.inject:1=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
junit:junit:4.13.2=testCompileClasspath,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy-agent:1.12.10=testCompileClasspath,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.12.10=testCompileClasspath,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy-agent:1.12.16=testCompileClasspath,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.12.16=testCompileClasspath,testRuntimeClasspath
|
||||
net.sf.saxon:Saxon-HE:10.3=checkstyle
|
||||
org.antlr:antlr4-runtime:4.8-1=checkstyle
|
||||
org.apache.commons:commons-lang3:3.11=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-text:1.9=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-lang3:3.12.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-text:1.10.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpclient:4.5.13=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpcore:4.4.15=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
|
||||
org.checkerframework:checker-qual:2.11.1=checkstyle
|
||||
org.checkerframework:checker-qual:3.0.0=annotationProcessor,testAnnotationProcessor
|
||||
org.checkerframework:checker-qual:3.22.2=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-qual:3.26.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.checkerframework:dataflow:3.0.0=annotationProcessor,testAnnotationProcessor
|
||||
org.checkerframework:javacutil:3.0.0=annotationProcessor,testAnnotationProcessor
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor,testAnnotationProcessor
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.22=testRuntimeClasspath
|
||||
org.conscrypt:conscrypt-openjdk-uber:2.5.2=testRuntimeClasspath
|
||||
org.hamcrest:hamcrest-core:1.3=testCompileClasspath,testRuntimeClasspath
|
||||
org.jacoco:org.jacoco.agent:0.8.6=jacocoAgent,jacocoAnt
|
||||
org.jacoco:org.jacoco.ant:0.8.6=jacocoAnt
|
||||
@@ -93,12 +117,12 @@ org.jacoco:org.jacoco.core:0.8.6=jacocoAnt
|
||||
org.jacoco:org.jacoco.report:0.8.6=jacocoAnt
|
||||
org.javassist:javassist:3.26.0-GA=checkstyle
|
||||
org.json:json:20160212=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit:junit-bom:5.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.mockito:mockito-core:4.6.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit:junit-bom:5.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.mockito:mockito-core:4.8.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.objenesis:objenesis:3.2=testRuntimeClasspath
|
||||
org.opentest4j:opentest4j:1.2.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-analysis:7.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -116,5 +140,5 @@ org.plumelib:plume-util:1.0.6=annotationProcessor,testAnnotationProcessor
|
||||
org.plumelib:reflection-util:0.0.2=annotationProcessor,testAnnotationProcessor
|
||||
org.plumelib:require-javadoc:0.1.0=annotationProcessor,testAnnotationProcessor
|
||||
org.reflections:reflections:0.9.12=checkstyle
|
||||
org.threeten:threetenbp:1.6.0=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.threeten:threetenbp:1.6.3=compileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
empty=
|
||||
|
||||
@@ -32,7 +32,7 @@ commons-collections:commons-collections:3.2.2=checkstyle
|
||||
info.picocli:picocli:4.5.2=checkstyle
|
||||
io.github.java-diff-utils:java-diff-utils:4.12=compileClasspath,default,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
javax.inject:javax.inject:1=compileClasspath,default,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
joda-time:joda-time:2.10.14=compileClasspath,default,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
joda-time:joda-time:2.12.1=compileClasspath,default,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
junit:junit:4.13.2=default,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
net.sf.saxon:Saxon-HE:10.3=checkstyle
|
||||
org.antlr:antlr4-runtime:4.8-1=checkstyle
|
||||
@@ -50,11 +50,11 @@ org.jacoco:org.jacoco.ant:0.8.6=jacocoAnt
|
||||
org.jacoco:org.jacoco.core:0.8.6=jacocoAnt
|
||||
org.jacoco:org.jacoco.report:0.8.6=jacocoAnt
|
||||
org.javassist:javassist:3.26.0-GA=checkstyle
|
||||
org.junit.jupiter:junit-jupiter-api:5.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit:junit-bom:5.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit:junit-bom:5.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.opentest4j:opentest4j:1.2.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-analysis:8.0.1=jacocoAnt
|
||||
org.ow2.asm:asm-commons:8.0.1=jacocoAnt
|
||||
|
||||
@@ -186,7 +186,6 @@ dependencies {
|
||||
implementation deps['com.google.apis:google-api-services-admin-directory']
|
||||
implementation deps['com.google.apis:google-api-services-appengine']
|
||||
implementation deps['com.google.apis:google-api-services-bigquery']
|
||||
implementation deps['com.google.apis:google-api-services-cloudkms']
|
||||
implementation deps['com.google.apis:google-api-services-dataflow']
|
||||
implementation deps['com.google.apis:google-api-services-dns']
|
||||
implementation deps['com.google.apis:google-api-services-drive']
|
||||
@@ -268,7 +267,7 @@ dependencies {
|
||||
testImplementation deps['org.apache.sshd:sshd-sftp']
|
||||
testImplementation deps['org.apache.tomcat:tomcat-annotations-api']
|
||||
implementation deps['org.bouncycastle:bcpg-jdk15on']
|
||||
testImplementation deps['org.bouncycastle:bcpkix-jdk15on']
|
||||
implementation deps['org.bouncycastle:bcpkix-jdk15on']
|
||||
implementation deps['org.bouncycastle:bcprov-jdk15on']
|
||||
testImplementation deps['com.fasterxml.jackson.core:jackson-databind']
|
||||
runtime deps['org.glassfish.jaxb:jaxb-runtime']
|
||||
@@ -704,9 +703,6 @@ createToolTask(
|
||||
'google.registry.tools.DevTool',
|
||||
sourceSets.nonprod)
|
||||
|
||||
createToolTask(
|
||||
'jpaDemoPipeline', 'google.registry.beam.common.JpaDemoPipeline')
|
||||
|
||||
createToolTask(
|
||||
'createSyntheticDomainHistories',
|
||||
'google.registry.tools.javascrap.CreateSyntheticDomainHistoriesPipeline')
|
||||
|
||||
@@ -8,13 +8,16 @@ args4j:args4j:2.0.26=css
|
||||
cglib:cglib-nodep:2.2=css
|
||||
com.101tec:zkclient:0.10=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.beust:jcommander:1.60=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.13.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.13.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.13.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.13.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.13.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.electronwill.night-config:core:3.6.6=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.electronwill.night-config:toml:3.6.6=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.13.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.13.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.13.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.13.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.13.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.13.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml:classmate:1.5.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.github.ben-manes.caffeine:caffeine:2.9.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -36,72 +39,73 @@ com.google.api-client:google-api-client-jackson2:1.32.2=compileClasspath,default
|
||||
com.google.api-client:google-api-client-java6:1.35.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-servlet:1.35.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client:1.35.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:2.12.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.136.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.136.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.14.0-alpha=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:2.20.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.144.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.144.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:1.27.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.6.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.98.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.5.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.23.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.23.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.23.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.2.2-alpha=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.8.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:2.12.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.136.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.136.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.6.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.6.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-datastore-v1:0.93.10=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-firestore-v1:3.1.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:1.64.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.98.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.5.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.3.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:2.3.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.23.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.23.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:6.23.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.2.2-alpha=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.3.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.93.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.93.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.9.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.4.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.11.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.102.13=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.6.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.29.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.29.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.29.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.14.0-alpha=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.9.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-iam-v1:1.6.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:2.20.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.144.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.144.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.11.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.11.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-datastore-v1:0.102.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-firestore-v1:3.4.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.4.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.102.13=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.6.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.5.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:2.5.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.29.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.29.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:6.29.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.14.0-alpha=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.5.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.95.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.95.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.9.6=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.6.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:api-common:2.2.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-grpc:2.18.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:0.103.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.18.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-grpc:2.19.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:0.104.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.19.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-appengine:v1-rev20220612-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20211129-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-clouddebugger:v2-rev20210813-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-cloudkms:v1-rev20220701-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20211017-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20210818-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-appengine:v1-rev20220818-2.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20220827-2.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-clouddebugger:v2-rev20220318-2.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20220828-2.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20220812-2.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-drive:v2-rev393-1.25.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev20210624-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-healthcare:v1-rev20211016-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev20210624-2.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-healthcare:v1-rev20220818-2.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-iamcredentials:v1-rev20210326-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-monitoring:v3-rev20220715-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-pubsub:v1-rev20211130-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sheets:v4-rev20220620-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sqladmin:v1beta4-rev20220623-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20220705-1.32.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-monitoring:v3-rev20220930-2.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-pubsub:v1-rev20220829-2.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sheets:v4-rev20220927-2.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sqladmin:v1beta4-rev20221017-2.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20220705-2.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine.tools:appengine-gcs-client:0.8.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine.tools:appengine-pipeline:0.2.13=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-1.0-sdk:2.0.5=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-stubs:2.0.5=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-remote-api:2.0.5=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-1.0-sdk:2.0.9=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-stubs:2.0.9=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-remote-api:2.0.9=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-testing:1.9.86=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.8.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.8.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.12.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.12.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.service:auto-service:1.0.1=annotationProcessor
|
||||
com.google.auto.value:auto-value-annotations:1.9=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value:1.9=annotationProcessor,default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.10=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value:1.10=annotationProcessor,default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testRuntimeClasspath
|
||||
com.google.auto:auto-common:0.10=errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.auto:auto-common:1.2=annotationProcessor
|
||||
com.google.closure-stylesheets:closure-stylesheets:1.5.0=css
|
||||
@@ -109,38 +113,39 @@ com.google.cloud.bigdataoss:gcsio:2.2.6=compileClasspath,default,deploy_jar,nonp
|
||||
com.google.cloud.bigdataoss:util:2.2.6=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigtable:bigtable-client-core:1.26.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigtable:bigtable-metrics-api:1.26.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.datastore:datastore-v1-proto-client:2.2.10=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:jdbc-socket-factory-core:1.6.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:postgres-socket-factory:1.6.2=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigquerystorage:2.12.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable:2.6.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.6.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.8.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.8.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-firestore:3.1.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-monitoring:1.82.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-nio:0.124.10=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsub:1.116.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsublite:1.5.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.3.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-spanner:6.23.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.10.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.3.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:grpc-gcp:1.1.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.1.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.datastore:datastore-v1-proto-client:2.9.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:jdbc-socket-factory-core:1.7.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:postgres-socket-factory:1.7.2=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigquerystorage:2.20.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable-stats:2.11.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable:2.11.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.8.22=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.8.22=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.8.22=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-firestore:3.4.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-monitoring:3.4.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-nio:0.124.19=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsub:1.120.13=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsublite:1.6.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.5.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-spanner:6.29.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.14.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.5.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:grpc-gcp:1.2.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.4.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.findbugs:jFormatString:3.0.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.code.findbugs:jsr305:3.0.1=css
|
||||
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,default,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntime,nonprodRuntimeClasspath,runtime,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.gson:gson:2.10=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.gson:gson:2.7=css,soy
|
||||
com.google.code.gson:gson:2.9.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.common.html.types:types:1.0.6=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.dagger:dagger-compiler:2.43=annotationProcessor,testAnnotationProcessor
|
||||
com.google.dagger:dagger-producers:2.43=annotationProcessor,testAnnotationProcessor
|
||||
com.google.dagger:dagger-spi:2.43=annotationProcessor,testAnnotationProcessor
|
||||
com.google.dagger:dagger:2.43=annotationProcessor,compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.dagger:dagger-compiler:2.44=annotationProcessor,testAnnotationProcessor
|
||||
com.google.dagger:dagger-producers:2.44=annotationProcessor,testAnnotationProcessor
|
||||
com.google.dagger:dagger-spi:2.44=annotationProcessor,testAnnotationProcessor
|
||||
com.google.dagger:dagger:2.44=annotationProcessor,compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6=annotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotation:2.3.4=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.14.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.16=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.3.4=checkstyle,errorprone,nonprodAnnotationProcessor,soy
|
||||
com.google.errorprone:error_prone_annotations:2.7.1=annotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_check_api:2.3.4=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
@@ -163,12 +168,12 @@ com.google.guava:guava:31.0.1-jre=annotationProcessor,testAnnotationProcessor
|
||||
com.google.guava:guava:31.1-jre=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,default,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.gwt:gwt-user:2.10.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-gson:1.42.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-protobuf:1.41.7=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client:1.42.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.42.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.42.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-gson:1.42.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.42.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-protobuf:1.41.8=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client:1.42.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.inject:guice:4.1.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.inject:guice:5.1.0=soy
|
||||
@@ -187,19 +192,19 @@ com.google.oauth-client:google-oauth-client-java6:1.34.1=compileClasspath,defaul
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.34.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.34.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client:1.34.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java-util:3.21.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java-util:3.21.8=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java:2.5.0=css
|
||||
com.google.protobuf:protobuf-java:3.21.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java:3.21.8=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java:3.4.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.protobuf:protobuf-java:4.0.0-rc-2=soy
|
||||
com.google.re2j:re2j:1.7=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.re2j:re2j:1.6=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.template:soy:2021-02-01=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.truth.extensions:truth-java8-extension:1.1.3=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.truth:truth:1.1.3=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.googlecode.json-simple:json-simple:1.1.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.ibm.icu:icu4j:57.1=compileClasspath,nonprodCompileClasspath,soy,testCompileClasspath
|
||||
com.ibm.icu:icu4j:71.1=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.ibm.icu:icu4j:72.1=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.jcraft:jsch:0.1.55=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.lmax:disruptor:3.4.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.puppycrawl.tools:checkstyle:8.37=checkstyle
|
||||
@@ -211,7 +216,7 @@ com.sun.activation:javax.activation:1.2.0=jaxb
|
||||
com.sun.istack:istack-commons-runtime:3.0.7=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.sun.istack:istack-commons-runtime:4.1.1=nonprodRuntime,runtime
|
||||
com.sun.xml.bind:jaxb-impl:2.3.3=jaxb
|
||||
com.sun.xml.bind:jaxb-osgi:4.0.0=jaxb
|
||||
com.sun.xml.bind:jaxb-osgi:4.0.1=jaxb
|
||||
com.sun.xml.bind:jaxb-xjc:2.3.3=jaxb
|
||||
com.sun.xml.fastinfoset:FastInfoset:1.2.15=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.thoughtworks.paranamer:paranamer:2.7=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -237,44 +242,43 @@ io.confluent:kafka-schema-registry-client:5.3.2=compileClasspath,default,deploy_
|
||||
io.dropwizard.metrics:metrics-core:3.1.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.github.classgraph:classgraph:4.8.104=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.github.java-diff-utils:java-diff-utils:4.12=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-alts:1.45.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-alts:1.47.0=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-api:1.47.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-auth:1.45.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-auth:1.47.0=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-census:1.45.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-context:1.47.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-core:1.45.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-core:1.47.0=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-googleapis:1.47.0=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-grpclb:1.45.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-grpclb:1.47.0=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-netty-shaded:1.45.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-netty-shaded:1.47.0=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-netty:1.45.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf-lite:1.47.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf:1.47.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-services:1.45.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-services:1.47.0=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-stub:1.47.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-xds:1.45.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-xds:1.47.0=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-buffer:4.1.72.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-http2:4.1.72.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-http:4.1.72.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-socks:4.1.72.Final=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec:4.1.72.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-common:4.1.72.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-handler-proxy:4.1.72.Final=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-handler:4.1.72.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-resolver:4.1.72.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-tcnative-boringssl-static:2.0.46.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-tcnative-classes:2.0.46.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-transport:4.1.72.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-alts:1.48.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-alts:1.50.1=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-api:1.50.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-auth:1.50.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-census:1.48.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-context:1.50.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-core:1.50.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-googleapis:1.50.1=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-grpclb:1.48.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-grpclb:1.50.1=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-netty-shaded:1.48.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-netty-shaded:1.50.1=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-netty:1.48.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf-lite:1.50.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf:1.50.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-services:1.48.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-services:1.50.1=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-stub:1.50.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-xds:1.48.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-xds:1.50.1=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-buffer:4.1.77.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-http2:4.1.77.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-http:4.1.77.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-socks:4.1.77.Final=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec:4.1.77.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-common:4.1.77.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-handler-proxy:4.1.77.Final=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-handler:4.1.77.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-resolver:4.1.77.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-tcnative-boringssl-static:2.0.52.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-tcnative-classes:2.0.52.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-transport-native-unix-common:4.1.77.Final=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-transport:4.1.77.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-api:0.31.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-exemplar-util:0.31.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-grpc-metrics:0.31.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-grpc-util:0.31.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-grpc-util:0.31.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-http-util:0.31.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-resource-util:0.31.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-exporter-metrics-util:0.31.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -302,9 +306,8 @@ jline:jline:1.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonp
|
||||
joda-time:joda-time:2.10.10=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
junit:junit:4.13.2=default,nonprodCompileClasspath,nonprodRuntimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
net.arnx:nashorn-promise:0.1.1=nonprodRuntime,runtime,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy-agent:1.12.10=testCompileClasspath,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.12.10=testCompileClasspath,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.12.9=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
net.bytebuddy:byte-buddy-agent:1.12.16=testCompileClasspath,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.12.18=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
net.java.dev.javacc:javacc:4.1=css
|
||||
net.java.dev.jna:jna:5.8.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
net.ltgt.gradle.incap:incap:0.2=annotationProcessor,testAnnotationProcessor
|
||||
@@ -314,31 +317,29 @@ org.apache.arrow:arrow-format:5.0.0=compileClasspath,default,deploy_jar,nonprodC
|
||||
org.apache.arrow:arrow-memory-core:5.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.arrow:arrow-vector:5.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.avro:avro:1.8.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-fn-execution:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-job-management:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-pipeline:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-construction-java:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-java:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-direct-java:2.40.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-java-fn-execution:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-core:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-expansion-service:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-arrow:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-fn-execution:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-io-kafka:2.40.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-bytebuddy-1_11_0:0.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-grpc-1_43_2:0.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-fn-execution:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-job-management:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-pipeline:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-construction-java:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-java:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-direct-java:2.42.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-java-fn-execution:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-core:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-expansion-service:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-arrow:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-fn-execution:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-io-kafka:2.42.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-grpc-1_48_1:0.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-guava-26_0-jre:0.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-compress:1.21=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-csv:1.9.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-exec:1.3=nonprodRuntime,runtime,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-lang3:3.11=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-lang3:3.12.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
org.apache.commons:commons-text:1.9=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-lang3:3.12.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-text:1.10.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.ftpserver:ftplet-api:1.2.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.ftpserver:ftpserver-core:1.2.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpclient:4.5.13=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -347,7 +348,7 @@ org.apache.mina:mina-core:2.1.6=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-core:2.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-scp:2.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-sftp:2.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.tomcat:tomcat-annotations-api:10.1.0-M17=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.tomcat:tomcat-annotations-api:10.1.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
|
||||
org.bouncycastle:bcpg-jdk15on:1.67=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpkix-jdk15on:1.67=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -357,23 +358,23 @@ org.checkerframework:checker-compat-qual:2.5.5=annotationProcessor,compileClassp
|
||||
org.checkerframework:checker-qual:2.11.1=checkstyle
|
||||
org.checkerframework:checker-qual:3.0.0=errorprone,nonprodAnnotationProcessor
|
||||
org.checkerframework:checker-qual:3.12.0=annotationProcessor,testAnnotationProcessor
|
||||
org.checkerframework:checker-qual:3.22.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-qual:3.26.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-qual:3.5.0=nonprodRuntime,runtime,soy
|
||||
org.checkerframework:dataflow:3.0.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
org.checkerframework:javacutil:3.0.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
org.codehaus.jackson:jackson-core-asl:1.9.13=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.codehaus.jackson:jackson-mapper-asl:1.9.13=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17=errorprone,nonprodAnnotationProcessor
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.21=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.conscrypt:conscrypt-openjdk-uber:2.5.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.22=default,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.conscrypt:conscrypt-openjdk-uber:2.5.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.easymock:easymock:3.0=css
|
||||
org.eclipse.angus:angus-activation:1.0.0=nonprodRuntime,runtime
|
||||
org.flywaydb:flyway-core:9.0.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:jaxb-core:4.0.0=nonprodRuntime,runtime
|
||||
org.flywaydb:flyway-core:9.7.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:jaxb-core:4.0.1=nonprodRuntime,runtime
|
||||
org.glassfish.jaxb:jaxb-runtime:2.3.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:jaxb-runtime:4.0.0=nonprodRuntime,runtime
|
||||
org.glassfish.jaxb:jaxb-runtime:4.0.1=nonprodRuntime,runtime
|
||||
org.glassfish.jaxb:txw2:2.3.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:txw2:4.0.0=nonprodRuntime,runtime
|
||||
org.glassfish.jaxb:txw2:4.0.1=nonprodRuntime,runtime
|
||||
org.gwtproject:gwt-user:2.10.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.hamcrest:hamcrest-core:1.1=css
|
||||
org.hamcrest:hamcrest-core:1.3=default,nonprodCompileClasspath,nonprodRuntimeClasspath
|
||||
@@ -382,8 +383,8 @@ org.hamcrest:hamcrest-library:2.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.hamcrest:hamcrest:2.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.hibernate.common:hibernate-commons-annotations:5.1.2.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.hibernate:hibernate-core:5.6.10.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.hibernate:hibernate-hikaricp:5.6.10.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.hibernate:hibernate-core:5.6.14.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.hibernate:hibernate-hikaricp:5.6.14.Final=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jacoco:org.jacoco.agent:0.8.6=jacocoAgent,jacocoAnt
|
||||
org.jacoco:org.jacoco.ant:0.8.6=jacocoAnt
|
||||
org.jacoco:org.jacoco.core:0.8.6=jacocoAnt
|
||||
@@ -396,29 +397,29 @@ org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0=annotationProcessor,testAnnotati
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0=annotationProcessor,testAnnotationProcessor
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0=annotationProcessor,testAnnotationProcessor
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.7.0=annotationProcessor,testAnnotationProcessor
|
||||
org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.4.2=annotationProcessor,testAnnotationProcessor
|
||||
org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0=annotationProcessor,testAnnotationProcessor
|
||||
org.jetbrains:annotations:13.0=annotationProcessor,testAnnotationProcessor
|
||||
org.jetbrains:annotations:17.0.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.joda:joda-money:1.0.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.joda:joda-money:1.0.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.json:json:20160212=soy
|
||||
org.json:json:20200518=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jsoup:jsoup:1.15.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jsoup:jsoup:1.15.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.junit-pioneer:junit-pioneer:1.7.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-migrationsupport:5.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-params:5.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-launcher:1.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-runner:1.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-api:1.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-commons:1.9.0=testRuntimeClasspath
|
||||
org.junit:junit-bom:5.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-migrationsupport:5.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-params:5.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-launcher:1.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-runner:1.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-api:1.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-commons:1.9.1=testRuntimeClasspath
|
||||
org.junit:junit-bom:5.9.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.jvnet.staxex:stax-ex:1.8=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.mockito:mockito-core:1.10.19=css
|
||||
org.mockito:mockito-core:4.6.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.mockito:mockito-junit-jupiter:4.6.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.mockito:mockito-core:4.8.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.mockito:mockito-junit-jupiter:4.8.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.mortbay.jetty:jetty-util:6.1.26=testCompileClasspath,testRuntimeClasspath
|
||||
org.mortbay.jetty:jetty:6.1.26=testCompileClasspath,testRuntimeClasspath
|
||||
org.objenesis:objenesis:2.1=css
|
||||
@@ -426,23 +427,23 @@ org.objenesis:objenesis:3.2=testRuntimeClasspath
|
||||
org.opentest4j:opentest4j:1.2.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-analysis:7.0=soy
|
||||
org.ow2.asm:asm-analysis:8.0.1=jacocoAnt
|
||||
org.ow2.asm:asm-analysis:9.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-analysis:9.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-commons:7.0=soy
|
||||
org.ow2.asm:asm-commons:8.0.1=jacocoAnt
|
||||
org.ow2.asm:asm-commons:9.2=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-tree:7.0=soy
|
||||
org.ow2.asm:asm-tree:8.0.1=jacocoAnt
|
||||
org.ow2.asm:asm-tree:9.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-tree:9.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-util:7.0=soy
|
||||
org.ow2.asm:asm-util:9.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-util:9.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm:7.0=soy
|
||||
org.ow2.asm:asm:8.0.1=jacocoAnt
|
||||
org.ow2.asm:asm:9.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm:9.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.pcollections:pcollections:2.1.2=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
org.plumelib:plume-util:1.0.6=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
org.plumelib:reflection-util:0.0.2=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
org.plumelib:require-javadoc:0.1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
org.postgresql:postgresql:42.4.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntime,nonprodRuntimeClasspath,runtime,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.postgresql:postgresql:42.5.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntime,nonprodRuntimeClasspath,runtime,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.reflections:reflections:0.9.12=checkstyle
|
||||
org.rnorth.duct-tape:duct-tape:1.0.8=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-api:3.141.59=testCompileClasspath,testRuntimeClasspath
|
||||
@@ -459,23 +460,23 @@ org.slf4j:jcl-over-slf4j:1.7.30=nonprodRuntime,runtime,testRuntimeClasspath
|
||||
org.slf4j:jul-to-slf4j:1.7.30=nonprodRuntime,runtime,testRuntimeClasspath
|
||||
org.slf4j:slf4j-api:1.7.30=nonprodRuntime,runtime
|
||||
org.slf4j:slf4j-api:1.7.36=compileClasspath,nonprodCompileClasspath,nonprodRuntimeClasspath,testCompileClasspath
|
||||
org.slf4j:slf4j-api:2.0.0-alpha7=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.slf4j:slf4j-jdk14:2.0.0-alpha7=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.slf4j:slf4j-api:2.0.3=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.slf4j:slf4j-jdk14:2.0.3=default,deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-core:5.3.18=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-expression:5.3.18=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-jcl:5.3.18=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:database-commons:1.17.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:jdbc:1.17.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:junit-jupiter:1.17.3=testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:postgresql:1.17.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:selenium:1.17.3=testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:testcontainers:1.17.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.threeten:threetenbp:1.6.0=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:database-commons:1.17.5=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:jdbc:1.17.5=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:junit-jupiter:1.17.5=testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:postgresql:1.17.5=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:selenium:1.17.5=testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:testcontainers:1.17.5=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.threeten:threetenbp:1.6.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.tukaani:xz:1.5=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.w3c.css:sac:1.3=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.webjars.npm:viz.js-graphviz-java:2.1.3=nonprodRuntime,runtime,testRuntimeClasspath
|
||||
org.xerial.snappy:snappy-java:1.1.8.4=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.yaml:snakeyaml:1.30=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.yaml:snakeyaml:1.31=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-api:16.10.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-diagram:16.10.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-tools:16.10.1=compileClasspath,default,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
|
||||
@@ -17,25 +17,16 @@ package google.registry.batch;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
|
||||
|
||||
import com.google.appengine.api.taskqueue.Queue;
|
||||
import com.google.appengine.api.taskqueue.TaskOptions;
|
||||
import com.google.appengine.api.taskqueue.TaskOptions.Method;
|
||||
import com.google.appengine.api.taskqueue.TransientFailureException;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.util.CloudTasksUtils;
|
||||
import google.registry.util.Retrier;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
@@ -44,45 +35,25 @@ public final class AsyncTaskEnqueuer {
|
||||
|
||||
/** The HTTP parameter names used by async flows. */
|
||||
public static final String PARAM_RESOURCE_KEY = "resourceKey";
|
||||
public static final String PARAM_REQUESTING_CLIENT_ID = "requestingClientId";
|
||||
public static final String PARAM_CLIENT_TRANSACTION_ID = "clientTransactionId";
|
||||
public static final String PARAM_SERVER_TRANSACTION_ID = "serverTransactionId";
|
||||
public static final String PARAM_IS_SUPERUSER = "isSuperuser";
|
||||
public static final String PARAM_HOST_KEY = "hostKey";
|
||||
public static final String PARAM_REQUESTED_TIME = "requestedTime";
|
||||
public static final String PARAM_RESAVE_TIMES = "resaveTimes";
|
||||
|
||||
/** The task queue names used by async flows. */
|
||||
public static final String QUEUE_ASYNC_ACTIONS = "async-actions";
|
||||
public static final String QUEUE_ASYNC_DELETE = "async-delete-pull";
|
||||
public static final String QUEUE_ASYNC_HOST_RENAME = "async-host-rename-pull";
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private static final Duration MAX_ASYNC_ETA = Duration.standardDays(30);
|
||||
|
||||
private final Duration asyncDeleteDelay;
|
||||
private final Queue asyncDeletePullQueue;
|
||||
private final Queue asyncDnsRefreshPullQueue;
|
||||
private final Retrier retrier;
|
||||
|
||||
private CloudTasksUtils cloudTasksUtils;
|
||||
private final CloudTasksUtils cloudTasksUtils;
|
||||
|
||||
@Inject
|
||||
public AsyncTaskEnqueuer(
|
||||
@Named(QUEUE_ASYNC_DELETE) Queue asyncDeletePullQueue,
|
||||
@Named(QUEUE_ASYNC_HOST_RENAME) Queue asyncDnsRefreshPullQueue,
|
||||
@Config("asyncDeleteDelay") Duration asyncDeleteDelay,
|
||||
CloudTasksUtils cloudTasksUtils,
|
||||
Retrier retrier) {
|
||||
this.asyncDeletePullQueue = asyncDeletePullQueue;
|
||||
this.asyncDnsRefreshPullQueue = asyncDnsRefreshPullQueue;
|
||||
this.asyncDeleteDelay = asyncDeleteDelay;
|
||||
public AsyncTaskEnqueuer(CloudTasksUtils cloudTasksUtils) {
|
||||
this.cloudTasksUtils = cloudTasksUtils;
|
||||
this.retrier = retrier;
|
||||
}
|
||||
|
||||
/** Enqueues a task to asynchronously re-save an entity at some point in the future. */
|
||||
public void enqueueAsyncResave(VKey<?> entityToResave, DateTime now, DateTime whenToResave) {
|
||||
public void enqueueAsyncResave(
|
||||
VKey<? extends EppResource> entityToResave, DateTime now, DateTime whenToResave) {
|
||||
enqueueAsyncResave(entityToResave, now, ImmutableSortedSet.of(whenToResave));
|
||||
}
|
||||
|
||||
@@ -93,7 +64,9 @@ public final class AsyncTaskEnqueuer {
|
||||
* itself to run at the next time if there are remaining re-saves scheduled.
|
||||
*/
|
||||
public void enqueueAsyncResave(
|
||||
VKey<?> entityKey, DateTime now, ImmutableSortedSet<DateTime> whenToResave) {
|
||||
VKey<? extends EppResource> entityKey,
|
||||
DateTime now,
|
||||
ImmutableSortedSet<DateTime> whenToResave) {
|
||||
DateTime firstResave = whenToResave.first();
|
||||
checkArgument(isBeforeOrAt(now, firstResave), "Can't enqueue a resave to run in the past");
|
||||
Duration etaDuration = new Duration(now, firstResave);
|
||||
@@ -115,46 +88,4 @@ public final class AsyncTaskEnqueuer {
|
||||
cloudTasksUtils.createPostTaskWithDelay(
|
||||
ResaveEntityAction.PATH, Service.BACKEND.toString(), params, etaDuration));
|
||||
}
|
||||
|
||||
/** Enqueues a task to asynchronously delete a contact or host, by key. */
|
||||
public void enqueueAsyncDelete(
|
||||
EppResource resourceToDelete,
|
||||
DateTime now,
|
||||
String requestingRegistrarId,
|
||||
Trid trid,
|
||||
boolean isSuperuser) {
|
||||
logger.atInfo().log(
|
||||
"Enqueuing async deletion of %s on behalf of registrar %s.",
|
||||
resourceToDelete.getRepoId(), requestingRegistrarId);
|
||||
TaskOptions task =
|
||||
TaskOptions.Builder.withMethod(Method.PULL)
|
||||
.countdownMillis(asyncDeleteDelay.getMillis())
|
||||
.param(PARAM_RESOURCE_KEY, resourceToDelete.createVKey().stringify())
|
||||
.param(PARAM_REQUESTING_CLIENT_ID, requestingRegistrarId)
|
||||
.param(PARAM_SERVER_TRANSACTION_ID, trid.getServerTransactionId())
|
||||
.param(PARAM_IS_SUPERUSER, Boolean.toString(isSuperuser))
|
||||
.param(PARAM_REQUESTED_TIME, now.toString());
|
||||
trid.getClientTransactionId()
|
||||
.ifPresent(clTrid -> task.param(PARAM_CLIENT_TRANSACTION_ID, clTrid));
|
||||
addTaskToQueueWithRetry(asyncDeletePullQueue, task);
|
||||
}
|
||||
|
||||
/** Enqueues a task to asynchronously refresh DNS for a renamed host. */
|
||||
public void enqueueAsyncDnsRefresh(Host host, DateTime now) {
|
||||
VKey<Host> hostKey = host.createVKey();
|
||||
logger.atInfo().log("Enqueuing async DNS refresh for renamed host %s.", hostKey);
|
||||
addTaskToQueueWithRetry(
|
||||
asyncDnsRefreshPullQueue,
|
||||
TaskOptions.Builder.withMethod(Method.PULL)
|
||||
.param(PARAM_HOST_KEY, hostKey.stringify())
|
||||
.param(PARAM_REQUESTED_TIME, now.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a task to a queue with retrying, to avoid aborting the entire flow over a transient issue
|
||||
* enqueuing a task.
|
||||
*/
|
||||
private void addTaskToQueueWithRetry(final Queue queue, final TaskOptions task) {
|
||||
retrier.callWithRetry(() -> queue.add(task), TransientFailureException.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
// Copyright 2017 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.batch;
|
||||
|
||||
import static com.google.appengine.api.taskqueue.QueueConstants.maxLeaseCount;
|
||||
import static com.google.monitoring.metrics.EventMetric.DEFAULT_FITTER;
|
||||
import static google.registry.batch.AsyncTaskMetrics.OperationType.CONTACT_AND_HOST_DELETE;
|
||||
import static google.registry.batch.AsyncTaskMetrics.OperationType.DNS_REFRESH;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.monitoring.metrics.DistributionFitter;
|
||||
import com.google.monitoring.metrics.EventMetric;
|
||||
import com.google.monitoring.metrics.FibonacciFitter;
|
||||
import com.google.monitoring.metrics.IncrementableMetric;
|
||||
import com.google.monitoring.metrics.LabelDescriptor;
|
||||
import com.google.monitoring.metrics.MetricRegistryImpl;
|
||||
import google.registry.util.Clock;
|
||||
import javax.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* Instrumentation for async flows (contact/host deletion and DNS refreshes).
|
||||
*
|
||||
* @see AsyncTaskEnqueuer
|
||||
*/
|
||||
public class AsyncTaskMetrics {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
public AsyncTaskMetrics(Clock clock) {
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Fibonacci fitter used for bucketing the batch count.
|
||||
*
|
||||
* <p>We use a Fibonacci filter because it provides better resolution at the low end than an
|
||||
* exponential fitter, which is important because most batch sizes are likely to be very low,
|
||||
* despite going up to 1,000 on the high end. Also, the precision is better, as batch size is
|
||||
* inherently an integer, whereas an exponential fitter with an exponent base less than 2 would
|
||||
* have unintuitive boundaries.
|
||||
*/
|
||||
private static final DistributionFitter FITTER_BATCH_SIZE =
|
||||
FibonacciFitter.create(maxLeaseCount());
|
||||
|
||||
private static final ImmutableSet<LabelDescriptor> LABEL_DESCRIPTORS =
|
||||
ImmutableSet.of(
|
||||
LabelDescriptor.create("operation_type", "The type of async flow operation."),
|
||||
LabelDescriptor.create("result", "The result of the async flow operation."));
|
||||
|
||||
@VisibleForTesting
|
||||
static final IncrementableMetric asyncFlowOperationCounts =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newIncrementableMetric(
|
||||
"/async_flows/operations",
|
||||
"Count of Async Flow Operations",
|
||||
"count",
|
||||
LABEL_DESCRIPTORS);
|
||||
|
||||
@VisibleForTesting
|
||||
static final EventMetric asyncFlowOperationProcessingTime =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newEventMetric(
|
||||
"/async_flows/processing_time",
|
||||
"Async Flow Processing Time",
|
||||
"milliseconds",
|
||||
LABEL_DESCRIPTORS,
|
||||
DEFAULT_FITTER);
|
||||
|
||||
@VisibleForTesting
|
||||
static final EventMetric asyncFlowBatchSize =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newEventMetric(
|
||||
"/async_flows/batch_size",
|
||||
"Async Operation Batch Size",
|
||||
"batch size",
|
||||
ImmutableSet.of(
|
||||
LabelDescriptor.create("operation_type", "The type of async flow operation.")),
|
||||
FITTER_BATCH_SIZE);
|
||||
|
||||
/** The type of asynchronous operation. */
|
||||
public enum OperationType {
|
||||
CONTACT_DELETE("contactDelete"),
|
||||
HOST_DELETE("hostDelete"),
|
||||
CONTACT_AND_HOST_DELETE("contactAndHostDelete"),
|
||||
DNS_REFRESH("dnsRefresh");
|
||||
|
||||
private final String metricLabelValue;
|
||||
|
||||
OperationType(String metricLabelValue) {
|
||||
this.metricLabelValue = metricLabelValue;
|
||||
}
|
||||
|
||||
String getMetricLabelValue() {
|
||||
return metricLabelValue;
|
||||
}
|
||||
}
|
||||
|
||||
/** The result of an asynchronous operation. */
|
||||
public enum OperationResult {
|
||||
/** The operation processed correctly and the result was success. */
|
||||
SUCCESS("success"),
|
||||
|
||||
/** The operation processed correctly and the result was failure. */
|
||||
FAILURE("failure"),
|
||||
|
||||
/** The operation did not process correctly due to some unexpected error. */
|
||||
ERROR("error"),
|
||||
|
||||
/** The operation was skipped because the request is now stale. */
|
||||
STALE("stale");
|
||||
|
||||
private final String metricLabelValue;
|
||||
|
||||
OperationResult(String metricLabelValue) {
|
||||
this.metricLabelValue = metricLabelValue;
|
||||
}
|
||||
|
||||
String getMetricLabelValue() {
|
||||
return metricLabelValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void recordAsyncFlowResult(
|
||||
OperationType operationType, OperationResult operationResult, DateTime whenEnqueued) {
|
||||
asyncFlowOperationCounts.increment(
|
||||
operationType.getMetricLabelValue(), operationResult.getMetricLabelValue());
|
||||
long processingMillis = new Duration(whenEnqueued, clock.nowUtc()).getMillis();
|
||||
asyncFlowOperationProcessingTime.record(
|
||||
processingMillis,
|
||||
operationType.getMetricLabelValue(),
|
||||
operationResult.getMetricLabelValue());
|
||||
logger.atInfo().log(
|
||||
"Asynchronous %s operation took %d ms to process, yielding result: %s.",
|
||||
operationType.getMetricLabelValue(),
|
||||
processingMillis,
|
||||
operationResult.getMetricLabelValue());
|
||||
}
|
||||
|
||||
public void recordContactHostDeletionBatchSize(long batchSize) {
|
||||
asyncFlowBatchSize.record(batchSize, CONTACT_AND_HOST_DELETE.getMetricLabelValue());
|
||||
}
|
||||
|
||||
public void recordDnsRefreshBatchSize(long batchSize) {
|
||||
asyncFlowBatchSize.record(batchSize, DNS_REFRESH.getMetricLabelValue());
|
||||
}
|
||||
}
|
||||
@@ -14,13 +14,10 @@
|
||||
|
||||
package google.registry.batch;
|
||||
|
||||
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_REQUESTED_TIME;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESAVE_TIMES;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_HOST_RENAME;
|
||||
import static google.registry.batch.CannedScriptExecutionAction.SCRIPT_PARAM;
|
||||
import static google.registry.request.RequestParameters.extractBooleanParameter;
|
||||
import static google.registry.request.RequestParameters.extractIntParameter;
|
||||
import static google.registry.request.RequestParameters.extractLongParameter;
|
||||
@@ -32,13 +29,11 @@ import static google.registry.request.RequestParameters.extractRequiredDatetimeP
|
||||
import static google.registry.request.RequestParameters.extractRequiredParameter;
|
||||
import static google.registry.request.RequestParameters.extractSetOfDatetimeParameters;
|
||||
|
||||
import com.google.appengine.api.taskqueue.Queue;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.request.Parameter;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Named;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@@ -128,21 +123,10 @@ public class BatchModule {
|
||||
return extractBooleanParameter(req, PARAM_DRY_RUN);
|
||||
}
|
||||
|
||||
// TODO(b/234424397): remove method after credential changes are rolled out.
|
||||
@Provides
|
||||
@Named(QUEUE_ASYNC_ACTIONS)
|
||||
static Queue provideAsyncActionsPushQueue() {
|
||||
return getQueue(QUEUE_ASYNC_ACTIONS);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named(QUEUE_ASYNC_DELETE)
|
||||
static Queue provideAsyncDeletePullQueue() {
|
||||
return getQueue(QUEUE_ASYNC_DELETE);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named(QUEUE_ASYNC_HOST_RENAME)
|
||||
static Queue provideAsyncHostRenamePullQueue() {
|
||||
return getQueue(QUEUE_ASYNC_HOST_RENAME);
|
||||
@Parameter(SCRIPT_PARAM)
|
||||
static String provideScriptName(HttpServletRequest req) {
|
||||
return extractRequiredParameter(req, SCRIPT_PARAM);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2022 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.batch;
|
||||
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.batch.cannedscript.GroupsApiChecker;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.auth.Auth;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Action that executes a canned script specified by the caller.
|
||||
*
|
||||
* <p>This class is introduced to help the safe rollout of credential changes. The delegated
|
||||
* credentials in particular, benefit from this: they require manual configuration of the peer
|
||||
* system in each environment, and may wait hours or even days after deployment until triggered by
|
||||
* user activities.
|
||||
*
|
||||
* <p>This action can be invoked using the Nomulus CLI command: {@code nomulus -e ${env} curl
|
||||
* --service BACKEND -X POST -u '/_dr/task/executeCannedScript?script=${script_name}'}
|
||||
*/
|
||||
// TODO(b/234424397): remove class after credential changes are rolled out.
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
path = "/_dr/task/executeCannedScript",
|
||||
method = POST,
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_INTERNAL_OR_ADMIN)
|
||||
public class CannedScriptExecutionAction implements Runnable {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
static final String SCRIPT_PARAM = "script";
|
||||
|
||||
static final ImmutableMap<String, Runnable> SCRIPTS =
|
||||
ImmutableMap.of("runGroupsApiChecks", GroupsApiChecker::runGroupsApiChecks);
|
||||
|
||||
private final String scriptName;
|
||||
|
||||
@Inject
|
||||
CannedScriptExecutionAction(@Parameter(SCRIPT_PARAM) String scriptName) {
|
||||
logger.atInfo().log("Received request to run script %s", scriptName);
|
||||
this.scriptName = scriptName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!SCRIPTS.containsKey(scriptName)) {
|
||||
throw new IllegalArgumentException("Script not found:" + scriptName);
|
||||
}
|
||||
try {
|
||||
SCRIPTS.get(scriptName).run();
|
||||
logger.atInfo().log("Finished running %s.", scriptName);
|
||||
} catch (Throwable t) {
|
||||
logger.atWarning().withCause(t).log("Error executing %s", scriptName);
|
||||
throw new RuntimeException("Execution failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,17 +13,24 @@
|
||||
// limitations under the License.
|
||||
package google.registry.batch;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import com.google.common.primitives.Ints;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.domain.token.PackagePromotion;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.request.auth.Auth;
|
||||
import java.util.List;
|
||||
import google.registry.ui.server.SendEmailUtils;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* An action that checks all {@link PackagePromotion} objects for compliance with their max create
|
||||
@@ -37,6 +44,22 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/checkPackagesCompliance";
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private final SendEmailUtils sendEmailUtils;
|
||||
private final String packageCreateLimitEmailSubjectText;
|
||||
private final String packageCreateLimitEmailBodyText;
|
||||
private final String registrySupportEmail;
|
||||
|
||||
@Inject
|
||||
public CheckPackagesComplianceAction(
|
||||
SendEmailUtils sendEmailUtils,
|
||||
@Config("packageCreateLimitEmailSubjectText") String packageCreateLimitEmailSubjectText,
|
||||
@Config("packageCreateLimitEmailBodyText") String packageCreateLimitEmailBodyText,
|
||||
@Config("registrySupportEmail") String registrySupportEmail) {
|
||||
this.sendEmailUtils = sendEmailUtils;
|
||||
this.packageCreateLimitEmailSubjectText = packageCreateLimitEmailSubjectText;
|
||||
this.packageCreateLimitEmailBodyText = packageCreateLimitEmailBodyText;
|
||||
this.registrySupportEmail = registrySupportEmail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -46,23 +69,23 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
ImmutableList.Builder<PackagePromotion> packagesOverCreateLimit =
|
||||
new ImmutableList.Builder<>();
|
||||
for (PackagePromotion packagePromo : packages) {
|
||||
List<DomainHistory> creates =
|
||||
jpaTm()
|
||||
.query(
|
||||
"FROM DomainHistory WHERE current_package_token = :token AND"
|
||||
+ " modificationTime >= :lastBilling AND type = 'DOMAIN_CREATE'",
|
||||
DomainHistory.class)
|
||||
.setParameter("token", packagePromo.getToken().getSqlKey().toString())
|
||||
.setParameter(
|
||||
"lastBilling", packagePromo.getNextBillingDate().minusYears(1))
|
||||
.getResultList();
|
||||
|
||||
if (creates.size() > packagePromo.getMaxCreates()) {
|
||||
int overage = creates.size() - packagePromo.getMaxCreates();
|
||||
Long creates =
|
||||
(Long)
|
||||
jpaTm()
|
||||
.query(
|
||||
"SELECT COUNT(*) FROM DomainHistory WHERE current_package_token ="
|
||||
+ " :token AND modificationTime >= :lastBilling AND type ="
|
||||
+ " 'DOMAIN_CREATE'")
|
||||
.setParameter("token", packagePromo.getToken().getKey().toString())
|
||||
.setParameter(
|
||||
"lastBilling", packagePromo.getNextBillingDate().minusYears(1))
|
||||
.getSingleResult();
|
||||
if (creates > packagePromo.getMaxCreates()) {
|
||||
int overage = Ints.saturatedCast(creates) - packagePromo.getMaxCreates();
|
||||
logger.atInfo().log(
|
||||
"Package with package token %s has exceeded their max domain creation limit"
|
||||
+ " by %d name(s).",
|
||||
packagePromo.getToken().getSqlKey(), overage);
|
||||
packagePromo.getToken().getKey(), overage);
|
||||
packagesOverCreateLimit.add(packagePromo);
|
||||
}
|
||||
}
|
||||
@@ -72,9 +95,43 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
logger.atInfo().log(
|
||||
"Found %d packages over their create limit.",
|
||||
packagesOverCreateLimit.build().size());
|
||||
// TODO(sarahbot@) Send email to registrar and registry informing of creation
|
||||
// overage once email template is finalized.
|
||||
for (PackagePromotion packagePromotion : packagesOverCreateLimit.build()) {
|
||||
AllocationToken packageToken = tm().loadByKey(packagePromotion.getToken());
|
||||
Optional<Registrar> registrar =
|
||||
Registrar.loadByRegistrarIdCached(
|
||||
packageToken.getAllowedRegistrarIds().iterator().next());
|
||||
if (registrar.isPresent()) {
|
||||
String body =
|
||||
String.format(
|
||||
packageCreateLimitEmailBodyText,
|
||||
registrar.get().getRegistrarName(),
|
||||
packageToken.getToken(),
|
||||
registrySupportEmail);
|
||||
sendNotification(
|
||||
packageToken, packageCreateLimitEmailSubjectText, body, registrar.get());
|
||||
} else {
|
||||
logger.atSevere().log(
|
||||
String.format(
|
||||
"Could not find registrar for package token %s", packageToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendNotification(
|
||||
AllocationToken packageToken, String subject, String body, Registrar registrar) {
|
||||
logger.atInfo().log(
|
||||
String.format(
|
||||
"Compliance email sent to the %s registrar regarding the package with token" + " %s.",
|
||||
registrar.getRegistrarName(), packageToken.getToken()));
|
||||
sendEmailUtils.sendEmail(
|
||||
subject,
|
||||
body,
|
||||
Optional.of(registrySupportEmail),
|
||||
registrar.getContacts().stream()
|
||||
.filter(c -> c.getTypes().contains(RegistrarPoc.Type.ADMIN))
|
||||
.map(RegistrarPoc::getEmailAddress)
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,15 +101,20 @@ public class DeleteProberDataAction implements Runnable {
|
||||
|
||||
@Inject DnsQueue dnsQueue;
|
||||
|
||||
@Inject @Parameter(PARAM_DRY_RUN) boolean isDryRun;
|
||||
@Inject
|
||||
@Parameter(PARAM_DRY_RUN)
|
||||
boolean isDryRun;
|
||||
/** List of TLDs to work on. If empty - will work on all TLDs that end with .test. */
|
||||
@Inject @Parameter(PARAM_TLDS) ImmutableSet<String> tlds;
|
||||
@Inject
|
||||
@Parameter(PARAM_TLDS)
|
||||
ImmutableSet<String> tlds;
|
||||
|
||||
@Inject
|
||||
@Config("registryAdminClientId")
|
||||
String registryAdminRegistrarId;
|
||||
|
||||
@Inject DeleteProberDataAction() {}
|
||||
@Inject
|
||||
DeleteProberDataAction() {}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -151,7 +156,7 @@ public class DeleteProberDataAction implements Runnable {
|
||||
DateTime now = tm().getTransactionTime();
|
||||
// Scroll through domains, soft-deleting as necessary (very few will be soft-deleted) and
|
||||
// keeping track of which domains to hard-delete (there can be many, so we batch them up)
|
||||
ScrollableResults scrollableResult =
|
||||
try (ScrollableResults scrollableResult =
|
||||
jpaTm()
|
||||
.query(DOMAIN_QUERY_STRING, Domain.class)
|
||||
.setParameter("tlds", deletableTlds)
|
||||
@@ -161,28 +166,30 @@ public class DeleteProberDataAction implements Runnable {
|
||||
.setParameter("nowAutoTimestamp", CreateAutoTimestamp.create(now))
|
||||
.unwrap(Query.class)
|
||||
.setCacheMode(CacheMode.IGNORE)
|
||||
.scroll(ScrollMode.FORWARD_ONLY);
|
||||
ImmutableList.Builder<String> domainRepoIdsToHardDelete = new ImmutableList.Builder<>();
|
||||
ImmutableList.Builder<String> hostNamesToHardDelete = new ImmutableList.Builder<>();
|
||||
for (int i = 1; scrollableResult.next(); i = (i + 1) % BATCH_SIZE) {
|
||||
Domain domain = (Domain) scrollableResult.get(0);
|
||||
processDomain(
|
||||
domain,
|
||||
domainRepoIdsToHardDelete,
|
||||
hostNamesToHardDelete,
|
||||
softDeletedDomains,
|
||||
hardDeletedDomains);
|
||||
// Batch the deletion and DB flush + session clearing so we don't OOM
|
||||
if (i == 0) {
|
||||
hardDeleteDomainsAndHosts(domainRepoIdsToHardDelete.build(), hostNamesToHardDelete.build());
|
||||
domainRepoIdsToHardDelete = new ImmutableList.Builder<>();
|
||||
hostNamesToHardDelete = new ImmutableList.Builder<>();
|
||||
jpaTm().getEntityManager().flush();
|
||||
jpaTm().getEntityManager().clear();
|
||||
.scroll(ScrollMode.FORWARD_ONLY)) {
|
||||
ImmutableList.Builder<String> domainRepoIdsToHardDelete = new ImmutableList.Builder<>();
|
||||
ImmutableList.Builder<String> hostNamesToHardDelete = new ImmutableList.Builder<>();
|
||||
for (int i = 1; scrollableResult.next(); i = (i + 1) % BATCH_SIZE) {
|
||||
Domain domain = (Domain) scrollableResult.get(0);
|
||||
processDomain(
|
||||
domain,
|
||||
domainRepoIdsToHardDelete,
|
||||
hostNamesToHardDelete,
|
||||
softDeletedDomains,
|
||||
hardDeletedDomains);
|
||||
// Batch the deletion and DB flush + session clearing, so we don't OOM
|
||||
if (i == 0) {
|
||||
hardDeleteDomainsAndHosts(
|
||||
domainRepoIdsToHardDelete.build(), hostNamesToHardDelete.build());
|
||||
domainRepoIdsToHardDelete = new ImmutableList.Builder<>();
|
||||
hostNamesToHardDelete = new ImmutableList.Builder<>();
|
||||
jpaTm().getEntityManager().flush();
|
||||
jpaTm().getEntityManager().clear();
|
||||
}
|
||||
}
|
||||
// process the remainder
|
||||
hardDeleteDomainsAndHosts(domainRepoIdsToHardDelete.build(), hostNamesToHardDelete.build());
|
||||
}
|
||||
// process the remainder
|
||||
hardDeleteDomainsAndHosts(domainRepoIdsToHardDelete.build(), hostNamesToHardDelete.build());
|
||||
}
|
||||
|
||||
private void processDomain(
|
||||
@@ -236,7 +243,7 @@ public class DeleteProberDataAction implements Runnable {
|
||||
.setParameter("repoIds", domainRepoIds)
|
||||
.executeUpdate();
|
||||
jpaTm()
|
||||
.query("DELETE FROM DomainHistory WHERE domainRepoId IN :repoIds")
|
||||
.query("DELETE FROM DomainHistory WHERE repoId IN :repoIds")
|
||||
.setParameter("repoIds", domainRepoIds)
|
||||
.executeUpdate();
|
||||
jpaTm()
|
||||
|
||||
@@ -131,12 +131,14 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
|
||||
+ "WHERE eventTime <= :executeTime "
|
||||
+ "AND eventTime < recurrenceEndTime "
|
||||
+ "AND id > :maxProcessedRecurrenceId "
|
||||
+ "AND recurrenceEndTime > :cursorTime "
|
||||
+ "AND recurrenceEndTime > :adjustedCursorTime "
|
||||
+ "ORDER BY id ASC",
|
||||
Recurring.class)
|
||||
.setParameter("executeTime", executeTime)
|
||||
.setParameter("maxProcessedRecurrenceId", prevMaxProcessedRecurrenceId)
|
||||
.setParameter("cursorTime", cursorTime)
|
||||
.setParameter(
|
||||
"adjustedCursorTime",
|
||||
cursorTime.minus(Registry.DEFAULT_AUTO_RENEW_GRACE_PERIOD))
|
||||
.setMaxResults(batchSize)
|
||||
.getResultList();
|
||||
for (Recurring recurring : recurrings) {
|
||||
@@ -253,7 +255,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
|
||||
final ImmutableSet<DateTime> billingTimes =
|
||||
getBillingTimesInScope(eventTimes, cursorTime, executeTime, tld);
|
||||
|
||||
VKey<Domain> domainKey = VKey.createSql(Domain.class, recurring.getDomainRepoId());
|
||||
VKey<Domain> domainKey = VKey.create(Domain.class, recurring.getDomainRepoId());
|
||||
Iterable<OneTime> oneTimesForDomain;
|
||||
oneTimesForDomain =
|
||||
tm().createQueryComposer(OneTime.class)
|
||||
@@ -279,6 +281,19 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
|
||||
.setReason("Domain autorenewal by ExpandRecurringBillingEventsAction")
|
||||
.setRequestedByRegistrar(false)
|
||||
.setType(DOMAIN_AUTORENEW)
|
||||
// Note: the following statement seems to not be entirely correct as manual renewal
|
||||
// during the autorenew grace period also closes out the existing recurrence, but in
|
||||
// that instance the autorenew history entry should still have the transaction records
|
||||
// for obvious reasons. It can be argued the history entry should always have the
|
||||
// transaction record, regardless of what happens afterward. If the domain is deleted
|
||||
// later during the autorenew grace period, another history entry for the delete would
|
||||
// record that mutation separately, but the previous autorenew should not have its
|
||||
// history entry retroactively altered, or in this case have the transaction records
|
||||
// omitted when its created belatedly (when billing time is in scope). However, since
|
||||
// we will be rewriting this action and only want to do the absolute minimum change to
|
||||
// fix it for now, we will leave the current logic in place to avoid any unnecessary
|
||||
// complications.
|
||||
//
|
||||
// Don't write a domain transaction record if the recurrence was
|
||||
// ended prior to the billing time (i.e. a domain was deleted
|
||||
// during the autorenew grace period).
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Method;
|
||||
@@ -75,14 +74,11 @@ public class ResaveEntityAction implements Runnable {
|
||||
"Re-saving entity %s which was enqueued at %s.", resourceKey, requestedTime);
|
||||
tm().transact(
|
||||
() -> {
|
||||
ImmutableObject entity = tm().loadByKey(VKey.create(resourceKey));
|
||||
tm().put(
|
||||
(entity instanceof EppResource)
|
||||
? ((EppResource) entity).cloneProjectedAtTime(tm().getTransactionTime())
|
||||
: entity);
|
||||
EppResource entity = tm().loadByKey(VKey.createEppVKeyFromString(resourceKey));
|
||||
tm().put(entity.cloneProjectedAtTime(tm().getTransactionTime()));
|
||||
if (!resaveTimes.isEmpty()) {
|
||||
asyncTaskEnqueuer.enqueueAsyncResave(
|
||||
VKey.create(resourceKey), requestedTime, resaveTimes);
|
||||
VKey.createEppVKeyFromString(resourceKey), requestedTime, resaveTimes);
|
||||
}
|
||||
});
|
||||
response.setPayload("Entity re-saved.");
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
// Copyright 2022 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.batch.cannedscript;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.util.RegistrarUtils.normalizeRegistrarId;
|
||||
|
||||
import com.google.api.services.admin.directory.Directory;
|
||||
import com.google.api.services.groupssettings.Groupssettings;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import dagger.Component;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule;
|
||||
import google.registry.config.CredentialModule.AdcDelegatedCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryConfig.ConfigModule;
|
||||
import google.registry.groups.DirectoryGroupsConnection;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import google.registry.util.UtilsModule;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Verifies that the credential with the {@link AdcDelegatedCredential} annotation can be used to
|
||||
* access the Google Workspace Groups API.
|
||||
*/
|
||||
// TODO(b/234424397): remove class after credential changes are rolled out.
|
||||
public class GroupsApiChecker {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private static final Supplier<GroupsConnectionComponent> COMPONENT_SUPPLIER =
|
||||
Suppliers.memoize(DaggerGroupsApiChecker_GroupsConnectionComponent::create);
|
||||
|
||||
public static void runGroupsApiChecks() {
|
||||
GroupsConnectionComponent component = COMPONENT_SUPPLIER.get();
|
||||
DirectoryGroupsConnection groupsConnection = component.groupsConnection();
|
||||
|
||||
List<Registrar> registrars =
|
||||
Streams.stream(Registrar.loadAllCached())
|
||||
.filter(registrar -> registrar.isLive() && registrar.getType() == Registrar.Type.REAL)
|
||||
.collect(toImmutableList());
|
||||
for (Registrar registrar : registrars) {
|
||||
for (final RegistrarPoc.Type type : RegistrarPoc.Type.values()) {
|
||||
String groupKey =
|
||||
String.format(
|
||||
"%s-%s-contacts@%s",
|
||||
normalizeRegistrarId(registrar.getRegistrarId()),
|
||||
type.getDisplayName(),
|
||||
component.gSuiteDomainName());
|
||||
try {
|
||||
Set<String> currentMembers = groupsConnection.getMembersOfGroup(groupKey);
|
||||
logger.atInfo().log("Found %s members for %s.", currentMembers.size(), groupKey);
|
||||
} catch (Exception e) {
|
||||
Throwables.throwIfUnchecked(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Component(
|
||||
modules = {
|
||||
ConfigModule.class,
|
||||
CredentialModule.class,
|
||||
GroupsApiModule.class,
|
||||
UtilsModule.class
|
||||
})
|
||||
interface GroupsConnectionComponent {
|
||||
DirectoryGroupsConnection groupsConnection();
|
||||
|
||||
@Config("gSuiteDomainName")
|
||||
String gSuiteDomainName();
|
||||
}
|
||||
|
||||
@Module
|
||||
static class GroupsApiModule {
|
||||
@Provides
|
||||
static Directory provideDirectory(
|
||||
@AdcDelegatedCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("projectId") String projectId) {
|
||||
return new Directory.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
static Groupssettings provideGroupsSettings(
|
||||
@AdcDelegatedCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("projectId") String projectId) {
|
||||
return new Groupssettings.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.beam.common;
|
||||
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.persistence.transaction.CriteriaQueryBuilder;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import java.io.Serializable;
|
||||
import org.apache.beam.sdk.Pipeline;
|
||||
import org.apache.beam.sdk.metrics.Counter;
|
||||
import org.apache.beam.sdk.metrics.Metrics;
|
||||
import org.apache.beam.sdk.options.PipelineOptionsFactory;
|
||||
import org.apache.beam.sdk.transforms.DoFn;
|
||||
import org.apache.beam.sdk.transforms.ParDo;
|
||||
|
||||
/**
|
||||
* Toy pipeline that demonstrates how to use {@link JpaTransactionManager} in BEAM pipelines.
|
||||
*
|
||||
* <p>This pipeline may also be used as an integration test for {@link RegistryJpaIO.Read} in a
|
||||
* project with realistic data.
|
||||
*/
|
||||
public class JpaDemoPipeline implements Serializable {
|
||||
|
||||
public static void main(String[] args) {
|
||||
RegistryPipelineOptions options =
|
||||
PipelineOptionsFactory.fromArgs(args).withValidation().as(RegistryPipelineOptions.class);
|
||||
RegistryPipelineOptions.validateRegistryPipelineOptions(options);
|
||||
|
||||
Pipeline pipeline = Pipeline.create(options);
|
||||
pipeline
|
||||
.apply(
|
||||
"Read contacts",
|
||||
RegistryJpaIO.read(
|
||||
() -> CriteriaQueryBuilder.create(Contact.class).build(), Contact::getRepoId))
|
||||
.apply(
|
||||
"Count Contacts",
|
||||
ParDo.of(
|
||||
new DoFn<String, Void>() {
|
||||
private Counter counter = Metrics.counter("Contacts", "Read");
|
||||
|
||||
@ProcessElement
|
||||
public void processElement() {
|
||||
// AppEngineEnvironment is needed as long as JPA entity classes still depends
|
||||
// on Objectify.
|
||||
int result =
|
||||
(Integer)
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery("select 1;")
|
||||
.getSingleResult());
|
||||
verify(result == 1, "Expecting 1, got %s.", result);
|
||||
counter.inc();
|
||||
}
|
||||
}));
|
||||
|
||||
pipeline.run();
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.beam.common;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static org.apache.beam.sdk.values.TypeDescriptors.integers;
|
||||
|
||||
@@ -21,18 +22,14 @@ import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Streams;
|
||||
import google.registry.beam.common.RegistryQuery.CriteriaQuerySupplier;
|
||||
import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.model.UpdateAutoTimestamp.DisableAutoUpdateResource;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import google.registry.persistence.transaction.TransactionManagerFactory;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import org.apache.beam.sdk.coders.Coder;
|
||||
import org.apache.beam.sdk.coders.SerializableCoder;
|
||||
import org.apache.beam.sdk.metrics.Counter;
|
||||
import org.apache.beam.sdk.metrics.Metrics;
|
||||
import org.apache.beam.sdk.transforms.Create;
|
||||
@@ -135,6 +132,7 @@ public final class RegistryJpaIO {
|
||||
|
||||
abstract SerializableFunction<R, T> resultMapper();
|
||||
|
||||
@Nullable
|
||||
abstract Coder<T> coder();
|
||||
|
||||
@Nullable
|
||||
@@ -145,13 +143,16 @@ public final class RegistryJpaIO {
|
||||
@Override
|
||||
@SuppressWarnings("deprecation") // Reshuffle still recommended by GCP.
|
||||
public PCollection<T> expand(PBegin input) {
|
||||
return input
|
||||
.apply("Starting " + name(), Create.of((Void) null))
|
||||
.apply(
|
||||
"Run query for " + name(),
|
||||
ParDo.of(new QueryRunner<>(query(), resultMapper(), snapshotId())))
|
||||
.setCoder(coder())
|
||||
.apply("Reshuffle", Reshuffle.viaRandomKey());
|
||||
PCollection<T> output =
|
||||
input
|
||||
.apply("Starting " + name(), Create.of((Void) null))
|
||||
.apply(
|
||||
"Run query for " + name(),
|
||||
ParDo.of(new QueryRunner<>(query(), resultMapper(), snapshotId())));
|
||||
if (coder() != null) {
|
||||
output = output.setCoder(coder());
|
||||
}
|
||||
return output.apply("Reshuffle", Reshuffle.viaRandomKey());
|
||||
}
|
||||
|
||||
public Read<R, T> withName(String name) {
|
||||
@@ -179,9 +180,7 @@ public final class RegistryJpaIO {
|
||||
}
|
||||
|
||||
static <R, T> Builder<R, T> builder() {
|
||||
return new AutoValue_RegistryJpaIO_Read.Builder<R, T>()
|
||||
.name(DEFAULT_NAME)
|
||||
.coder(SerializableCoder.of(Serializable.class));
|
||||
return new AutoValue_RegistryJpaIO_Read.Builder<R, T>().name(DEFAULT_NAME);
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
@@ -193,7 +192,7 @@ public final class RegistryJpaIO {
|
||||
|
||||
abstract Builder<R, T> resultMapper(SerializableFunction<R, T> mapper);
|
||||
|
||||
abstract Builder<R, T> coder(Coder coder);
|
||||
abstract Builder<R, T> coder(Coder<T> coder);
|
||||
|
||||
abstract Builder<R, T> snapshotId(@Nullable String sharedSnapshotId);
|
||||
|
||||
@@ -298,12 +297,6 @@ public final class RegistryJpaIO {
|
||||
|
||||
public abstract SerializableFunction<T, Object> jpaConverter();
|
||||
|
||||
/**
|
||||
* Signal to the writer that the {@link UpdateAutoTimestamp} property should be allowed to
|
||||
* manipulate its value before persistence. The default value is {@code true}.
|
||||
*/
|
||||
abstract boolean withUpdateAutoTimestamp();
|
||||
|
||||
public Write<T> withName(String name) {
|
||||
return toBuilder().name(name).build();
|
||||
}
|
||||
@@ -324,10 +317,6 @@ public final class RegistryJpaIO {
|
||||
return toBuilder().jpaConverter(jpaConverter).build();
|
||||
}
|
||||
|
||||
public Write<T> disableUpdateAutoTimestamp() {
|
||||
return toBuilder().withUpdateAutoTimestamp(false).build();
|
||||
}
|
||||
|
||||
abstract Builder<T> toBuilder();
|
||||
|
||||
@Override
|
||||
@@ -344,7 +333,7 @@ public final class RegistryJpaIO {
|
||||
GroupIntoBatches.<Integer, T>ofSize(batchSize()).withShardedKey())
|
||||
.apply(
|
||||
"Write in batch for " + name(),
|
||||
ParDo.of(new SqlBatchWriter<>(name(), jpaConverter(), withUpdateAutoTimestamp())));
|
||||
ParDo.of(new SqlBatchWriter<>(name(), jpaConverter())));
|
||||
}
|
||||
|
||||
static <T> Builder<T> builder() {
|
||||
@@ -352,8 +341,7 @@ public final class RegistryJpaIO {
|
||||
.name(DEFAULT_NAME)
|
||||
.batchSize(DEFAULT_BATCH_SIZE)
|
||||
.shards(DEFAULT_SHARDS)
|
||||
.jpaConverter(x -> x)
|
||||
.withUpdateAutoTimestamp(true);
|
||||
.jpaConverter(x -> x);
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
@@ -367,8 +355,6 @@ public final class RegistryJpaIO {
|
||||
|
||||
abstract Builder<T> jpaConverter(SerializableFunction<T, Object> jpaConverter);
|
||||
|
||||
abstract Builder<T> withUpdateAutoTimestamp(boolean withUpdateAutoTimestamp);
|
||||
|
||||
abstract Write<T> build();
|
||||
}
|
||||
}
|
||||
@@ -377,24 +363,15 @@ public final class RegistryJpaIO {
|
||||
private static class SqlBatchWriter<T> extends DoFn<KV<ShardedKey<Integer>, Iterable<T>>, Void> {
|
||||
private final Counter counter;
|
||||
private final SerializableFunction<T, Object> jpaConverter;
|
||||
private final boolean withAutoTimestamp;
|
||||
|
||||
SqlBatchWriter(
|
||||
String type, SerializableFunction<T, Object> jpaConverter, boolean withAutoTimestamp) {
|
||||
SqlBatchWriter(String type, SerializableFunction<T, Object> jpaConverter) {
|
||||
counter = Metrics.counter("SQL_WRITE", type);
|
||||
this.jpaConverter = jpaConverter;
|
||||
this.withAutoTimestamp = withAutoTimestamp;
|
||||
}
|
||||
|
||||
@ProcessElement
|
||||
public void processElement(@Element KV<ShardedKey<Integer>, Iterable<T>> kv) {
|
||||
if (withAutoTimestamp) {
|
||||
actuallyProcessElement(kv);
|
||||
return;
|
||||
}
|
||||
try (DisableAutoUpdateResource disable = UpdateAutoTimestamp.disableAutoUpdate()) {
|
||||
actuallyProcessElement(kv);
|
||||
}
|
||||
actuallyProcessElement(kv);
|
||||
}
|
||||
|
||||
private void actuallyProcessElement(@Element KV<ShardedKey<Integer>, Iterable<T>> kv) {
|
||||
@@ -405,7 +382,13 @@ public final class RegistryJpaIO {
|
||||
.filter(Objects::nonNull)
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
try {
|
||||
jpaTm().transact(() -> jpaTm().putAll(entities));
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
// Don't modify existing objects as it could lead to race conditions
|
||||
entities.forEach(this::verifyObjectNonexistence);
|
||||
jpaTm().putAll(entities);
|
||||
});
|
||||
counter.inc(entities.size());
|
||||
} catch (RuntimeException e) {
|
||||
processSingly(entities);
|
||||
@@ -419,7 +402,13 @@ public final class RegistryJpaIO {
|
||||
private void processSingly(ImmutableList<Object> entities) {
|
||||
for (Object entity : entities) {
|
||||
try {
|
||||
jpaTm().transact(() -> jpaTm().put(entity));
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
// Don't modify existing objects as it could lead to race conditions
|
||||
verifyObjectNonexistence(entity);
|
||||
jpaTm().put(entity);
|
||||
});
|
||||
counter.inc();
|
||||
} catch (RuntimeException e) {
|
||||
throw new RuntimeException(toEntityKeyString(entity), e);
|
||||
@@ -445,5 +434,16 @@ public final class RegistryJpaIO {
|
||||
return "Non-SqlEntity: " + entity;
|
||||
}
|
||||
}
|
||||
|
||||
/** SqlBatchWriter should not re-write existing entities due to potential race conditions. */
|
||||
private void verifyObjectNonexistence(Object obj) {
|
||||
// We cannot rely on calling "insert" on the objects because the underlying JPA persist call
|
||||
// adds the input object to the persistence context, meaning that any modifications (e.g.
|
||||
// updateTimestamp) are reflected in the input object. Beam doesn't allow modification of
|
||||
// input objects, so this throws an exception.
|
||||
// TODO(go/non-datastore-allocateid): also check that all the objects have IDs
|
||||
checkArgument(
|
||||
!jpaTm().exists(obj), "Entities created in SqlBatchWriter must not already exist");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,7 @@ import dagger.Lazy;
|
||||
import google.registry.config.CredentialModule;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryConfig.ConfigModule;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.persistence.PersistenceModule;
|
||||
import google.registry.persistence.PersistenceModule.BeamBulkQueryJpaTm;
|
||||
import google.registry.persistence.PersistenceModule.BeamJpaTm;
|
||||
import google.registry.persistence.PersistenceModule.BeamReadOnlyReplicaJpaTm;
|
||||
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
|
||||
@@ -52,14 +50,6 @@ public interface RegistryPipelineComponent {
|
||||
@BeamJpaTm
|
||||
Lazy<JpaTransactionManager> getJpaTransactionManager();
|
||||
|
||||
/**
|
||||
* Returns a {@link JpaTransactionManager} optimized for bulk loading multi-level JPA entities
|
||||
* ({@link Domain} and {@link google.registry.model.domain.DomainHistory}). Please refer to {@link
|
||||
* google.registry.model.bulkquery.BulkQueryEntities} for more information.
|
||||
*/
|
||||
@BeamBulkQueryJpaTm
|
||||
Lazy<JpaTransactionManager> getBulkQueryJpaTransactionManager();
|
||||
|
||||
/**
|
||||
* A {@link JpaTransactionManager} that uses the Postgres read-only replica if configured (uses
|
||||
* the standard DB otherwise).
|
||||
|
||||
@@ -23,7 +23,6 @@ import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.config.SystemPropertySetter;
|
||||
import google.registry.model.AppEngineEnvironment;
|
||||
import google.registry.model.IdService;
|
||||
import google.registry.model.IdService.SelfAllocatedIdSupplier;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import google.registry.persistence.transaction.TransactionManagerFactory;
|
||||
import org.apache.beam.sdk.harness.JvmInitializer;
|
||||
@@ -55,9 +54,6 @@ public class RegistryPipelineWorkerInitializer implements JvmInitializer {
|
||||
toRegistryPipelineComponent(registryOptions);
|
||||
Lazy<JpaTransactionManager> transactionManagerLazy;
|
||||
switch (registryOptions.getJpaTransactionManagerType()) {
|
||||
case BULK_QUERY:
|
||||
transactionManagerLazy = registryPipelineComponent.getBulkQueryJpaTransactionManager();
|
||||
break;
|
||||
case READ_ONLY_REPLICA:
|
||||
transactionManagerLazy =
|
||||
registryPipelineComponent.getReadOnlyReplicaJpaTransactionManager();
|
||||
@@ -80,7 +76,7 @@ public class RegistryPipelineWorkerInitializer implements JvmInitializer {
|
||||
// allocated, and you don't care about the generated IDs as long
|
||||
// as you can build the entities.
|
||||
if (registryOptions.getUseSelfAllocatedId()) {
|
||||
IdService.setIdSupplier(SelfAllocatedIdSupplier.getInstance());
|
||||
IdService.setForceUseSelfAllocatedId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public abstract class BillingEvent implements Serializable {
|
||||
"amount",
|
||||
"flags");
|
||||
|
||||
/** Returns the unique Objectify ID for the {@code OneTime} associated with this event. */
|
||||
/** Returns the unique ID for the {@code OneTime} associated with this event. */
|
||||
abstract long id();
|
||||
|
||||
/** Returns the UTC DateTime this event becomes billable. */
|
||||
|
||||
@@ -37,6 +37,7 @@ import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.beam.sdk.Pipeline;
|
||||
import org.apache.beam.sdk.PipelineResult;
|
||||
import org.apache.beam.sdk.coders.SerializableCoder;
|
||||
import org.apache.beam.sdk.coders.StringUtf8Coder;
|
||||
import org.apache.beam.sdk.io.FileIO;
|
||||
import org.apache.beam.sdk.io.TextIO;
|
||||
@@ -93,8 +94,9 @@ public class InvoicingPipeline implements Serializable {
|
||||
static PCollection<BillingEvent> readFromCloudSql(
|
||||
InvoicingPipelineOptions options, Pipeline pipeline) {
|
||||
Read<Object[], BillingEvent> read =
|
||||
RegistryJpaIO.read(
|
||||
makeCloudSqlQuery(options.getYearMonth()), false, row -> parseRow(row).orElse(null));
|
||||
RegistryJpaIO.<Object[], BillingEvent>read(
|
||||
makeCloudSqlQuery(options.getYearMonth()), false, row -> parseRow(row).orElse(null))
|
||||
.withCoder(SerializableCoder.of(BillingEvent.class));
|
||||
|
||||
PCollection<BillingEvent> billingEventsWithNulls =
|
||||
pipeline.apply("Read BillingEvents from Cloud SQL", read);
|
||||
|
||||
@@ -55,7 +55,7 @@ import google.registry.model.rde.RdeMode;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.Type;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.reporting.HistoryEntryDao;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.rde.DepositFragment;
|
||||
@@ -71,11 +71,9 @@ import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashSet;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.persistence.IdClass;
|
||||
import org.apache.beam.sdk.Pipeline;
|
||||
import org.apache.beam.sdk.PipelineResult;
|
||||
import org.apache.beam.sdk.coders.KvCoder;
|
||||
@@ -172,6 +170,7 @@ import org.joda.time.DateTime;
|
||||
* @see <a href="https://cloud.google.com/dataflow/docs/guides/templates/using-flex-templates">Using
|
||||
* Flex Templates</a>
|
||||
*/
|
||||
@SuppressWarnings("ALL")
|
||||
@Singleton
|
||||
public class RdePipeline implements Serializable {
|
||||
|
||||
@@ -191,16 +190,6 @@ public class RdePipeline implements Serializable {
|
||||
private static final ImmutableSet<Type> IGNORED_REGISTRAR_TYPES =
|
||||
Sets.immutableEnumSet(Registrar.Type.MONITORING, Registrar.Type.TEST);
|
||||
|
||||
// The field name of the EPP resource embedded in its corresponding history entry.
|
||||
private static final ImmutableMap<Class<? extends HistoryEntry>, String> EPP_RESOURCE_FIELD_NAME =
|
||||
ImmutableMap.of(
|
||||
DomainHistory.class,
|
||||
"domainBase",
|
||||
ContactHistory.class,
|
||||
"contactBase",
|
||||
HostHistory.class,
|
||||
"hostBase");
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@Inject
|
||||
@@ -301,10 +290,11 @@ public class RdePipeline implements Serializable {
|
||||
.apply(
|
||||
"Read all production Registrars",
|
||||
RegistryJpaIO.read(
|
||||
"SELECT registrarId FROM Registrar WHERE type NOT IN (:types)",
|
||||
ImmutableMap.of("types", IGNORED_REGISTRAR_TYPES),
|
||||
String.class,
|
||||
id -> VKey.createSql(Registrar.class, id)))
|
||||
"SELECT registrarId FROM Registrar WHERE type NOT IN (:types)",
|
||||
ImmutableMap.of("types", IGNORED_REGISTRAR_TYPES),
|
||||
String.class,
|
||||
x -> x)
|
||||
.withCoder(StringUtf8Coder.of()))
|
||||
.apply(
|
||||
"Marshall Registrar into DepositFragment",
|
||||
FlatMapElements.into(
|
||||
@@ -312,7 +302,8 @@ public class RdePipeline implements Serializable {
|
||||
TypeDescriptor.of(PendingDeposit.class),
|
||||
TypeDescriptor.of(DepositFragment.class)))
|
||||
.via(
|
||||
(VKey<Registrar> key) -> {
|
||||
(String registrarRepoId) -> {
|
||||
VKey<Registrar> key = VKey.create(Registrar.class, registrarRepoId);
|
||||
includedRegistrarCounter.inc();
|
||||
Registrar registrar = jpaTm().transact(() -> jpaTm().loadByKey(key));
|
||||
DepositFragment fragment = marshaller.marshalRegistrar(registrar);
|
||||
@@ -335,31 +326,24 @@ public class RdePipeline implements Serializable {
|
||||
*/
|
||||
private <T extends HistoryEntry> PCollection<KV<String, Long>> getMostRecentHistoryEntries(
|
||||
Pipeline pipeline, Class<T> historyClass) {
|
||||
String repoIdFieldName = HistoryEntryDao.REPO_ID_FIELD_NAMES.get(historyClass);
|
||||
String resourceFieldName = EPP_RESOURCE_FIELD_NAME.get(historyClass);
|
||||
return pipeline
|
||||
.apply(
|
||||
String.format("Load most recent %s", historyClass.getSimpleName()),
|
||||
RegistryJpaIO.read(
|
||||
("SELECT %repoIdField%, id FROM %entity% WHERE (%repoIdField%, modificationTime)"
|
||||
+ " IN (SELECT %repoIdField%, MAX(modificationTime) FROM %entity% WHERE"
|
||||
+ " modificationTime <= :watermark GROUP BY %repoIdField%) AND"
|
||||
+ " %resourceField%.deletionTime > :watermark AND"
|
||||
+ " COALESCE(%resourceField%.creationClientId, '') NOT LIKE 'prober-%' AND"
|
||||
+ " COALESCE(%resourceField%.currentSponsorClientId, '') NOT LIKE 'prober-%'"
|
||||
+ " AND COALESCE(%resourceField%.lastEppUpdateClientId, '') NOT LIKE"
|
||||
return pipeline.apply(
|
||||
String.format("Load most recent %s", historyClass.getSimpleName()),
|
||||
RegistryJpaIO.read(
|
||||
("SELECT repoId, revisionId FROM %entity% WHERE (repoId, modificationTime) IN"
|
||||
+ " (SELECT repoId, MAX(modificationTime) FROM %entity% WHERE"
|
||||
+ " modificationTime <= :watermark GROUP BY repoId) AND resource.deletionTime"
|
||||
+ " > :watermark AND COALESCE(resource.creationRegistrarId, '') NOT LIKE"
|
||||
+ " 'prober-%' AND COALESCE(resource.currentSponsorRegistrarId, '') NOT LIKE"
|
||||
+ " 'prober-%' AND COALESCE(resource.lastEppUpdateRegistrarId, '') NOT LIKE"
|
||||
+ " 'prober-%' "
|
||||
+ (historyClass == DomainHistory.class
|
||||
? "AND %resourceField%.tld IN "
|
||||
+ "(SELECT id FROM Tld WHERE tldType = 'REAL')"
|
||||
? "AND resource.tld IN " + "(SELECT id FROM Tld WHERE tldType = 'REAL')"
|
||||
: ""))
|
||||
.replace("%entity%", historyClass.getSimpleName())
|
||||
.replace("%repoIdField%", repoIdFieldName)
|
||||
.replace("%resourceField%", resourceFieldName),
|
||||
.replace("%entity%", historyClass.getSimpleName()),
|
||||
ImmutableMap.of("watermark", watermark),
|
||||
Object[].class,
|
||||
row -> KV.of((String) row[0], (long) row[1])))
|
||||
.setCoder(KvCoder.of(StringUtf8Coder.of(), VarLongCoder.of()));
|
||||
row -> KV.of((String) row[0], (long) row[1]))
|
||||
.withCoder(KvCoder.of(StringUtf8Coder.of(), VarLongCoder.of())));
|
||||
}
|
||||
|
||||
private <T extends HistoryEntry> EppResource loadResourceByHistoryEntryId(
|
||||
@@ -379,38 +363,28 @@ public class RdePipeline implements Serializable {
|
||||
checkState(
|
||||
dedupedIds.size() == 1,
|
||||
"Multiple unique revision IDs detected for %s repo ID %s: %s",
|
||||
EPP_RESOURCE_FIELD_NAME.get(historyEntryClazz),
|
||||
historyEntryClazz.getSimpleName(),
|
||||
repoId,
|
||||
ids);
|
||||
logger.atSevere().log(
|
||||
"Duplicate revision IDs detected for %s repo ID %s: %s",
|
||||
EPP_RESOURCE_FIELD_NAME.get(historyEntryClazz), repoId, ids);
|
||||
historyEntryClazz.getSimpleName(), repoId, ids);
|
||||
}
|
||||
return loadResourceByHistoryEntryId(historyEntryClazz, repoId, ids.get(0));
|
||||
}
|
||||
|
||||
private <T extends HistoryEntry> EppResource loadResourceByHistoryEntryId(
|
||||
Class<T> historyEntryClazz, String repoId, long revisionId) {
|
||||
try {
|
||||
Class<?> idClazz = historyEntryClazz.getAnnotation(IdClass.class).value();
|
||||
Serializable idObject =
|
||||
(Serializable)
|
||||
idClazz.getConstructor(String.class, long.class).newInstance(repoId, revisionId);
|
||||
return jpaTm()
|
||||
.transact(() -> jpaTm().loadByKey(VKey.createSql(historyEntryClazz, idObject)))
|
||||
.getResourceAtPointInTime()
|
||||
.map(resource -> resource.cloneProjectedAtTime(watermark))
|
||||
.get();
|
||||
} catch (NoSuchMethodException
|
||||
| InvocationTargetException
|
||||
| InstantiationException
|
||||
| IllegalAccessException e) {
|
||||
throw new RuntimeException(
|
||||
String.format(
|
||||
"Cannot load resource from %s with repoId %s and revisionId %s",
|
||||
historyEntryClazz.getSimpleName(), repoId, revisionId),
|
||||
e);
|
||||
}
|
||||
|
||||
return jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.loadByKey(
|
||||
VKey.create(historyEntryClazz, new HistoryEntryId(repoId, revisionId))))
|
||||
.getResourceAtPointInTime()
|
||||
.map(resource -> resource.cloneProjectedAtTime(watermark))
|
||||
.get();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -495,12 +469,12 @@ public class RdePipeline implements Serializable {
|
||||
// Contacts and hosts are only deposited in RDE, not BRDA.
|
||||
if (pendingDeposit.mode() == RdeMode.FULL) {
|
||||
HashSet<Serializable> contacts = new HashSet<>();
|
||||
contacts.add(domain.getAdminContact().getSqlKey());
|
||||
contacts.add(domain.getTechContact().getSqlKey());
|
||||
contacts.add(domain.getRegistrant().getSqlKey());
|
||||
contacts.add(domain.getAdminContact().getKey());
|
||||
contacts.add(domain.getTechContact().getKey());
|
||||
contacts.add(domain.getRegistrant().getKey());
|
||||
// Billing contact is not mandatory.
|
||||
if (domain.getBillingContact() != null) {
|
||||
contacts.add(domain.getBillingContact().getSqlKey());
|
||||
contacts.add(domain.getBillingContact().getKey());
|
||||
}
|
||||
referencedContactCounter.inc(contacts.size());
|
||||
contacts.forEach(
|
||||
@@ -518,7 +492,7 @@ public class RdePipeline implements Serializable {
|
||||
.get(REFERENCED_HOSTS)
|
||||
.output(
|
||||
KV.of(
|
||||
(String) hostKey.getSqlKey(),
|
||||
(String) hostKey.getKey(),
|
||||
pendingDeposit)));
|
||||
}
|
||||
}
|
||||
@@ -591,7 +565,7 @@ public class RdePipeline implements Serializable {
|
||||
// The output are pairs of
|
||||
// (superordinateDomainRepoId,
|
||||
// (subordinateHostRepoId, (pendingDeposit, revisionId))).
|
||||
KV.of((String) host.getSuperordinateDomain().getSqlKey(), kv));
|
||||
KV.of((String) host.getSuperordinateDomain().getKey(), kv));
|
||||
} else {
|
||||
externalHostCounter.inc();
|
||||
DepositFragment fragment = marshaller.marshalExternalHost(host);
|
||||
@@ -715,12 +689,14 @@ public class RdePipeline implements Serializable {
|
||||
PipelineOptionsFactory.register(RdePipelineOptions.class);
|
||||
RdePipelineOptions options =
|
||||
PipelineOptionsFactory.fromArgs(args).withValidation().as(RdePipelineOptions.class);
|
||||
|
||||
// We need to self allocate the IDs because the pipeline creates EPP resources from history
|
||||
// entries and projects them to watermark. These buildable entities would otherwise request an
|
||||
// ID from datastore, which Beam does not have access to. The IDs are not included in the
|
||||
// deposits or are these entities persisted back to the database, so it is OK to use a self
|
||||
// allocated ID to get around the limitations of beam.
|
||||
options.setUseSelfAllocatedId(true);
|
||||
|
||||
RegistryPipelineOptions.validateRegistryPipelineOptions(options);
|
||||
options.setIsolationOverride(TransactionIsolationLevel.TRANSACTION_READ_COMMITTED);
|
||||
DaggerRdePipeline_RdePipelineComponent.builder().options(options).build().rdePipeline().run();
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.io.Serializable;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import org.apache.beam.sdk.Pipeline;
|
||||
import org.apache.beam.sdk.PipelineResult;
|
||||
import org.apache.beam.sdk.coders.StringUtf8Coder;
|
||||
import org.apache.beam.sdk.options.PipelineOptionsFactory;
|
||||
import org.apache.beam.sdk.transforms.DoFn;
|
||||
import org.apache.beam.sdk.transforms.GroupIntoBatches;
|
||||
@@ -103,10 +104,11 @@ public class ResaveAllEppResourcesPipeline implements Serializable {
|
||||
private void fastResaveContacts(Pipeline pipeline) {
|
||||
Read<String, String> repoIdRead =
|
||||
RegistryJpaIO.read(
|
||||
"SELECT repoId FROM Contact WHERE transferData.transferStatus = 'PENDING' AND"
|
||||
+ " transferData.pendingTransferExpirationTime < current_timestamp()",
|
||||
String.class,
|
||||
r -> r);
|
||||
"SELECT repoId FROM Contact WHERE transferData.transferStatus = 'PENDING' AND"
|
||||
+ " transferData.pendingTransferExpirationTime < current_timestamp()",
|
||||
String.class,
|
||||
r -> r)
|
||||
.withCoder(StringUtf8Coder.of());
|
||||
projectAndResaveResources(pipeline, Contact.class, repoIdRead);
|
||||
}
|
||||
|
||||
@@ -120,10 +122,11 @@ public class ResaveAllEppResourcesPipeline implements Serializable {
|
||||
private void fastResaveDomains(Pipeline pipeline) {
|
||||
Read<String, String> repoIdRead =
|
||||
RegistryJpaIO.read(
|
||||
DOMAINS_TO_PROJECT_QUERY,
|
||||
ImmutableMap.of("END_OF_TIME", DateTimeUtils.END_OF_TIME),
|
||||
String.class,
|
||||
r -> r);
|
||||
DOMAINS_TO_PROJECT_QUERY,
|
||||
ImmutableMap.of("END_OF_TIME", DateTimeUtils.END_OF_TIME),
|
||||
String.class,
|
||||
r -> r)
|
||||
.withCoder(StringUtf8Coder.of());
|
||||
projectAndResaveResources(pipeline, Domain.class, repoIdRead);
|
||||
}
|
||||
|
||||
@@ -131,8 +134,9 @@ public class ResaveAllEppResourcesPipeline implements Serializable {
|
||||
private <T extends EppResource> void forceResaveAllResources(Pipeline pipeline, Class<T> clazz) {
|
||||
Read<String, String> repoIdRead =
|
||||
RegistryJpaIO.read(
|
||||
// Note: cannot use SQL parameters for the table name
|
||||
String.format("SELECT repoId FROM %s", clazz.getSimpleName()), String.class, r -> r);
|
||||
// Note: cannot use SQL parameters for the table name
|
||||
String.format("SELECT repoId FROM %s", clazz.getSimpleName()), String.class, r -> r)
|
||||
.withCoder(StringUtf8Coder.of());
|
||||
projectAndResaveResources(pipeline, clazz, repoIdRead);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ import java.io.Serializable;
|
||||
import javax.inject.Singleton;
|
||||
import org.apache.beam.sdk.Pipeline;
|
||||
import org.apache.beam.sdk.PipelineResult;
|
||||
import org.apache.beam.sdk.coders.KvCoder;
|
||||
import org.apache.beam.sdk.coders.StringUtf8Coder;
|
||||
import org.apache.beam.sdk.io.TextIO;
|
||||
import org.apache.beam.sdk.options.PipelineOptionsFactory;
|
||||
import org.apache.beam.sdk.transforms.DoFn;
|
||||
@@ -112,11 +114,12 @@ public class Spec11Pipeline implements Serializable {
|
||||
static PCollection<DomainNameInfo> readFromCloudSql(Pipeline pipeline) {
|
||||
Read<Object[], KV<String, String>> read =
|
||||
RegistryJpaIO.read(
|
||||
"select d.repoId, r.emailAddress from Domain d join Registrar r on"
|
||||
+ " d.currentSponsorClientId = r.registrarId where r.type = 'REAL' and"
|
||||
+ " d.deletionTime > now()",
|
||||
false,
|
||||
Spec11Pipeline::parseRow);
|
||||
"select d.repoId, r.emailAddress from Domain d join Registrar r on"
|
||||
+ " d.currentSponsorRegistrarId = r.registrarId where r.type = 'REAL' and"
|
||||
+ " d.deletionTime > now()",
|
||||
false,
|
||||
Spec11Pipeline::parseRow)
|
||||
.withCoder(KvCoder.of(StringUtf8Coder.of(), StringUtf8Coder.of()));
|
||||
|
||||
return pipeline
|
||||
.apply("Read active domains from Cloud SQL", read)
|
||||
@@ -130,9 +133,7 @@ public class Spec11Pipeline implements Serializable {
|
||||
Domain domain =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.loadByKey(VKey.createSql(Domain.class, input.getKey())));
|
||||
() -> jpaTm().loadByKey(VKey.create(Domain.class, input.getKey())));
|
||||
String emailAddress = input.getValue();
|
||||
if (emailAddress == null) {
|
||||
emailAddress = "";
|
||||
@@ -214,8 +215,7 @@ public class Spec11Pipeline implements Serializable {
|
||||
return output.toString();
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(
|
||||
String.format(
|
||||
"Encountered an error constructing the JSON for %s", kv.toString()),
|
||||
String.format("Encountered an error constructing the JSON for %s", kv),
|
||||
e);
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -14,21 +14,21 @@
|
||||
|
||||
package google.registry.config;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import com.google.auth.ServiceAccountSigner;
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.keyring.api.KeyModule.Key;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.time.Duration;
|
||||
import javax.inject.Qualifier;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@@ -115,47 +115,45 @@ public abstract class CredentialModule {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a {@link GoogleCredentialsBundle} from the service account's JSON key file.
|
||||
* Provides a {@link GoogleCredentialsBundle} with delegated access to Google Workspace APIs for
|
||||
* the application default credential user.
|
||||
*
|
||||
* <p>On App Engine, a thread created using Java's built-in API needs this credential when it
|
||||
* calls App Engine API. The Google Sheets API also needs this credential.
|
||||
* <p>The Workspace domain must grant delegated admin access to the default service account user
|
||||
* (project-id@appspot.gserviceaccount.com on AppEngine) with all scopes in {@code defaultScopes}
|
||||
* and {@code delegationScopes}.
|
||||
*/
|
||||
@JsonCredential
|
||||
@AdcDelegatedCredential
|
||||
@Provides
|
||||
@Singleton
|
||||
public static GoogleCredentialsBundle provideJsonCredential(
|
||||
@Config("defaultCredentialOauthScopes") ImmutableList<String> requiredScopes,
|
||||
@Key("jsonCredential") String jsonCredential) {
|
||||
GoogleCredentials credential;
|
||||
try {
|
||||
credential =
|
||||
GoogleCredentials.fromStream(new ByteArrayInputStream(jsonCredential.getBytes(UTF_8)));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
if (credential.createScopedRequired()) {
|
||||
credential = credential.createScoped(requiredScopes);
|
||||
}
|
||||
return GoogleCredentialsBundle.create(credential);
|
||||
}
|
||||
public static GoogleCredentialsBundle provideSelfSignedDelegatedCredential(
|
||||
@Config("defaultCredentialOauthScopes") ImmutableList<String> defaultScopes,
|
||||
@Config("delegatedCredentialOauthScopes") ImmutableList<String> delegationScopes,
|
||||
@ApplicationDefaultCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("gSuiteAdminAccountEmailAddress") String gSuiteAdminAccountEmailAddress,
|
||||
@Config("tokenRefreshDelay") Duration tokenRefreshDelay,
|
||||
Clock clock) {
|
||||
GoogleCredentials signer = credentialsBundle.getGoogleCredentials();
|
||||
|
||||
/**
|
||||
* Provides a {@link GoogleCredentialsBundle} with delegated admin access for a G Suite domain.
|
||||
*
|
||||
* <p>The G Suite domain must grant delegated admin access to the registry service account with
|
||||
* all scopes in {@code requiredScopes}, including ones not related to G Suite.
|
||||
*/
|
||||
@DelegatedCredential
|
||||
@Provides
|
||||
@Singleton
|
||||
public static GoogleCredentialsBundle provideDelegatedCredential(
|
||||
@Config("delegatedCredentialOauthScopes") ImmutableList<String> requiredScopes,
|
||||
@JsonCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("gSuiteAdminAccountEmailAddress") String gSuiteAdminAccountEmailAddress) {
|
||||
return GoogleCredentialsBundle.create(credentialsBundle
|
||||
.getGoogleCredentials()
|
||||
.createDelegated(gSuiteAdminAccountEmailAddress)
|
||||
.createScoped(requiredScopes));
|
||||
checkArgument(
|
||||
signer instanceof ServiceAccountSigner,
|
||||
"Expecting a ServiceAccountSigner, found %s.",
|
||||
signer.getClass().getSimpleName());
|
||||
|
||||
try {
|
||||
// Refreshing as sanity check on the ADC.
|
||||
signer.refresh();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Cannot refresh the ApplicationDefaultCredential", e);
|
||||
}
|
||||
|
||||
DelegatedCredentials credential =
|
||||
DelegatedCredentials.createSelfSignedDelegatedCredential(
|
||||
(ServiceAccountSigner) signer,
|
||||
ImmutableList.<String>builder().addAll(defaultScopes).addAll(delegationScopes).build(),
|
||||
gSuiteAdminAccountEmailAddress,
|
||||
clock,
|
||||
tokenRefreshDelay);
|
||||
return GoogleCredentialsBundle.create(credential);
|
||||
}
|
||||
|
||||
/** Dagger qualifier for the scope-less Application Default Credential. */
|
||||
@@ -178,22 +176,13 @@ public abstract class CredentialModule {
|
||||
public @interface GoogleWorkspaceCredential {}
|
||||
|
||||
/**
|
||||
* Dagger qualifier for a credential from a service account's JSON key, to be used in non-request
|
||||
* threads.
|
||||
* Dagger qualifier for a credential with delegated admin access for a dasher domain (for Google
|
||||
* Workspace) backed by the application default credential (ADC).
|
||||
*/
|
||||
@Qualifier
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface JsonCredential {}
|
||||
|
||||
/**
|
||||
* Dagger qualifier for a credential with delegated admin access for a dasher domain (for G
|
||||
* Suite).
|
||||
*/
|
||||
@Qualifier
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DelegatedCredential {}
|
||||
public @interface AdcDelegatedCredential {}
|
||||
|
||||
/** Dagger qualifier for the local credential used in the nomulus tool. */
|
||||
@Qualifier
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
// Copyright 2022 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.config;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import com.google.api.client.http.GenericUrl;
|
||||
import com.google.api.client.http.HttpBackOffIOExceptionHandler;
|
||||
import com.google.api.client.http.HttpBackOffUnsuccessfulResponseHandler;
|
||||
import com.google.api.client.http.HttpRequest;
|
||||
import com.google.api.client.http.HttpRequestFactory;
|
||||
import com.google.api.client.http.HttpResponse;
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.api.client.http.UrlEncodedContent;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import com.google.api.client.json.JsonFactory;
|
||||
import com.google.api.client.json.JsonObjectParser;
|
||||
import com.google.api.client.json.gson.GsonFactory;
|
||||
import com.google.api.client.json.webtoken.JsonWebSignature;
|
||||
import com.google.api.client.json.webtoken.JsonWebToken;
|
||||
import com.google.api.client.util.ExponentialBackOff;
|
||||
import com.google.api.client.util.GenericData;
|
||||
import com.google.api.client.util.StringUtils;
|
||||
import com.google.auth.ServiceAccountSigner;
|
||||
import com.google.auth.http.HttpTransportFactory;
|
||||
import com.google.auth.oauth2.AccessToken;
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import google.registry.util.Clock;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
/**
|
||||
* OAuth2 credentials for accessing Google Workspace APIs with domain-wide delegation. It fetches
|
||||
* access tokens using JSON Web Tokens (JWT) signed by a user-provided {@link ServiceAccountSigner}.
|
||||
*
|
||||
* <p>This class accepts the application-default-credential as {@code ServiceAccountSigner},
|
||||
* avoiding the need for exported private keys. In this case, the default credential user itself
|
||||
* (project-id@appspot.gserviceaccount.com on AppEngine) must have domain-wide delegation to the
|
||||
* Workspace APIs. The default credential user also must have the Token Creator role to itself.
|
||||
*
|
||||
* <p>If the user provides a credential {@code S} that carries its own private key, such as {@link
|
||||
* com.google.auth.oauth2.ServiceAccountCredentials}, this class can use {@code S} to impersonate
|
||||
* another service account {@code D} and gain delegated access as {@code D}, as long as S has the
|
||||
* Token Creator role to {@code D}. This usage is documented here for future reference.
|
||||
*
|
||||
* <p>As of October 2022, the functionalities described above are not implemented in the GCP Java
|
||||
* Auth library, although they are available in the Python library. We have filed a <a
|
||||
* href="https://github.com/googleapis/google-auth-library-java/issues/1064">feature request</a>.
|
||||
* This class is a stop-gap implementation.
|
||||
*
|
||||
* <p>The main body of this class is adapted from {@link
|
||||
* com.google.auth.oauth2.ServiceAccountCredentials} with cosmetic changes. The important changes
|
||||
* include the removal of all uses of the private key and the signing of the JWT (in {@link
|
||||
* #signAssertion}). We choose not to extend {@code ServiceAccountCredentials} because it would add
|
||||
* dependency to the non-public details of that class.
|
||||
*/
|
||||
public class DelegatedCredentials extends GoogleCredentials {
|
||||
|
||||
private static final long serialVersionUID = 617127523756785546L;
|
||||
|
||||
private static final String DEFAULT_TOKEN_URI = "https://accounts.google.com/o/oauth2/token";
|
||||
private static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer";
|
||||
|
||||
private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
|
||||
private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
|
||||
|
||||
private static final String VALUE_NOT_FOUND_MESSAGE = "%sExpected value %s not found.";
|
||||
private static final String VALUE_WRONG_TYPE_MESSAGE = "%sExpected %s value %s of wrong type.";
|
||||
private static final String PARSE_ERROR_PREFIX = "Error parsing token refresh response. ";
|
||||
|
||||
private static final Duration MAX_TOKEN_REFRESH_DELAY = Duration.ofHours(1);
|
||||
|
||||
private final ServiceAccountSigner signer;
|
||||
private final String delegatedServiceAccountUser;
|
||||
private final ImmutableList<String> scopes;
|
||||
private final String delegatingUserEmail;
|
||||
|
||||
private final Clock clock;
|
||||
private final Duration tokenRefreshDelay;
|
||||
|
||||
private final HttpTransportFactory transportFactory;
|
||||
|
||||
/**
|
||||
* Creates a {@link DelegatedCredentials} instance that is self-signed by the signer, which must
|
||||
* have delegated access to the Workspace APIs.
|
||||
*
|
||||
* @param signer Signs for the generated JWT tokens. This may be the application default
|
||||
* credential
|
||||
* @param scopes The scopes to use when generating JWT tokens
|
||||
* @param delegatingUserEmail The Workspace user whose permissions are delegated to the signer
|
||||
* @param clock Used for setting token expiration times.
|
||||
* @param tokenRefreshDelay The lifetime of each token. Should not exceed one hour according to
|
||||
* GCP recommendations.
|
||||
* @return
|
||||
*/
|
||||
static DelegatedCredentials createSelfSignedDelegatedCredential(
|
||||
ServiceAccountSigner signer,
|
||||
Collection<String> scopes,
|
||||
String delegatingUserEmail,
|
||||
Clock clock,
|
||||
Duration tokenRefreshDelay) {
|
||||
return new DelegatedCredentials(
|
||||
signer, signer.getAccount(), scopes, delegatingUserEmail, clock, tokenRefreshDelay);
|
||||
}
|
||||
|
||||
private DelegatedCredentials(
|
||||
ServiceAccountSigner signer,
|
||||
String delegatedServiceAccountUser,
|
||||
Collection<String> scopes,
|
||||
String delegatingUserEmail,
|
||||
Clock clock,
|
||||
Duration tokenRefreshDelay) {
|
||||
checkArgument(
|
||||
tokenRefreshDelay.getSeconds() <= MAX_TOKEN_REFRESH_DELAY.getSeconds(),
|
||||
"Max refresh delay must not exceed %s.",
|
||||
MAX_TOKEN_REFRESH_DELAY);
|
||||
|
||||
this.signer = signer;
|
||||
this.delegatedServiceAccountUser = delegatedServiceAccountUser;
|
||||
this.scopes = ImmutableList.copyOf(scopes);
|
||||
this.delegatingUserEmail = delegatingUserEmail;
|
||||
|
||||
this.clock = clock;
|
||||
this.tokenRefreshDelay = tokenRefreshDelay;
|
||||
|
||||
this.transportFactory =
|
||||
getFromServiceLoader(
|
||||
HttpTransportFactory.class, DelegatedCredentials::provideHttpTransport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the OAuth2 access token by getting a new access token using a JSON Web Token (JWT).
|
||||
*/
|
||||
@Override
|
||||
public AccessToken refreshAccessToken() throws IOException {
|
||||
JsonFactory jsonFactory = JSON_FACTORY;
|
||||
long currentTime = clock.nowUtc().getMillis();
|
||||
String assertion = createAssertion(jsonFactory, currentTime);
|
||||
|
||||
GenericData tokenRequest = new GenericData();
|
||||
tokenRequest.set("grant_type", GRANT_TYPE);
|
||||
tokenRequest.set("assertion", assertion);
|
||||
UrlEncodedContent content = new UrlEncodedContent(tokenRequest);
|
||||
|
||||
HttpRequestFactory requestFactory = transportFactory.create().createRequestFactory();
|
||||
HttpRequest request =
|
||||
requestFactory.buildPostRequest(new GenericUrl(DEFAULT_TOKEN_URI), content);
|
||||
request.setParser(new JsonObjectParser(jsonFactory));
|
||||
|
||||
request.setIOExceptionHandler(new HttpBackOffIOExceptionHandler(new ExponentialBackOff()));
|
||||
request.setUnsuccessfulResponseHandler(
|
||||
new HttpBackOffUnsuccessfulResponseHandler(new ExponentialBackOff())
|
||||
.setBackOffRequired(
|
||||
response -> {
|
||||
int code = response.getStatusCode();
|
||||
return (
|
||||
// Server error --- includes timeout errors, which use 500 instead of 408
|
||||
code / 100 == 5
|
||||
// Forbidden error --- for historical reasons, used for rate_limit_exceeded
|
||||
// errors instead of 429, but there currently seems no robust automatic way
|
||||
// to
|
||||
// distinguish these cases: see
|
||||
// https://github.com/google/google-api-java-client/issues/662
|
||||
|| code == 403);
|
||||
}));
|
||||
|
||||
HttpResponse response;
|
||||
try {
|
||||
response = request.execute();
|
||||
} catch (IOException e) {
|
||||
throw new IOException(
|
||||
String.format("Error getting access token for service account: %s", e.getMessage()), e);
|
||||
}
|
||||
|
||||
GenericData responseData = response.parseAs(GenericData.class);
|
||||
String accessToken = validateString(responseData, "access_token", PARSE_ERROR_PREFIX);
|
||||
int expiresInSeconds = validateInt32(responseData, "expires_in", PARSE_ERROR_PREFIX);
|
||||
long expiresAtMilliseconds = clock.nowUtc().getMillis() + expiresInSeconds * 1000L;
|
||||
return new AccessToken(accessToken, new Date(expiresAtMilliseconds));
|
||||
}
|
||||
|
||||
String createAssertion(JsonFactory jsonFactory, long currentTime) throws IOException {
|
||||
JsonWebSignature.Header header = new JsonWebSignature.Header();
|
||||
header.setAlgorithm("RS256");
|
||||
header.setType("JWT");
|
||||
|
||||
JsonWebToken.Payload payload = new JsonWebToken.Payload();
|
||||
payload.setIssuer(this.delegatedServiceAccountUser);
|
||||
payload.setIssuedAtTimeSeconds(currentTime / 1000);
|
||||
payload.setExpirationTimeSeconds(currentTime / 1000 + tokenRefreshDelay.getSeconds());
|
||||
payload.setSubject(delegatingUserEmail);
|
||||
payload.put("scope", Joiner.on(' ').join(scopes));
|
||||
payload.setAudience(DEFAULT_TOKEN_URI);
|
||||
|
||||
return signAssertion(jsonFactory, header, payload);
|
||||
}
|
||||
|
||||
String signAssertion(
|
||||
JsonFactory jsonFactory, JsonWebSignature.Header header, JsonWebToken.Payload payload)
|
||||
throws IOException {
|
||||
String content =
|
||||
Base64.encodeBase64URLSafeString(jsonFactory.toByteArray(header))
|
||||
+ "."
|
||||
+ Base64.encodeBase64URLSafeString(jsonFactory.toByteArray(payload));
|
||||
byte[] contentBytes = StringUtils.getBytesUtf8(content);
|
||||
byte[] signature = signer.sign(contentBytes); // Changed from ServiceAccountCredentials.
|
||||
return content + "." + Base64.encodeBase64URLSafeString(signature);
|
||||
}
|
||||
|
||||
static HttpTransport provideHttpTransport() {
|
||||
return HTTP_TRANSPORT;
|
||||
}
|
||||
|
||||
protected static <T> T getFromServiceLoader(Class<? extends T> clazz, T defaultInstance) {
|
||||
return Iterables.getFirst(ServiceLoader.load(clazz), defaultInstance);
|
||||
}
|
||||
|
||||
/** Return the specified string from JSON or throw a helpful error message. */
|
||||
static String validateString(Map<String, Object> map, String key, String errorPrefix)
|
||||
throws IOException {
|
||||
Object value = map.get(key);
|
||||
if (value == null) {
|
||||
throw new IOException(String.format(VALUE_NOT_FOUND_MESSAGE, errorPrefix, key));
|
||||
}
|
||||
if (!(value instanceof String)) {
|
||||
throw new IOException(String.format(VALUE_WRONG_TYPE_MESSAGE, errorPrefix, "string", key));
|
||||
}
|
||||
return (String) value;
|
||||
}
|
||||
|
||||
/** Return the specified integer from JSON or throw a helpful error message. */
|
||||
static int validateInt32(Map<String, Object> map, String key, String errorPrefix)
|
||||
throws IOException {
|
||||
Object value = map.get(key);
|
||||
if (value == null) {
|
||||
throw new IOException(String.format(VALUE_NOT_FOUND_MESSAGE, errorPrefix, key));
|
||||
}
|
||||
if (value instanceof BigDecimal) {
|
||||
BigDecimal bigDecimalValue = (BigDecimal) value;
|
||||
return bigDecimalValue.intValueExact();
|
||||
}
|
||||
if (!(value instanceof Integer)) {
|
||||
throw new IOException(String.format(VALUE_WRONG_TYPE_MESSAGE, errorPrefix, "integer", key));
|
||||
}
|
||||
return (Integer) value;
|
||||
}
|
||||
}
|
||||
@@ -1027,38 +1027,6 @@ public final class RegistryConfig {
|
||||
return 50;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the delay before executing async delete flow mapreduces.
|
||||
*
|
||||
* <p>This delay should be sufficiently longer than a transaction, to solve the following
|
||||
* problem:
|
||||
*
|
||||
* <ul>
|
||||
* <li>a domain mutation flow starts a transaction
|
||||
* <li>the domain flow non-transactionally reads a resource and sees that it's not in
|
||||
* PENDING_DELETE
|
||||
* <li>the domain flow creates a new reference to this resource
|
||||
* <li>a contact/host delete flow runs and marks the resource PENDING_DELETE and commits
|
||||
* <li>the domain flow commits
|
||||
* </ul>
|
||||
*
|
||||
* <p>Although we try not to add references to a PENDING_DELETE resource, strictly speaking that
|
||||
* is ok as long as the mapreduce eventually sees the new reference (and therefore
|
||||
* asynchronously fails the delete). Without this delay, the mapreduce might have started before
|
||||
* the domain flow committed, and could potentially miss the reference.
|
||||
*
|
||||
* <p>If you are using EPP resource caching (eppResourceCachingEnabled in YAML), then this
|
||||
* duration should also be longer than that cache duration (eppResourceCachingSeconds).
|
||||
*
|
||||
* @see google.registry.config.RegistryConfigSettings.Caching
|
||||
* @see google.registry.batch.AsyncTaskEnqueuer
|
||||
*/
|
||||
@Provides
|
||||
@Config("asyncDeleteDelay")
|
||||
public static Duration provideAsyncDeleteDelay(RegistryConfigSettings config) {
|
||||
return Duration.standardSeconds(config.misc.asyncDeleteDelaySeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* The server ID used in the 'svID' element of an EPP 'greeting'.
|
||||
*
|
||||
@@ -1076,24 +1044,6 @@ public final class RegistryConfig {
|
||||
return config.keyring.activeKeyring;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name to use for the Cloud KMS KeyRing containing encryption keys for Nomulus secrets.
|
||||
*
|
||||
* @see <a
|
||||
* href="https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings#KeyRing">projects.locations.keyRings</a>
|
||||
*/
|
||||
@Provides
|
||||
@Config("cloudKmsKeyRing")
|
||||
public static String provideCloudKmsKeyRing(RegistryConfigSettings config) {
|
||||
return config.keyring.kms.keyringName;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("cloudKmsProjectId")
|
||||
public static String provideCloudKmsProjectId(RegistryConfigSettings config) {
|
||||
return config.keyring.kms.projectId;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("customLogicFactoryClass")
|
||||
public static String provideCustomLogicFactoryClass(RegistryConfigSettings config) {
|
||||
@@ -1223,6 +1173,12 @@ public final class RegistryConfig {
|
||||
return ImmutableList.copyOf(config.credentialOAuth.localCredentialOauthScopes);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("tokenRefreshDelay")
|
||||
public static java.time.Duration provideTokenRefreshDelay(RegistryConfigSettings config) {
|
||||
return java.time.Duration.ofSeconds(config.credentialOAuth.tokenRefreshDelaySeconds);
|
||||
}
|
||||
|
||||
/** OAuth client ID used by the nomulus tool. */
|
||||
@Provides
|
||||
@Config("toolsClientId")
|
||||
@@ -1353,6 +1309,18 @@ public final class RegistryConfig {
|
||||
public static int provideHibernateJdbcBatchSize(RegistryConfigSettings config) {
|
||||
return config.hibernate.jdbcBatchSize;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("packageCreateLimitEmailSubjectText")
|
||||
public static String providePackageCreateLimitEmailSubjectText(RegistryConfigSettings config) {
|
||||
return config.packageMonitoring.packageCreateLimitEmailSubjectText;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("packageCreateLimitEmailBodyText")
|
||||
public static String providePackageCreateLimitEmailBodyText(RegistryConfigSettings config) {
|
||||
return config.packageMonitoring.packageCreateLimitEmailBodyText;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the App Engine project ID, which is based off the environment name. */
|
||||
|
||||
@@ -43,6 +43,7 @@ public class RegistryConfigSettings {
|
||||
public SslCertificateValidation sslCertificateValidation;
|
||||
public ContactHistory contactHistory;
|
||||
public DnsUpdate dnsUpdate;
|
||||
public PackageMonitoring packageMonitoring;
|
||||
|
||||
/** Configuration options that apply to the entire App Engine project. */
|
||||
public static class AppEngine {
|
||||
@@ -67,6 +68,7 @@ public class RegistryConfigSettings {
|
||||
public List<String> defaultCredentialOauthScopes;
|
||||
public List<String> delegatedCredentialOauthScopes;
|
||||
public List<String> localCredentialOauthScopes;
|
||||
public int tokenRefreshDelaySeconds;
|
||||
}
|
||||
|
||||
/** Configuration options for the G Suite account used by Nomulus. */
|
||||
@@ -206,13 +208,13 @@ public class RegistryConfigSettings {
|
||||
public String alertRecipientEmailAddress;
|
||||
public String spec11OutgoingEmailAddress;
|
||||
public List<String> spec11BccEmailAddresses;
|
||||
public int asyncDeleteDelaySeconds;
|
||||
public int transientFailureRetries;
|
||||
}
|
||||
|
||||
/** Configuration for keyrings (used to store secrets outside of source). */
|
||||
public static class Keyring {
|
||||
public String activeKeyring;
|
||||
// TODO(b/257276342): Remove after config files in nomulus-internal are updated.
|
||||
public Kms kms;
|
||||
}
|
||||
|
||||
@@ -255,4 +257,10 @@ public class RegistryConfigSettings {
|
||||
public String registrySupportEmail;
|
||||
public String registryCcEmail;
|
||||
}
|
||||
|
||||
/** Configuration for package compliance monitoring. */
|
||||
public static class PackageMonitoring {
|
||||
public String packageCreateLimitEmailSubjectText;
|
||||
public String packageCreateLimitEmailBodyText;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,6 +340,9 @@ credentialOAuth:
|
||||
- https://www.googleapis.com/auth/userinfo.email
|
||||
# View and manage your applications deployed on Google App Engine
|
||||
- https://www.googleapis.com/auth/appengine.admin
|
||||
# The lifetime of an access token generated by our custom credentials classes
|
||||
# Must be shorter than one hour.
|
||||
tokenRefreshDelaySeconds: 1800
|
||||
|
||||
icannReporting:
|
||||
# URL we PUT monthly ICANN transactions reports to.
|
||||
@@ -418,11 +421,6 @@ misc:
|
||||
spec11BccEmailAddresses:
|
||||
- abuse@example.com
|
||||
|
||||
# How long to delay processing of asynchronous deletions. This should always
|
||||
# be longer than eppResourceCachingSeconds, to prevent deleted contacts or
|
||||
# hosts from being used on domains.
|
||||
asyncDeleteDelaySeconds: 90
|
||||
|
||||
# Number of times to retry a GAE operation when a transient exception is thrown.
|
||||
# The number of milliseconds it'll sleep before giving up is (2^n - 2) * 100.
|
||||
transientFailureRetries: 12
|
||||
@@ -446,7 +444,8 @@ beam:
|
||||
stagingBucketUrl: gcs-bucket-with-staged-templates
|
||||
|
||||
keyring:
|
||||
# The name of the active keyring, either "KMS" or "Dummy".
|
||||
# The name of the active keyring, either "Dummy" or "CSM". The latter stands
|
||||
# for Cloud SecretManager.
|
||||
activeKeyring: Dummy
|
||||
|
||||
# Configuration options specific to Google Cloud KMS.
|
||||
@@ -536,3 +535,21 @@ sslCertificateValidation:
|
||||
allowedEcdsaCurves:
|
||||
- secp256r1
|
||||
- secp384r1
|
||||
|
||||
# Configuration options for the package compliance monitoring
|
||||
packageMonitoring:
|
||||
# Email subject text to notify partners their package has exceeded the limit for domain creates
|
||||
packageCreateLimitEmailSubjectText: "NOTICE: Your Package Is Being Upgraded"
|
||||
# Email body text template notify partners their package has exceeded the limit for domain creates
|
||||
packageCreateLimitEmailBodyText: >
|
||||
Dear %1$s,
|
||||
|
||||
We are contacting you to inform you that your package with the package token
|
||||
%2$s has exceeded its limit for annual domain creations.
|
||||
Your package will now be upgraded to the next tier.
|
||||
|
||||
If you have any questions or require additional support, please contact us
|
||||
at %3$s.
|
||||
|
||||
Regards,
|
||||
Example Registry
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.dns;
|
||||
|
||||
import static google.registry.dns.DnsConstants.DNS_PUBLISH_PUSH_QUEUE_NAME;
|
||||
import static google.registry.dns.DnsConstants.DNS_PULL_QUEUE_NAME;
|
||||
import static google.registry.dns.RefreshDnsOnHostRenameAction.PARAM_HOST_KEY;
|
||||
import static google.registry.request.RequestParameters.extractEnumParameter;
|
||||
import static google.registry.request.RequestParameters.extractIntParameter;
|
||||
import static google.registry.request.RequestParameters.extractRequiredParameter;
|
||||
@@ -61,7 +62,7 @@ public abstract class DnsModule {
|
||||
*/
|
||||
@Provides
|
||||
static HashFunction provideHashFunction() {
|
||||
return Hashing.murmur3_32();
|
||||
return Hashing.murmur3_32_fixed();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -118,6 +119,12 @@ public abstract class DnsModule {
|
||||
return extractSetOfParameters(req, PARAM_HOSTS);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter(PARAM_HOST_KEY)
|
||||
static String provideResourceKey(HttpServletRequest req) {
|
||||
return extractRequiredParameter(req, PARAM_HOST_KEY);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter("domainOrHostName")
|
||||
static String provideName(HttpServletRequest req) {
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright 2022 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.dns;
|
||||
|
||||
import static google.registry.dns.RefreshDnsOnHostRenameAction.PATH;
|
||||
import static google.registry.model.EppResourceUtils.getLinkedDomainKeys;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.model.EppResourceUtils;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import javax.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@Action(
|
||||
service = Service.BACKEND,
|
||||
path = PATH,
|
||||
method = Action.Method.POST,
|
||||
auth = Auth.AUTH_INTERNAL_OR_ADMIN)
|
||||
public class RefreshDnsOnHostRenameAction implements Runnable {
|
||||
|
||||
public static final String QUEUE_HOST_RENAME = "async-host-rename";
|
||||
public static final String PARAM_HOST_KEY = "hostKey";
|
||||
public static final String PATH = "/_dr/task/refreshDnsOnHostRename";
|
||||
|
||||
private final VKey<Host> hostKey;
|
||||
private final Response response;
|
||||
private final DnsQueue dnsQueue;
|
||||
|
||||
@Inject
|
||||
RefreshDnsOnHostRenameAction(
|
||||
@Parameter(PARAM_HOST_KEY) String hostKey, Response response, DnsQueue dnsQueue) {
|
||||
this.hostKey = VKey.createEppVKeyFromString(hostKey);
|
||||
this.response = response;
|
||||
this.dnsQueue = dnsQueue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
tm().transact(
|
||||
() -> {
|
||||
DateTime now = tm().getTransactionTime();
|
||||
Host host = tm().loadByKeyIfPresent(hostKey).orElse(null);
|
||||
boolean hostValid = true;
|
||||
String failureMessage = null;
|
||||
if (host == null) {
|
||||
hostValid = false;
|
||||
failureMessage = String.format("Host to refresh does not exist: %s", hostKey);
|
||||
} else if (EppResourceUtils.isDeleted(host, now)) {
|
||||
hostValid = false;
|
||||
failureMessage =
|
||||
String.format("Host to refresh is already deleted: %s", host.getHostName());
|
||||
} else {
|
||||
getLinkedDomainKeys(
|
||||
host.createVKey(), host.getUpdateTimestamp().getTimestamp(), null)
|
||||
.stream()
|
||||
.map(domainKey -> tm().loadByKey(domainKey))
|
||||
.filter(Domain::shouldPublishToDns)
|
||||
.forEach(domain -> dnsQueue.addDomainRefreshTask(domain.getDomainName()));
|
||||
}
|
||||
|
||||
if (!hostValid) {
|
||||
// Set the response status code to be 204 so to not retry.
|
||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||
response.setStatus(SC_NO_CONTENT);
|
||||
response.setPayload(failureMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -244,12 +244,6 @@
|
||||
<url-pattern>/_dr/task/resaveEntity</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Enqueues DNS update tasks following a host rename. -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>backend-servlet</servlet-name>
|
||||
<url-pattern>/_dr/task/dnsRefreshForHostRename</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Enqueues DNS update tasks following a host rename. -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>backend-servlet</servlet-name>
|
||||
@@ -293,6 +287,12 @@ have been in the database for a certain period of time. -->
|
||||
<url-pattern>/_dr/task/wipeOutCloudSql</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Action to execute canned scripts -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>backend-servlet</servlet-name>
|
||||
<url-pattern>/_dr/task/executeCannedScript</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Security config -->
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
|
||||
@@ -18,86 +18,6 @@
|
||||
</retry-parameters>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>async-delete-pull</name>
|
||||
<mode>pull</mode>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>async-host-rename-pull</name>
|
||||
<mode>pull</mode>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>export-commits</name>
|
||||
<rate>10/s</rate>
|
||||
<bucket-size>100</bucket-size>
|
||||
<retry-parameters>
|
||||
<!-- Retry aggressively since a single delayed export increases our time window of
|
||||
unrecoverable data loss in the event of a Datastore failure. -->
|
||||
<min-backoff-seconds>1</min-backoff-seconds>
|
||||
<max-backoff-seconds>60</max-backoff-seconds>
|
||||
<!-- No age limit; a failed export should be retried as long as possible to avoid
|
||||
having data missing from our exported commit log record. -->
|
||||
</retry-parameters>
|
||||
</queue>
|
||||
|
||||
<!-- Queue for polling export BigQuery jobs for completion. -->
|
||||
<queue>
|
||||
<name>export-bigquery-poll</name>
|
||||
<!-- Limit queue to 5 concurrent tasks and 5 per second to avoid hitting BigQuery quotas. -->
|
||||
<rate>5/s</rate>
|
||||
<bucket-size>5</bucket-size>
|
||||
<max-concurrent-requests>5</max-concurrent-requests>
|
||||
<!-- Check every 20s and increase interval to every 5 minutes. -->
|
||||
<retry-parameters>
|
||||
<min-backoff-seconds>20</min-backoff-seconds>
|
||||
<max-backoff-seconds>300</max-backoff-seconds>
|
||||
<max-doublings>2</max-doublings>
|
||||
</retry-parameters>
|
||||
</queue>
|
||||
|
||||
<!-- Queue for launching new snapshots and for triggering the initial BigQuery load jobs. -->
|
||||
<queue>
|
||||
<name>export-snapshot</name>
|
||||
<rate>1/s</rate>
|
||||
<retry-parameters>
|
||||
<!-- Should be less than the exportSnapshot cron interval; see cron.xml. -->
|
||||
<task-age-limit>22h</task-age-limit>
|
||||
<!-- Retry starting at a 5m interval and increasing up to a 30m interval. -->
|
||||
<min-backoff-seconds>300</min-backoff-seconds>
|
||||
<max-backoff-seconds>1800</max-backoff-seconds>
|
||||
<task-retry-limit>10</task-retry-limit>
|
||||
</retry-parameters>
|
||||
</queue>
|
||||
|
||||
<!-- Queue for polling managed backup snapshots for completion. -->
|
||||
<queue>
|
||||
<name>export-snapshot-poll</name>
|
||||
<rate>5/m</rate>
|
||||
<retry-parameters>
|
||||
<!-- Should be less than the exportSnapshot cron interval; see cron.xml. -->
|
||||
<task-age-limit>22h</task-age-limit>
|
||||
<!-- Retry starting at a 1m interval and increasing up to a 5m interval. -->
|
||||
<min-backoff-seconds>60</min-backoff-seconds>
|
||||
<max-backoff-seconds>300</max-backoff-seconds>
|
||||
</retry-parameters>
|
||||
</queue>
|
||||
|
||||
<!-- Queue for updating BigQuery views after a snapshot kind's load job completes. -->
|
||||
<queue>
|
||||
<name>export-snapshot-update-view</name>
|
||||
<rate>1/s</rate>
|
||||
<retry-parameters>
|
||||
<!-- Should be less than the exportSnapshot cron interval; see cron.xml. -->
|
||||
<task-age-limit>22h</task-age-limit>
|
||||
<!-- Retry starting at a 10s interval and increasing up to a 1m interval. -->
|
||||
<min-backoff-seconds>10</min-backoff-seconds>
|
||||
<max-backoff-seconds>60</max-backoff-seconds>
|
||||
<task-retry-limit>10</task-retry-limit>
|
||||
</retry-parameters>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>rde-upload</name>
|
||||
<rate>10/m</rate>
|
||||
@@ -126,6 +46,12 @@
|
||||
</retry-parameters>
|
||||
</queue>
|
||||
|
||||
<!-- Queue for tasks that trigger domain DNS update upon host rename. -->
|
||||
<queue>
|
||||
<name>async-host-rename</name>
|
||||
<rate>1/s</rate>
|
||||
</queue>
|
||||
|
||||
<!-- Queue for tasks that wait for a Beam pipeline to complete (i.e. Spec11 and invoicing). -->
|
||||
<queue>
|
||||
<name>beam-reporting</name>
|
||||
@@ -149,7 +75,7 @@
|
||||
</retry-parameters>
|
||||
</queue>
|
||||
|
||||
<!-- Queue for tasks to produce LORDN CSV reports, either by by the query or queue method. -->
|
||||
<!-- Queue for tasks to produce LORDN CSV reports, either by the query or queue method. -->
|
||||
<queue>
|
||||
<name>nordn</name>
|
||||
<rate>1/s</rate>
|
||||
@@ -171,17 +97,6 @@
|
||||
<mode>pull</mode>
|
||||
</queue>
|
||||
|
||||
<!-- Queue used by the MapReduce library for running tasks.
|
||||
|
||||
Do not re-use this queue for tasks that our code creates (e.g. tasks to launch MapReduces
|
||||
that aren't themselves part of a running MapReduce).-->
|
||||
<queue>
|
||||
<name>mapreduce</name>
|
||||
<!-- Warning: DO NOT SET A <target> parameter for this queue. See b/24782801 for why. -->
|
||||
<rate>500/s</rate>
|
||||
<bucket-size>100</bucket-size>
|
||||
</queue>
|
||||
|
||||
<!-- Queue for tasks that sync data to Google Spreadsheets. -->
|
||||
<queue>
|
||||
<name>sheet</name>
|
||||
@@ -208,71 +123,4 @@
|
||||
<max-concurrent-requests>5</max-concurrent-requests>
|
||||
</queue>
|
||||
|
||||
<!-- Queue for replaying commit logs to SQL during the transition from Datastore -> SQL. -->
|
||||
<queue>
|
||||
<name>replay-commit-logs-to-sql</name>
|
||||
<rate>1/s</rate>
|
||||
</queue>
|
||||
|
||||
<!-- The load[0-9] queues are used for load-testing, and can be safely deleted
|
||||
in any environment that doesn't require load-testing. -->
|
||||
<queue>
|
||||
<name>load0</name>
|
||||
<rate>500/s</rate>
|
||||
<bucket-size>500</bucket-size>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>load1</name>
|
||||
<rate>500/s</rate>
|
||||
<bucket-size>500</bucket-size>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>load2</name>
|
||||
<rate>500/s</rate>
|
||||
<bucket-size>500</bucket-size>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>load3</name>
|
||||
<rate>500/s</rate>
|
||||
<bucket-size>500</bucket-size>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>load4</name>
|
||||
<rate>500/s</rate>
|
||||
<bucket-size>500</bucket-size>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>load5</name>
|
||||
<rate>500/s</rate>
|
||||
<bucket-size>500</bucket-size>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>load6</name>
|
||||
<rate>500/s</rate>
|
||||
<bucket-size>500</bucket-size>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>load7</name>
|
||||
<rate>500/s</rate>
|
||||
<bucket-size>500</bucket-size>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>load8</name>
|
||||
<rate>500/s</rate>
|
||||
<bucket-size>500</bucket-size>
|
||||
</queue>
|
||||
|
||||
<queue>
|
||||
<name>load9</name>
|
||||
<rate>500/s</rate>
|
||||
<bucket-size>500</bucket-size>
|
||||
</queue>
|
||||
</queue-entries>
|
||||
|
||||
@@ -163,7 +163,7 @@ public final class SyncGroupMembersAction implements Runnable {
|
||||
registrarsToSave.add(result.getKey().asBuilder().setContactsRequireSyncing(false).build());
|
||||
}
|
||||
}
|
||||
tm().transactNew(() -> tm().updateAll(registrarsToSave.build()));
|
||||
tm().transact(() -> tm().updateAll(registrarsToSave.build()));
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,19 +23,18 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException.CommandUseErrorException;
|
||||
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
||||
import google.registry.flows.EppException.SyntaxErrorException;
|
||||
import google.registry.flows.EppException.UnimplementedProtocolVersionException;
|
||||
import google.registry.flows.custom.EntityChanges;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.adapters.CurrencyUnitAdapter.UnknownCurrencyException;
|
||||
import google.registry.model.eppcommon.EppXmlTransformer;
|
||||
import google.registry.model.eppinput.EppInput.WrongProtocolVersionException;
|
||||
import google.registry.model.eppoutput.EppOutput;
|
||||
import google.registry.model.host.InetAddressAdapter.IpVersionMismatchException;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.translators.CurrencyUnitAdapter.UnknownCurrencyException;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.xml.XmlException;
|
||||
import java.util.List;
|
||||
|
||||
@@ -103,9 +102,8 @@ public final class FlowUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static <H extends HistoryEntry> Key<H> createHistoryKey(
|
||||
EppResource parent, Class<H> clazz) {
|
||||
return Key.create(Key.create(parent), clazz, allocateId());
|
||||
public static HistoryEntryId createHistoryEntryId(EppResource parent) {
|
||||
return new HistoryEntryId(parent.getRepoId(), allocateId());
|
||||
}
|
||||
|
||||
/** Registrar is not logged in. */
|
||||
@@ -118,7 +116,7 @@ public final class FlowUtils {
|
||||
/** IP address version mismatch. */
|
||||
public static class IpAddressVersionMismatchException extends ParameterValueRangeErrorException {
|
||||
public IpAddressVersionMismatchException() {
|
||||
super("IP adddress version mismatch");
|
||||
super("IP address version mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ public final class ResourceFlowUtils {
|
||||
// The roid should match one of the contacts.
|
||||
Optional<VKey<Contact>> foundContact =
|
||||
domain.getReferencedContacts().stream()
|
||||
.filter(key -> key.getSqlKey().equals(authRepoId))
|
||||
.filter(key -> key.getKey().equals(authRepoId))
|
||||
.findFirst();
|
||||
if (!foundContact.isPresent()) {
|
||||
throw new BadAuthInfoForResourceException();
|
||||
|
||||
@@ -27,7 +27,6 @@ import static google.registry.model.transfer.TransferStatus.SERVER_CANCELLED;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.batch.AsyncTaskEnqueuer;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
@@ -79,7 +78,6 @@ public final class ContactDeleteFlow implements TransactionalFlow {
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject ContactHistory.Builder historyBuilder;
|
||||
@Inject AsyncTaskEnqueuer asyncTaskEnqueuer;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
|
||||
@Inject
|
||||
|
||||
@@ -20,17 +20,15 @@ import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
|
||||
import google.registry.flows.EppException.ParameterValueSyntaxErrorException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAddress;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactHistory.ContactHistoryId;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse.ContactPendingActionNotificationResponse;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import google.registry.model.transfer.TransferResponse.ContactTransferResponse;
|
||||
import java.util.Set;
|
||||
@@ -69,10 +67,7 @@ public class ContactFlowUtils {
|
||||
|
||||
/** Create a poll message for the gaining client in a transfer. */
|
||||
static PollMessage createGainingTransferPollMessage(
|
||||
String targetId,
|
||||
TransferData transferData,
|
||||
DateTime now,
|
||||
Key<ContactHistory> contactHistoryKey) {
|
||||
String targetId, TransferData transferData, DateTime now, HistoryEntryId contactHistoryId) {
|
||||
return new PollMessage.OneTime.Builder()
|
||||
.setRegistrarId(transferData.getGainingRegistrarId())
|
||||
.setEventTime(transferData.getPendingTransferExpirationTime())
|
||||
@@ -85,23 +80,19 @@ public class ContactFlowUtils {
|
||||
transferData.getTransferStatus().isApproved(),
|
||||
transferData.getTransferRequestTrid(),
|
||||
now)))
|
||||
.setContactHistoryId(
|
||||
new ContactHistoryId(
|
||||
contactHistoryKey.getParent().getName(), contactHistoryKey.getId()))
|
||||
.setContactHistoryId(contactHistoryId)
|
||||
.build();
|
||||
}
|
||||
|
||||
/** Create a poll message for the losing client in a transfer. */
|
||||
static PollMessage createLosingTransferPollMessage(
|
||||
String targetId, TransferData transferData, Key<ContactHistory> contactHistoryKey) {
|
||||
String targetId, TransferData transferData, HistoryEntryId contactHistoryId) {
|
||||
return new PollMessage.OneTime.Builder()
|
||||
.setRegistrarId(transferData.getLosingRegistrarId())
|
||||
.setEventTime(transferData.getPendingTransferExpirationTime())
|
||||
.setMsg(transferData.getTransferStatus().getMessage())
|
||||
.setResponseData(ImmutableList.of(createTransferResponse(targetId, transferData)))
|
||||
.setContactHistoryId(
|
||||
new ContactHistoryId(
|
||||
contactHistoryKey.getParent().getName(), contactHistoryKey.getId()))
|
||||
.setContactHistoryId(contactHistoryId)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -90,10 +90,10 @@ public final class ContactInfoFlow implements Flow {
|
||||
.setVoiceNumber(contact.getVoiceNumber())
|
||||
.setFaxNumber(contact.getFaxNumber())
|
||||
.setEmailAddress(contact.getEmailAddress())
|
||||
.setCurrentSponsorClientId(contact.getCurrentSponsorRegistrarId())
|
||||
.setCreationClientId(contact.getCreationRegistrarId())
|
||||
.setCurrentSponsorRegistrarId(contact.getCurrentSponsorRegistrarId())
|
||||
.setCreationRegistrarId(contact.getCreationRegistrarId())
|
||||
.setCreationTime(contact.getCreationTime())
|
||||
.setLastEppUpdateClientId(contact.getLastEppUpdateRegistrarId())
|
||||
.setLastEppUpdateRegistrarId(contact.getLastEppUpdateRegistrarId())
|
||||
.setLastEppUpdateTime(contact.getLastEppUpdateTime())
|
||||
.setLastTransferTime(contact.getLastTransferTime())
|
||||
.setAuthInfo(includeAuthInfo ? contact.getAuthInfo() : null)
|
||||
|
||||
@@ -26,7 +26,6 @@ import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_TRANSFER
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
@@ -93,7 +92,7 @@ public final class ContactTransferApproveFlow implements TransactionalFlow {
|
||||
// Create a poll message for the gaining client.
|
||||
PollMessage gainingPollMessage =
|
||||
createGainingTransferPollMessage(
|
||||
targetId, newContact.getTransferData(), now, Key.create(contactHistory));
|
||||
targetId, newContact.getTransferData(), now, contactHistory.getHistoryEntryId());
|
||||
tm().insertAll(ImmutableSet.of(contactHistory, gainingPollMessage));
|
||||
tm().update(newContact);
|
||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||
|
||||
@@ -26,7 +26,6 @@ import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_TRANSFER
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
@@ -73,7 +72,7 @@ public final class ContactTransferCancelFlow implements TransactionalFlow {
|
||||
@Inject ContactTransferCancelFlow() {}
|
||||
|
||||
@Override
|
||||
public final EppResponse run() throws EppException {
|
||||
public EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
extensionManager.validate();
|
||||
@@ -89,7 +88,7 @@ public final class ContactTransferCancelFlow implements TransactionalFlow {
|
||||
// Create a poll message for the losing client.
|
||||
PollMessage losingPollMessage =
|
||||
createLosingTransferPollMessage(
|
||||
targetId, newContact.getTransferData(), Key.create(contactHistory));
|
||||
targetId, newContact.getTransferData(), contactHistory.getHistoryEntryId());
|
||||
tm().insertAll(ImmutableSet.of(contactHistory, losingPollMessage));
|
||||
tm().update(newContact);
|
||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||
|
||||
@@ -26,7 +26,6 @@ import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_TRANSFER
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
@@ -86,7 +85,7 @@ public final class ContactTransferRejectFlow implements TransactionalFlow {
|
||||
historyBuilder.setType(CONTACT_TRANSFER_REJECT).setContact(newContact).build();
|
||||
PollMessage gainingPollMessage =
|
||||
createGainingTransferPollMessage(
|
||||
targetId, newContact.getTransferData(), now, Key.create(contactHistory));
|
||||
targetId, newContact.getTransferData(), now, contactHistory.getHistoryEntryId());
|
||||
tm().insertAll(ImmutableSet.of(contactHistory, gainingPollMessage));
|
||||
tm().update(newContact);
|
||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.createHistoryEntryId;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfo;
|
||||
@@ -28,7 +28,6 @@ import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_TRANSFER
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
@@ -46,6 +45,7 @@ import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.eppoutput.EppResponse;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.model.transfer.ContactTransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
@@ -74,21 +74,27 @@ import org.joda.time.Duration;
|
||||
@ReportingSpec(ActivityReportField.CONTACT_TRANSFER_REQUEST)
|
||||
public final class ContactTransferRequestFlow implements TransactionalFlow {
|
||||
|
||||
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
||||
StatusValue.CLIENT_TRANSFER_PROHIBITED,
|
||||
StatusValue.PENDING_DELETE,
|
||||
StatusValue.SERVER_TRANSFER_PROHIBITED);
|
||||
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES =
|
||||
ImmutableSet.of(
|
||||
StatusValue.CLIENT_TRANSFER_PROHIBITED,
|
||||
StatusValue.PENDING_DELETE,
|
||||
StatusValue.SERVER_TRANSFER_PROHIBITED);
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @RegistrarId String gainingClientId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Config("contactAutomaticTransferLength") Duration automaticTransferLength;
|
||||
|
||||
@Inject
|
||||
@Config("contactAutomaticTransferLength")
|
||||
Duration automaticTransferLength;
|
||||
|
||||
@Inject ContactHistory.Builder historyBuilder;
|
||||
@Inject Trid trid;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
@Inject ContactTransferRequestFlow() {}
|
||||
|
||||
@Inject
|
||||
ContactTransferRequestFlow() {}
|
||||
|
||||
@Override
|
||||
public EppResponse run() throws EppException {
|
||||
@@ -120,29 +126,31 @@ public final class ContactTransferRequestFlow implements TransactionalFlow {
|
||||
.setPendingTransferExpirationTime(transferExpirationTime)
|
||||
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
||||
.build();
|
||||
Key<ContactHistory> contactHistoryKey = createHistoryKey(existingContact, ContactHistory.class);
|
||||
historyBuilder.setId(contactHistoryKey.getId()).setType(CONTACT_TRANSFER_REQUEST);
|
||||
HistoryEntryId contactHistoryId = createHistoryEntryId(existingContact);
|
||||
historyBuilder
|
||||
.setRevisionId(contactHistoryId.getRevisionId())
|
||||
.setType(CONTACT_TRANSFER_REQUEST);
|
||||
// If the transfer is server approved, this message will be sent to the losing registrar. */
|
||||
PollMessage serverApproveLosingPollMessage =
|
||||
createLosingTransferPollMessage(targetId, serverApproveTransferData, contactHistoryKey);
|
||||
createLosingTransferPollMessage(targetId, serverApproveTransferData, contactHistoryId);
|
||||
// If the transfer is server approved, this message will be sent to the gaining registrar. */
|
||||
PollMessage serverApproveGainingPollMessage =
|
||||
createGainingTransferPollMessage(
|
||||
targetId, serverApproveTransferData, now, contactHistoryKey);
|
||||
targetId, serverApproveTransferData, now, contactHistoryId);
|
||||
ContactTransferData pendingTransferData =
|
||||
serverApproveTransferData
|
||||
.asBuilder()
|
||||
.setTransferStatus(TransferStatus.PENDING)
|
||||
.setServerApproveEntities(
|
||||
serverApproveGainingPollMessage.getContactRepoId(),
|
||||
contactHistoryKey.getId(),
|
||||
contactHistoryId.getRevisionId(),
|
||||
ImmutableSet.of(
|
||||
serverApproveGainingPollMessage.createVKey(),
|
||||
serverApproveLosingPollMessage.createVKey()))
|
||||
.build();
|
||||
// When a transfer is requested, a poll message is created to notify the losing registrar.
|
||||
PollMessage requestPollMessage =
|
||||
createLosingTransferPollMessage(targetId, pendingTransferData, contactHistoryKey)
|
||||
createLosingTransferPollMessage(targetId, pendingTransferData, contactHistoryId)
|
||||
.asBuilder()
|
||||
.setEventTime(now) // Unlike the serverApprove messages, this applies immediately.
|
||||
.build();
|
||||
@@ -165,4 +173,3 @@ public final class ContactTransferRequestFlow implements TransactionalFlow {
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,6 @@ import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainCommand;
|
||||
import google.registry.model.domain.DomainCommand.Create;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.domain.fee.FeeCreateCommandExtension;
|
||||
@@ -110,6 +109,7 @@ import google.registry.model.poll.PollMessage.Autorenew;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.tld.Registry.TldState;
|
||||
@@ -327,14 +327,14 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||
FeesAndCredits feesAndCredits =
|
||||
pricingLogic.getCreatePrice(
|
||||
registry, targetId, now, years, isAnchorTenant, allocationToken);
|
||||
validateFeeChallenge(targetId, now, feeCreate, feesAndCredits);
|
||||
validateFeeChallenge(feeCreate, feesAndCredits);
|
||||
Optional<SecDnsCreateExtension> secDnsCreate =
|
||||
validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class));
|
||||
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
|
||||
String repoId = createDomainRepoId(allocateId(), registry.getTldStr());
|
||||
long historyRevisionId = allocateId();
|
||||
DomainHistoryId domainHistoryId = new DomainHistoryId(repoId, historyRevisionId);
|
||||
historyBuilder.setId(historyRevisionId);
|
||||
HistoryEntryId domainHistoryId = new HistoryEntryId(repoId, historyRevisionId);
|
||||
historyBuilder.setRevisionId(historyRevisionId);
|
||||
// Bill for the create.
|
||||
BillingEvent.OneTime createBillingEvent =
|
||||
createOneTimeBillingEvent(
|
||||
@@ -406,7 +406,8 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||
if (allocationToken.isPresent()
|
||||
&& TokenType.SINGLE_USE.equals(allocationToken.get().getTokenType())) {
|
||||
entitiesToSave.add(
|
||||
allocationTokenFlowUtils.redeemToken(allocationToken.get(), domainHistory.createVKey()));
|
||||
allocationTokenFlowUtils.redeemToken(
|
||||
allocationToken.get(), domainHistory.getHistoryEntryId()));
|
||||
}
|
||||
enqueueTasks(domain, hasSignedMarks, hasClaimsNotice);
|
||||
|
||||
@@ -562,7 +563,7 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||
boolean isReserved,
|
||||
int years,
|
||||
FeesAndCredits feesAndCredits,
|
||||
DomainHistoryId domainHistoryId,
|
||||
HistoryEntryId domainHistoryId,
|
||||
Optional<AllocationToken> allocationToken,
|
||||
DateTime now) {
|
||||
ImmutableSet.Builder<Flag> flagsBuilder = new ImmutableSet.Builder<>();
|
||||
@@ -596,7 +597,7 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||
}
|
||||
|
||||
private Recurring createAutorenewBillingEvent(
|
||||
DomainHistoryId domainHistoryId,
|
||||
HistoryEntryId domainHistoryId,
|
||||
DateTime registrationExpirationTime,
|
||||
RenewalPriceInfo renewalpriceInfo) {
|
||||
return new BillingEvent.Recurring.Builder()
|
||||
@@ -613,7 +614,7 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||
}
|
||||
|
||||
private Autorenew createAutorenewPollMessage(
|
||||
DomainHistoryId domainHistoryId, DateTime registrationExpirationTime) {
|
||||
HistoryEntryId domainHistoryId, DateTime registrationExpirationTime) {
|
||||
return new PollMessage.Autorenew.Builder()
|
||||
.setTargetId(targetId)
|
||||
.setRegistrarId(registrarId)
|
||||
@@ -634,7 +635,7 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||
.setEventTime(createBillingEvent.getEventTime())
|
||||
.setBillingTime(createBillingEvent.getBillingTime())
|
||||
.setFlags(createBillingEvent.getFlags())
|
||||
.setDomainHistoryId(createBillingEvent.getDomainHistoryId())
|
||||
.setDomainHistoryId(createBillingEvent.getHistoryEntryId())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -674,11 +675,11 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||
Optional<AllocationToken> allocationToken,
|
||||
FeesAndCredits feesAndCredits) {
|
||||
if (isAnchorTenant) {
|
||||
if (allocationToken.isPresent()) {
|
||||
checkArgument(
|
||||
allocationToken.get().getRenewalPriceBehavior() != RenewalPriceBehavior.SPECIFIED,
|
||||
"Renewal price behavior cannot be SPECIFIED for anchor tenant");
|
||||
}
|
||||
allocationToken.ifPresent(
|
||||
token ->
|
||||
checkArgument(
|
||||
token.getRenewalPriceBehavior() != RenewalPriceBehavior.SPECIFIED,
|
||||
"Renewal price behavior cannot be SPECIFIED for anchor tenant"));
|
||||
return RenewalPriceInfo.create(RenewalPriceBehavior.NONPREMIUM, null);
|
||||
} else if (allocationToken.isPresent()
|
||||
&& allocationToken.get().getRenewalPriceBehavior() == RenewalPriceBehavior.SPECIFIED) {
|
||||
@@ -705,9 +706,12 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||
|
||||
private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
|
||||
Optional<FeeCreateCommandExtension> feeCreate, FeesAndCredits feesAndCredits) {
|
||||
return feeCreate.isPresent()
|
||||
? ImmutableList.of(createFeeCreateResponse(feeCreate.get(), feesAndCredits))
|
||||
: ImmutableList.of();
|
||||
return feeCreate
|
||||
.map(
|
||||
feeCreateCommandExtension ->
|
||||
ImmutableList.of(
|
||||
createFeeCreateResponse(feeCreateCommandExtension, feesAndCredits)))
|
||||
.orElseGet(ImmutableList::of);
|
||||
}
|
||||
|
||||
/** Signed marks are only allowed during sunrise. */
|
||||
|
||||
@@ -16,7 +16,7 @@ package google.registry.flows.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.createHistoryEntryId;
|
||||
import static google.registry.flows.FlowUtils.persistEntityChanges;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
@@ -43,7 +43,6 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.batch.AsyncTaskEnqueuer;
|
||||
import google.registry.dns.DnsQueue;
|
||||
import google.registry.flows.EppException;
|
||||
@@ -66,7 +65,6 @@ import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Recurring;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.fee.BaseFee.FeeType;
|
||||
import google.registry.model.domain.fee.Credit;
|
||||
@@ -88,6 +86,7 @@ import google.registry.model.poll.PendingActionNotificationResponse.DomainPendin
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.tld.Registry.TldType;
|
||||
@@ -181,8 +180,8 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
? Duration.ZERO
|
||||
// By default, this should be 30 days of grace, and 5 days of pending delete.
|
||||
: redemptionGracePeriodLength.plus(pendingDeleteLength);
|
||||
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
|
||||
historyBuilder.setId(domainHistoryKey.getId());
|
||||
HistoryEntryId domainHistoryId = createHistoryEntryId(existingDomain);
|
||||
historyBuilder.setRevisionId(domainHistoryId.getRevisionId());
|
||||
DateTime deletionTime = now.plus(durationUntilDelete);
|
||||
if (durationUntilDelete.equals(Duration.ZERO)) {
|
||||
builder.setDeletionTime(now).setStatusValues(null);
|
||||
@@ -214,7 +213,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
// it is synchronous).
|
||||
if (durationUntilDelete.isLongerThan(Duration.ZERO) || isSuperuser) {
|
||||
PollMessage.OneTime deletePollMessage =
|
||||
createDeletePollMessage(existingDomain, domainHistoryKey, deletionTime);
|
||||
createDeletePollMessage(existingDomain, domainHistoryId, deletionTime);
|
||||
entitiesToSave.add(deletePollMessage);
|
||||
builder.setDeletePollMessage(deletePollMessage.createVKey());
|
||||
}
|
||||
@@ -224,7 +223,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
if (durationUntilDelete.isLongerThan(Duration.ZERO)
|
||||
&& !registrarId.equals(existingDomain.getPersistedCurrentSponsorRegistrarId())) {
|
||||
entitiesToSave.add(
|
||||
createImmediateDeletePollMessage(existingDomain, domainHistoryKey, now, deletionTime));
|
||||
createImmediateDeletePollMessage(existingDomain, domainHistoryId, now, deletionTime));
|
||||
}
|
||||
|
||||
// Cancel any grace periods that were still active, and set the expiration time accordingly.
|
||||
@@ -233,14 +232,9 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
// No cancellation is written if the grace period was not for a billable event.
|
||||
if (gracePeriod.hasBillingEvent()) {
|
||||
entitiesToSave.add(
|
||||
BillingEvent.Cancellation.forGracePeriod(
|
||||
gracePeriod,
|
||||
now,
|
||||
new DomainHistoryId(
|
||||
domainHistoryKey.getParent().getName(), domainHistoryKey.getId()),
|
||||
targetId));
|
||||
BillingEvent.Cancellation.forGracePeriod(gracePeriod, now, domainHistoryId, targetId));
|
||||
if (gracePeriod.getOneTimeBillingEvent() != null) {
|
||||
// Take the amount of amount of registration time being refunded off the expiration time.
|
||||
// Take the amount of registration time being refunded off the expiration time.
|
||||
// This can be either add grace periods or renew grace periods.
|
||||
BillingEvent.OneTime oneTime = tm().loadByKey(gracePeriod.getOneTimeBillingEvent());
|
||||
newExpirationTime = newExpirationTime.minusYears(oneTime.getPeriodYears());
|
||||
@@ -262,7 +256,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
|
||||
BillingEvent.Recurring recurringBillingEvent =
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
existingDomain, existingRecurring, now, domainHistory.getDomainHistoryId());
|
||||
existingDomain, existingRecurring, now, domainHistory.getHistoryEntryId());
|
||||
// If there's a pending transfer, the gaining client's autorenew billing
|
||||
// event and poll message will already have been deleted in
|
||||
// ResourceDeleteFlow since it's listed in serverApproveEntities.
|
||||
@@ -343,7 +337,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
}
|
||||
|
||||
private PollMessage.OneTime createDeletePollMessage(
|
||||
Domain existingDomain, Key<DomainHistory> domainHistoryKey, DateTime deletionTime) {
|
||||
Domain existingDomain, HistoryEntryId domainHistoryId, DateTime deletionTime) {
|
||||
Optional<MetadataExtension> metadataExtension =
|
||||
eppInput.getSingleExtension(MetadataExtension.class);
|
||||
boolean hasMetadataMessage =
|
||||
@@ -362,21 +356,16 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
ImmutableList.of(
|
||||
DomainPendingActionNotificationResponse.create(
|
||||
existingDomain.getDomainName(), true, trid, deletionTime)))
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build();
|
||||
}
|
||||
|
||||
private PollMessage.OneTime createImmediateDeletePollMessage(
|
||||
Domain existingDomain,
|
||||
Key<DomainHistory> domainHistoryKey,
|
||||
DateTime now,
|
||||
DateTime deletionTime) {
|
||||
Domain existingDomain, HistoryEntryId domainHistoryId, DateTime now, DateTime deletionTime) {
|
||||
return new PollMessage.OneTime.Builder()
|
||||
.setRegistrarId(existingDomain.getPersistedCurrentSponsorRegistrarId())
|
||||
.setEventTime(now)
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.setMsg(
|
||||
String.format(
|
||||
"Domain %s was deleted by registry administrator with final deletion effective: %s",
|
||||
|
||||
@@ -88,7 +88,6 @@ import google.registry.model.domain.DomainCommand.CreateOrUpdate;
|
||||
import google.registry.model.domain.DomainCommand.InvalidReferencesException;
|
||||
import google.registry.model.domain.DomainCommand.Update;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.domain.ForeignKeyedDesignatedContact;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.domain.fee.BaseFee;
|
||||
@@ -121,7 +120,7 @@ import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.State;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.tld.Registry.TldState;
|
||||
import google.registry.model.tld.Registry.TldType;
|
||||
@@ -429,7 +428,7 @@ public class DomainFlowUtils {
|
||||
contacts.stream()
|
||||
.collect(
|
||||
toImmutableSetMultimap(
|
||||
DesignatedContact::getType, contact -> contact.getContactKey()));
|
||||
DesignatedContact::getType, DesignatedContact::getContactKey));
|
||||
|
||||
// If any contact type has multiple contacts:
|
||||
if (contactsByType.asMap().values().stream().anyMatch(v -> v.size() > 1)) {
|
||||
@@ -590,7 +589,7 @@ public class DomainFlowUtils {
|
||||
Domain domain,
|
||||
Recurring existingRecurring,
|
||||
DateTime newEndTime,
|
||||
@Nullable DomainHistoryId historyId) {
|
||||
@Nullable HistoryEntryId historyId) {
|
||||
Optional<PollMessage.Autorenew> autorenewPollMessage =
|
||||
tm().loadByKeyIfPresent(domain.getAutorenewPollMessage());
|
||||
|
||||
@@ -609,7 +608,7 @@ public class DomainFlowUtils {
|
||||
historyId, "Cannot create a new autorenew poll message without a domain history id");
|
||||
updatedAutorenewPollMessage =
|
||||
newAutorenewPollMessage(domain)
|
||||
.setId((Long) domain.getAutorenewPollMessage().getSqlKey())
|
||||
.setId((Long) domain.getAutorenewPollMessage().getKey())
|
||||
.setAutorenewEndTime(newEndTime)
|
||||
.setDomainHistoryId(historyId)
|
||||
.build();
|
||||
@@ -773,8 +772,6 @@ public class DomainFlowUtils {
|
||||
* domain names.
|
||||
*/
|
||||
public static void validateFeeChallenge(
|
||||
String domainName,
|
||||
DateTime priceTime,
|
||||
final Optional<? extends FeeTransformCommandExtension> feeCommand,
|
||||
FeesAndCredits feesAndCredits)
|
||||
throws EppException {
|
||||
@@ -1135,9 +1132,9 @@ public class DomainFlowUtils {
|
||||
Duration maxSearchPeriod,
|
||||
final ImmutableSet<TransactionReportField> cancelableFields) {
|
||||
|
||||
List<? extends HistoryEntry> recentHistoryEntries =
|
||||
List<DomainHistory> recentHistoryEntries =
|
||||
findRecentHistoryEntries(domain, now, maxSearchPeriod);
|
||||
Optional<? extends HistoryEntry> entryToCancel =
|
||||
Optional<DomainHistory> entryToCancel =
|
||||
Streams.findLast(
|
||||
recentHistoryEntries.stream()
|
||||
.filter(
|
||||
@@ -1174,11 +1171,11 @@ public class DomainFlowUtils {
|
||||
return recordsBuilder.build();
|
||||
}
|
||||
|
||||
private static List<? extends HistoryEntry> findRecentHistoryEntries(
|
||||
private static List<DomainHistory> findRecentHistoryEntries(
|
||||
Domain domain, DateTime now, Duration maxSearchPeriod) {
|
||||
return jpaTm()
|
||||
.query(
|
||||
"FROM DomainHistory WHERE modificationTime >= :beginning AND domainRepoId = "
|
||||
"FROM DomainHistory WHERE modificationTime >= :beginning AND repoId = "
|
||||
+ ":repoId ORDER BY modificationTime ASC",
|
||||
DomainHistory.class)
|
||||
.setParameter("beginning", now.minus(maxSearchPeriod))
|
||||
|
||||
@@ -105,32 +105,33 @@ public final class DomainInfoFlow implements Flow {
|
||||
verifyOptionalAuthInfo(authInfo, domain);
|
||||
flowCustomLogic.afterValidation(
|
||||
AfterValidationParameters.newBuilder().setDomain(domain).build());
|
||||
HostsRequest hostsRequest = ((Info) resourceCommand).getHostsRequest();
|
||||
// Registrars can only see a few fields on unauthorized domains.
|
||||
// This is a policy decision that is left up to us by the rfcs.
|
||||
DomainInfoData.Builder infoBuilder =
|
||||
DomainInfoData.newBuilder()
|
||||
.setDomainName(domain.getDomainName())
|
||||
.setRepoId(domain.getRepoId())
|
||||
.setCurrentSponsorClientId(domain.getCurrentSponsorRegistrarId())
|
||||
.setCurrentSponsorRegistrarId(domain.getCurrentSponsorRegistrarId())
|
||||
.setStatusValues(domain.getStatusValues())
|
||||
.setNameservers(
|
||||
hostsRequest.requestDelegated() ? domain.loadNameserverHostNames() : null)
|
||||
.setCreationTime(domain.getCreationTime())
|
||||
.setLastEppUpdateTime(domain.getLastEppUpdateTime())
|
||||
.setRegistrationExpirationTime(domain.getRegistrationExpirationTime())
|
||||
.setLastTransferTime(domain.getLastTransferTime())
|
||||
.setRegistrant(
|
||||
tm().transact(() -> tm().loadByKey(domain.getRegistrant())).getContactId());
|
||||
// If authInfo is non-null, then the caller is authorized to see the full information since we
|
||||
// will have already verified the authInfo is valid.
|
||||
if (registrarId.equals(domain.getCurrentSponsorRegistrarId()) || authInfo.isPresent()) {
|
||||
HostsRequest hostsRequest = ((Info) resourceCommand).getHostsRequest();
|
||||
infoBuilder
|
||||
.setStatusValues(domain.getStatusValues())
|
||||
.setContacts(
|
||||
tm().transact(() -> loadForeignKeyedDesignatedContacts(domain.getContacts())))
|
||||
.setNameservers(hostsRequest.requestDelegated() ? domain.loadNameserverHostNames() : null)
|
||||
.setSubordinateHosts(
|
||||
hostsRequest.requestSubordinate() ? domain.getSubordinateHosts() : null)
|
||||
.setCreationClientId(domain.getCreationRegistrarId())
|
||||
.setCreationTime(domain.getCreationTime())
|
||||
.setLastEppUpdateClientId(domain.getLastEppUpdateRegistrarId())
|
||||
.setLastEppUpdateTime(domain.getLastEppUpdateTime())
|
||||
.setRegistrationExpirationTime(domain.getRegistrationExpirationTime())
|
||||
.setLastTransferTime(domain.getLastTransferTime())
|
||||
.setCreationRegistrarId(domain.getCreationRegistrarId())
|
||||
.setLastEppUpdateRegistrarId(domain.getLastEppUpdateRegistrarId())
|
||||
.setAuthInfo(domain.getAuthInfo());
|
||||
}
|
||||
BeforeResponseReturnData responseData =
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.createHistoryEntryId;
|
||||
import static google.registry.flows.FlowUtils.persistEntityChanges;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
@@ -38,7 +38,6 @@ import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
@@ -62,7 +61,6 @@ import google.registry.model.billing.BillingEvent.Recurring;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainCommand.Renew;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.domain.DomainRenewData;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.Period;
|
||||
@@ -83,6 +81,7 @@ import google.registry.model.eppoutput.EppResponse;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.model.tld.Registry;
|
||||
import java.util.Optional;
|
||||
@@ -100,7 +99,7 @@ import org.joda.time.Duration;
|
||||
*
|
||||
* <p>ICANN prohibits any registration from being longer than ten years so if the request would
|
||||
* result in a registration greater than ten years long it will fail. In practice this means it's
|
||||
* impossible to request a ten year renewal, since that will always cause the new registration to be
|
||||
* impossible to request a ten-year renewal, since that will always cause the new registration to be
|
||||
* longer than 10 years unless it comes in at the exact millisecond that the domain would have
|
||||
* expired.
|
||||
*
|
||||
@@ -200,44 +199,36 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
now,
|
||||
years,
|
||||
existingRecurringBillingEvent);
|
||||
validateFeeChallenge(targetId, now, feeRenew, feesAndCredits);
|
||||
validateFeeChallenge(feeRenew, feesAndCredits);
|
||||
flowCustomLogic.afterValidation(
|
||||
AfterValidationParameters.newBuilder()
|
||||
.setExistingDomain(existingDomain)
|
||||
.setNow(now)
|
||||
.setYears(years)
|
||||
.build());
|
||||
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
|
||||
historyBuilder.setId(domainHistoryKey.getId());
|
||||
HistoryEntryId domainHistoryId = createHistoryEntryId(existingDomain);
|
||||
historyBuilder.setRevisionId(domainHistoryId.getRevisionId());
|
||||
String tld = existingDomain.getTld();
|
||||
// Bill for this explicit renew itself.
|
||||
BillingEvent.OneTime explicitRenewEvent =
|
||||
createRenewBillingEvent(
|
||||
tld, feesAndCredits.getTotalCost(), years, domainHistoryKey, allocationToken, now);
|
||||
tld, feesAndCredits.getTotalCost(), years, domainHistoryId, allocationToken, now);
|
||||
// Create a new autorenew billing event and poll message starting at the new expiration time.
|
||||
BillingEvent.Recurring newAutorenewEvent =
|
||||
newAutorenewBillingEvent(existingDomain)
|
||||
.setEventTime(newExpirationTime)
|
||||
.setRenewalPrice(existingRecurringBillingEvent.getRenewalPrice().orElse(null))
|
||||
.setRenewalPriceBehavior(existingRecurringBillingEvent.getRenewalPriceBehavior())
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(
|
||||
domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build();
|
||||
PollMessage.Autorenew newAutorenewPollMessage =
|
||||
newAutorenewPollMessage(existingDomain)
|
||||
.setEventTime(newExpirationTime)
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(
|
||||
domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build();
|
||||
// End the old autorenew billing event and poll message now. This may delete the poll message.
|
||||
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
existingDomain,
|
||||
existingRecurring,
|
||||
now,
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()));
|
||||
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, now, domainHistoryId);
|
||||
Domain newDomain =
|
||||
existingDomain
|
||||
.asBuilder()
|
||||
@@ -260,7 +251,8 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
if (allocationToken.isPresent()
|
||||
&& TokenType.SINGLE_USE.equals(allocationToken.get().getTokenType())) {
|
||||
entitiesToSave.add(
|
||||
allocationTokenFlowUtils.redeemToken(allocationToken.get(), domainHistory.createVKey()));
|
||||
allocationTokenFlowUtils.redeemToken(
|
||||
allocationToken.get(), domainHistory.getHistoryEntryId()));
|
||||
}
|
||||
EntityChanges entityChanges =
|
||||
flowCustomLogic.beforeSave(
|
||||
@@ -339,7 +331,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
String tld,
|
||||
Money renewCost,
|
||||
int years,
|
||||
Key<DomainHistory> domainHistoryKey,
|
||||
HistoryEntryId domainHistoryId,
|
||||
Optional<AllocationToken> allocationToken,
|
||||
DateTime now) {
|
||||
return new BillingEvent.OneTime.Builder()
|
||||
@@ -355,27 +347,27 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
.map(AllocationToken::createVKey)
|
||||
.orElse(null))
|
||||
.setBillingTime(now.plus(Registry.get(tld).getRenewGracePeriodLength()))
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build();
|
||||
}
|
||||
|
||||
private ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
|
||||
FeesAndCredits feesAndCredits, Optional<FeeRenewCommandExtension> feeRenew) {
|
||||
return feeRenew.isPresent()
|
||||
? ImmutableList.of(
|
||||
feeRenew
|
||||
.get()
|
||||
.createResponseBuilder()
|
||||
.setCurrency(feesAndCredits.getCurrency())
|
||||
.setFees(
|
||||
ImmutableList.of(
|
||||
Fee.create(
|
||||
feesAndCredits.getRenewCost().getAmount(),
|
||||
FeeType.RENEW,
|
||||
feesAndCredits.hasPremiumFeesOfType(FeeType.RENEW))))
|
||||
.build())
|
||||
: ImmutableList.of();
|
||||
return feeRenew
|
||||
.map(
|
||||
feeRenewCommandExtension ->
|
||||
ImmutableList.of(
|
||||
feeRenewCommandExtension
|
||||
.createResponseBuilder()
|
||||
.setCurrency(feesAndCredits.getCurrency())
|
||||
.setFees(
|
||||
ImmutableList.of(
|
||||
Fee.create(
|
||||
feesAndCredits.getRenewCost().getAmount(),
|
||||
FeeType.RENEW,
|
||||
feesAndCredits.hasPremiumFeesOfType(FeeType.RENEW))))
|
||||
.build()))
|
||||
.orElseGet(ImmutableList::of);
|
||||
}
|
||||
|
||||
/** The current expiration date is incorrect. */
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.createHistoryEntryId;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
@@ -34,7 +34,6 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.dns.DnsQueue;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.CommandUseErrorException;
|
||||
@@ -52,7 +51,6 @@ import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainCommand.Update;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.domain.fee.BaseFee.FeeType;
|
||||
import google.registry.model.domain.fee.Fee;
|
||||
import google.registry.model.domain.fee.FeeTransformResponseExtension;
|
||||
@@ -67,6 +65,7 @@ import google.registry.model.eppoutput.EppResponse;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.model.tld.Registry;
|
||||
import java.util.Optional;
|
||||
@@ -85,12 +84,12 @@ import org.joda.time.DateTime;
|
||||
*
|
||||
* <p>This flow is called a restore "request" because technically it is only supposed to signal that
|
||||
* the registrar requests the restore, which the registry can choose to process or not based on a
|
||||
* restore report that is submitted through an out of band process and details the request. However,
|
||||
* in practice this flow does the restore immediately. This is allowable because all of the fields
|
||||
* on a restore report are optional or have default values, and so by policy when the request comes
|
||||
* in we consider it to have been accompanied by a default-initialized report which we auto-approve.
|
||||
* restore report that is submitted through an out-of-band process and details the request. However,
|
||||
* in practice this flow does the restore immediately. This is allowable because all the fields on a
|
||||
* restore report are optional or have default values, and so by policy when the request comes in we
|
||||
* consider it to have been accompanied by a default-initialized report which we auto-approve.
|
||||
*
|
||||
* <p>Restores cost a fixed restore fee plus a one year renewal fee for the domain. The domain is
|
||||
* <p>Restores cost a fixed restore fee plus a one-year renewal fee for the domain. The domain is
|
||||
* restored to a single year expiration starting at the restore time, regardless of what the
|
||||
* original expiration time was.
|
||||
*
|
||||
@@ -147,10 +146,8 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
Optional<FeeUpdateCommandExtension> feeUpdate =
|
||||
eppInput.getSingleExtension(FeeUpdateCommandExtension.class);
|
||||
verifyRestoreAllowed(command, existingDomain, feeUpdate, feesAndCredits, now);
|
||||
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
|
||||
historyBuilder.setId(domainHistoryKey.getId());
|
||||
DomainHistoryId domainHistoryId =
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId());
|
||||
HistoryEntryId domainHistoryId = createHistoryEntryId(existingDomain);
|
||||
historyBuilder.setRevisionId(domainHistoryId.getRevisionId());
|
||||
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
||||
|
||||
DateTime newExpirationTime =
|
||||
@@ -175,9 +172,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
newAutorenewPollMessage(existingDomain)
|
||||
.setEventTime(newExpirationTime)
|
||||
.setAutorenewEndTime(END_OF_TIME)
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(
|
||||
domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build();
|
||||
Domain newDomain =
|
||||
performRestore(
|
||||
@@ -231,7 +226,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
if (!existingDomain.getGracePeriodStatuses().contains(GracePeriodStatus.REDEMPTION)) {
|
||||
throw new DomainNotEligibleForRestoreException();
|
||||
}
|
||||
validateFeeChallenge(targetId, now, feeUpdate, feesAndCredits);
|
||||
validateFeeChallenge(feeUpdate, feesAndCredits);
|
||||
}
|
||||
|
||||
private static Domain performRestore(
|
||||
@@ -259,17 +254,17 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
}
|
||||
|
||||
private OneTime createRenewBillingEvent(
|
||||
DomainHistoryId domainHistoryId, Money renewCost, DateTime now) {
|
||||
HistoryEntryId domainHistoryId, Money renewCost, DateTime now) {
|
||||
return prepareBillingEvent(domainHistoryId, renewCost, now).setReason(Reason.RENEW).build();
|
||||
}
|
||||
|
||||
private BillingEvent.OneTime createRestoreBillingEvent(
|
||||
DomainHistoryId domainHistoryId, Money restoreCost, DateTime now) {
|
||||
HistoryEntryId domainHistoryId, Money restoreCost, DateTime now) {
|
||||
return prepareBillingEvent(domainHistoryId, restoreCost, now).setReason(Reason.RESTORE).build();
|
||||
}
|
||||
|
||||
private OneTime.Builder prepareBillingEvent(
|
||||
DomainHistoryId domainHistoryId, Money cost, DateTime now) {
|
||||
HistoryEntryId domainHistoryId, Money cost, DateTime now) {
|
||||
return new BillingEvent.OneTime.Builder()
|
||||
.setTargetId(targetId)
|
||||
.setRegistrarId(registrarId)
|
||||
@@ -297,15 +292,16 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
FeeType.RENEW,
|
||||
feesAndCredits.hasPremiumFeesOfType(FeeType.RENEW)));
|
||||
}
|
||||
return feeUpdate.isPresent()
|
||||
? ImmutableList.of(
|
||||
feeUpdate
|
||||
.get()
|
||||
.createResponseBuilder()
|
||||
.setCurrency(feesAndCredits.getCurrency())
|
||||
.setFees(fees.build())
|
||||
.build())
|
||||
: ImmutableList.of();
|
||||
return feeUpdate
|
||||
.map(
|
||||
feeUpdateCommandExtension ->
|
||||
ImmutableList.of(
|
||||
feeUpdateCommandExtension
|
||||
.createResponseBuilder()
|
||||
.setCurrency(feesAndCredits.getCurrency())
|
||||
.setFees(fees.build())
|
||||
.build()))
|
||||
.orElseGet(ImmutableList::of);
|
||||
}
|
||||
|
||||
/** Restore command cannot have other changes specified. */
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.createHistoryEntryId;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.computeExDateForApprovalTime;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
@@ -36,7 +36,6 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
@@ -52,7 +51,6 @@ import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.billing.BillingEvent.Recurring;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
@@ -62,6 +60,7 @@ import google.registry.model.eppinput.EppInput;
|
||||
import google.registry.model.eppoutput.EppResponse;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
@@ -146,8 +145,8 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
// Create a transfer billing event for 1 year, unless the superuser extension was used to set
|
||||
// the transfer period to zero. There is not a transfer cost if the transfer period is zero.
|
||||
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
|
||||
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
|
||||
historyBuilder.setId(domainHistoryKey.getId());
|
||||
HistoryEntryId domainHistoryId = createHistoryEntryId(existingDomain);
|
||||
historyBuilder.setRevisionId(domainHistoryId.getRevisionId());
|
||||
Optional<BillingEvent.OneTime> billingEvent =
|
||||
transferData.getTransferPeriod().getValue() == 0
|
||||
? Optional.empty()
|
||||
@@ -167,9 +166,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
.getRenewCost())
|
||||
.setEventTime(now)
|
||||
.setBillingTime(now.plus(Registry.get(tld).getTransferGracePeriodLength()))
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(
|
||||
domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build());
|
||||
ImmutableList.Builder<ImmutableObject> entitiesToSave = new ImmutableList.Builder<>();
|
||||
// If we are within an autorenew grace period, cancel the autorenew billing event and don't
|
||||
@@ -185,20 +182,12 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
if (billingEvent.isPresent()) {
|
||||
entitiesToSave.add(
|
||||
BillingEvent.Cancellation.forGracePeriod(
|
||||
autorenewGrace,
|
||||
now,
|
||||
new DomainHistoryId(
|
||||
domainHistoryKey.getParent().getName(), domainHistoryKey.getId()),
|
||||
targetId));
|
||||
autorenewGrace, now, domainHistoryId, targetId));
|
||||
}
|
||||
}
|
||||
// Close the old autorenew event and poll message at the transfer time (aka now). This may end
|
||||
// up deleting the poll message.
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
existingDomain,
|
||||
existingRecurring,
|
||||
now,
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()));
|
||||
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, now, domainHistoryId);
|
||||
DateTime newExpirationTime =
|
||||
computeExDateForApprovalTime(existingDomain, now, transferData.getTransferPeriod());
|
||||
// Create a new autorenew event starting at the expiration time.
|
||||
@@ -212,9 +201,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
.setRenewalPriceBehavior(existingRecurring.getRenewalPriceBehavior())
|
||||
.setRenewalPrice(existingRecurring.getRenewalPrice().orElse(null))
|
||||
.setRecurrenceEndTime(END_OF_TIME)
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(
|
||||
domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build();
|
||||
// Create a new autorenew poll message.
|
||||
PollMessage.Autorenew gainingClientAutorenewPollMessage =
|
||||
@@ -224,9 +211,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
.setEventTime(newExpirationTime)
|
||||
.setAutorenewEndTime(END_OF_TIME)
|
||||
.setMsg("Domain was auto-renewed.")
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(
|
||||
domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build();
|
||||
// Construct the post-transfer domain.
|
||||
Domain partiallyApprovedDomain =
|
||||
@@ -264,7 +249,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
// Create a poll message for the gaining client.
|
||||
PollMessage gainingClientPollMessage =
|
||||
createGainingTransferPollMessage(
|
||||
targetId, newDomain.getTransferData(), newExpirationTime, now, domainHistoryKey);
|
||||
targetId, newDomain.getTransferData(), newExpirationTime, now, domainHistoryId);
|
||||
billingEvent.ifPresent(entitiesToSave::add);
|
||||
entitiesToSave.add(
|
||||
autorenewEvent,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.createHistoryEntryId;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
||||
@@ -32,7 +32,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
@@ -47,6 +46,7 @@ import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.eppoutput.EppResponse;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
@@ -83,7 +83,9 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject DomainHistory.Builder historyBuilder;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
@Inject DomainTransferCancelFlow() {}
|
||||
|
||||
@Inject
|
||||
DomainTransferCancelFlow() {}
|
||||
|
||||
@Override
|
||||
public EppResponse run() throws EppException {
|
||||
@@ -100,9 +102,9 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
|
||||
}
|
||||
Registry registry = Registry.get(existingDomain.getTld());
|
||||
|
||||
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
|
||||
HistoryEntryId domainHistoryId = createHistoryEntryId(existingDomain);
|
||||
historyBuilder
|
||||
.setId(domainHistoryKey.getId())
|
||||
.setRevisionId(domainHistoryId.getRevisionId())
|
||||
.setOtherRegistrarId(existingDomain.getTransferData().getLosingRegistrarId());
|
||||
|
||||
Domain newDomain =
|
||||
@@ -112,12 +114,12 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
|
||||
newDomain,
|
||||
domainHistory,
|
||||
createLosingTransferPollMessage(
|
||||
targetId, newDomain.getTransferData(), null, domainHistoryKey));
|
||||
targetId, newDomain.getTransferData(), null, domainHistoryId));
|
||||
// Reopen the autorenew event and poll message that we closed for the implicit transfer. This
|
||||
// may recreate the autorenew poll message if it was deleted when the transfer request was made.
|
||||
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
existingDomain, existingRecurring, END_OF_TIME, domainHistory.getDomainHistoryId());
|
||||
existingDomain, existingRecurring, END_OF_TIME, domainHistory.getHistoryEntryId());
|
||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||
// been implicitly server approved.
|
||||
tm().delete(existingDomain.getTransferData().getServerApproveEntities());
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.createHistoryEntryId;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
||||
@@ -34,7 +34,6 @@ import static google.registry.util.CollectionUtils.union;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
@@ -49,6 +48,7 @@ import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.eppoutput.EppResponse;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
@@ -95,9 +95,9 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
|
||||
DateTime now = tm().getTransactionTime();
|
||||
Domain existingDomain = loadAndVerifyExistence(Domain.class, targetId, now);
|
||||
Registry registry = Registry.get(existingDomain.getTld());
|
||||
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
|
||||
HistoryEntryId domainHistoryId = createHistoryEntryId(existingDomain);
|
||||
historyBuilder
|
||||
.setId(domainHistoryKey.getId())
|
||||
.setRevisionId(domainHistoryId.getRevisionId())
|
||||
.setOtherRegistrarId(existingDomain.getTransferData().getGainingRegistrarId());
|
||||
|
||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||
@@ -113,12 +113,12 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
|
||||
newDomain,
|
||||
domainHistory,
|
||||
createGainingTransferPollMessage(
|
||||
targetId, newDomain.getTransferData(), null, now, domainHistoryKey));
|
||||
targetId, newDomain.getTransferData(), null, now, domainHistoryId));
|
||||
// Reopen the autorenew event and poll message that we closed for the implicit transfer. This
|
||||
// may end up recreating the poll message if it was deleted upon the transfer request.
|
||||
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
existingDomain, existingRecurring, END_OF_TIME, domainHistory.getDomainHistoryId());
|
||||
existingDomain, existingRecurring, END_OF_TIME, domainHistory.getHistoryEntryId());
|
||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||
// been implicitly server approved.
|
||||
tm().delete(existingDomain.getTransferData().getServerApproveEntities());
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.createHistoryEntryId;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.computeExDateForApprovalTime;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
@@ -38,7 +38,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.batch.AsyncTaskEnqueuer;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
@@ -57,13 +56,11 @@ import google.registry.model.billing.BillingEvent.Recurring;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainCommand.Transfer;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.domain.fee.FeeTransferCommandExtension;
|
||||
import google.registry.model.domain.fee.FeeTransformResponseExtension;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.domain.superuser.DomainTransferRequestSuperuserExtension;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.domain.token.AllocationTokenExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
@@ -74,6 +71,7 @@ import google.registry.model.eppoutput.EppResponse;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
@@ -170,20 +168,19 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
extensionManager.validate();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
Domain existingDomain = loadAndVerifyExistence(Domain.class, targetId, now);
|
||||
Optional<AllocationToken> allocationToken =
|
||||
allocationTokenFlowUtils.verifyAllocationTokenIfPresent(
|
||||
existingDomain,
|
||||
Registry.get(existingDomain.getTld()),
|
||||
gainingClientId,
|
||||
now,
|
||||
eppInput.getSingleExtension(AllocationTokenExtension.class));
|
||||
allocationTokenFlowUtils.verifyAllocationTokenIfPresent(
|
||||
existingDomain,
|
||||
Registry.get(existingDomain.getTld()),
|
||||
gainingClientId,
|
||||
now,
|
||||
eppInput.getSingleExtension(AllocationTokenExtension.class));
|
||||
Optional<DomainTransferRequestSuperuserExtension> superuserExtension =
|
||||
eppInput.getSingleExtension(DomainTransferRequestSuperuserExtension.class);
|
||||
Period period =
|
||||
superuserExtension.isPresent()
|
||||
? superuserExtension.get().getRenewalPeriod()
|
||||
: ((Transfer) resourceCommand).getPeriod();
|
||||
verifyTransferAllowed(existingDomain, period, now, superuserExtension, allocationToken);
|
||||
verifyTransferAllowed(existingDomain, period, now, superuserExtension);
|
||||
|
||||
String tld = existingDomain.getTld();
|
||||
Registry registry = Registry.get(tld);
|
||||
@@ -197,17 +194,27 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
}
|
||||
// If the period is zero, then there is no fee for the transfer.
|
||||
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
|
||||
Optional<FeesAndCredits> feesAndCredits =
|
||||
(period.getValue() == 0)
|
||||
? Optional.empty()
|
||||
: Optional.of(
|
||||
pricingLogic.getTransferPrice(registry, targetId, now, existingRecurring));
|
||||
if (feesAndCredits.isPresent()) {
|
||||
validateFeeChallenge(targetId, now, feeTransfer, feesAndCredits.get());
|
||||
Optional<FeesAndCredits> feesAndCredits;
|
||||
if (period.getValue() == 0) {
|
||||
feesAndCredits = Optional.empty();
|
||||
} else if (!existingDomain.getCurrentPackageToken().isPresent()) {
|
||||
feesAndCredits =
|
||||
Optional.of(pricingLogic.getTransferPrice(registry, targetId, now, existingRecurring));
|
||||
} else {
|
||||
// If existing domain is in a package, calculate the transfer price with default renewal price
|
||||
// behavior
|
||||
feesAndCredits =
|
||||
period.getValue() == 0
|
||||
? Optional.empty()
|
||||
: Optional.of(pricingLogic.getTransferPrice(registry, targetId, now, null));
|
||||
}
|
||||
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
|
||||
|
||||
if (feesAndCredits.isPresent()) {
|
||||
validateFeeChallenge(feeTransfer, feesAndCredits.get());
|
||||
}
|
||||
HistoryEntryId domainHistoryId = createHistoryEntryId(existingDomain);
|
||||
historyBuilder
|
||||
.setId(domainHistoryKey.getId())
|
||||
.setRevisionId(domainHistoryId.getRevisionId())
|
||||
.setOtherRegistrarId(existingDomain.getCurrentSponsorRegistrarId());
|
||||
DateTime automaticTransferTime =
|
||||
superuserExtension
|
||||
@@ -232,7 +239,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
createTransferServerApproveEntities(
|
||||
automaticTransferTime,
|
||||
serverApproveNewExpirationTime,
|
||||
domainHistoryKey,
|
||||
domainHistoryId,
|
||||
existingDomain,
|
||||
existingRecurring,
|
||||
trid,
|
||||
@@ -243,7 +250,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
DomainTransferData pendingTransferData =
|
||||
createPendingTransferData(
|
||||
domainAtTransferTime.getRepoId(),
|
||||
domainHistoryKey.getId(),
|
||||
domainHistoryId.getRevisionId(),
|
||||
new DomainTransferData.Builder()
|
||||
.setTransferRequestTrid(trid)
|
||||
.setTransferRequestTime(now)
|
||||
@@ -256,7 +263,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
// Create a poll message to notify the losing registrar that a transfer was requested.
|
||||
PollMessage requestPollMessage =
|
||||
createLosingTransferPollMessage(
|
||||
targetId, pendingTransferData, serverApproveNewExpirationTime, domainHistoryKey)
|
||||
targetId, pendingTransferData, serverApproveNewExpirationTime, domainHistoryId)
|
||||
.asBuilder()
|
||||
.setEventTime(now)
|
||||
.build();
|
||||
@@ -265,10 +272,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
// cloneProjectedAtTime() will replace these old autorenew entities with the server approve ones
|
||||
// that we've created in this flow and stored in pendingTransferData.
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
existingDomain,
|
||||
existingRecurring,
|
||||
automaticTransferTime,
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()));
|
||||
existingDomain, existingRecurring, automaticTransferTime, domainHistoryId);
|
||||
Domain newDomain =
|
||||
existingDomain
|
||||
.asBuilder()
|
||||
@@ -296,8 +300,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
Domain existingDomain,
|
||||
Period period,
|
||||
DateTime now,
|
||||
Optional<DomainTransferRequestSuperuserExtension> superuserExtension,
|
||||
Optional<AllocationToken> allocationToken)
|
||||
Optional<DomainTransferRequestSuperuserExtension> superuserExtension)
|
||||
throws EppException {
|
||||
verifyNoDisallowedStatuses(existingDomain, DISALLOWED_STATUSES);
|
||||
if (!isSuperuser) {
|
||||
@@ -388,7 +391,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
|
||||
private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
|
||||
Optional<FeesAndCredits> feesAndCredits, Optional<FeeTransferCommandExtension> feeTransfer) {
|
||||
return (feeTransfer.isPresent() && feesAndCredits.isPresent())
|
||||
return feeTransfer.isPresent() && feesAndCredits.isPresent()
|
||||
? ImmutableList.of(
|
||||
feeTransfer
|
||||
.get()
|
||||
|
||||
@@ -20,20 +20,19 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Flag;
|
||||
import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.billing.BillingEvent.Recurring;
|
||||
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
@@ -109,7 +108,7 @@ public final class DomainTransferUtils {
|
||||
public static ImmutableSet<TransferServerApproveEntity> createTransferServerApproveEntities(
|
||||
DateTime automaticTransferTime,
|
||||
DateTime serverApproveNewExpirationTime,
|
||||
Key<DomainHistory> domainHistoryKey,
|
||||
HistoryEntryId domainHistoryId,
|
||||
Domain existingDomain,
|
||||
Recurring existingRecurring,
|
||||
Trid trid,
|
||||
@@ -135,38 +134,44 @@ public final class DomainTransferUtils {
|
||||
builder.add(
|
||||
createTransferBillingEvent(
|
||||
automaticTransferTime,
|
||||
domainHistoryKey,
|
||||
domainHistoryId,
|
||||
targetId,
|
||||
gainingRegistrarId,
|
||||
registry,
|
||||
cost)));
|
||||
createOptionalAutorenewCancellation(
|
||||
automaticTransferTime, now, domainHistoryKey, targetId, existingDomain, transferCost)
|
||||
automaticTransferTime, now, domainHistoryId, targetId, existingDomain, transferCost)
|
||||
.ifPresent(builder::add);
|
||||
return builder
|
||||
.add(
|
||||
createGainingClientAutorenewEvent(
|
||||
existingRecurring,
|
||||
existingDomain.getCurrentPackageToken().isPresent()
|
||||
? existingRecurring
|
||||
.asBuilder()
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.DEFAULT)
|
||||
.setRenewalPrice(null)
|
||||
.build()
|
||||
: existingRecurring,
|
||||
serverApproveNewExpirationTime,
|
||||
domainHistoryKey,
|
||||
domainHistoryId,
|
||||
targetId,
|
||||
gainingRegistrarId))
|
||||
.add(
|
||||
createGainingClientAutorenewPollMessage(
|
||||
serverApproveNewExpirationTime, domainHistoryKey, targetId, gainingRegistrarId))
|
||||
serverApproveNewExpirationTime, domainHistoryId, targetId, gainingRegistrarId))
|
||||
.add(
|
||||
createGainingTransferPollMessage(
|
||||
targetId,
|
||||
serverApproveTransferData,
|
||||
serverApproveNewExpirationTime,
|
||||
now,
|
||||
domainHistoryKey))
|
||||
domainHistoryId))
|
||||
.add(
|
||||
createLosingTransferPollMessage(
|
||||
targetId,
|
||||
serverApproveTransferData,
|
||||
serverApproveNewExpirationTime,
|
||||
domainHistoryKey))
|
||||
domainHistoryId))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -176,7 +181,7 @@ public final class DomainTransferUtils {
|
||||
TransferData transferData,
|
||||
@Nullable DateTime extendedRegistrationExpirationTime,
|
||||
DateTime now,
|
||||
Key<DomainHistory> domainHistoryKey) {
|
||||
HistoryEntryId domainHistoryId) {
|
||||
return new PollMessage.OneTime.Builder()
|
||||
.setRegistrarId(transferData.getGainingRegistrarId())
|
||||
.setEventTime(transferData.getPendingTransferExpirationTime())
|
||||
@@ -189,8 +194,7 @@ public final class DomainTransferUtils {
|
||||
transferData.getTransferStatus().isApproved(),
|
||||
transferData.getTransferRequestTrid(),
|
||||
now)))
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -199,7 +203,7 @@ public final class DomainTransferUtils {
|
||||
String targetId,
|
||||
TransferData transferData,
|
||||
@Nullable DateTime extendedRegistrationExpirationTime,
|
||||
Key<DomainHistory> domainHistoryKey) {
|
||||
HistoryEntryId domainHistoryId) {
|
||||
return new PollMessage.OneTime.Builder()
|
||||
.setRegistrarId(transferData.getLosingRegistrarId())
|
||||
.setEventTime(transferData.getPendingTransferExpirationTime())
|
||||
@@ -207,8 +211,7 @@ public final class DomainTransferUtils {
|
||||
.setResponseData(
|
||||
ImmutableList.of(
|
||||
createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime)))
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -230,7 +233,7 @@ public final class DomainTransferUtils {
|
||||
|
||||
private static PollMessage.Autorenew createGainingClientAutorenewPollMessage(
|
||||
DateTime serverApproveNewExpirationTime,
|
||||
Key<DomainHistory> domainHistoryKey,
|
||||
HistoryEntryId domainHistoryId,
|
||||
String targetId,
|
||||
String gainingRegistrarId) {
|
||||
return new PollMessage.Autorenew.Builder()
|
||||
@@ -239,15 +242,14 @@ public final class DomainTransferUtils {
|
||||
.setEventTime(serverApproveNewExpirationTime)
|
||||
.setAutorenewEndTime(END_OF_TIME)
|
||||
.setMsg("Domain was auto-renewed.")
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static BillingEvent.Recurring createGainingClientAutorenewEvent(
|
||||
Recurring existingRecurring,
|
||||
DateTime serverApproveNewExpirationTime,
|
||||
Key<DomainHistory> domainHistoryKey,
|
||||
HistoryEntryId domainHistoryId,
|
||||
String targetId,
|
||||
String gainingRegistrarId) {
|
||||
return new BillingEvent.Recurring.Builder()
|
||||
@@ -259,8 +261,7 @@ public final class DomainTransferUtils {
|
||||
.setRecurrenceEndTime(END_OF_TIME)
|
||||
.setRenewalPriceBehavior(existingRecurring.getRenewalPriceBehavior())
|
||||
.setRenewalPrice(existingRecurring.getRenewalPrice().orElse(null))
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -283,7 +284,7 @@ public final class DomainTransferUtils {
|
||||
private static Optional<BillingEvent.Cancellation> createOptionalAutorenewCancellation(
|
||||
DateTime automaticTransferTime,
|
||||
DateTime now,
|
||||
Key<DomainHistory> domainHistoryKey,
|
||||
HistoryEntryId domainHistoryId,
|
||||
String targetId,
|
||||
Domain existingDomain,
|
||||
Optional<Money> transferCost) {
|
||||
@@ -294,11 +295,7 @@ public final class DomainTransferUtils {
|
||||
if (autorenewGracePeriod != null && transferCost.isPresent()) {
|
||||
return Optional.of(
|
||||
BillingEvent.Cancellation.forGracePeriod(
|
||||
autorenewGracePeriod,
|
||||
now,
|
||||
new DomainHistoryId(
|
||||
domainHistoryKey.getParent().getName(), domainHistoryKey.getId()),
|
||||
targetId)
|
||||
autorenewGracePeriod, now, domainHistoryId, targetId)
|
||||
.asBuilder()
|
||||
.setEventTime(automaticTransferTime)
|
||||
.build());
|
||||
@@ -308,7 +305,7 @@ public final class DomainTransferUtils {
|
||||
|
||||
private static BillingEvent.OneTime createTransferBillingEvent(
|
||||
DateTime automaticTransferTime,
|
||||
Key<DomainHistory> domainHistoryKey,
|
||||
HistoryEntryId domainHistoryId,
|
||||
String targetId,
|
||||
String gainingRegistrarId,
|
||||
Registry registry,
|
||||
@@ -321,8 +318,7 @@ public final class DomainTransferUtils {
|
||||
.setPeriodYears(1)
|
||||
.setEventTime(automaticTransferTime)
|
||||
.setBillingTime(automaticTransferTime.plus(registry.getTransferGracePeriodLength()))
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
.setDomainHistoryId(domainHistoryId)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -208,12 +208,9 @@ public final class DomainUpdateFlow implements TransactionalFlow {
|
||||
|
||||
/** Determines if any of the changes to new domain should trigger DNS update. */
|
||||
private boolean requiresDnsUpdate(Domain existingDomain, Domain newDomain) {
|
||||
if (existingDomain.shouldPublishToDns() != newDomain.shouldPublishToDns()
|
||||
return existingDomain.shouldPublishToDns() != newDomain.shouldPublishToDns()
|
||||
|| !Objects.equals(newDomain.getDsData(), existingDomain.getDsData())
|
||||
|| !Objects.equals(newDomain.getNsHosts(), existingDomain.getNsHosts())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|| !Objects.equals(newDomain.getNsHosts(), existingDomain.getNsHosts());
|
||||
}
|
||||
|
||||
/** Fail if the object doesn't exist or was deleted. */
|
||||
@@ -363,7 +360,7 @@ public final class DomainUpdateFlow implements TransactionalFlow {
|
||||
.map(StatusValue::getXmlName)
|
||||
.collect(toImmutableSortedSet(Ordering.natural()));
|
||||
|
||||
String msg = "";
|
||||
String msg;
|
||||
if (addedServerStatuses.size() > 0 && removedServerStatuses.size() > 0) {
|
||||
msg =
|
||||
String.format(
|
||||
|
||||
@@ -36,7 +36,7 @@ import google.registry.model.domain.token.AllocationToken.TokenBehavior;
|
||||
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||
import google.registry.model.domain.token.AllocationToken.TokenType;
|
||||
import google.registry.model.domain.token.AllocationTokenExtension;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.List;
|
||||
@@ -95,12 +95,11 @@ public class AllocationTokenFlowUtils {
|
||||
}
|
||||
|
||||
/** Redeems a SINGLE_USE {@link AllocationToken}, returning the redeemed copy. */
|
||||
public AllocationToken redeemToken(
|
||||
AllocationToken token, VKey<? extends HistoryEntry> redemptionHistoryEntry) {
|
||||
public AllocationToken redeemToken(AllocationToken token, HistoryEntryId redemptionHistoryId) {
|
||||
checkArgument(
|
||||
TokenType.SINGLE_USE.equals(token.getTokenType()),
|
||||
"Only SINGLE_USE tokens can be marked as redeemed");
|
||||
return token.asBuilder().setRedemptionHistoryEntry(redemptionHistoryEntry).build();
|
||||
return token.asBuilder().setRedemptionHistoryId(redemptionHistoryId).build();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +109,7 @@ public class AllocationTokenFlowUtils {
|
||||
*
|
||||
* @throws EppException if the token is invalid in any way
|
||||
*/
|
||||
private void validateToken(
|
||||
private static void validateToken(
|
||||
InternetDomainName domainName, AllocationToken token, String registrarId, DateTime now)
|
||||
throws EppException {
|
||||
|
||||
@@ -138,7 +137,7 @@ public class AllocationTokenFlowUtils {
|
||||
}
|
||||
|
||||
/** Loads a given token and validates that it is not redeemed */
|
||||
private AllocationToken loadToken(String token) throws EppException {
|
||||
private static AllocationToken loadToken(String token) throws EppException {
|
||||
if (Strings.isNullOrEmpty(token)) {
|
||||
// We load the token directly from the input XML. If it's null or empty we should throw
|
||||
// an InvalidAllocationTokenException before the database load attempt fails.
|
||||
@@ -152,7 +151,7 @@ public class AllocationTokenFlowUtils {
|
||||
}
|
||||
|
||||
maybeTokenEntity =
|
||||
tm().transact(() -> tm().loadByKeyIfPresent(VKey.createSql(AllocationToken.class, token)));
|
||||
tm().transact(() -> tm().loadByKeyIfPresent(VKey.create(AllocationToken.class, token)));
|
||||
|
||||
if (!maybeTokenEntity.isPresent()) {
|
||||
throw new InvalidAllocationTokenException();
|
||||
|
||||
@@ -24,7 +24,6 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.batch.AsyncTaskEnqueuer;
|
||||
import google.registry.dns.DnsQueue;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
@@ -79,7 +78,6 @@ public final class HostDeleteFlow implements TransactionalFlow {
|
||||
@Inject Trid trid;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject HostHistory.Builder historyBuilder;
|
||||
@Inject AsyncTaskEnqueuer asyncTaskEnqueuer;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
|
||||
@Inject
|
||||
|
||||
@@ -80,14 +80,14 @@ public final class HostInfoFlow implements Flow {
|
||||
tm().transact(
|
||||
() -> tm().loadByKey(host.getSuperordinateDomain()).cloneProjectedAtTime(now));
|
||||
hostInfoDataBuilder
|
||||
.setCurrentSponsorClientId(superordinateDomain.getCurrentSponsorRegistrarId())
|
||||
.setCurrentSponsorRegistrarId(superordinateDomain.getCurrentSponsorRegistrarId())
|
||||
.setLastTransferTime(host.computeLastTransferTime(superordinateDomain));
|
||||
if (superordinateDomain.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) {
|
||||
statusValues.add(StatusValue.PENDING_TRANSFER);
|
||||
}
|
||||
} else {
|
||||
hostInfoDataBuilder
|
||||
.setCurrentSponsorClientId(host.getPersistedCurrentSponsorRegistrarId())
|
||||
.setCurrentSponsorRegistrarId(host.getPersistedCurrentSponsorRegistrarId())
|
||||
.setLastTransferTime(host.getLastTransferTime());
|
||||
}
|
||||
return responseBuilder
|
||||
@@ -97,9 +97,9 @@ public final class HostInfoFlow implements Flow {
|
||||
.setRepoId(host.getRepoId())
|
||||
.setStatusValues(statusValues.build())
|
||||
.setInetAddresses(host.getInetAddresses())
|
||||
.setCreationClientId(host.getCreationRegistrarId())
|
||||
.setCreationRegistrarId(host.getCreationRegistrarId())
|
||||
.setCreationTime(host.getCreationTime())
|
||||
.setLastEppUpdateClientId(host.getLastEppUpdateRegistrarId())
|
||||
.setLastEppUpdateRegistrarId(host.getLastEppUpdateRegistrarId())
|
||||
.setLastEppUpdateTime(host.getLastEppUpdateTime())
|
||||
.build())
|
||||
.build();
|
||||
|
||||
@@ -16,6 +16,8 @@ package google.registry.flows.host;
|
||||
|
||||
import static com.google.common.base.MoreObjects.firstNonNull;
|
||||
import static com.google.common.collect.Sets.union;
|
||||
import static google.registry.dns.RefreshDnsOnHostRenameAction.PARAM_HOST_KEY;
|
||||
import static google.registry.dns.RefreshDnsOnHostRenameAction.QUEUE_HOST_RENAME;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.checkSameValuesNotAddedAndRemoved;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
@@ -30,9 +32,12 @@ import static google.registry.model.reporting.HistoryEntry.Type.HOST_UPDATE;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||
|
||||
import com.google.cloud.tasks.v2.Task;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.batch.AsyncTaskEnqueuer;
|
||||
import google.registry.dns.DnsQueue;
|
||||
import google.registry.dns.RefreshDnsOnHostRenameAction;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ObjectAlreadyExistsException;
|
||||
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
||||
@@ -59,6 +64,8 @@ import google.registry.model.host.HostCommand.Update.Change;
|
||||
import google.registry.model.host.HostHistory;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.util.CloudTasksUtils;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
@@ -107,9 +114,8 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
* requires special checking, since you must be able to clear the status off the object with an
|
||||
* update.
|
||||
*/
|
||||
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
||||
StatusValue.PENDING_DELETE,
|
||||
StatusValue.SERVER_UPDATE_PROHIBITED);
|
||||
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES =
|
||||
ImmutableSet.of(StatusValue.PENDING_DELETE, StatusValue.SERVER_UPDATE_PROHIBITED);
|
||||
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@@ -120,7 +126,10 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
@Inject AsyncTaskEnqueuer asyncTaskEnqueuer;
|
||||
@Inject DnsQueue dnsQueue;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
@Inject HostUpdateFlow() {}
|
||||
@Inject CloudTasksUtils cloudTasksUtils;
|
||||
|
||||
@Inject
|
||||
HostUpdateFlow() {}
|
||||
|
||||
@Override
|
||||
public EppResponse run() throws EppException {
|
||||
@@ -268,7 +277,12 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
}
|
||||
// We must also enqueue updates for all domains that use this host as their nameserver so
|
||||
// that their NS records can be updated to point at the new name.
|
||||
asyncTaskEnqueuer.enqueueAsyncDnsRefresh(existingHost, tm().getTransactionTime());
|
||||
Task task =
|
||||
cloudTasksUtils.createPostTask(
|
||||
RefreshDnsOnHostRenameAction.PATH,
|
||||
Service.BACKEND.toString(),
|
||||
ImmutableMultimap.of(PARAM_HOST_KEY, existingHost.createVKey().stringify()));
|
||||
cloudTasksUtils.enqueue(QUEUE_HOST_RENAME, task);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ public final class PollAckFlow implements TransactionalFlow {
|
||||
// acked, then we return a special status code indicating that. Note that the query will
|
||||
// include the message being acked.
|
||||
|
||||
int messageCount = tm().doTransactionless(() -> getPollMessageCount(registrarId, now));
|
||||
int messageCount = tm().transact(() -> getPollMessageCount(registrarId, now));
|
||||
if (messageCount <= 0) {
|
||||
return responseBuilder.setResultFromCode(SUCCESS_WITH_NO_MESSAGES).build();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ package google.registry.groups;
|
||||
import com.google.api.services.admin.directory.Directory;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.DelegatedCredential;
|
||||
import google.registry.config.CredentialModule.AdcDelegatedCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
|
||||
@@ -27,7 +27,7 @@ public final class DirectoryModule {
|
||||
|
||||
@Provides
|
||||
static Directory provideDirectory(
|
||||
@DelegatedCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@AdcDelegatedCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("projectId") String projectId) {
|
||||
return new Directory.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
|
||||
@@ -17,7 +17,7 @@ package google.registry.groups;
|
||||
import com.google.api.services.groupssettings.Groupssettings;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.DelegatedCredential;
|
||||
import google.registry.config.CredentialModule.AdcDelegatedCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
|
||||
@@ -27,7 +27,7 @@ public final class GroupssettingsModule {
|
||||
|
||||
@Provides
|
||||
static Groupssettings provideDirectory(
|
||||
@DelegatedCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@AdcDelegatedCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("projectId") String projectId) {
|
||||
return new Groupssettings.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
|
||||
@@ -120,10 +120,4 @@ public final class KeyModule {
|
||||
static String provideSafeBrowsingAPIKey(Keyring keyring) {
|
||||
return keyring.getSafeBrowsingAPIKey();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Key("jsonCredential")
|
||||
static String provideJsonCredential(Keyring keyring) {
|
||||
return keyring.getJsonCredential();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright 2017 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.keyring.kms;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
/**
|
||||
* A value type class containing a Cloud KMS encrypted and encoded ciphertext, and the name of the
|
||||
* CryptoKeyVersion used to encrypt it.
|
||||
*/
|
||||
@AutoValue
|
||||
abstract class EncryptResponse {
|
||||
|
||||
static EncryptResponse create(
|
||||
com.google.api.services.cloudkms.v1.model.EncryptResponse cloudKmsEncryptResponse) {
|
||||
return new AutoValue_EncryptResponse(
|
||||
cloudKmsEncryptResponse.getCiphertext(), cloudKmsEncryptResponse.getName());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static EncryptResponse create(String ciphertext, String cryptoKeyVersionName) {
|
||||
return new AutoValue_EncryptResponse(ciphertext, cryptoKeyVersionName);
|
||||
}
|
||||
|
||||
abstract String ciphertext();
|
||||
|
||||
abstract String cryptoKeyVersionName();
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright 2017 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.keyring.kms;
|
||||
|
||||
import google.registry.keyring.api.KeyringException;
|
||||
|
||||
/** An abstraction to simplify Cloud KMS operations. */
|
||||
public interface KmsConnection {
|
||||
|
||||
/**
|
||||
* The maximum allowable secret size, as set by Cloud KMS.
|
||||
*
|
||||
* @see <a
|
||||
* href="https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys/encrypt#request-body">projects.locations.keyRings.cryptoKeys.encrypt</a>
|
||||
*/
|
||||
int MAX_SECRET_SIZE_BYTES = 64 * 1024;
|
||||
|
||||
/**
|
||||
* Encrypts a plaintext with CryptoKey {@code cryptoKeyName} on KeyRing {@code keyRingName}.
|
||||
*
|
||||
* <p>The latest CryptoKeyVersion is used to encrypt the value. The value must not be larger than
|
||||
* {@code MAX_SECRET_SIZE_BYTES}.
|
||||
*
|
||||
* <p>If no applicable CryptoKey or CryptoKeyVersion exist, they will be created.
|
||||
*
|
||||
* @throws KeyringException on encryption failure.
|
||||
*/
|
||||
EncryptResponse encrypt(String cryptoKeyName, byte[] plaintext);
|
||||
|
||||
/**
|
||||
* Decrypts a Cloud KMS encrypted and encoded value with CryptoKey {@code cryptoKeyName}.
|
||||
*
|
||||
* @throws KeyringException on decryption failure.
|
||||
*/
|
||||
byte[] decrypt(String cryptoKeyName, String encodedCiphertext);
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
// Copyright 2017 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.keyring.kms;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
|
||||
import com.google.api.client.http.HttpStatusCodes;
|
||||
import com.google.api.services.cloudkms.v1.CloudKMS;
|
||||
import com.google.api.services.cloudkms.v1.model.CryptoKey;
|
||||
import com.google.api.services.cloudkms.v1.model.CryptoKeyVersion;
|
||||
import com.google.api.services.cloudkms.v1.model.DecryptRequest;
|
||||
import com.google.api.services.cloudkms.v1.model.EncryptRequest;
|
||||
import com.google.api.services.cloudkms.v1.model.KeyRing;
|
||||
import com.google.api.services.cloudkms.v1.model.UpdateCryptoKeyPrimaryVersionRequest;
|
||||
import google.registry.keyring.api.KeyringException;
|
||||
import google.registry.util.Retrier;
|
||||
import java.io.IOException;
|
||||
|
||||
/** The {@link KmsConnection} which talks to Cloud KMS. */
|
||||
class KmsConnectionImpl implements KmsConnection {
|
||||
|
||||
private static final String KMS_LOCATION_FORMAT = "projects/%s/locations/global";
|
||||
private static final String KMS_KEYRING_NAME_FORMAT = "projects/%s/locations/global/keyRings/%s";
|
||||
private static final String KMS_CRYPTO_KEY_NAME_FORMAT =
|
||||
"projects/%s/locations/global/keyRings/%s/cryptoKeys/%s";
|
||||
|
||||
private final CloudKMS kms;
|
||||
private final String kmsKeyRingName;
|
||||
private final String projectId;
|
||||
private final Retrier retrier;
|
||||
|
||||
KmsConnectionImpl(String projectId, String kmsKeyRingName, Retrier retrier, CloudKMS kms) {
|
||||
this.projectId = projectId;
|
||||
this.kmsKeyRingName = kmsKeyRingName;
|
||||
this.retrier = retrier;
|
||||
this.kms = kms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EncryptResponse encrypt(String cryptoKeyName, byte[] value) {
|
||||
checkArgument(
|
||||
value.length <= MAX_SECRET_SIZE_BYTES,
|
||||
"Value to encrypt was larger than %s bytes",
|
||||
MAX_SECRET_SIZE_BYTES);
|
||||
try {
|
||||
return attemptEncrypt(cryptoKeyName, value);
|
||||
} catch (IOException e) {
|
||||
throw new KeyringException(
|
||||
String.format("CloudKMS encrypt operation failed for secret %s", cryptoKeyName), e);
|
||||
}
|
||||
}
|
||||
|
||||
private EncryptResponse attemptEncrypt(String cryptoKeyName, byte[] value) throws IOException {
|
||||
String fullKeyRingName = getKeyRingName(projectId, kmsKeyRingName);
|
||||
try {
|
||||
kms.projects().locations().keyRings().get(fullKeyRingName).execute();
|
||||
} catch (GoogleJsonResponseException jsonException) {
|
||||
if (jsonException.getStatusCode() == HttpStatusCodes.STATUS_CODE_NOT_FOUND) {
|
||||
// Create the KeyRing in the "global" namespace. Encryption keys will be accessible from all
|
||||
// GCP regions.
|
||||
kms.projects()
|
||||
.locations()
|
||||
.keyRings()
|
||||
.create(getLocationName(projectId), new KeyRing())
|
||||
.setKeyRingId(kmsKeyRingName)
|
||||
.execute();
|
||||
} else {
|
||||
throw jsonException;
|
||||
}
|
||||
}
|
||||
|
||||
String fullKeyName = getCryptoKeyName(projectId, kmsKeyRingName, cryptoKeyName);
|
||||
|
||||
boolean newCryptoKey = false;
|
||||
try {
|
||||
kms.projects().locations().keyRings().cryptoKeys().get(fullKeyName).execute();
|
||||
} catch (GoogleJsonResponseException jsonException) {
|
||||
if (jsonException.getStatusCode() == HttpStatusCodes.STATUS_CODE_NOT_FOUND) {
|
||||
newCryptoKey = true;
|
||||
kms.projects()
|
||||
.locations()
|
||||
.keyRings()
|
||||
.cryptoKeys()
|
||||
.create(fullKeyRingName, new CryptoKey().setPurpose("ENCRYPT_DECRYPT"))
|
||||
.setCryptoKeyId(cryptoKeyName)
|
||||
.execute();
|
||||
} else {
|
||||
throw jsonException;
|
||||
}
|
||||
}
|
||||
|
||||
// New CryptoKeys start with a CryptoKeyVersion, so we only create a new CryptoKeyVersion and
|
||||
// rotate to it if we're dealing with an existing CryptoKey.
|
||||
if (!newCryptoKey) {
|
||||
CryptoKeyVersion cryptoKeyVersion =
|
||||
kms.projects()
|
||||
.locations()
|
||||
.keyRings()
|
||||
.cryptoKeys()
|
||||
.cryptoKeyVersions()
|
||||
.create(fullKeyName, new CryptoKeyVersion())
|
||||
.execute();
|
||||
|
||||
kms.projects()
|
||||
.locations()
|
||||
.keyRings()
|
||||
.cryptoKeys()
|
||||
.updatePrimaryVersion(
|
||||
fullKeyName,
|
||||
new UpdateCryptoKeyPrimaryVersionRequest()
|
||||
.setCryptoKeyVersionId(getCryptoKeyVersionId(cryptoKeyVersion)))
|
||||
.execute();
|
||||
}
|
||||
|
||||
return EncryptResponse.create(
|
||||
kms.projects()
|
||||
.locations()
|
||||
.keyRings()
|
||||
.cryptoKeys()
|
||||
.encrypt(fullKeyName, new EncryptRequest().encodePlaintext(value))
|
||||
.execute());
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] decrypt(final String cryptoKeyName, final String encodedCiphertext) {
|
||||
try {
|
||||
return retrier.callWithRetry(
|
||||
() -> attemptDecrypt(cryptoKeyName, encodedCiphertext), IOException.class);
|
||||
} catch (RuntimeException e) {
|
||||
throw new KeyringException(
|
||||
String.format("CloudKMS decrypt operation failed for secret %s", cryptoKeyName), e);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] attemptDecrypt(String cryptoKeyName, String encodedCiphertext) throws IOException {
|
||||
return kms.projects()
|
||||
.locations()
|
||||
.keyRings()
|
||||
.cryptoKeys()
|
||||
.decrypt(
|
||||
getCryptoKeyName(projectId, kmsKeyRingName, cryptoKeyName),
|
||||
new DecryptRequest().setCiphertext(encodedCiphertext))
|
||||
.execute()
|
||||
.decodePlaintext();
|
||||
}
|
||||
|
||||
private static String getLocationName(String projectId) {
|
||||
return String.format(KMS_LOCATION_FORMAT, projectId);
|
||||
}
|
||||
|
||||
private static String getKeyRingName(String projectId, String kmsKeyRingName) {
|
||||
return String.format(KMS_KEYRING_NAME_FORMAT, projectId, kmsKeyRingName);
|
||||
}
|
||||
|
||||
private static String getCryptoKeyName(
|
||||
String projectId, String kmsKeyRingName, String cryptoKeyName) {
|
||||
return String.format(KMS_CRYPTO_KEY_NAME_FORMAT, projectId, kmsKeyRingName, cryptoKeyName);
|
||||
}
|
||||
|
||||
private static String getCryptoKeyVersionId(CryptoKeyVersion cryptoKeyVersion) {
|
||||
String cryptoKeyVersionName = cryptoKeyVersion.getName();
|
||||
return cryptoKeyVersionName.substring(cryptoKeyVersionName.lastIndexOf('/') + 1);
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
// Copyright 2017 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.keyring.kms;
|
||||
|
||||
import com.google.api.services.cloudkms.v1.CloudKMS;
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import dagger.multibindings.IntoMap;
|
||||
import dagger.multibindings.StringKey;
|
||||
import google.registry.config.CredentialModule.DefaultCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.keyring.api.Keyring;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import google.registry.util.Retrier;
|
||||
|
||||
/** Dagger module for Cloud KMS. */
|
||||
@Module
|
||||
public abstract class KmsModule {
|
||||
|
||||
public static final String NAME = "KMS";
|
||||
|
||||
@Provides
|
||||
@Config("defaultKms")
|
||||
static CloudKMS provideKms(
|
||||
@DefaultCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("cloudKmsProjectId") String projectId) {
|
||||
return createKms(credentialsBundle, projectId);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("beamKms")
|
||||
static CloudKMS provideBeamKms(
|
||||
@DefaultCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("beamCloudKmsProjectId") String projectId) {
|
||||
return createKms(credentialsBundle, projectId);
|
||||
}
|
||||
|
||||
private static CloudKMS createKms(GoogleCredentialsBundle credentialsBundle, String projectId) {
|
||||
return new CloudKMS.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("defaultKmsConnection")
|
||||
static KmsConnection provideKmsConnection(
|
||||
@Config("cloudKmsProjectId") String projectId,
|
||||
@Config("cloudKmsKeyRing") String keyringName,
|
||||
Retrier retrier,
|
||||
@Config("defaultKms") CloudKMS defaultKms) {
|
||||
return new KmsConnectionImpl(projectId, keyringName, retrier, defaultKms);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("beamKmsConnection")
|
||||
static KmsConnection provideBeamKmsConnection(
|
||||
@Config("beamCloudKmsProjectId") String projectId,
|
||||
@Config("beamCloudKmsKeyRing") String keyringName,
|
||||
Retrier retrier,
|
||||
@Config("beamKms") CloudKMS defaultKms) {
|
||||
return new KmsConnectionImpl(projectId, keyringName, retrier, defaultKms);
|
||||
}
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@StringKey(NAME)
|
||||
abstract Keyring provideKeyring(KmsKeyring keyring);
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.keyring.kms;
|
||||
package google.registry.keyring.secretmanager;
|
||||
|
||||
import static com.google.common.base.CaseFormat.LOWER_HYPHEN;
|
||||
import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
|
||||
@@ -29,8 +29,7 @@ import org.bouncycastle.openpgp.PGPPrivateKey;
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
|
||||
/** A {@link Keyring} implementation which stores sensitive data in the Secret Manager. */
|
||||
// TODO(2021-08-01): rename this class to SecretManagerKeyring and update config files.
|
||||
public class KmsKeyring implements Keyring {
|
||||
public class SecretManagerKeyring implements Keyring {
|
||||
|
||||
/** Key labels for private key secrets. */
|
||||
enum PrivateKeyLabel {
|
||||
@@ -75,7 +74,7 @@ public class KmsKeyring implements Keyring {
|
||||
private final KeyringSecretStore secretStore;
|
||||
|
||||
@Inject
|
||||
KmsKeyring(KeyringSecretStore secretStore) {
|
||||
SecretManagerKeyring(KeyringSecretStore secretStore) {
|
||||
this.secretStore = secretStore;
|
||||
}
|
||||
|
||||
@@ -144,6 +143,7 @@ public class KmsKeyring implements Keyring {
|
||||
return getString(StringKeyLabel.MARKSDB_SMDRL_LOGIN_STRING);
|
||||
}
|
||||
|
||||
// TODO(b/237305940): remove this method and all supports, including entry in secretmanager
|
||||
@Override
|
||||
public String getJsonCredential() {
|
||||
return getString(StringKeyLabel.JSON_CREDENTIAL_STRING);
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2017 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.keyring.secretmanager;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.multibindings.IntoMap;
|
||||
import dagger.multibindings.StringKey;
|
||||
import google.registry.keyring.api.Keyring;
|
||||
|
||||
/** Dagger module for {@link Keyring} backed by the Cloud SecretManager. */
|
||||
@Module
|
||||
public abstract class SecretManagerKeyringModule {
|
||||
|
||||
public static final String NAME = "CSM";
|
||||
// TODO(b/257276342): Remove after configs in nomulus-internal are updated.
|
||||
public static final String DEPRECATED_NAME = "KMS";
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@StringKey(DEPRECATED_NAME)
|
||||
abstract Keyring provideDeprecatedKeyring(SecretManagerKeyring keyring);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@StringKey(NAME)
|
||||
abstract Keyring provideKeyring(SecretManagerKeyring keyring);
|
||||
}
|
||||
@@ -12,33 +12,33 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.keyring.kms;
|
||||
package google.registry.keyring.secretmanager;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.keyring.kms.KmsKeyring.PrivateKeyLabel.BRDA_SIGNING_PRIVATE;
|
||||
import static google.registry.keyring.kms.KmsKeyring.PrivateKeyLabel.RDE_SIGNING_PRIVATE;
|
||||
import static google.registry.keyring.kms.KmsKeyring.PrivateKeyLabel.RDE_STAGING_PRIVATE;
|
||||
import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.BRDA_RECEIVER_PUBLIC;
|
||||
import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.BRDA_SIGNING_PUBLIC;
|
||||
import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.RDE_RECEIVER_PUBLIC;
|
||||
import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.RDE_SIGNING_PUBLIC;
|
||||
import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.RDE_STAGING_PUBLIC;
|
||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.ICANN_REPORTING_PASSWORD_STRING;
|
||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.JSON_CREDENTIAL_STRING;
|
||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.MARKSDB_DNL_LOGIN_STRING;
|
||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.MARKSDB_LORDN_PASSWORD_STRING;
|
||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.MARKSDB_SMDRL_LOGIN_STRING;
|
||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.RDE_SSH_CLIENT_PRIVATE_STRING;
|
||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.RDE_SSH_CLIENT_PUBLIC_STRING;
|
||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.SAFE_BROWSING_API_KEY;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PrivateKeyLabel.BRDA_SIGNING_PRIVATE;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PrivateKeyLabel.RDE_SIGNING_PRIVATE;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PrivateKeyLabel.RDE_STAGING_PRIVATE;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.BRDA_RECEIVER_PUBLIC;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.BRDA_SIGNING_PUBLIC;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.RDE_RECEIVER_PUBLIC;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.RDE_SIGNING_PUBLIC;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel.RDE_STAGING_PUBLIC;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.ICANN_REPORTING_PASSWORD_STRING;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.JSON_CREDENTIAL_STRING;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.MARKSDB_DNL_LOGIN_STRING;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.MARKSDB_LORDN_PASSWORD_STRING;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.MARKSDB_SMDRL_LOGIN_STRING;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.RDE_SSH_CLIENT_PRIVATE_STRING;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.RDE_SSH_CLIENT_PUBLIC_STRING;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.SAFE_BROWSING_API_KEY;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.keyring.api.KeySerializer;
|
||||
import google.registry.keyring.kms.KmsKeyring.PrivateKeyLabel;
|
||||
import google.registry.keyring.kms.KmsKeyring.PublicKeyLabel;
|
||||
import google.registry.keyring.kms.KmsKeyring.StringKeyLabel;
|
||||
import google.registry.keyring.secretmanager.SecretManagerKeyring.PrivateKeyLabel;
|
||||
import google.registry.keyring.secretmanager.SecretManagerKeyring.PublicKeyLabel;
|
||||
import google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel;
|
||||
import google.registry.privileges.secretmanager.KeyringSecretStore;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
@@ -50,73 +50,77 @@ import org.bouncycastle.openpgp.PGPKeyPair;
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
|
||||
/**
|
||||
* The {@link KmsUpdater} accumulates updates to a {@link KmsKeyring} and persists them to KMS and
|
||||
* Datastore when closed.
|
||||
* The {@link SecretManagerKeyringUpdater} accumulates updates to a {@link SecretManagerKeyring} and
|
||||
* persists them to KMS and Datastore when closed.
|
||||
*/
|
||||
// TODO(2021-06-01): rename this class to SecretManagerKeyringUpdater
|
||||
public final class KmsUpdater {
|
||||
public final class SecretManagerKeyringUpdater {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private final KeyringSecretStore secretStore;
|
||||
private final HashMap<String, byte[]> secretValues;
|
||||
|
||||
@Inject
|
||||
public KmsUpdater(KeyringSecretStore secretStore) {
|
||||
public SecretManagerKeyringUpdater(KeyringSecretStore secretStore) {
|
||||
this.secretStore = secretStore;
|
||||
|
||||
// Use LinkedHashMap to preserve insertion order on update() to simplify testing and debugging
|
||||
this.secretValues = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public KmsUpdater setRdeSigningKey(PGPKeyPair keyPair) throws IOException, PGPException {
|
||||
public SecretManagerKeyringUpdater setRdeSigningKey(PGPKeyPair keyPair)
|
||||
throws IOException, PGPException {
|
||||
return setKeyPair(keyPair, RDE_SIGNING_PRIVATE, RDE_SIGNING_PUBLIC);
|
||||
}
|
||||
|
||||
public KmsUpdater setRdeStagingKey(PGPKeyPair keyPair) throws IOException, PGPException {
|
||||
public SecretManagerKeyringUpdater setRdeStagingKey(PGPKeyPair keyPair)
|
||||
throws IOException, PGPException {
|
||||
return setKeyPair(keyPair, RDE_STAGING_PRIVATE, RDE_STAGING_PUBLIC);
|
||||
}
|
||||
|
||||
public KmsUpdater setRdeReceiverPublicKey(PGPPublicKey publicKey) throws IOException {
|
||||
public SecretManagerKeyringUpdater setRdeReceiverPublicKey(PGPPublicKey publicKey)
|
||||
throws IOException {
|
||||
return setPublicKey(publicKey, RDE_RECEIVER_PUBLIC);
|
||||
}
|
||||
|
||||
public KmsUpdater setBrdaSigningKey(PGPKeyPair keyPair) throws IOException, PGPException {
|
||||
public SecretManagerKeyringUpdater setBrdaSigningKey(PGPKeyPair keyPair)
|
||||
throws IOException, PGPException {
|
||||
return setKeyPair(keyPair, BRDA_SIGNING_PRIVATE, BRDA_SIGNING_PUBLIC);
|
||||
}
|
||||
|
||||
public KmsUpdater setBrdaReceiverPublicKey(PGPPublicKey publicKey) throws IOException {
|
||||
public SecretManagerKeyringUpdater setBrdaReceiverPublicKey(PGPPublicKey publicKey)
|
||||
throws IOException {
|
||||
return setPublicKey(publicKey, BRDA_RECEIVER_PUBLIC);
|
||||
}
|
||||
|
||||
public KmsUpdater setRdeSshClientPublicKey(String asciiPublicKey) {
|
||||
public SecretManagerKeyringUpdater setRdeSshClientPublicKey(String asciiPublicKey) {
|
||||
return setString(asciiPublicKey, RDE_SSH_CLIENT_PUBLIC_STRING);
|
||||
}
|
||||
|
||||
public KmsUpdater setRdeSshClientPrivateKey(String asciiPrivateKey) {
|
||||
public SecretManagerKeyringUpdater setRdeSshClientPrivateKey(String asciiPrivateKey) {
|
||||
return setString(asciiPrivateKey, RDE_SSH_CLIENT_PRIVATE_STRING);
|
||||
}
|
||||
|
||||
public KmsUpdater setSafeBrowsingAPIKey(String apiKey) {
|
||||
public SecretManagerKeyringUpdater setSafeBrowsingAPIKey(String apiKey) {
|
||||
return setString(apiKey, SAFE_BROWSING_API_KEY);
|
||||
}
|
||||
|
||||
public KmsUpdater setIcannReportingPassword(String password) {
|
||||
public SecretManagerKeyringUpdater setIcannReportingPassword(String password) {
|
||||
return setString(password, ICANN_REPORTING_PASSWORD_STRING);
|
||||
}
|
||||
|
||||
public KmsUpdater setMarksdbDnlLoginAndPassword(String login) {
|
||||
public SecretManagerKeyringUpdater setMarksdbDnlLoginAndPassword(String login) {
|
||||
return setString(login, MARKSDB_DNL_LOGIN_STRING);
|
||||
}
|
||||
|
||||
public KmsUpdater setMarksdbLordnPassword(String password) {
|
||||
public SecretManagerKeyringUpdater setMarksdbLordnPassword(String password) {
|
||||
return setString(password, MARKSDB_LORDN_PASSWORD_STRING);
|
||||
}
|
||||
|
||||
public KmsUpdater setMarksdbSmdrlLoginAndPassword(String login) {
|
||||
public SecretManagerKeyringUpdater setMarksdbSmdrlLoginAndPassword(String login) {
|
||||
return setString(login, MARKSDB_SMDRL_LOGIN_STRING);
|
||||
}
|
||||
|
||||
public KmsUpdater setJsonCredential(String credential) {
|
||||
public SecretManagerKeyringUpdater setJsonCredential(String credential) {
|
||||
return setString(credential, JSON_CREDENTIAL_STRING);
|
||||
}
|
||||
|
||||
@@ -144,22 +148,22 @@ public final class KmsUpdater {
|
||||
}
|
||||
}
|
||||
|
||||
private KmsUpdater setString(String key, StringKeyLabel stringKeyLabel) {
|
||||
private SecretManagerKeyringUpdater setString(String key, StringKeyLabel stringKeyLabel) {
|
||||
checkArgumentNotNull(key);
|
||||
|
||||
setSecret(stringKeyLabel.getLabel(), KeySerializer.serializeString(key));
|
||||
return this;
|
||||
}
|
||||
|
||||
private KmsUpdater setPublicKey(PGPPublicKey publicKey, PublicKeyLabel publicKeyLabel)
|
||||
throws IOException {
|
||||
private SecretManagerKeyringUpdater setPublicKey(
|
||||
PGPPublicKey publicKey, PublicKeyLabel publicKeyLabel) throws IOException {
|
||||
checkArgumentNotNull(publicKey);
|
||||
|
||||
setSecret(publicKeyLabel.getLabel(), KeySerializer.serializePublicKey(publicKey));
|
||||
return this;
|
||||
}
|
||||
|
||||
private KmsUpdater setKeyPair(
|
||||
private SecretManagerKeyringUpdater setKeyPair(
|
||||
PGPKeyPair keyPair, PrivateKeyLabel privateKeyLabel, PublicKeyLabel publicKeyLabel)
|
||||
throws IOException, PGPException {
|
||||
checkArgumentNotNull(keyPair);
|
||||
@@ -19,8 +19,7 @@ import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.model.IdService.allocateId;
|
||||
import static google.registry.model.ModelUtils.getAllFields;
|
||||
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.annotations.OfyIdAllocation;
|
||||
import google.registry.model.annotations.IdAllocation;
|
||||
import google.registry.util.TypeUtils.TypeInstantiator;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Optional;
|
||||
@@ -56,14 +55,10 @@ public interface Buildable {
|
||||
/** Build the instance. */
|
||||
public S build() {
|
||||
try {
|
||||
// If this object has a Long or long Objectify @Id field that is not set, set it now. For
|
||||
// any entity it has one and only one @Id field in its class hierarchy.
|
||||
// If this object has a Long or long @IdAllocation field that is not set, set it now.
|
||||
Field idField =
|
||||
getAllFields(instance.getClass()).values().stream()
|
||||
.filter(
|
||||
field ->
|
||||
field.isAnnotationPresent(Id.class)
|
||||
|| field.isAnnotationPresent(OfyIdAllocation.class))
|
||||
.filter(field -> field.isAnnotationPresent(IdAllocation.class))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (idField != null
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
// Copyright 2017 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.model;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.common.GaeUserIdConverter;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.host.HostHistory;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
|
||||
/** Sets of classes of the Objectify-registered entities in use throughout the model. */
|
||||
@DeleteAfterMigration
|
||||
public final class EntityClasses {
|
||||
|
||||
/** Set of entity classes. */
|
||||
public static final ImmutableSet<Class<? extends ImmutableObject>> ALL_CLASSES =
|
||||
ImmutableSet.of(
|
||||
Contact.class,
|
||||
ContactHistory.class,
|
||||
Domain.class,
|
||||
DomainHistory.class,
|
||||
GaeUserIdConverter.class,
|
||||
HistoryEntry.class,
|
||||
Host.class,
|
||||
HostHistory.class);
|
||||
|
||||
private EntityClasses() {}
|
||||
}
|
||||
@@ -31,11 +31,9 @@ import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.model.CacheUtils.AppEngineEnvironmentCacheLoader;
|
||||
import google.registry.model.annotations.IdAllocation;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import google.registry.persistence.VKey;
|
||||
@@ -47,7 +45,6 @@ import java.util.Set;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Transient;
|
||||
@@ -55,8 +52,8 @@ import org.joda.time.DateTime;
|
||||
|
||||
/** An EPP entity object (i.e. a domain, contact, or host). */
|
||||
@MappedSuperclass
|
||||
@Access(AccessType.FIELD) // otherwise it'll use the default if the repoId (property)
|
||||
public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
@Access(AccessType.FIELD) // otherwise it'll use the default of the repoId (property)
|
||||
public abstract class EppResource extends UpdateAutoTimestampEntity implements Buildable {
|
||||
|
||||
private static final long serialVersionUID = -252782773382339534L;
|
||||
|
||||
@@ -70,7 +67,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc5730">RFC 5730</a>
|
||||
*/
|
||||
@Id @Transient String repoId;
|
||||
@IdAllocation @Transient String repoId;
|
||||
|
||||
/**
|
||||
* The ID of the registrar that is currently sponsoring this resource.
|
||||
@@ -78,9 +75,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
* <p>This can be null in the case of pre-Registry-3.0-migration history objects with null
|
||||
* resource fields.
|
||||
*/
|
||||
@Index
|
||||
@Column(name = "currentSponsorRegistrarId")
|
||||
String currentSponsorClientId;
|
||||
String currentSponsorRegistrarId;
|
||||
|
||||
/**
|
||||
* The ID of the registrar that created this resource.
|
||||
@@ -88,8 +83,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
* <p>This can be null in the case of pre-Registry-3.0-migration history objects with null
|
||||
* resource fields.
|
||||
*/
|
||||
@Column(name = "creationRegistrarId")
|
||||
String creationClientId;
|
||||
String creationRegistrarId;
|
||||
|
||||
/**
|
||||
* The ID of the registrar that last updated this resource.
|
||||
@@ -98,8 +92,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
* edits; it only includes EPP-visible modifications such as {@literal <update>}. Can be null if
|
||||
* the resource has never been modified.
|
||||
*/
|
||||
@Column(name = "lastEppUpdateRegistrarId")
|
||||
String lastEppUpdateClientId;
|
||||
String lastEppUpdateRegistrarId;
|
||||
|
||||
/**
|
||||
* The time when this resource was created.
|
||||
@@ -111,8 +104,8 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
* <p>This can be null in the case of pre-Registry-3.0-migration history objects with null
|
||||
* resource fields.
|
||||
*/
|
||||
@AttributeOverrides(@AttributeOverride(name = "creationTime", column = @Column))
|
||||
@Ignore
|
||||
// Need to override the default non-null column attribute.
|
||||
@AttributeOverride(name = "creationTime", column = @Column)
|
||||
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
|
||||
/**
|
||||
@@ -128,7 +121,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
* out of the index at that time, as long as we query for resources whose deletion time is before
|
||||
* now.
|
||||
*/
|
||||
@Index DateTime deletionTime;
|
||||
DateTime deletionTime;
|
||||
|
||||
/**
|
||||
* The time that this resource was last updated.
|
||||
@@ -140,7 +133,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
DateTime lastEppUpdateTime;
|
||||
|
||||
/** Status values associated with this resource. */
|
||||
@Ignore Set<StatusValue> statuses;
|
||||
Set<StatusValue> statuses;
|
||||
|
||||
public String getRepoId() {
|
||||
return repoId;
|
||||
@@ -164,7 +157,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
}
|
||||
|
||||
public String getCreationRegistrarId() {
|
||||
return creationClientId;
|
||||
return creationRegistrarId;
|
||||
}
|
||||
|
||||
public DateTime getLastEppUpdateTime() {
|
||||
@@ -172,17 +165,17 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
}
|
||||
|
||||
public String getLastEppUpdateRegistrarId() {
|
||||
return lastEppUpdateClientId;
|
||||
return lastEppUpdateRegistrarId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stored value of {@link #currentSponsorClientId}.
|
||||
* Get the stored value of {@link #currentSponsorRegistrarId}.
|
||||
*
|
||||
* <p>For subordinate hosts, this value may not represent the actual current client id, which is
|
||||
* the client id of the superordinate host. For all other resources this is the true client id.
|
||||
*/
|
||||
public final String getPersistedCurrentSponsorRegistrarId() {
|
||||
return currentSponsorClientId;
|
||||
return currentSponsorRegistrarId;
|
||||
}
|
||||
|
||||
public final ImmutableSet<StatusValue> getStatusValues() {
|
||||
@@ -272,13 +265,13 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
|
||||
/** Set the current sponsoring registrar. */
|
||||
public B setPersistedCurrentSponsorRegistrarId(String currentSponsorRegistrarId) {
|
||||
getInstance().currentSponsorClientId = currentSponsorRegistrarId;
|
||||
getInstance().currentSponsorRegistrarId = currentSponsorRegistrarId;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
/** Set the registrar that created this resource. */
|
||||
public B setCreationRegistrarId(String creationRegistrarId) {
|
||||
getInstance().creationClientId = creationRegistrarId;
|
||||
getInstance().creationRegistrarId = creationRegistrarId;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
@@ -290,7 +283,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
|
||||
/** Set the registrar who last performed a {@literal <update>} on this resource. */
|
||||
public B setLastEppUpdateRegistrarId(String lastEppUpdateRegistrarId) {
|
||||
getInstance().lastEppUpdateClientId = lastEppUpdateRegistrarId;
|
||||
getInstance().lastEppUpdateRegistrarId = lastEppUpdateRegistrarId;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
@@ -320,14 +313,14 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
|
||||
/** Add to this resource's status values. */
|
||||
public B addStatusValues(ImmutableSet<StatusValue> statusValues) {
|
||||
return setStatusValues(ImmutableSet.copyOf(
|
||||
union(getInstance().getStatusValues(), statusValues)));
|
||||
return setStatusValues(
|
||||
ImmutableSet.copyOf(union(getInstance().getStatusValues(), statusValues)));
|
||||
}
|
||||
|
||||
/** Remove from this resource's status values. */
|
||||
public B removeStatusValues(ImmutableSet<StatusValue> statusValues) {
|
||||
return setStatusValues(ImmutableSet.copyOf(
|
||||
difference(getInstance().getStatusValues(), statusValues)));
|
||||
return setStatusValues(
|
||||
ImmutableSet.copyOf(difference(getInstance().getStatusValues(), statusValues)));
|
||||
}
|
||||
|
||||
/** Set this resource's repoId. */
|
||||
@@ -339,7 +332,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
/**
|
||||
* Set the update timestamp.
|
||||
*
|
||||
* <p>This is provided at EppResource since BackupGroupRoot doesn't have a Builder.
|
||||
* <p>This is provided at EppResource since UpdateAutoTimestampEntity doesn't have a Builder.
|
||||
*/
|
||||
public B setUpdateTimestamp(UpdateAutoTimestamp updateTimestamp) {
|
||||
getInstance().setUpdateTimestamp(updateTimestamp);
|
||||
@@ -365,13 +358,13 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
|
||||
@Override
|
||||
public EppResource load(VKey<? extends EppResource> key) {
|
||||
return replicaTm().doTransactionless(() -> replicaTm().loadByKey(key));
|
||||
return replicaTm().transact(() -> replicaTm().loadByKey(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<VKey<? extends EppResource>, EppResource> loadAll(
|
||||
Iterable<? extends VKey<? extends EppResource>> keys) {
|
||||
return replicaTm().doTransactionless(() -> replicaTm().loadByKeys(keys));
|
||||
return replicaTm().transact(() -> replicaTm().loadByKeys(keys));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ package google.registry.model;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
@@ -27,7 +26,6 @@ import static google.registry.util.DateTimeUtils.latestOf;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.model.EppResource.BuilderWithTransferData;
|
||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||
@@ -67,7 +65,7 @@ public final class EppResourceUtils {
|
||||
+ "AND deletionTime > :now";
|
||||
|
||||
// We have to use the native SQL query here because DomainHost table doesn't have its entity
|
||||
// class so we cannot reference its property like domainHost.hostRepoId in a JPQL query.
|
||||
// class, so we cannot reference its property like domainHost.hostRepoId in a JPQL query.
|
||||
private static final String HOST_LINKED_DOMAIN_QUERY =
|
||||
"SELECT d.repo_id FROM \"Domain\" d "
|
||||
+ "JOIN \"DomainHost\" dh ON dh.domain_repo_id = d.repo_id "
|
||||
@@ -260,7 +258,7 @@ public final class EppResourceUtils {
|
||||
/**
|
||||
* Rewinds an {@link EppResource} object to a given point in time.
|
||||
*
|
||||
* <p>This method costs nothing if {@code resource} is already current. Otherwise it needs to
|
||||
* <p>This method costs nothing if {@code resource} is already current. Otherwise, it needs to
|
||||
* perform a single fetch operation.
|
||||
*
|
||||
* <p><b>Warning:</b> A resource can only be rolled backwards in time, not forwards; therefore
|
||||
@@ -292,7 +290,7 @@ public final class EppResourceUtils {
|
||||
/**
|
||||
* Rewinds an {@link EppResource} object to a given point in time.
|
||||
*
|
||||
* <p>This method costs nothing if {@code resource} is already current. Otherwise it returns an
|
||||
* <p>This method costs nothing if {@code resource} is already current. Otherwise, it returns an
|
||||
* async operation that performs a single fetch operation.
|
||||
*
|
||||
* @return an asynchronous operation returning resource at {@code timestamp} or {@code null} if
|
||||
@@ -346,50 +344,35 @@ public final class EppResourceUtils {
|
||||
"key must be either VKey<Contact> or VKey<Host>, but it is %s",
|
||||
key);
|
||||
boolean isContactKey = key.getKind().equals(Contact.class);
|
||||
if (tm().isOfy()) {
|
||||
com.googlecode.objectify.cmd.Query<Domain> query =
|
||||
auditedOfy()
|
||||
.load()
|
||||
.type(Domain.class)
|
||||
.filter(isContactKey ? "allContacts.contact" : "nsHosts", key.getOfyKey())
|
||||
.filter("deletionTime >", now);
|
||||
if (limit != null) {
|
||||
query.limit(limit);
|
||||
}
|
||||
return query.keys().list().stream().map(Domain::createVKey).collect(toImmutableSet());
|
||||
} else {
|
||||
return tm().transact(
|
||||
() -> {
|
||||
Query query;
|
||||
if (isContactKey) {
|
||||
query =
|
||||
jpaTm()
|
||||
.query(CONTACT_LINKED_DOMAIN_QUERY, String.class)
|
||||
.setParameter("fkRepoId", key)
|
||||
.setParameter("now", now);
|
||||
} else {
|
||||
query =
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(HOST_LINKED_DOMAIN_QUERY)
|
||||
.setParameter("fkRepoId", key.getSqlKey())
|
||||
.setParameter("now", now.toDate());
|
||||
}
|
||||
if (limit != null) {
|
||||
query.setMaxResults(limit);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
ImmutableSet<VKey<Domain>> domainKeySet =
|
||||
(ImmutableSet<VKey<Domain>>)
|
||||
query
|
||||
.getResultStream()
|
||||
.map(
|
||||
repoId ->
|
||||
Domain.createVKey(Key.create(Domain.class, (String) repoId)))
|
||||
.collect(toImmutableSet());
|
||||
return domainKeySet;
|
||||
});
|
||||
}
|
||||
return tm().transact(
|
||||
() -> {
|
||||
Query query;
|
||||
if (isContactKey) {
|
||||
query =
|
||||
jpaTm()
|
||||
.query(CONTACT_LINKED_DOMAIN_QUERY, String.class)
|
||||
.setParameter("fkRepoId", key)
|
||||
.setParameter("now", now);
|
||||
} else {
|
||||
query =
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(HOST_LINKED_DOMAIN_QUERY)
|
||||
.setParameter("fkRepoId", key.getKey())
|
||||
.setParameter("now", now.toDate());
|
||||
}
|
||||
if (limit != null) {
|
||||
query.setMaxResults(limit);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
ImmutableSet<VKey<Domain>> domainKeySet =
|
||||
(ImmutableSet<VKey<Domain>>)
|
||||
query
|
||||
.getResultStream()
|
||||
.map(repoId -> Domain.createVKey((String) repoId))
|
||||
.collect(toImmutableSet());
|
||||
return domainKeySet;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -89,7 +89,7 @@ public final class ForeignKeyUtils {
|
||||
Class<E> clazz, Collection<String> foreignKeys, final DateTime now) {
|
||||
return load(clazz, foreignKeys, false).entrySet().stream()
|
||||
.filter(e -> now.isBefore(e.getValue().deletionTime()))
|
||||
.collect(toImmutableMap(Entry::getKey, e -> VKey.createSql(clazz, e.getValue().repoId())));
|
||||
.collect(toImmutableMap(Entry::getKey, e -> VKey.create(clazz, e.getValue().repoId())));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,16 +146,14 @@ public final class ForeignKeyUtils {
|
||||
// called, it is always passed with a list of VKeys with the same type.
|
||||
Class<? extends EppResource> clazz = keys.iterator().next().getKind();
|
||||
ImmutableList<String> foreignKeys =
|
||||
Streams.stream(keys)
|
||||
.map(key -> (String) key.getSqlKey())
|
||||
.collect(toImmutableList());
|
||||
Streams.stream(keys).map(key -> (String) key.getKey()).collect(toImmutableList());
|
||||
ImmutableMap<String, MostRecentResource> existingKeys =
|
||||
ForeignKeyUtils.load(clazz, foreignKeys, true);
|
||||
// The above map only contains keys that exist in the database, so we re-add the
|
||||
// missing ones with Optional.empty() values for caching.
|
||||
return Maps.asMap(
|
||||
ImmutableSet.copyOf(keys),
|
||||
key -> Optional.ofNullable(existingKeys.get((String) key.getSqlKey())));
|
||||
key -> Optional.ofNullable(existingKeys.get((String) key.getKey())));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -211,15 +209,14 @@ public final class ForeignKeyUtils {
|
||||
return load(clazz, foreignKeys, now);
|
||||
}
|
||||
return foreignKeyCache
|
||||
.getAll(
|
||||
foreignKeys.stream().map(fk -> VKey.createSql(clazz, fk)).collect(toImmutableList()))
|
||||
.getAll(foreignKeys.stream().map(fk -> VKey.create(clazz, fk)).collect(toImmutableList()))
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e.getValue().isPresent() && now.isBefore(e.getValue().get().deletionTime()))
|
||||
.collect(
|
||||
toImmutableMap(
|
||||
e -> (String) e.getKey().getSqlKey(),
|
||||
e -> VKey.createSql(clazz, e.getValue().get().repoId())));
|
||||
e -> (String) e.getKey().getKey(),
|
||||
e -> VKey.create(clazz, e.getValue().get().repoId())));
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
|
||||
@@ -15,106 +15,48 @@
|
||||
package google.registry.model;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.google.appengine.api.datastore.DatastoreServiceFactory;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.beam.common.RegistryPipelineWorkerInitializer;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
|
||||
import java.math.BigInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Supplier;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* Allocates a {@link long} to use as a {@code @Id}, (part) of the primary SQL key for an entity.
|
||||
*
|
||||
* <p>Normally, the ID is globally unique and allocated by Datastore. It is possible to override
|
||||
* this behavior by providing an ID supplier, such as in unit tests, where a self-allocated ID based
|
||||
* on a monotonically increasing atomic {@link long} is used. Such an ID supplier can also be used
|
||||
* in other scenarios, such as in a Beam pipeline to get around the limitation of Beam's inability
|
||||
* to use GAE SDK to access Datastore. The override should be used with great care lest it results
|
||||
* in irreversible data corruption.
|
||||
*
|
||||
* @see #setIdSupplier(Supplier)
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public final class IdService {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private IdService() {}
|
||||
// TODO(ptkach): remove once the Cloud SQL sequence-based method is live in production
|
||||
private static boolean forceUseSelfAllocateId = false;
|
||||
|
||||
private static Supplier<Long> idSupplier =
|
||||
RegistryEnvironment.UNITTEST.equals(RegistryEnvironment.get())
|
||||
? SelfAllocatedIdSupplier.getInstance()
|
||||
: DatastoreIdSupplier.getInstance();
|
||||
|
||||
/**
|
||||
* Provides a {@link Supplier} of ID that overrides the default.
|
||||
*
|
||||
* <p>Currently, the only use case for an override is in the Beam pipeline, where access to
|
||||
* Datastore is not possible through the App Engine API. As such, the setter explicitly checks if
|
||||
* the runtime is Beam.
|
||||
*
|
||||
* <p>Because the provided supplier is not guaranteed to be globally unique and compatible with
|
||||
* existing IDs in the database, one should proceed with great care. It is safe to use an
|
||||
* arbitrary supplier when the resulting IDs are not significant and not persisted back to the
|
||||
* database, i.e. the IDs are only required by the {@link Buildable} contract but are not used in
|
||||
* any meaningful way. One example is the RDE pipeline where we project EPP resource entities from
|
||||
* history entries to watermark time, which are then marshalled into XML elements in the RDE
|
||||
* deposits, where the IDs are omitted.
|
||||
*/
|
||||
public static void setIdSupplier(Supplier<Long> idSupplier) {
|
||||
public static void setForceUseSelfAllocatedId() {
|
||||
checkState(
|
||||
"true".equals(System.getProperty(RegistryPipelineWorkerInitializer.PROPERTY, "false")),
|
||||
"Can only set ID supplier in a Beam pipeline");
|
||||
logger.atWarning().log("Using ID supplier override!");
|
||||
IdService.idSupplier = idSupplier;
|
||||
IdService.forceUseSelfAllocateId = true;
|
||||
}
|
||||
|
||||
/** Allocates an id. */
|
||||
public static long allocateId() {
|
||||
return idSupplier.get();
|
||||
}
|
||||
|
||||
// TODO(b/201547855): Find a way to allocate a unique ID without datastore.
|
||||
private static class DatastoreIdSupplier implements Supplier<Long> {
|
||||
|
||||
private static final DatastoreIdSupplier INSTANCE = new DatastoreIdSupplier();
|
||||
|
||||
/**
|
||||
* A placeholder String passed into {@code DatastoreService.allocateIds} that ensures that all
|
||||
* IDs are initialized from the same ID pool.
|
||||
*/
|
||||
private static final String APP_WIDE_ALLOCATION_KIND = "common";
|
||||
|
||||
public static DatastoreIdSupplier getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long get() {
|
||||
return DatastoreServiceFactory.getDatastoreService()
|
||||
.allocateIds(APP_WIDE_ALLOCATION_KIND, 1)
|
||||
.iterator()
|
||||
.next()
|
||||
.getId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An ID supplier that allocates an ID from a monotonically increasing atomic {@link long}.
|
||||
*
|
||||
* <p>The generated IDs are only unique within the same JVM. It is not suitable for production use
|
||||
* unless in cases the IDs are not significant.
|
||||
*/
|
||||
public static class SelfAllocatedIdSupplier implements Supplier<Long> {
|
||||
private static class SelfAllocatedIdSupplier implements Supplier<Long> {
|
||||
|
||||
private static final SelfAllocatedIdSupplier INSTANCE = new SelfAllocatedIdSupplier();
|
||||
|
||||
/** Counts of used ids for self allocating IDs. */
|
||||
private static final AtomicLong nextSelfAllocatedId = new AtomicLong(1); // ids cannot be zero
|
||||
|
||||
public static SelfAllocatedIdSupplier getInstance() {
|
||||
private static SelfAllocatedIdSupplier getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@@ -122,9 +64,50 @@ public final class IdService {
|
||||
public Long get() {
|
||||
return nextSelfAllocatedId.getAndIncrement();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* A SQL Sequence based ID allocator that generates an ID from a monotonically increasing atomic
|
||||
* {@link long}
|
||||
*
|
||||
* <p>The generated IDs are project-wide unique
|
||||
*/
|
||||
private static Long getSequenceBasedId() {
|
||||
return jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
(BigInteger)
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery("SELECT nextval('project_wide_unique_id_seq')")
|
||||
.getSingleResult())
|
||||
.longValue();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
nextSelfAllocatedId.set(1);
|
||||
// TODO(ptkach): Remove once all instances switch to sequenceBasedId
|
||||
/**
|
||||
* A Datastore based ID allocator that generates an ID from a monotonically increasing atomic
|
||||
* {@link long}
|
||||
*
|
||||
* <p>The generated IDs are project-wide unique
|
||||
*/
|
||||
private static Long getDatastoreBasedId() {
|
||||
return DatastoreServiceFactory.getDatastoreService()
|
||||
.allocateIds("common", 1)
|
||||
.iterator()
|
||||
.next()
|
||||
.getId();
|
||||
}
|
||||
|
||||
private IdService() {}
|
||||
|
||||
public static long allocateId() {
|
||||
if (DatabaseMigrationStateSchedule.getValueAtTime(DateTime.now(UTC))
|
||||
.equals(MigrationState.SEQUENCE_BASED_ALLOCATE_ID)
|
||||
|| RegistryEnvironment.UNITTEST.equals(RegistryEnvironment.get())) {
|
||||
return getSequenceBasedId();
|
||||
} else if (IdService.forceUseSelfAllocateId) {
|
||||
return SelfAllocatedIdSupplier.getInstance().get();
|
||||
}
|
||||
return getDatastoreBasedId();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ import static java.util.stream.Collectors.toCollection;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -76,7 +74,7 @@ public abstract class ImmutableObject implements Cloneable {
|
||||
// Note: if this class is made to implement Serializable, this field must become 'transient' since
|
||||
// hashing is not stable across executions. Also note that @XmlTransient is forbidden on transient
|
||||
// fields and need to be removed if transient is added.
|
||||
@Ignore @XmlTransient protected Integer hashCode;
|
||||
@XmlTransient protected Integer hashCode;
|
||||
|
||||
private boolean equalsImmutableObject(ImmutableObject other) {
|
||||
return getClass().equals(other.getClass())
|
||||
@@ -176,9 +174,6 @@ public abstract class ImmutableObject implements Cloneable {
|
||||
|
||||
/** Helper function to recursively hydrate an ImmutableObject. */
|
||||
private static Object hydrate(Object value) {
|
||||
if (value instanceof Key) {
|
||||
return value;
|
||||
}
|
||||
if (value instanceof Map) {
|
||||
return transformValues((Map<?, ?>) value, ImmutableObject::hydrate);
|
||||
}
|
||||
|
||||
@@ -25,22 +25,13 @@ import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -49,7 +40,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/** A collection of static methods that deal with reflection on model classes. */
|
||||
@@ -86,84 +76,6 @@ public class ModelUtils {
|
||||
return ALL_FIELDS_CACHE.get(clazz);
|
||||
}
|
||||
|
||||
/** Return a string representing the persisted schema of a type or enum. */
|
||||
static String getSchema(Class<?> clazz) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
Stream<?> body;
|
||||
if (clazz.isEnum()) {
|
||||
stringBuilder.append("enum ");
|
||||
body = Arrays.stream(clazz.getEnumConstants());
|
||||
} else {
|
||||
stringBuilder.append("class ");
|
||||
body =
|
||||
getAllFields(clazz)
|
||||
.values()
|
||||
.stream()
|
||||
.filter(field -> !field.isAnnotationPresent(Ignore.class))
|
||||
.map(
|
||||
field -> {
|
||||
String annotation =
|
||||
field.isAnnotationPresent(Id.class)
|
||||
? "@Id "
|
||||
: field.isAnnotationPresent(Parent.class) ? "@Parent " : "";
|
||||
String type =
|
||||
field.getType().isArray()
|
||||
? field.getType().getComponentType().getName() + "[]"
|
||||
: field.getGenericType().toString().replaceFirst("class ", "");
|
||||
return String.format("%s%s %s", annotation, type, field.getName());
|
||||
});
|
||||
}
|
||||
return stringBuilder
|
||||
.append(clazz.getName())
|
||||
.append(" {\n ")
|
||||
.append(body.map(Object::toString).sorted().collect(Collectors.joining(";\n ")))
|
||||
.append(";\n}")
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of Class objects of all persisted fields. This includes the parameterized
|
||||
* type(s) of any fields (if any).
|
||||
*/
|
||||
static Set<Class<?>> getPersistedFieldTypes(Class<?> clazz) {
|
||||
ImmutableSet.Builder<Class<?>> builder = new ImmutableSet.Builder<>();
|
||||
for (Field field : getAllFields(clazz).values()) {
|
||||
// Skip fields that aren't persisted to Datastore.
|
||||
if (field.isAnnotationPresent(Ignore.class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the field's type is the same as the field's class object, then it's a non-parameterized
|
||||
// type, and thus we just add it directly. We also don't bother looking at the parameterized
|
||||
// types of Key and VKey objects, since they are just references to other objects and don't
|
||||
// actually embed themselves in the persisted object anyway.
|
||||
Class<?> fieldClazz = field.getType();
|
||||
Type fieldType = field.getGenericType();
|
||||
if (VKey.class.equals(fieldClazz)) {
|
||||
continue;
|
||||
}
|
||||
builder.add(fieldClazz);
|
||||
if (fieldType.equals(fieldClazz) || Key.class.equals(clazz)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the field is a parameterized type, then also add the parameterized field.
|
||||
if (fieldType instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) fieldType;
|
||||
for (Type actualType : parameterizedType.getActualTypeArguments()) {
|
||||
if (actualType instanceof Class<?>) {
|
||||
builder.add((Class<?>) actualType);
|
||||
} else {
|
||||
// We intentionally ignore types that are parameterized on non-concrete types. In theory
|
||||
// we could have collections embedded within collections, but Objectify does not allow
|
||||
// that.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/** Retrieves a field value via reflection. */
|
||||
static Object getFieldValue(Object instance, Field field) {
|
||||
try {
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.common.GaeUserIdConverter;
|
||||
import google.registry.model.pricing.StaticPremiumListPricingEngine;
|
||||
@@ -199,9 +198,8 @@ public final class OteAccountBuilder {
|
||||
*
|
||||
* <p>Use this to set up registrar fields.
|
||||
*
|
||||
* <p>NOTE: DO NOT change anything that would affect the {@link Key#create} result on Registrars.
|
||||
* If you want to make this function public, add a check that the Key.create on the registrars
|
||||
* hasn't changed.
|
||||
* <p>NOTE: DO NOT change anything that would affect the result of {@link Registrar#createVKey()}
|
||||
* . If you want to make this function public, add a check that the value hasn't changed.
|
||||
*
|
||||
* @param func a function setting the requested fields on Registrar Builders. Will be applied to
|
||||
* all the Registrars.
|
||||
|
||||
@@ -26,7 +26,6 @@ import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.domain.DomainCommand;
|
||||
import google.registry.model.domain.fee.FeeCreateCommandExtension;
|
||||
import google.registry.model.domain.launch.LaunchCreateExtension;
|
||||
@@ -202,7 +201,7 @@ public class OteStats {
|
||||
try {
|
||||
record(historyEntry);
|
||||
} catch (XmlException e) {
|
||||
throw new RuntimeException("Couldn't parse history entry " + Key.create(historyEntry), e);
|
||||
throw new RuntimeException("Couldn't parse history entry " + historyEntry.createVKey(), e);
|
||||
}
|
||||
// Break out early if all tests were passed.
|
||||
if (wereAllTestsPassed()) {
|
||||
|
||||
@@ -183,11 +183,11 @@ public final class ResourceTransferUtils {
|
||||
* sets the last EPP update client id to the given client id.
|
||||
*/
|
||||
public static <R extends EppResource & ResourceWithTransferData> R denyPendingTransfer(
|
||||
R resource, TransferStatus transferStatus, DateTime now, String lastEppUpdateClientId) {
|
||||
R resource, TransferStatus transferStatus, DateTime now, String lastEppUpdateRegistrarId) {
|
||||
checkArgument(transferStatus.isDenied(), "Not a denial transfer status");
|
||||
return resolvePendingTransfer(resource, transferStatus, now)
|
||||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateRegistrarId(lastEppUpdateClientId)
|
||||
.setLastEppUpdateRegistrarId(lastEppUpdateRegistrarId)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
// Copyright 2017 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.model;
|
||||
|
||||
import static com.google.common.base.Predicates.or;
|
||||
import static com.google.common.base.Predicates.subtypeOf;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import com.google.common.collect.Ordering;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/** Utility methods for getting the version of the model schema from the model code. */
|
||||
@DeleteAfterMigration
|
||||
public final class SchemaVersion {
|
||||
|
||||
/**
|
||||
* Returns a set of classes corresponding to all types persisted within the model classes, sorted
|
||||
* by the string representation.
|
||||
*/
|
||||
private static SortedSet<Class<?>> getAllPersistedTypes() {
|
||||
SortedSet<Class<?>> persistedTypes = new TreeSet<>(Ordering.usingToString());
|
||||
// Do a breadth-first search for persisted types, starting with @Entity types and expanding each
|
||||
// ImmutableObject by querying it for all its persisted field types.
|
||||
persistedTypes.addAll(EntityClasses.ALL_CLASSES);
|
||||
Queue<Class<?>> queue = new ArrayDeque<>(persistedTypes);
|
||||
while (!queue.isEmpty()) {
|
||||
Class<?> clazz = queue.remove();
|
||||
if (ImmutableObject.class.isAssignableFrom(clazz)) {
|
||||
for (Class<?> persistedFieldType : ModelUtils.getPersistedFieldTypes(clazz)) {
|
||||
if (persistedTypes.add(persistedFieldType)) {
|
||||
// If we haven't seen this type before, add it to the queue to query its field types.
|
||||
queue.add(persistedFieldType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return persistedTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representing the schema which includes the definition of all persisted entity
|
||||
* types (and their field types, recursively). Each definition contains the field names and their
|
||||
* types (for classes), or else a list of all possible values (for enums).
|
||||
*/
|
||||
public static String getSchema() {
|
||||
return getAllPersistedTypes().stream()
|
||||
.filter(or(subtypeOf(Enum.class), subtypeOf(ImmutableObject.class)))
|
||||
.map(ModelUtils::getSchema)
|
||||
.collect(joining("\n"));
|
||||
}
|
||||
|
||||
private SchemaVersion() {}
|
||||
}
|
||||
@@ -23,8 +23,8 @@ import java.io.Serializable;
|
||||
* the migration. Note that only objects loaded from the SQL database need serialization support.
|
||||
*
|
||||
* <p>All entities implementing this interface take advantage of the fact that all Java collection
|
||||
* classes we use, either directly or indirectly, including those in Java libraries, Guava,
|
||||
* Objectify, and Hibernate are {@code Serializable}.
|
||||
* classes we use, either directly or indirectly, including those in Java libraries, Guava, and
|
||||
* Hibernate are {@code Serializable}.
|
||||
*
|
||||
* <p>The {@code serialVersionUID} field has also been omitted in the implementing classes, since
|
||||
* they are not used for persistence.
|
||||
|
||||
@@ -29,12 +29,7 @@ import org.joda.time.DateTime;
|
||||
@Embeddable
|
||||
public class UpdateAutoTimestamp extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
// When set to true, database converters/translators should do the auto update. When set to
|
||||
// false, auto update should be suspended (this exists to allow us to preserve the original value
|
||||
// during a replay).
|
||||
private static final ThreadLocal<Boolean> autoUpdateEnabled = ThreadLocal.withInitial(() -> true);
|
||||
|
||||
@Column(nullable = false)
|
||||
@Column(name = "updateTimestamp")
|
||||
DateTime lastUpdateTime;
|
||||
|
||||
// Unfortunately, we cannot use the @UpdateTimestamp annotation on "lastUpdateTime" in this class
|
||||
@@ -43,9 +38,7 @@ public class UpdateAutoTimestamp extends ImmutableObject implements UnsafeSerial
|
||||
@PrePersist
|
||||
@PreUpdate
|
||||
void setTimestamp() {
|
||||
if (autoUpdateEnabled() || lastUpdateTime == null) {
|
||||
lastUpdateTime = jpaTm().getTransactionTime();
|
||||
}
|
||||
lastUpdateTime = jpaTm().getTransactionTime();
|
||||
}
|
||||
|
||||
/** Returns the timestamp, or {@code START_OF_TIME} if it's null. */
|
||||
@@ -58,30 +51,4 @@ public class UpdateAutoTimestamp extends ImmutableObject implements UnsafeSerial
|
||||
instance.lastUpdateTime = timestamp;
|
||||
return instance;
|
||||
}
|
||||
|
||||
// TODO(b/175610935): Remove the auto-update disabling code below after migration.
|
||||
|
||||
/** Class to allow us to safely disable auto-update in a try-with-resources block. */
|
||||
public static class DisableAutoUpdateResource implements AutoCloseable {
|
||||
DisableAutoUpdateResource() {
|
||||
autoUpdateEnabled.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
autoUpdateEnabled.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resturns a resource that disables auto-updates on all {@link UpdateAutoTimestamp}s in the
|
||||
* current thread, suitable for use with in a try-with-resources block.
|
||||
*/
|
||||
public static DisableAutoUpdateResource disableAutoUpdate() {
|
||||
return new DisableAutoUpdateResource();
|
||||
}
|
||||
|
||||
public static boolean autoUpdateEnabled() {
|
||||
return autoUpdateEnabled.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,28 +14,22 @@
|
||||
|
||||
package google.registry.model;
|
||||
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.util.PreconditionsUtils;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
/**
|
||||
* Base class for entities that are the root of a Registry 2.0 entity group that gets enrolled in
|
||||
* commit logs for backup purposes.
|
||||
*
|
||||
* <p>The commit log system needs to preserve the ordering of closely timed mutations to entities in
|
||||
* a single entity group. We require an {@link UpdateAutoTimestamp} field on the root of a group so
|
||||
* that we can enforce strictly increasing timestamps.
|
||||
* Base class for entities that contains an {@link UpdateAutoTimestamp} which is updated every time
|
||||
* the entity is persisted.
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class BackupGroupRoot extends ImmutableObject implements UnsafeSerializable {
|
||||
public abstract class UpdateAutoTimestampEntity extends ImmutableObject
|
||||
implements UnsafeSerializable {
|
||||
|
||||
/**
|
||||
* An automatically managed timestamp of when this object was last written to Datastore.
|
||||
* An automatically managed timestamp of when this object was last written to the database.
|
||||
*
|
||||
* <p>Note that this is distinct from the EPP-specified {@link EppResource#lastEppUpdateTime}, in
|
||||
* that this is updated on every save, rather than only in response to an {@code <update>} command
|
||||
@@ -44,8 +38,6 @@ public abstract class BackupGroupRoot extends ImmutableObject implements UnsafeS
|
||||
// Prevents subclasses from unexpectedly accessing as property (e.g., Host), which would
|
||||
// require an unnecessary non-private setter method.
|
||||
@Access(AccessType.FIELD)
|
||||
@AttributeOverride(name = "lastUpdateTime", column = @Column(name = "updateTimestamp"))
|
||||
@Ignore
|
||||
UpdateAutoTimestamp updateTimestamp = UpdateAutoTimestamp.create(null);
|
||||
|
||||
/** Get the {@link UpdateAutoTimestamp} for this entity. */
|
||||
@@ -59,7 +51,7 @@ public abstract class BackupGroupRoot extends ImmutableObject implements UnsafeS
|
||||
* <p>This method is for the few cases when {@code updateTimestamp} is copied between different
|
||||
* types of entities. Use {@link #clone} for same-type copying.
|
||||
*/
|
||||
protected void copyUpdateTimestamp(BackupGroupRoot other) {
|
||||
protected void copyUpdateTimestamp(UpdateAutoTimestampEntity other) {
|
||||
this.updateTimestamp = PreconditionsUtils.checkArgumentNotNull(other, "other").updateTimestamp;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.translators;
|
||||
package google.registry.model.adapters;
|
||||
|
||||
import static com.google.common.base.Strings.nullToEmpty;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.translators;
|
||||
package google.registry.model.adapters;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.translators;
|
||||
package google.registry.model.adapters;
|
||||
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
// Copyright 2022 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.
|
||||
@@ -14,16 +14,16 @@
|
||||
|
||||
package google.registry.model.annotations;
|
||||
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import google.registry.model.IdService;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation for an Objectify {@link Entity} to indicate that it should be exported to BigQuery.
|
||||
* This annotation is needed for any ID field that needs to be allocated with {@link IdService}
|
||||
* class
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface ReportedOn {}
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface IdAllocation {}
|
||||
@@ -1,36 +0,0 @@
|
||||
// Copyright 2022 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.model.annotations;
|
||||
|
||||
import google.registry.model.IdService;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation to indicate an ID field that needs to be allocated by Ofy.
|
||||
*
|
||||
* <p>This annotation is only used for the field of a {@link google.registry.model.Buildable} class
|
||||
* that was previously annotated by both Ofy's and JPA's {@code @Id} annotations, of which the Ofy
|
||||
* annotation has been removed. The field still needs to be allocated automatically by the builder,
|
||||
* via the {@link IdService#allocateId()}.
|
||||
*
|
||||
* <p>It should be removed after we switch to using SQL to directly allocate IDs.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface OfyIdAllocation {}
|
||||
@@ -28,14 +28,13 @@ import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.annotations.OfyIdAllocation;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.annotations.IdAllocation;
|
||||
import google.registry.model.common.TimeOfYear;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.transfer.TransferData.TransferServerApproveEntity;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithVKey;
|
||||
@@ -147,7 +146,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
}
|
||||
|
||||
/** Entity id. */
|
||||
@OfyIdAllocation @Id Long id;
|
||||
@IdAllocation @Id Long id;
|
||||
|
||||
/** The registrar to bill. */
|
||||
@Column(name = "registrarId", nullable = false)
|
||||
@@ -204,8 +203,8 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
return targetId;
|
||||
}
|
||||
|
||||
public DomainHistoryId getDomainHistoryId() {
|
||||
return new DomainHistoryId(domainRepoId, domainHistoryRevisionId);
|
||||
public HistoryEntryId getHistoryEntryId() {
|
||||
return new HistoryEntryId(domainRepoId, domainHistoryRevisionId);
|
||||
}
|
||||
|
||||
public ImmutableSet<Flag> getFlags() {
|
||||
@@ -259,14 +258,14 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setDomainHistoryId(DomainHistoryId domainHistoryId) {
|
||||
getInstance().domainHistoryRevisionId = domainHistoryId.getId();
|
||||
getInstance().domainRepoId = domainHistoryId.getDomainRepoId();
|
||||
public B setDomainHistoryId(HistoryEntryId domainHistoryId) {
|
||||
getInstance().domainHistoryRevisionId = domainHistoryId.getRevisionId();
|
||||
getInstance().domainRepoId = domainHistoryId.getRepoId();
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setDomainHistory(DomainHistory domainHistory) {
|
||||
return setDomainHistoryId(domainHistory.getDomainHistoryId());
|
||||
return setDomainHistoryId(domainHistory.getHistoryEntryId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -375,7 +374,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
}
|
||||
|
||||
public static VKey<OneTime> createVKey(long id) {
|
||||
return VKey.createSql(OneTime.class, id);
|
||||
return VKey.create(OneTime.class, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -538,7 +537,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
}
|
||||
|
||||
public static VKey<Recurring> createVKey(Long id) {
|
||||
return VKey.createSql(Recurring.class, id);
|
||||
return VKey.create(Recurring.class, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -594,7 +593,6 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
* <p>This is implemented as a separate event rather than a bit on BillingEvent in order to
|
||||
* preserve the immutability of billing events.
|
||||
*/
|
||||
@ReportedOn
|
||||
@Entity(name = "BillingCancellation")
|
||||
@Table(
|
||||
indexes = {
|
||||
@@ -653,7 +651,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
public static Cancellation forGracePeriod(
|
||||
GracePeriod gracePeriod,
|
||||
DateTime eventTime,
|
||||
DomainHistoryId domainHistoryId,
|
||||
HistoryEntryId domainHistoryId,
|
||||
String targetId) {
|
||||
checkArgument(
|
||||
gracePeriod.hasBillingEvent(),
|
||||
@@ -682,7 +680,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
}
|
||||
|
||||
public static VKey<Cancellation> createVKey(long id) {
|
||||
return VKey.createSql(Cancellation.class, id);
|
||||
return VKey.create(Cancellation.class, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
// 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.model.bulkquery;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.GracePeriod.GracePeriodHistory;
|
||||
import google.registry.model.domain.secdns.DomainDsData;
|
||||
import google.registry.model.domain.secdns.DomainDsDataHistory;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
|
||||
/**
|
||||
* Utilities for managing an alternative JPA entity model optimized for bulk loading multi-level
|
||||
* entities such as {@link Domain} and {@link DomainHistory}.
|
||||
*
|
||||
* <p>In a bulk query for a multi-level JPA entity type, the JPA framework only generates a bulk
|
||||
* query (SELECT * FROM table) for the base table. Then, for each row in the base table, additional
|
||||
* queries are issued to load associated rows in child tables. This can be very slow when an entity
|
||||
* type has multiple child tables.
|
||||
*
|
||||
* <p>We have defined an alternative entity model for {@link Domain} and {@link DomainHistory},
|
||||
* where the base table as well as the child tables are mapped to single-level entity types. The
|
||||
* idea is to load each of these types using a bulk query, and assemble them into the target type in
|
||||
* memory in a pipeline. The main use case is Datastore-Cloud SQL validation during the Registry
|
||||
* database migration, where we will need the full database snapshots frequently.
|
||||
*/
|
||||
public class BulkQueryEntities {
|
||||
/**
|
||||
* The JPA entity classes in persistence.xml to replace when creating the {@link
|
||||
* JpaTransactionManager} for bulk query.
|
||||
*/
|
||||
public static final ImmutableMap<String, String> JPA_ENTITIES_REPLACEMENTS =
|
||||
ImmutableMap.of(
|
||||
Domain.class.getCanonicalName(),
|
||||
DomainLite.class.getCanonicalName(),
|
||||
DomainHistory.class.getCanonicalName(),
|
||||
DomainHistoryLite.class.getCanonicalName());
|
||||
|
||||
/* The JPA entity classes that are not included in persistence.xml and need to be added to
|
||||
* the {@link JpaTransactionManager} for bulk query.*/
|
||||
public static final ImmutableList<String> JPA_ENTITIES_NEW =
|
||||
ImmutableList.of(
|
||||
DomainHost.class.getCanonicalName(), DomainHistoryHost.class.getCanonicalName());
|
||||
|
||||
public static Domain assembleDomain(
|
||||
DomainLite domainLite,
|
||||
ImmutableSet<GracePeriod> gracePeriods,
|
||||
ImmutableSet<DomainDsData> domainDsData,
|
||||
ImmutableSet<VKey<Host>> nsHosts) {
|
||||
Domain.Builder builder = new Domain.Builder();
|
||||
builder.copyFrom(domainLite);
|
||||
builder.setGracePeriods(gracePeriods);
|
||||
builder.setDsData(domainDsData);
|
||||
builder.setNameservers(nsHosts);
|
||||
// Restore the original update timestamp (this gets cleared when we set nameservers or DS data).
|
||||
builder.setUpdateTimestamp(domainLite.getUpdateTimestamp());
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static DomainHistory assembleDomainHistory(
|
||||
DomainHistoryLite domainHistoryLite,
|
||||
ImmutableSet<DomainDsDataHistory> dsDataHistories,
|
||||
ImmutableSet<VKey<Host>> domainHistoryHosts,
|
||||
ImmutableSet<GracePeriodHistory> gracePeriodHistories,
|
||||
ImmutableSet<DomainTransactionRecord> transactionRecords) {
|
||||
DomainHistory.Builder builder = new DomainHistory.Builder();
|
||||
builder.copyFrom(domainHistoryLite);
|
||||
DomainBase rawDomainBase = domainHistoryLite.domainBase;
|
||||
if (rawDomainBase != null) {
|
||||
DomainBase newDomainBase =
|
||||
domainHistoryLite
|
||||
.domainBase
|
||||
.asBuilder()
|
||||
.setNameservers(domainHistoryHosts)
|
||||
.setGracePeriods(
|
||||
gracePeriodHistories.stream()
|
||||
.map(GracePeriod::createFromHistory)
|
||||
.collect(toImmutableSet()))
|
||||
.setDsData(
|
||||
dsDataHistories.stream().map(DomainDsData::create).collect(toImmutableSet()))
|
||||
// Restore the original update timestamp (this gets cleared when we set nameservers or
|
||||
// DS data).
|
||||
.setUpdateTimestamp(domainHistoryLite.domainBase.getUpdateTimestamp())
|
||||
.build();
|
||||
builder.setDomain(newDomainBase);
|
||||
}
|
||||
return builder.buildAndAssemble(
|
||||
dsDataHistories, domainHistoryHosts, gracePeriodHistories, transactionRecords);
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
// 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.model.bulkquery;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
|
||||
/**
|
||||
* A name server host referenced by a {@link google.registry.model.domain.DomainHistory} record.
|
||||
* Please refer to {@link BulkQueryEntities} for usage.
|
||||
*/
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
@IdClass(DomainHistoryHost.class)
|
||||
public class DomainHistoryHost implements Serializable {
|
||||
|
||||
@Id private Long domainHistoryHistoryRevisionId;
|
||||
@Id private String domainHistoryDomainRepoId;
|
||||
@Id private String hostRepoId;
|
||||
|
||||
private DomainHistoryHost() {}
|
||||
|
||||
public DomainHistoryId getDomainHistoryId() {
|
||||
return new DomainHistoryId(domainHistoryDomainRepoId, domainHistoryHistoryRevisionId);
|
||||
}
|
||||
|
||||
public VKey<Host> getHostVKey() {
|
||||
return VKey.create(Host.class, hostRepoId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof DomainHistoryHost)) {
|
||||
return false;
|
||||
}
|
||||
DomainHistoryHost that = (DomainHistoryHost) o;
|
||||
return Objects.equal(domainHistoryHistoryRevisionId, that.domainHistoryHistoryRevisionId)
|
||||
&& Objects.equal(domainHistoryDomainRepoId, that.domainHistoryDomainRepoId)
|
||||
&& Objects.equal(hostRepoId, that.hostRepoId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(domainHistoryHistoryRevisionId, domainHistoryDomainRepoId, hostRepoId);
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
// 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.model.bulkquery;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.PostLoad;
|
||||
|
||||
/**
|
||||
* A 'light' version of {@link DomainHistory} with only base table ("DomainHistory") attributes,
|
||||
* which allows fast bulk loading. They are used in in-memory assembly of {@code DomainHistory}
|
||||
* instances along with bulk-loaded child entities ({@code GracePeriodHistory} etc). The in-memory
|
||||
* assembly achieves much higher performance than loading {@code DomainHistory} directly.
|
||||
*
|
||||
* <p>Please refer to {@link BulkQueryEntities} for more information.
|
||||
*
|
||||
* <p>This class is adapted from {@link DomainHistory} by removing the {@code dsDataHistories},
|
||||
* {@code gracePeriodHistories}, and {@code nsHosts} fields and associated methods.
|
||||
*/
|
||||
@Entity(name = "DomainHistory")
|
||||
@Access(AccessType.FIELD)
|
||||
@IdClass(DomainHistoryId.class)
|
||||
public class DomainHistoryLite extends HistoryEntry {
|
||||
|
||||
// Store DomainBase instead of Domain so we don't pick up its @Id
|
||||
// Nullable for the sake of pre-Registry-3.0 history objects
|
||||
@Nullable DomainBase domainBase;
|
||||
|
||||
@Id
|
||||
@Access(AccessType.PROPERTY)
|
||||
public String getDomainRepoId() {
|
||||
// We need to handle null case here because Hibernate sometimes accesses this method before
|
||||
// parent gets initialized
|
||||
return parent == null ? null : parent.getName();
|
||||
}
|
||||
|
||||
/** This method is private because it is only used by Hibernate. */
|
||||
@SuppressWarnings("unused")
|
||||
private void setDomainRepoId(String domainRepoId) {
|
||||
parent = Key.create(Domain.class, domainRepoId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
@Access(AccessType.PROPERTY)
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "unit", column = @Column(name = "historyPeriodUnit")),
|
||||
@AttributeOverride(name = "value", column = @Column(name = "historyPeriodValue"))
|
||||
})
|
||||
public Period getPeriod() {
|
||||
return super.getPeriod();
|
||||
}
|
||||
|
||||
/**
|
||||
* For transfers, the id of the other registrar.
|
||||
*
|
||||
* <p>For requests and cancels, the other registrar is the losing party (because the registrar
|
||||
* sending the EPP transfer command is the gaining party). For approves and rejects, the other
|
||||
* registrar is the gaining party.
|
||||
*/
|
||||
@Nullable
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Column(name = "historyOtherRegistrarId")
|
||||
@Override
|
||||
public String getOtherRegistrarId() {
|
||||
return super.getOtherRegistrarId();
|
||||
}
|
||||
|
||||
@Id
|
||||
@Column(name = "historyRevisionId")
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Override
|
||||
public long getId() {
|
||||
return super.getId();
|
||||
}
|
||||
|
||||
/** The key to the {@link Domain} this is based off of. */
|
||||
public VKey<Domain> getParentVKey() {
|
||||
return VKey.create(Domain.class, getDomainRepoId());
|
||||
}
|
||||
|
||||
public DomainHistoryId getDomainHistoryId() {
|
||||
return new DomainHistoryId(getDomainRepoId(), getId());
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
if (domainBase == null) {
|
||||
return;
|
||||
}
|
||||
// See inline comments in DomainHistory.postLoad for reasons for the following lines.
|
||||
if (domainBase.getDomainName() == null) {
|
||||
domainBase = null;
|
||||
} else if (domainBase.getRepoId() == null) {
|
||||
domainBase.setRepoId(parent.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
// 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.model.bulkquery;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
|
||||
/** A name server host of a domain. Please refer to {@link BulkQueryEntities} for usage. */
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
@IdClass(DomainHost.class)
|
||||
public class DomainHost implements Serializable {
|
||||
|
||||
@Id private String domainRepoId;
|
||||
|
||||
@Id private String hostRepoId;
|
||||
|
||||
DomainHost() {}
|
||||
|
||||
public String getDomainRepoId() {
|
||||
return domainRepoId;
|
||||
}
|
||||
|
||||
public VKey<Host> getHostVKey() {
|
||||
return VKey.create(Host.class, hostRepoId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof DomainHost)) {
|
||||
return false;
|
||||
}
|
||||
DomainHost that = (DomainHost) o;
|
||||
return Objects.equal(domainRepoId, that.domainRepoId)
|
||||
&& Objects.equal(hostRepoId, that.hostRepoId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(domainRepoId, hostRepoId);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
// 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.model.bulkquery;
|
||||
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithVKey;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
/**
|
||||
* A 'light' version of {@link Domain} with only base table ("Domain") attributes, which allows fast
|
||||
* bulk loading. They are used in in-memory assembly of {@code Domain} instances along with
|
||||
* bulk-loaded child entities ({@code GracePeriod} etc). The in-memory assembly achieves much higher
|
||||
* performance than loading {@code Domain} directly.
|
||||
*
|
||||
* <p>Please refer to {@link BulkQueryEntities} for more information.
|
||||
*/
|
||||
@Entity(name = "Domain")
|
||||
@WithVKey(String.class)
|
||||
@Access(AccessType.FIELD)
|
||||
public class DomainLite extends DomainBase {
|
||||
|
||||
@Override
|
||||
@javax.persistence.Id
|
||||
@Access(AccessType.PROPERTY)
|
||||
public String getRepoId() {
|
||||
return super.getRepoId();
|
||||
}
|
||||
|
||||
public static VKey<DomainLite> createVKey(String repoId) {
|
||||
return VKey.createSql(DomainLite.class, repoId);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
// 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.model.common;
|
||||
|
||||
import static com.google.common.base.Functions.identity;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.model.EntityClasses.ALL_CLASSES;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/** A helper to manage class name and class path mapping. */
|
||||
public class ClassPathManager {
|
||||
/**
|
||||
* Class registry allowing us to restore the original class object from the unqualified class
|
||||
* name, which is all the datastore key gives us. Note that entities annotated
|
||||
* with @EntitySubclass are removed because they share the same kind of the key with their parent
|
||||
* class.
|
||||
*/
|
||||
public static final Map<String, Class<?>> CLASS_REGISTRY =
|
||||
ALL_CLASSES.stream()
|
||||
.filter(clazz -> !clazz.isAnnotationPresent(EntitySubclass.class))
|
||||
.collect(Collectors.toMap(com.googlecode.objectify.Key::getKind, identity()));
|
||||
|
||||
/**
|
||||
* Class name registry allowing us to obtain the class name the unqualified class, which is all
|
||||
* the datastore key gives us. Note that entities annotated with @EntitySubclass are removed
|
||||
* because they share the same kind of the key with their parent class.
|
||||
*/
|
||||
public static final Map<Class<?>, String> CLASS_NAME_REGISTRY =
|
||||
ALL_CLASSES.stream()
|
||||
.filter(clazz -> !clazz.isAnnotationPresent(EntitySubclass.class))
|
||||
.collect(Collectors.toMap(identity(), com.googlecode.objectify.Key::getKind));
|
||||
|
||||
@VisibleForTesting
|
||||
public static void addTestEntityClass(Class<?> clazz) {
|
||||
CLASS_REGISTRY.put(clazz.getSimpleName(), clazz);
|
||||
CLASS_NAME_REGISTRY.put(clazz, clazz.getSimpleName());
|
||||
}
|
||||
|
||||
public static <T> Class<T> getClass(String className) {
|
||||
checkArgument(
|
||||
CLASS_REGISTRY.containsKey(className), "Class %s not found in class registry", className);
|
||||
return (Class<T>) CLASS_REGISTRY.get(className);
|
||||
}
|
||||
|
||||
public static <T> String getClassName(Class<T> clazz) {
|
||||
checkArgument(
|
||||
CLASS_NAME_REGISTRY.containsKey(clazz),
|
||||
"Class %s not found in class name registry",
|
||||
clazz.getSimpleName());
|
||||
return CLASS_NAME_REGISTRY.get(clazz);
|
||||
}
|
||||
}
|
||||
@@ -14,22 +14,15 @@
|
||||
|
||||
package google.registry.model.common;
|
||||
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
/**
|
||||
* A singleton entity in the database.
|
||||
*
|
||||
* <p>This class should not be deleted after the migration, because there is still a concept of
|
||||
* singleton in SQL. We should remove the ofy @Id annotation after all of its subclass are Ofy-free.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
/** A singleton entity in the database. */
|
||||
@MappedSuperclass
|
||||
public abstract class CrossTldSingleton extends ImmutableObject {
|
||||
|
||||
public static final long SINGLETON_ID = 1; // There is always exactly one of these.
|
||||
|
||||
@Id @javax.persistence.Id long id = SINGLETON_ID;
|
||||
@Id long id = SINGLETON_ID;
|
||||
}
|
||||
|
||||
@@ -20,11 +20,12 @@ import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.model.UpdateAutoTimestampEntity;
|
||||
import google.registry.model.common.Cursor.CursorId;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
@@ -41,7 +42,10 @@ import org.joda.time.DateTime;
|
||||
*/
|
||||
@Entity
|
||||
@IdClass(CursorId.class)
|
||||
public class Cursor extends ImmutableObject implements UnsafeSerializable {
|
||||
@AttributeOverride(
|
||||
name = "updateTimestamp.lastUpdateTime",
|
||||
column = @Column(nullable = false, name = "lastUpdateTime"))
|
||||
public class Cursor extends UpdateAutoTimestampEntity {
|
||||
|
||||
private static final long serialVersionUID = 5777891565780594961L;
|
||||
|
||||
@@ -122,10 +126,6 @@ public class Cursor extends ImmutableObject implements UnsafeSerializable {
|
||||
@Column(nullable = false)
|
||||
DateTime cursorTime = START_OF_TIME;
|
||||
|
||||
/** An automatically managed timestamp of when this object was last written to Datastore. */
|
||||
@Column(nullable = false)
|
||||
UpdateAutoTimestamp lastUpdateTime = UpdateAutoTimestamp.create(null);
|
||||
|
||||
@Override
|
||||
public VKey<Cursor> createVKey() {
|
||||
return createVKey(type, scope);
|
||||
@@ -141,13 +141,14 @@ public class Cursor extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
private static VKey<Cursor> createVKey(CursorType type, String scope) {
|
||||
checkValidCursorTypeForScope(type, scope);
|
||||
return VKey.createSql(Cursor.class, new CursorId(type, scope));
|
||||
return VKey.create(Cursor.class, new CursorId(type, scope));
|
||||
}
|
||||
|
||||
public DateTime getLastUpdateTime() {
|
||||
return lastUpdateTime.getTimestamp();
|
||||
return getUpdateTimestamp().getTimestamp();
|
||||
}
|
||||
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,10 @@ public class DatabaseMigrationStateSchedule extends CrossTldSingleton {
|
||||
SQL_PRIMARY(PrimaryDatabase.CLOUD_SQL, false, ReplayDirection.SQL_TO_DATASTORE),
|
||||
|
||||
/** Cloud SQL is the only DB being used. */
|
||||
SQL_ONLY(PrimaryDatabase.CLOUD_SQL, false, ReplayDirection.NO_REPLAY);
|
||||
SQL_ONLY(PrimaryDatabase.CLOUD_SQL, false, ReplayDirection.NO_REPLAY),
|
||||
|
||||
/** Toggles SQL Sequence based allocateId */
|
||||
SEQUENCE_BASED_ALLOCATE_ID(PrimaryDatabase.CLOUD_SQL, false, ReplayDirection.NO_REPLAY);
|
||||
|
||||
private final PrimaryDatabase primaryDatabase;
|
||||
private final boolean isReadOnly;
|
||||
@@ -160,7 +163,8 @@ public class DatabaseMigrationStateSchedule extends CrossTldSingleton {
|
||||
.putAll(
|
||||
MigrationState.SQL_ONLY,
|
||||
MigrationState.SQL_PRIMARY_READ_ONLY,
|
||||
MigrationState.SQL_PRIMARY);
|
||||
MigrationState.SQL_PRIMARY)
|
||||
.putAll(MigrationState.SQL_ONLY, MigrationState.SEQUENCE_BASED_ALLOCATE_ID);
|
||||
|
||||
// In addition, we can always transition from a state to itself (useful when updating the map).
|
||||
Arrays.stream(MigrationState.values()).forEach(state -> builder.put(state, state));
|
||||
|
||||
@@ -25,7 +25,6 @@ import static org.joda.time.DateTimeZone.UTC;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ContiguousSet;
|
||||
import com.google.common.collect.Range;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import java.util.List;
|
||||
@@ -50,7 +49,6 @@ public class TimeOfYear extends ImmutableObject implements UnsafeSerializable {
|
||||
* The time as "month day millis" with all fields left-padded with zeroes so that lexographic
|
||||
* sorting will do the right thing.
|
||||
*/
|
||||
@Index
|
||||
String timeString;
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,8 +22,8 @@ import static google.registry.util.PasswordUtils.SALT_SUPPLIER;
|
||||
import static google.registry.util.PasswordUtils.hashPassword;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.UpdateAutoTimestampEntity;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
@@ -39,7 +39,7 @@ import javax.persistence.Table;
|
||||
@Index(columnList = "gaiaId", name = "user_gaia_id_idx"),
|
||||
@Index(columnList = "emailAddress", name = "user_email_address_idx")
|
||||
})
|
||||
public class User extends BackupGroupRoot implements Buildable {
|
||||
public class User extends UpdateAutoTimestampEntity implements Buildable {
|
||||
|
||||
/** Autogenerated unique ID of this user. */
|
||||
@Id
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user