mirror of
https://github.com/google/nomulus
synced 2026-05-25 01:01:57 +00:00
Compare commits
48 Commits
nomulus-20
...
nomulus-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18b808bd34 | ||
|
|
d7689539d7 | ||
|
|
c14ce6866b | ||
|
|
3b84542e46 | ||
|
|
fc7db91d70 | ||
|
|
3d8aa85d63 | ||
|
|
e14cd8bfa2 | ||
|
|
82e8641816 | ||
|
|
7461ada0fb | ||
|
|
d91ca0eb8a | ||
|
|
12dac76dc8 | ||
|
|
ad6471b3fd | ||
|
|
942584b880 | ||
|
|
8d421e995e | ||
|
|
adc10131a0 | ||
|
|
a8ddb5c053 | ||
|
|
88be34808d | ||
|
|
099555c789 | ||
|
|
652d099e0e | ||
|
|
f31d77c570 | ||
|
|
1ced2b0a5d | ||
|
|
0e6b5e949d | ||
|
|
fe714329c9 | ||
|
|
9297b11a57 | ||
|
|
031f4ea063 | ||
|
|
0a25182fea | ||
|
|
f1dcb1299f | ||
|
|
d46594c610 | ||
|
|
0a9fa8cf23 | ||
|
|
db4bf90538 | ||
|
|
d6127e4c0c | ||
|
|
447bfa162b | ||
|
|
c9efa61198 | ||
|
|
054c0625a8 | ||
|
|
b03639d7fc | ||
|
|
bd9af0de84 | ||
|
|
ae911a5280 | ||
|
|
d57597f40f | ||
|
|
2641d0d462 | ||
|
|
5b41f0b9b6 | ||
|
|
1a26677d72 | ||
|
|
f1beeb4016 | ||
|
|
5c33286056 | ||
|
|
603a95d719 | ||
|
|
0a3774d3f7 | ||
|
|
cc60b27dd3 | ||
|
|
52c18f9967 | ||
|
|
5339b3cb6c |
14
build.gradle
14
build.gradle
@@ -457,8 +457,6 @@ task javaIncrementalFormatApply {
|
||||
task javadoc(type: Javadoc) {
|
||||
source javadocSource
|
||||
classpath = files(javadocClasspath)
|
||||
// Exclude the misbehaving generated-by-Soy Java files
|
||||
exclude "**/*SoyInfo.java"
|
||||
destinationDir = file("${buildDir}/docs/javadoc")
|
||||
options.encoding = "UTF-8"
|
||||
// In a lot of places we don't write @return so suppress warnings about that.
|
||||
@@ -483,3 +481,15 @@ task coreDev {
|
||||
}
|
||||
|
||||
javadocDependentTasks.each { tasks.javadoc.dependsOn(it) }
|
||||
|
||||
// disable javadoc in subprojects, these will break because they don't have
|
||||
// the correct classpath (see above).
|
||||
gradle.taskGraph.whenReady { graph ->
|
||||
graph.getAllTasks().each { task ->
|
||||
def subprojectJavadoc = (task.path =~ /:.+:javadoc/)
|
||||
if (subprojectJavadoc) {
|
||||
println "Skipping ${task.path} for javadoc (only root javadoc works)"
|
||||
task.enabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,11 @@ These aren't built in to the static code analysis tools we use (e.g. Checkstyle,
|
||||
Error Prone) so we must write them manually.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from typing import List, Tuple
|
||||
import sys
|
||||
import textwrap
|
||||
import re
|
||||
|
||||
# We should never analyze any generated files
|
||||
@@ -28,6 +30,13 @@ UNIVERSALLY_SKIPPED_PATTERNS = {"/build/", "cloudbuild-caches", "/out/", ".git/"
|
||||
FORBIDDEN = 1
|
||||
REQUIRED = 2
|
||||
|
||||
# The list of expected json packages and their licenses.
|
||||
# These should be one of the allowed licenses in:
|
||||
# config/dependency-license/allowed_licenses.json
|
||||
EXPECTED_JS_PACKAGES = [
|
||||
'google-closure-library', # Owned by Google, Apache 2.0
|
||||
]
|
||||
|
||||
|
||||
class PresubmitCheck:
|
||||
|
||||
@@ -206,15 +215,13 @@ PRESUBMITS = {
|
||||
"RegistryJpaIO.java",
|
||||
# TODO(b/179158393): Remove everything below, which should be done
|
||||
# using Criteria
|
||||
"ForeignKeyIndex.java",
|
||||
"HistoryEntryDao.java",
|
||||
"JpaTransactionManager.java",
|
||||
"JpaTransactionManagerImpl.java",
|
||||
# CriteriaQueryBuilder is a false positive
|
||||
"CriteriaQueryBuilder.java",
|
||||
"RdapDomainSearchAction.java",
|
||||
"RdapNameserverSearchAction.java",
|
||||
"RdapSearchActionBase.java",
|
||||
"ReadOnlyCheckingEntityManager.java",
|
||||
"RegistryQuery",
|
||||
},
|
||||
):
|
||||
@@ -310,6 +317,26 @@ def verify_flyway_index():
|
||||
return not success
|
||||
|
||||
|
||||
def verify_javascript_deps():
|
||||
"""Verifies that we haven't introduced any new javascript dependencies."""
|
||||
with open('package.json') as f:
|
||||
package = json.load(f)
|
||||
|
||||
deps = list(package['dependencies'].keys())
|
||||
if deps != EXPECTED_JS_PACKAGES:
|
||||
print('Unexpected javascript dependencies. Was expecting '
|
||||
'%s, got %s.' % (EXPECTED_JS_PACKAGES, deps))
|
||||
print(textwrap.dedent("""
|
||||
* If the new dependencies are intentional, please verify that the
|
||||
* license is one of the allowed licenses (see
|
||||
* config/dependency-license/allowed_licenses.json) and add an entry
|
||||
* for the package (with the license in a comment) to the
|
||||
* EXPECTED_JS_PACKAGES variable in config/presubmits.py.
|
||||
"""))
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def get_files():
|
||||
for root, dirnames, filenames in os.walk("."):
|
||||
for filename in filenames:
|
||||
@@ -333,5 +360,8 @@ if __name__ == "__main__":
|
||||
# when we put it here it fails fast before all of the tests are run.
|
||||
failed |= verify_flyway_index()
|
||||
|
||||
# Make sure we haven't introduced any javascript dependencies.
|
||||
failed |= verify_javascript_deps()
|
||||
|
||||
if failed:
|
||||
sys.exit(1)
|
||||
|
||||
@@ -44,7 +44,6 @@ def outcastTestPatterns = [
|
||||
"google/registry/flows/domain/DomainCreateFlowTest.*",
|
||||
"google/registry/flows/domain/DomainUpdateFlowTest.*",
|
||||
"google/registry/tools/CreateDomainCommandTest.*",
|
||||
"google/registry/tools/server/CreatePremiumListActionTest.*",
|
||||
]
|
||||
|
||||
// Tests that fail when running Gradle in a docker container, e. g. when
|
||||
@@ -70,8 +69,6 @@ def dockerIncompatibleTestPatterns = [
|
||||
// Nomulus classes, e.g., threads and objects retained by frameworks.
|
||||
// TODO(weiminyu): identify cause and fix offending tests.
|
||||
def fragileTestPatterns = [
|
||||
// Problem seems to lie with AppEngine TaskQueue for test.
|
||||
"google/registry/cron/TldFanoutActionTest.*",
|
||||
// Test Datastore inexplicably aborts transaction.
|
||||
"google/registry/model/tmch/ClaimsListShardTest.*",
|
||||
// Changes cache timeouts and for some reason appears to have contention
|
||||
@@ -185,6 +182,7 @@ dependencies {
|
||||
compile deps['com.google.monitoring-client:metrics']
|
||||
compile deps['com.google.monitoring-client:stackdriver']
|
||||
compile deps['com.google.api-client:google-api-client-java6']
|
||||
compile deps['com.google.api.grpc:proto-google-cloud-tasks-v2']
|
||||
compile deps['com.google.apis:google-api-services-admin-directory']
|
||||
compile deps['com.google.apis:google-api-services-appengine']
|
||||
compile deps['com.google.apis:google-api-services-bigquery']
|
||||
@@ -217,11 +215,13 @@ dependencies {
|
||||
compile deps['com.google.flogger:flogger']
|
||||
runtime deps['com.google.flogger:flogger-system-backend']
|
||||
compile deps['com.google.guava:guava']
|
||||
compile deps['com.google.protobuf:protobuf-java']
|
||||
gradleLint.ignore('unused-dependency') {
|
||||
compile deps['com.google.gwt:gwt-user']
|
||||
}
|
||||
compile deps['com.google.cloud:google-cloud-core']
|
||||
compile deps['com.google.cloud:google-cloud-storage']
|
||||
compile deps['com.google.cloud:google-cloud-tasks']
|
||||
compile deps['com.google.http-client:google-http-client']
|
||||
compile deps['com.google.http-client:google-http-client-appengine']
|
||||
compile deps['com.google.http-client:google-http-client-jackson2']
|
||||
@@ -457,6 +457,22 @@ task soyToJava {
|
||||
"--srcs", "${soyFiles.join(',')}",
|
||||
"--compileTimeGlobalsFile", "${resourcesSourceDir}/google/registry/ui/globals.txt"
|
||||
}
|
||||
|
||||
// Replace the "@link" tags after the "@deprecated" tags in the generated
|
||||
// files. The soy compiler doesn't generate imports for these, causing
|
||||
// us to get warnings when we generate javadocs.
|
||||
// TODO(b/200296387): To be fair, the deprecations are accurate: we're
|
||||
// using the old "SoyInfo" classes instead of the new "Templates" files.
|
||||
// When we convert to the new classes, this hack can go away.
|
||||
def outputs = fileTree(outputDirectory) {
|
||||
include '**/*.java'
|
||||
}
|
||||
|
||||
outputs.each { file ->
|
||||
exec {
|
||||
commandLine 'sed', '-i', 's/@link/LINK/g', file.getCanonicalPath()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doLast {
|
||||
|
||||
@@ -54,12 +54,15 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.1.0
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.10
|
||||
com.google.api:api-common:1.10.1
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.79.0
|
||||
com.google.api:gax:1.62.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
com.google.apis:google-api-services-appengine:v1-rev130-1.25.0
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20200916-1.30.10
|
||||
@@ -83,10 +86,10 @@ com.google.appengine.tools:appengine-pipeline:0.2.13
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86
|
||||
com.google.appengine:appengine-remote-api:1.9.86
|
||||
com.google.appengine:appengine-testing:1.9.86
|
||||
com.google.auth:google-auth-library-credentials:0.24.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.24.1
|
||||
com.google.auth:google-auth-library-credentials:0.26.0
|
||||
com.google.auth:google-auth-library-oauth2-http:0.26.0
|
||||
com.google.auto.service:auto-service-annotations:1.0-rc7
|
||||
com.google.auto.value:auto-value-annotations:1.7.4
|
||||
com.google.auto.value:auto-value-annotations:1.8.1
|
||||
com.google.auto.value:auto-value:1.7.4
|
||||
com.google.cloud.bigdataoss:gcsio:2.1.6
|
||||
com.google.cloud.bigdataoss:util:2.1.6
|
||||
@@ -104,11 +107,12 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.113.12
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.6
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
com.google.dagger:dagger:2.33
|
||||
com.google.errorprone:error_prone_annotations:2.5.1
|
||||
com.google.errorprone:error_prone_annotations:2.7.1
|
||||
com.google.escapevelocity:escapevelocity:0.9.1
|
||||
com.google.flogger:flogger-system-backend:0.5.1
|
||||
com.google.flogger:flogger:0.5.1
|
||||
@@ -119,10 +123,10 @@ com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.9.0
|
||||
com.google.http-client:google-http-client-apache-v2:1.39.0
|
||||
com.google.http-client:google-http-client-appengine:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.2
|
||||
com.google.http-client:google-http-client-jackson2:1.39.0
|
||||
com.google.http-client:google-http-client-protobuf:1.33.0
|
||||
com.google.http-client:google-http-client:1.39.0
|
||||
com.google.http-client:google-http-client:1.39.2
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
@@ -134,8 +138,8 @@ com.google.oauth-client:google-oauth-client-java6:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.31.4
|
||||
com.google.oauth-client:google-oauth-client:1.31.4
|
||||
com.google.protobuf:protobuf-java-util:3.15.3
|
||||
com.google.protobuf:protobuf-java:3.15.3
|
||||
com.google.protobuf:protobuf-java-util:3.17.3
|
||||
com.google.protobuf:protobuf-java:3.17.3
|
||||
com.google.re2j:re2j:1.6
|
||||
com.google.template:soy:2021-02-01
|
||||
com.googlecode.charts4j:charts4j:1.3
|
||||
@@ -151,17 +155,17 @@ commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:3.3.1
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-context:1.36.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
@@ -259,7 +263,7 @@ org.testcontainers:database-commons:1.15.2
|
||||
org.testcontainers:jdbc:1.15.2
|
||||
org.testcontainers:postgresql:1.15.2
|
||||
org.testcontainers:testcontainers:1.15.2
|
||||
org.threeten:threetenbp:1.5.0
|
||||
org.threeten:threetenbp:1.5.1
|
||||
org.tukaani:xz:1.5
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
|
||||
@@ -53,12 +53,15 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.1.0
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.10
|
||||
com.google.api:api-common:1.10.1
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.79.0
|
||||
com.google.api:gax:1.62.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
com.google.apis:google-api-services-appengine:v1-rev130-1.25.0
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20200916-1.30.10
|
||||
@@ -82,10 +85,10 @@ com.google.appengine.tools:appengine-pipeline:0.2.13
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86
|
||||
com.google.appengine:appengine-remote-api:1.9.86
|
||||
com.google.appengine:appengine-testing:1.9.86
|
||||
com.google.auth:google-auth-library-credentials:0.24.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.24.1
|
||||
com.google.auth:google-auth-library-credentials:0.26.0
|
||||
com.google.auth:google-auth-library-oauth2-http:0.26.0
|
||||
com.google.auto.service:auto-service-annotations:1.0-rc7
|
||||
com.google.auto.value:auto-value-annotations:1.7.4
|
||||
com.google.auto.value:auto-value-annotations:1.8.1
|
||||
com.google.auto.value:auto-value:1.7.4
|
||||
com.google.cloud.bigdataoss:gcsio:2.1.6
|
||||
com.google.cloud.bigdataoss:util:2.1.6
|
||||
@@ -103,11 +106,12 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.113.12
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.6
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
com.google.dagger:dagger:2.33
|
||||
com.google.errorprone:error_prone_annotations:2.5.1
|
||||
com.google.errorprone:error_prone_annotations:2.7.1
|
||||
com.google.escapevelocity:escapevelocity:0.9.1
|
||||
com.google.flogger:flogger:0.5.1
|
||||
com.google.flogger:google-extensions:0.5.1
|
||||
@@ -117,10 +121,10 @@ com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.9.0
|
||||
com.google.http-client:google-http-client-apache-v2:1.39.0
|
||||
com.google.http-client:google-http-client-appengine:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.2
|
||||
com.google.http-client:google-http-client-jackson2:1.39.0
|
||||
com.google.http-client:google-http-client-protobuf:1.33.0
|
||||
com.google.http-client:google-http-client:1.39.0
|
||||
com.google.http-client:google-http-client:1.39.2
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
@@ -133,7 +137,7 @@ com.google.oauth-client:google-oauth-client-jetty:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.31.4
|
||||
com.google.oauth-client:google-oauth-client:1.31.4
|
||||
com.google.protobuf:protobuf-java-util:3.15.3
|
||||
com.google.protobuf:protobuf-java:3.15.3
|
||||
com.google.protobuf:protobuf-java:3.17.3
|
||||
com.google.re2j:re2j:1.6
|
||||
com.google.template:soy:2021-02-01
|
||||
com.googlecode.charts4j:charts4j:1.3
|
||||
@@ -149,17 +153,17 @@ commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:3.3.1
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-context:1.36.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
@@ -252,7 +256,7 @@ org.testcontainers:database-commons:1.15.2
|
||||
org.testcontainers:jdbc:1.15.2
|
||||
org.testcontainers:postgresql:1.15.2
|
||||
org.testcontainers:testcontainers:1.15.2
|
||||
org.threeten:threetenbp:1.5.0
|
||||
org.threeten:threetenbp:1.5.1
|
||||
org.tukaani:xz:1.5
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
|
||||
@@ -58,12 +58,15 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.1.0
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.10
|
||||
com.google.api:api-common:1.10.1
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.79.0
|
||||
com.google.api:gax:1.62.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
com.google.apis:google-api-services-appengine:v1-rev130-1.25.0
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20200916-1.30.10
|
||||
@@ -87,10 +90,10 @@ com.google.appengine.tools:appengine-pipeline:0.2.13
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86
|
||||
com.google.appengine:appengine-remote-api:1.9.86
|
||||
com.google.appengine:appengine-testing:1.9.86
|
||||
com.google.auth:google-auth-library-credentials:0.24.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.24.1
|
||||
com.google.auth:google-auth-library-credentials:0.26.0
|
||||
com.google.auth:google-auth-library-oauth2-http:0.26.0
|
||||
com.google.auto.service:auto-service-annotations:1.0-rc7
|
||||
com.google.auto.value:auto-value-annotations:1.7.4
|
||||
com.google.auto.value:auto-value-annotations:1.8.1
|
||||
com.google.auto.value:auto-value:1.7.4
|
||||
com.google.cloud.bigdataoss:gcsio:2.1.6
|
||||
com.google.cloud.bigdataoss:util:2.1.6
|
||||
@@ -109,11 +112,12 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.113.12
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.6
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
com.google.dagger:dagger:2.33
|
||||
com.google.errorprone:error_prone_annotations:2.5.1
|
||||
com.google.errorprone:error_prone_annotations:2.7.1
|
||||
com.google.escapevelocity:escapevelocity:0.9.1
|
||||
com.google.flogger:flogger-system-backend:0.5.1
|
||||
com.google.flogger:flogger:0.5.1
|
||||
@@ -124,10 +128,10 @@ com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.9.0
|
||||
com.google.http-client:google-http-client-apache-v2:1.39.0
|
||||
com.google.http-client:google-http-client-appengine:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.2
|
||||
com.google.http-client:google-http-client-jackson2:1.39.0
|
||||
com.google.http-client:google-http-client-protobuf:1.33.0
|
||||
com.google.http-client:google-http-client:1.39.0
|
||||
com.google.http-client:google-http-client:1.39.2
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
@@ -139,8 +143,8 @@ com.google.oauth-client:google-oauth-client-java6:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.31.4
|
||||
com.google.oauth-client:google-oauth-client:1.31.4
|
||||
com.google.protobuf:protobuf-java-util:3.15.3
|
||||
com.google.protobuf:protobuf-java:3.15.3
|
||||
com.google.protobuf:protobuf-java-util:3.17.3
|
||||
com.google.protobuf:protobuf-java:3.17.3
|
||||
com.google.re2j:re2j:1.6
|
||||
com.google.template:soy:2021-02-01
|
||||
com.googlecode.charts4j:charts4j:1.3
|
||||
@@ -159,17 +163,17 @@ guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-context:1.36.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
@@ -273,7 +277,7 @@ org.testcontainers:database-commons:1.15.2
|
||||
org.testcontainers:jdbc:1.15.2
|
||||
org.testcontainers:postgresql:1.15.2
|
||||
org.testcontainers:testcontainers:1.15.2
|
||||
org.threeten:threetenbp:1.5.0
|
||||
org.threeten:threetenbp:1.5.1
|
||||
org.tukaani:xz:1.5
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
|
||||
@@ -58,12 +58,15 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.1.0
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.10
|
||||
com.google.api:api-common:1.10.1
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.79.0
|
||||
com.google.api:gax:1.62.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
com.google.apis:google-api-services-appengine:v1-rev130-1.25.0
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20200916-1.30.10
|
||||
@@ -87,10 +90,10 @@ com.google.appengine.tools:appengine-pipeline:0.2.13
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86
|
||||
com.google.appengine:appengine-remote-api:1.9.86
|
||||
com.google.appengine:appengine-testing:1.9.86
|
||||
com.google.auth:google-auth-library-credentials:0.24.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.24.1
|
||||
com.google.auth:google-auth-library-credentials:0.26.0
|
||||
com.google.auth:google-auth-library-oauth2-http:0.26.0
|
||||
com.google.auto.service:auto-service-annotations:1.0-rc7
|
||||
com.google.auto.value:auto-value-annotations:1.7.4
|
||||
com.google.auto.value:auto-value-annotations:1.8.1
|
||||
com.google.auto.value:auto-value:1.7.4
|
||||
com.google.cloud.bigdataoss:gcsio:2.1.6
|
||||
com.google.cloud.bigdataoss:util:2.1.6
|
||||
@@ -109,11 +112,12 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.113.12
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.6
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
com.google.dagger:dagger:2.33
|
||||
com.google.errorprone:error_prone_annotations:2.5.1
|
||||
com.google.errorprone:error_prone_annotations:2.7.1
|
||||
com.google.escapevelocity:escapevelocity:0.9.1
|
||||
com.google.flogger:flogger-system-backend:0.5.1
|
||||
com.google.flogger:flogger:0.5.1
|
||||
@@ -124,10 +128,10 @@ com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.9.0
|
||||
com.google.http-client:google-http-client-apache-v2:1.39.0
|
||||
com.google.http-client:google-http-client-appengine:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.2
|
||||
com.google.http-client:google-http-client-jackson2:1.39.0
|
||||
com.google.http-client:google-http-client-protobuf:1.33.0
|
||||
com.google.http-client:google-http-client:1.39.0
|
||||
com.google.http-client:google-http-client:1.39.2
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
@@ -139,8 +143,8 @@ com.google.oauth-client:google-oauth-client-java6:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.31.4
|
||||
com.google.oauth-client:google-oauth-client:1.31.4
|
||||
com.google.protobuf:protobuf-java-util:3.15.3
|
||||
com.google.protobuf:protobuf-java:3.15.3
|
||||
com.google.protobuf:protobuf-java-util:3.17.3
|
||||
com.google.protobuf:protobuf-java:3.17.3
|
||||
com.google.re2j:re2j:1.6
|
||||
com.google.template:soy:2021-02-01
|
||||
com.googlecode.charts4j:charts4j:1.3
|
||||
@@ -159,17 +163,17 @@ guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-context:1.36.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
@@ -272,7 +276,7 @@ org.testcontainers:database-commons:1.15.2
|
||||
org.testcontainers:jdbc:1.15.2
|
||||
org.testcontainers:postgresql:1.15.2
|
||||
org.testcontainers:testcontainers:1.15.2
|
||||
org.threeten:threetenbp:1.5.0
|
||||
org.threeten:threetenbp:1.5.1
|
||||
org.tukaani:xz:1.5
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
|
||||
@@ -54,12 +54,15 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.1.0
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.10
|
||||
com.google.api:api-common:1.10.1
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.79.0
|
||||
com.google.api:gax:1.62.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
com.google.apis:google-api-services-appengine:v1-rev130-1.25.0
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20200916-1.30.10
|
||||
@@ -83,10 +86,10 @@ com.google.appengine.tools:appengine-pipeline:0.2.13
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86
|
||||
com.google.appengine:appengine-remote-api:1.9.86
|
||||
com.google.appengine:appengine-testing:1.9.86
|
||||
com.google.auth:google-auth-library-credentials:0.24.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.24.1
|
||||
com.google.auth:google-auth-library-credentials:0.26.0
|
||||
com.google.auth:google-auth-library-oauth2-http:0.26.0
|
||||
com.google.auto.service:auto-service-annotations:1.0-rc7
|
||||
com.google.auto.value:auto-value-annotations:1.7.4
|
||||
com.google.auto.value:auto-value-annotations:1.8.1
|
||||
com.google.auto.value:auto-value:1.7.4
|
||||
com.google.cloud.bigdataoss:gcsio:2.1.6
|
||||
com.google.cloud.bigdataoss:util:2.1.6
|
||||
@@ -104,11 +107,12 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.113.12
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.6
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
com.google.dagger:dagger:2.33
|
||||
com.google.errorprone:error_prone_annotations:2.5.1
|
||||
com.google.errorprone:error_prone_annotations:2.7.1
|
||||
com.google.escapevelocity:escapevelocity:0.9.1
|
||||
com.google.flogger:flogger-system-backend:0.5.1
|
||||
com.google.flogger:flogger:0.5.1
|
||||
@@ -119,10 +123,10 @@ com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.9.0
|
||||
com.google.http-client:google-http-client-apache-v2:1.39.0
|
||||
com.google.http-client:google-http-client-appengine:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.2
|
||||
com.google.http-client:google-http-client-jackson2:1.39.0
|
||||
com.google.http-client:google-http-client-protobuf:1.33.0
|
||||
com.google.http-client:google-http-client:1.39.0
|
||||
com.google.http-client:google-http-client:1.39.2
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
@@ -134,8 +138,8 @@ com.google.oauth-client:google-oauth-client-java6:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.31.4
|
||||
com.google.oauth-client:google-oauth-client:1.31.4
|
||||
com.google.protobuf:protobuf-java-util:3.15.3
|
||||
com.google.protobuf:protobuf-java:3.15.3
|
||||
com.google.protobuf:protobuf-java-util:3.17.3
|
||||
com.google.protobuf:protobuf-java:3.17.3
|
||||
com.google.re2j:re2j:1.6
|
||||
com.google.template:soy:2021-02-01
|
||||
com.googlecode.charts4j:charts4j:1.3
|
||||
@@ -151,17 +155,17 @@ commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:3.3.1
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-context:1.36.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
@@ -259,7 +263,7 @@ org.testcontainers:database-commons:1.15.2
|
||||
org.testcontainers:jdbc:1.15.2
|
||||
org.testcontainers:postgresql:1.15.2
|
||||
org.testcontainers:testcontainers:1.15.2
|
||||
org.threeten:threetenbp:1.5.0
|
||||
org.threeten:threetenbp:1.5.1
|
||||
org.tukaani:xz:1.5
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
|
||||
@@ -53,12 +53,15 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.1.0
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.10
|
||||
com.google.api:api-common:1.10.1
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.79.0
|
||||
com.google.api:gax:1.62.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
com.google.apis:google-api-services-appengine:v1-rev130-1.25.0
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20200916-1.30.10
|
||||
@@ -82,10 +85,10 @@ com.google.appengine.tools:appengine-pipeline:0.2.13
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86
|
||||
com.google.appengine:appengine-remote-api:1.9.86
|
||||
com.google.appengine:appengine-testing:1.9.86
|
||||
com.google.auth:google-auth-library-credentials:0.24.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.24.1
|
||||
com.google.auth:google-auth-library-credentials:0.26.0
|
||||
com.google.auth:google-auth-library-oauth2-http:0.26.0
|
||||
com.google.auto.service:auto-service-annotations:1.0-rc7
|
||||
com.google.auto.value:auto-value-annotations:1.7.4
|
||||
com.google.auto.value:auto-value-annotations:1.8.1
|
||||
com.google.auto.value:auto-value:1.7.4
|
||||
com.google.cloud.bigdataoss:gcsio:2.1.6
|
||||
com.google.cloud.bigdataoss:util:2.1.6
|
||||
@@ -103,11 +106,12 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.113.12
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.6
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
com.google.dagger:dagger:2.33
|
||||
com.google.errorprone:error_prone_annotations:2.5.1
|
||||
com.google.errorprone:error_prone_annotations:2.7.1
|
||||
com.google.escapevelocity:escapevelocity:0.9.1
|
||||
com.google.flogger:flogger:0.5.1
|
||||
com.google.flogger:google-extensions:0.5.1
|
||||
@@ -117,10 +121,10 @@ com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.9.0
|
||||
com.google.http-client:google-http-client-apache-v2:1.39.0
|
||||
com.google.http-client:google-http-client-appengine:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.2
|
||||
com.google.http-client:google-http-client-jackson2:1.39.0
|
||||
com.google.http-client:google-http-client-protobuf:1.33.0
|
||||
com.google.http-client:google-http-client:1.39.0
|
||||
com.google.http-client:google-http-client:1.39.2
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
@@ -133,7 +137,7 @@ com.google.oauth-client:google-oauth-client-jetty:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.31.4
|
||||
com.google.oauth-client:google-oauth-client:1.31.4
|
||||
com.google.protobuf:protobuf-java-util:3.15.3
|
||||
com.google.protobuf:protobuf-java:3.15.3
|
||||
com.google.protobuf:protobuf-java:3.17.3
|
||||
com.google.re2j:re2j:1.6
|
||||
com.google.template:soy:2021-02-01
|
||||
com.googlecode.charts4j:charts4j:1.3
|
||||
@@ -149,17 +153,17 @@ commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:3.3.1
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-context:1.36.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
@@ -253,7 +257,7 @@ org.testcontainers:database-commons:1.15.2
|
||||
org.testcontainers:jdbc:1.15.2
|
||||
org.testcontainers:postgresql:1.15.2
|
||||
org.testcontainers:testcontainers:1.15.2
|
||||
org.threeten:threetenbp:1.5.0
|
||||
org.threeten:threetenbp:1.5.1
|
||||
org.tukaani:xz:1.5
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
|
||||
@@ -58,12 +58,15 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.1.0
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.10
|
||||
com.google.api:api-common:1.10.1
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.79.0
|
||||
com.google.api:gax:1.62.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
com.google.apis:google-api-services-appengine:v1-rev130-1.25.0
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20200916-1.30.10
|
||||
@@ -87,10 +90,10 @@ com.google.appengine.tools:appengine-pipeline:0.2.13
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86
|
||||
com.google.appengine:appengine-remote-api:1.9.86
|
||||
com.google.appengine:appengine-testing:1.9.86
|
||||
com.google.auth:google-auth-library-credentials:0.24.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.24.1
|
||||
com.google.auth:google-auth-library-credentials:0.26.0
|
||||
com.google.auth:google-auth-library-oauth2-http:0.26.0
|
||||
com.google.auto.service:auto-service-annotations:1.0-rc7
|
||||
com.google.auto.value:auto-value-annotations:1.7.4
|
||||
com.google.auto.value:auto-value-annotations:1.8.1
|
||||
com.google.auto.value:auto-value:1.7.4
|
||||
com.google.cloud.bigdataoss:gcsio:2.1.6
|
||||
com.google.cloud.bigdataoss:util:2.1.6
|
||||
@@ -108,11 +111,12 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.113.12
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.6
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
com.google.dagger:dagger:2.33
|
||||
com.google.errorprone:error_prone_annotations:2.5.1
|
||||
com.google.errorprone:error_prone_annotations:2.7.1
|
||||
com.google.escapevelocity:escapevelocity:0.9.1
|
||||
com.google.flogger:flogger-system-backend:0.5.1
|
||||
com.google.flogger:flogger:0.5.1
|
||||
@@ -123,10 +127,10 @@ com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.9.0
|
||||
com.google.http-client:google-http-client-apache-v2:1.39.0
|
||||
com.google.http-client:google-http-client-appengine:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.2
|
||||
com.google.http-client:google-http-client-jackson2:1.39.0
|
||||
com.google.http-client:google-http-client-protobuf:1.33.0
|
||||
com.google.http-client:google-http-client:1.39.0
|
||||
com.google.http-client:google-http-client:1.39.2
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
@@ -138,8 +142,8 @@ com.google.oauth-client:google-oauth-client-java6:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.31.4
|
||||
com.google.oauth-client:google-oauth-client:1.31.4
|
||||
com.google.protobuf:protobuf-java-util:3.15.3
|
||||
com.google.protobuf:protobuf-java:3.15.3
|
||||
com.google.protobuf:protobuf-java-util:3.17.3
|
||||
com.google.protobuf:protobuf-java:3.17.3
|
||||
com.google.re2j:re2j:1.6
|
||||
com.google.template:soy:2021-02-01
|
||||
com.googlecode.charts4j:charts4j:1.3
|
||||
@@ -158,17 +162,17 @@ guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-context:1.36.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
@@ -271,7 +275,7 @@ org.testcontainers:database-commons:1.15.2
|
||||
org.testcontainers:jdbc:1.15.2
|
||||
org.testcontainers:postgresql:1.15.2
|
||||
org.testcontainers:testcontainers:1.15.2
|
||||
org.threeten:threetenbp:1.5.0
|
||||
org.threeten:threetenbp:1.5.1
|
||||
org.tukaani:xz:1.5
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
|
||||
@@ -58,12 +58,15 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.1.0
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.10
|
||||
com.google.api:api-common:1.10.1
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.79.0
|
||||
com.google.api:gax:1.62.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
com.google.apis:google-api-services-appengine:v1-rev130-1.25.0
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20200916-1.30.10
|
||||
@@ -87,10 +90,10 @@ com.google.appengine.tools:appengine-pipeline:0.2.13
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86
|
||||
com.google.appengine:appengine-remote-api:1.9.86
|
||||
com.google.appengine:appengine-testing:1.9.86
|
||||
com.google.auth:google-auth-library-credentials:0.24.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.24.1
|
||||
com.google.auth:google-auth-library-credentials:0.26.0
|
||||
com.google.auth:google-auth-library-oauth2-http:0.26.0
|
||||
com.google.auto.service:auto-service-annotations:1.0-rc7
|
||||
com.google.auto.value:auto-value-annotations:1.7.4
|
||||
com.google.auto.value:auto-value-annotations:1.8.1
|
||||
com.google.auto.value:auto-value:1.7.4
|
||||
com.google.cloud.bigdataoss:gcsio:2.1.6
|
||||
com.google.cloud.bigdataoss:util:2.1.6
|
||||
@@ -108,11 +111,12 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.113.12
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.6
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
com.google.dagger:dagger:2.33
|
||||
com.google.errorprone:error_prone_annotations:2.5.1
|
||||
com.google.errorprone:error_prone_annotations:2.7.1
|
||||
com.google.escapevelocity:escapevelocity:0.9.1
|
||||
com.google.flogger:flogger-system-backend:0.5.1
|
||||
com.google.flogger:flogger:0.5.1
|
||||
@@ -123,10 +127,10 @@ com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.9.0
|
||||
com.google.http-client:google-http-client-apache-v2:1.39.0
|
||||
com.google.http-client:google-http-client-appengine:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.2
|
||||
com.google.http-client:google-http-client-jackson2:1.39.0
|
||||
com.google.http-client:google-http-client-protobuf:1.33.0
|
||||
com.google.http-client:google-http-client:1.39.0
|
||||
com.google.http-client:google-http-client:1.39.2
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
@@ -138,8 +142,8 @@ com.google.oauth-client:google-oauth-client-java6:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.31.4
|
||||
com.google.oauth-client:google-oauth-client:1.31.4
|
||||
com.google.protobuf:protobuf-java-util:3.15.3
|
||||
com.google.protobuf:protobuf-java:3.15.3
|
||||
com.google.protobuf:protobuf-java-util:3.17.3
|
||||
com.google.protobuf:protobuf-java:3.17.3
|
||||
com.google.re2j:re2j:1.6
|
||||
com.google.template:soy:2021-02-01
|
||||
com.googlecode.charts4j:charts4j:1.3
|
||||
@@ -158,17 +162,17 @@ guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-context:1.36.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
@@ -271,7 +275,7 @@ org.testcontainers:database-commons:1.15.2
|
||||
org.testcontainers:jdbc:1.15.2
|
||||
org.testcontainers:postgresql:1.15.2
|
||||
org.testcontainers:testcontainers:1.15.2
|
||||
org.threeten:threetenbp:1.5.0
|
||||
org.threeten:threetenbp:1.5.1
|
||||
org.tukaani:xz:1.5
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
|
||||
@@ -58,12 +58,15 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.1.0
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.10
|
||||
com.google.api:api-common:1.10.1
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.79.0
|
||||
com.google.api:gax:1.62.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
com.google.apis:google-api-services-appengine:v1-rev130-1.25.0
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20200916-1.30.10
|
||||
@@ -87,10 +90,10 @@ com.google.appengine.tools:appengine-pipeline:0.2.13
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86
|
||||
com.google.appengine:appengine-remote-api:1.9.86
|
||||
com.google.appengine:appengine-testing:1.9.86
|
||||
com.google.auth:google-auth-library-credentials:0.24.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.24.1
|
||||
com.google.auth:google-auth-library-credentials:0.26.0
|
||||
com.google.auth:google-auth-library-oauth2-http:0.26.0
|
||||
com.google.auto.service:auto-service-annotations:1.0-rc7
|
||||
com.google.auto.value:auto-value-annotations:1.7.4
|
||||
com.google.auto.value:auto-value-annotations:1.8.1
|
||||
com.google.auto.value:auto-value:1.7.4
|
||||
com.google.cloud.bigdataoss:gcsio:2.1.6
|
||||
com.google.cloud.bigdataoss:util:2.1.6
|
||||
@@ -108,11 +111,12 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.113.12
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.6
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
com.google.dagger:dagger:2.33
|
||||
com.google.errorprone:error_prone_annotations:2.5.1
|
||||
com.google.errorprone:error_prone_annotations:2.7.1
|
||||
com.google.escapevelocity:escapevelocity:0.9.1
|
||||
com.google.flogger:flogger-system-backend:0.5.1
|
||||
com.google.flogger:flogger:0.5.1
|
||||
@@ -123,10 +127,10 @@ com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.9.0
|
||||
com.google.http-client:google-http-client-apache-v2:1.39.0
|
||||
com.google.http-client:google-http-client-appengine:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.2
|
||||
com.google.http-client:google-http-client-jackson2:1.39.0
|
||||
com.google.http-client:google-http-client-protobuf:1.33.0
|
||||
com.google.http-client:google-http-client:1.39.0
|
||||
com.google.http-client:google-http-client:1.39.2
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
@@ -138,8 +142,8 @@ com.google.oauth-client:google-oauth-client-java6:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.31.4
|
||||
com.google.oauth-client:google-oauth-client:1.31.4
|
||||
com.google.protobuf:protobuf-java-util:3.15.3
|
||||
com.google.protobuf:protobuf-java:3.15.3
|
||||
com.google.protobuf:protobuf-java-util:3.17.3
|
||||
com.google.protobuf:protobuf-java:3.17.3
|
||||
com.google.re2j:re2j:1.6
|
||||
com.google.template:soy:2021-02-01
|
||||
com.googlecode.charts4j:charts4j:1.3
|
||||
@@ -158,17 +162,17 @@ guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-context:1.36.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
@@ -271,7 +275,7 @@ org.testcontainers:database-commons:1.15.2
|
||||
org.testcontainers:jdbc:1.15.2
|
||||
org.testcontainers:postgresql:1.15.2
|
||||
org.testcontainers:testcontainers:1.15.2
|
||||
org.threeten:threetenbp:1.5.0
|
||||
org.threeten:threetenbp:1.5.1
|
||||
org.tukaani:xz:1.5
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
|
||||
@@ -58,12 +58,15 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.1.0
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.10
|
||||
com.google.api:api-common:1.10.1
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.79.0
|
||||
com.google.api:gax:1.62.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
com.google.apis:google-api-services-appengine:v1-rev130-1.25.0
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20200916-1.30.10
|
||||
@@ -87,10 +90,10 @@ com.google.appengine.tools:appengine-pipeline:0.2.13
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86
|
||||
com.google.appengine:appengine-remote-api:1.9.86
|
||||
com.google.appengine:appengine-testing:1.9.86
|
||||
com.google.auth:google-auth-library-credentials:0.24.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.24.1
|
||||
com.google.auth:google-auth-library-credentials:0.26.0
|
||||
com.google.auth:google-auth-library-oauth2-http:0.26.0
|
||||
com.google.auto.service:auto-service-annotations:1.0-rc7
|
||||
com.google.auto.value:auto-value-annotations:1.7.4
|
||||
com.google.auto.value:auto-value-annotations:1.8.1
|
||||
com.google.auto.value:auto-value:1.7.4
|
||||
com.google.cloud.bigdataoss:gcsio:2.1.6
|
||||
com.google.cloud.bigdataoss:util:2.1.6
|
||||
@@ -109,11 +112,12 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.113.12
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.6
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
com.google.dagger:dagger:2.33
|
||||
com.google.errorprone:error_prone_annotations:2.5.1
|
||||
com.google.errorprone:error_prone_annotations:2.7.1
|
||||
com.google.escapevelocity:escapevelocity:0.9.1
|
||||
com.google.flogger:flogger-system-backend:0.5.1
|
||||
com.google.flogger:flogger:0.5.1
|
||||
@@ -124,10 +128,10 @@ com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.9.0
|
||||
com.google.http-client:google-http-client-apache-v2:1.39.0
|
||||
com.google.http-client:google-http-client-appengine:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.0
|
||||
com.google.http-client:google-http-client-gson:1.39.2
|
||||
com.google.http-client:google-http-client-jackson2:1.39.0
|
||||
com.google.http-client:google-http-client-protobuf:1.33.0
|
||||
com.google.http-client:google-http-client:1.39.0
|
||||
com.google.http-client:google-http-client:1.39.2
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
@@ -139,8 +143,8 @@ com.google.oauth-client:google-oauth-client-java6:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.31.4
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.31.4
|
||||
com.google.oauth-client:google-oauth-client:1.31.4
|
||||
com.google.protobuf:protobuf-java-util:3.15.3
|
||||
com.google.protobuf:protobuf-java:3.15.3
|
||||
com.google.protobuf:protobuf-java-util:3.17.3
|
||||
com.google.protobuf:protobuf-java:3.17.3
|
||||
com.google.re2j:re2j:1.6
|
||||
com.google.template:soy:2021-02-01
|
||||
com.googlecode.charts4j:charts4j:1.3
|
||||
@@ -159,17 +163,17 @@ guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-context:1.36.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
@@ -272,7 +276,7 @@ org.testcontainers:database-commons:1.15.2
|
||||
org.testcontainers:jdbc:1.15.2
|
||||
org.testcontainers:postgresql:1.15.2
|
||||
org.testcontainers:testcontainers:1.15.2
|
||||
org.threeten:threetenbp:1.5.0
|
||||
org.threeten:threetenbp:1.5.1
|
||||
org.tukaani:xz:1.5
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
|
||||
@@ -54,10 +54,13 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.83.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
@@ -106,6 +109,7 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.118.0
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
@@ -160,17 +164,17 @@ commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:3.3.1
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.102
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
|
||||
@@ -53,10 +53,13 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.83.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
@@ -105,6 +108,7 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.118.0
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
@@ -158,17 +162,17 @@ commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:3.3.1
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.102
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
|
||||
@@ -58,10 +58,13 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.83.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
@@ -111,6 +114,7 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.118.0
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
@@ -169,17 +173,17 @@ guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.102
|
||||
io.github.java-diff-utils:java-diff-utils:4.9
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
|
||||
@@ -58,10 +58,13 @@ com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:1.4.0
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:2.0.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:1.33.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.89.2
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.89.2
|
||||
com.google.api.grpc:proto-google-common-protos:2.3.2
|
||||
com.google.api.grpc:proto-google-iam-v1:1.0.14
|
||||
com.google.api:api-common:1.10.4
|
||||
com.google.api:gax-grpc:1.62.0
|
||||
com.google.api:gax-grpc:1.66.0
|
||||
com.google.api:gax-httpjson:0.83.0
|
||||
com.google.api:gax:1.66.0
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0
|
||||
@@ -111,6 +114,7 @@ com.google.cloud:google-cloud-pubsublite:0.7.0
|
||||
com.google.cloud:google-cloud-secretmanager:1.4.0
|
||||
com.google.cloud:google-cloud-spanner:2.0.2
|
||||
com.google.cloud:google-cloud-storage:1.118.0
|
||||
com.google.cloud:google-cloud-tasks:1.33.2
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.7
|
||||
com.google.common.html.types:types:1.0.6
|
||||
@@ -169,17 +173,17 @@ guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.102
|
||||
io.github.java-diff-utils:java-diff-utils:4.9
|
||||
io.grpc:grpc-alts:1.36.0
|
||||
io.grpc:grpc-api:1.36.0
|
||||
io.grpc:grpc-auth:1.36.0
|
||||
io.grpc:grpc-alts:1.39.0
|
||||
io.grpc:grpc-api:1.39.0
|
||||
io.grpc:grpc-auth:1.39.0
|
||||
io.grpc:grpc-context:1.39.0
|
||||
io.grpc:grpc-core:1.36.0
|
||||
io.grpc:grpc-grpclb:1.36.0
|
||||
io.grpc:grpc-netty-shaded:1.36.0
|
||||
io.grpc:grpc-core:1.39.0
|
||||
io.grpc:grpc-grpclb:1.39.0
|
||||
io.grpc:grpc-netty-shaded:1.39.0
|
||||
io.grpc:grpc-netty:1.32.2
|
||||
io.grpc:grpc-protobuf-lite:1.36.0
|
||||
io.grpc:grpc-protobuf:1.36.0
|
||||
io.grpc:grpc-stub:1.36.0
|
||||
io.grpc:grpc-protobuf-lite:1.39.0
|
||||
io.grpc:grpc-protobuf:1.39.0
|
||||
io.grpc:grpc-stub:1.39.0
|
||||
io.netty:netty-buffer:4.1.51.Final
|
||||
io.netty:netty-codec-http2:4.1.51.Final
|
||||
io.netty:netty-codec-http:4.1.51.Final
|
||||
|
||||
@@ -48,7 +48,7 @@ public class AppEngineEnvironment implements Closeable {
|
||||
|
||||
public AppEngineEnvironment(String appId) {
|
||||
isPlaceHolderNeeded = ApiProxy.getCurrentEnvironment() == null;
|
||||
// isPlaceHolderNeeded may be true when we are invoked in a test with AppEngineRule.
|
||||
// isPlaceHolderNeeded may be true when we are invoked in a test with AppEngineExtension.
|
||||
if (isPlaceHolderNeeded) {
|
||||
ApiProxy.setEnvironmentForCurrentThread(createAppEngineEnvironment(appId));
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.ReplayDirection;
|
||||
@@ -222,8 +223,11 @@ public class ReplayCommitLogsToSqlAction implements Runnable {
|
||||
// Load and process the Datastore transactions one at a time
|
||||
ImmutableList<ImmutableList<VersionedEntity>> allTransactions =
|
||||
CommitLogImports.loadEntitiesByTransaction(input);
|
||||
allTransactions.forEach(
|
||||
transaction -> jpaTm().transact(() -> replayTransaction(transaction)));
|
||||
try (UpdateAutoTimestamp.DisableAutoUpdateResource disabler =
|
||||
UpdateAutoTimestamp.disableAutoUpdate()) {
|
||||
allTransactions.forEach(
|
||||
transaction -> jpaTm().transact(() -> replayTransaction(transaction)));
|
||||
}
|
||||
// if we succeeded, set the last-seen time
|
||||
DateTime checkpoint = DateTime.parse(metadata.getName().substring(DIFF_FILE_PREFIX.length()));
|
||||
jpaTm().transact(() -> SqlReplayCheckpoint.set(checkpoint));
|
||||
@@ -260,7 +264,7 @@ public class ReplayCommitLogsToSqlAction implements Runnable {
|
||||
.ifPresent(
|
||||
sqlEntity -> {
|
||||
sqlEntity.beforeSqlSaveOnReplay();
|
||||
jpaTm().put(sqlEntity);
|
||||
jpaTm().putIgnoringReadOnly(sqlEntity);
|
||||
});
|
||||
} else {
|
||||
// this should never happen, but we shouldn't fail on it
|
||||
@@ -293,7 +297,7 @@ public class ReplayCommitLogsToSqlAction implements Runnable {
|
||||
&& !DatastoreOnlyEntity.class.isAssignableFrom(entityClass)
|
||||
&& entityClass.getAnnotation(javax.persistence.Entity.class) != null) {
|
||||
ReplaySpecializer.beforeSqlDelete(entityVKey);
|
||||
jpaTm().delete(entityVKey);
|
||||
jpaTm().deleteIgnoringReadOnly(entityVKey);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
logger.atSevere().log("Error when deleting key %s", entityVKey);
|
||||
|
||||
@@ -126,18 +126,18 @@ public final class AsyncTaskEnqueuer {
|
||||
public void enqueueAsyncDelete(
|
||||
EppResource resourceToDelete,
|
||||
DateTime now,
|
||||
String requestingClientId,
|
||||
String requestingRegistrarId,
|
||||
Trid trid,
|
||||
boolean isSuperuser) {
|
||||
Key<EppResource> resourceKey = Key.create(resourceToDelete);
|
||||
logger.atInfo().log(
|
||||
"Enqueuing async deletion of %s on behalf of registrar %s.",
|
||||
resourceKey, requestingClientId);
|
||||
resourceKey, requestingRegistrarId);
|
||||
TaskOptions task =
|
||||
TaskOptions.Builder.withMethod(Method.PULL)
|
||||
.countdownMillis(asyncDeleteDelay.getMillis())
|
||||
.param(PARAM_RESOURCE_KEY, resourceKey.getString())
|
||||
.param(PARAM_REQUESTING_CLIENT_ID, requestingClientId)
|
||||
.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());
|
||||
|
||||
@@ -24,6 +24,7 @@ import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_HOST_RENAME;
|
||||
import static google.registry.request.RequestParameters.extractIntParameter;
|
||||
import static google.registry.request.RequestParameters.extractLongParameter;
|
||||
import static google.registry.request.RequestParameters.extractOptionalBooleanParameter;
|
||||
import static google.registry.request.RequestParameters.extractOptionalDatetimeParameter;
|
||||
import static google.registry.request.RequestParameters.extractOptionalIntParameter;
|
||||
import static google.registry.request.RequestParameters.extractOptionalParameter;
|
||||
import static google.registry.request.RequestParameters.extractRequiredDatetimeParameter;
|
||||
@@ -106,6 +107,13 @@ public class BatchModule {
|
||||
return extractIntParameter(req, RelockDomainAction.PREVIOUS_ATTEMPTS_PARAM);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter(ExpandRecurringBillingEventsAction.PARAM_CURSOR_TIME)
|
||||
static Optional<DateTime> provideCursorTime(HttpServletRequest req) {
|
||||
return extractOptionalDatetimeParameter(
|
||||
req, ExpandRecurringBillingEventsAction.PARAM_CURSOR_TIME);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named(QUEUE_ASYNC_ACTIONS)
|
||||
static Queue provideAsyncActionsPushQueue() {
|
||||
|
||||
@@ -343,15 +343,15 @@ public class DeleteContactsAndHostsAction implements Runnable {
|
||||
}
|
||||
// Contacts and external hosts have a direct client id. For subordinate hosts it needs to be
|
||||
// read off of the superordinate domain.
|
||||
String resourceClientId = resource.getPersistedCurrentSponsorClientId();
|
||||
String resourceRegistrarId = resource.getPersistedCurrentSponsorRegistrarId();
|
||||
if (resource instanceof HostResource && ((HostResource) resource).isSubordinate()) {
|
||||
resourceClientId =
|
||||
resourceRegistrarId =
|
||||
tm().loadByKey(((HostResource) resource).getSuperordinateDomain())
|
||||
.cloneProjectedAtTime(now)
|
||||
.getCurrentSponsorClientId();
|
||||
.getCurrentSponsorRegistrarId();
|
||||
}
|
||||
boolean requestedByCurrentOwner =
|
||||
resourceClientId.equals(deletionRequest.requestingClientId());
|
||||
resourceRegistrarId.equals(deletionRequest.requestingClientId());
|
||||
|
||||
boolean deleteAllowed =
|
||||
hasNoActiveReferences && (requestedByCurrentOwner || deletionRequest.isSuperuser());
|
||||
@@ -371,14 +371,14 @@ public class DeleteContactsAndHostsAction implements Runnable {
|
||||
|
||||
HistoryEntry historyEntry =
|
||||
HistoryEntry.createBuilderForResource(resource)
|
||||
.setClientId(deletionRequest.requestingClientId())
|
||||
.setRegistrarId(deletionRequest.requestingClientId())
|
||||
.setModificationTime(now)
|
||||
.setType(getHistoryEntryType(resource, deleteAllowed))
|
||||
.build();
|
||||
|
||||
PollMessage.OneTime pollMessage =
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setClientId(deletionRequest.requestingClientId())
|
||||
.setRegistrarId(deletionRequest.requestingClientId())
|
||||
.setMsg(pollMessageText)
|
||||
.setParent(historyEntry)
|
||||
.setEventTime(now)
|
||||
|
||||
@@ -135,7 +135,7 @@ public class DeleteLoadTestDataAction implements Runnable {
|
||||
}
|
||||
|
||||
private void deleteContact(ContactResource contact) {
|
||||
if (!LOAD_TEST_REGISTRARS.contains(contact.getPersistedCurrentSponsorClientId())) {
|
||||
if (!LOAD_TEST_REGISTRARS.contains(contact.getPersistedCurrentSponsorRegistrarId())) {
|
||||
return;
|
||||
}
|
||||
// We cannot remove contacts from domains in the general case, so we cannot delete contacts
|
||||
@@ -150,7 +150,7 @@ public class DeleteLoadTestDataAction implements Runnable {
|
||||
}
|
||||
|
||||
private void deleteHost(HostResource host) {
|
||||
if (!LOAD_TEST_REGISTRARS.contains(host.getPersistedCurrentSponsorClientId())) {
|
||||
if (!LOAD_TEST_REGISTRARS.contains(host.getPersistedCurrentSponsorRegistrarId())) {
|
||||
return;
|
||||
}
|
||||
VKey<HostResource> hostVKey = host.createVKey();
|
||||
@@ -198,7 +198,7 @@ public class DeleteLoadTestDataAction implements Runnable {
|
||||
|
||||
@Override
|
||||
public final void map(EppResource resource) {
|
||||
if (LOAD_TEST_REGISTRARS.contains(resource.getPersistedCurrentSponsorClientId())) {
|
||||
if (LOAD_TEST_REGISTRARS.contains(resource.getPersistedCurrentSponsorRegistrarId())) {
|
||||
deleteResource(resource);
|
||||
getContext()
|
||||
.incrementCounter(
|
||||
|
||||
@@ -23,6 +23,7 @@ import static google.registry.model.ResourceTransferUtils.updateForeignKeyIndexD
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_DELETE;
|
||||
import static google.registry.model.tld.Registries.getTldsOfType;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.request.RequestParameters.PARAM_TLDS;
|
||||
@@ -42,6 +43,7 @@ import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.dns.DnsQueue;
|
||||
import google.registry.mapreduce.MapreduceRunner;
|
||||
import google.registry.mapreduce.inputs.EppResourceInputs;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import google.registry.model.EppResourceUtils;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
@@ -54,15 +56,18 @@ import google.registry.request.Parameter;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import javax.inject.Inject;
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.query.Query;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* Deletes all prober DomainBases and their subordinate history entries, poll messages, and
|
||||
* billing events, along with their ForeignKeyDomainIndex and EppResourceIndex entities.
|
||||
*
|
||||
* <p>See: https://www.youtube.com/watch?v=xuuv0syoHnM
|
||||
* Deletes all prober DomainBases and their subordinate history entries, poll messages, and billing
|
||||
* events, along with their ForeignKeyDomainIndex and EppResourceIndex entities.
|
||||
*/
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
@@ -73,10 +78,51 @@ public class DeleteProberDataAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
/**
|
||||
* The maximum amount of time we allow a prober domain to be in use.
|
||||
*
|
||||
* <p>In practice, the prober's connection will time out well before this duration. This includes
|
||||
* a decent buffer.
|
||||
*/
|
||||
private static final Duration DOMAIN_USED_DURATION = Duration.standardHours(1);
|
||||
|
||||
/**
|
||||
* The minimum amount of time we want a domain to be "soft deleted".
|
||||
*
|
||||
* <p>The domain has to remain soft deleted for at least enough time for the DNS task to run and
|
||||
* remove it from DNS itself. This is probably on the order of minutes.
|
||||
*/
|
||||
private static final Duration SOFT_DELETE_DELAY = Duration.standardHours(1);
|
||||
|
||||
private static final DnsQueue dnsQueue = DnsQueue.create();
|
||||
|
||||
// Domains to delete must:
|
||||
// 1. Be in one of the prober TLDs
|
||||
// 2. Not be a nic domain
|
||||
// 3. Have no subordinate hosts
|
||||
// 4. Not still be used (within an hour of creation time)
|
||||
// 5. Either be active (creationTime <= now < deletionTime) or have been deleted a while ago (this
|
||||
// prevents accidental double-map with the same key from immediately deleting active domains)
|
||||
//
|
||||
// Note: creationTime must be compared to a Java object (CreateAutoTimestamp) but deletionTime can
|
||||
// be compared directly to the SQL timestamp (it's a DateTime)
|
||||
private static final String DOMAIN_QUERY_STRING =
|
||||
"FROM Domain d WHERE d.tld IN :tlds AND d.fullyQualifiedDomainName NOT LIKE 'nic.%' AND"
|
||||
+ " (d.subordinateHosts IS EMPTY OR d.subordinateHosts IS NULL) AND d.creationTime <"
|
||||
+ " :creationTimeCutoff AND ((d.creationTime <= :nowAutoTimestamp AND d.deletionTime >"
|
||||
+ " current_timestamp()) OR d.deletionTime < :nowMinusSoftDeleteDelay) ORDER BY d.repoId";
|
||||
|
||||
/** Number of domains to retrieve and delete per SQL transaction. */
|
||||
private static final int BATCH_SIZE = 1000;
|
||||
|
||||
@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 @Config("registryAdminClientId") String registryAdminClientId;
|
||||
|
||||
@Inject
|
||||
@Config("registryAdminClientId")
|
||||
String registryAdminRegistrarId;
|
||||
|
||||
@Inject MapreduceRunner mrRunner;
|
||||
@Inject Response response;
|
||||
@Inject DeleteProberDataAction() {}
|
||||
@@ -84,25 +130,14 @@ public class DeleteProberDataAction implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
checkState(
|
||||
!Strings.isNullOrEmpty(registryAdminClientId),
|
||||
!Strings.isNullOrEmpty(registryAdminRegistrarId),
|
||||
"Registry admin client ID must be configured for prober data deletion to work");
|
||||
mrRunner
|
||||
.setJobName("Delete prober data")
|
||||
.setModuleName("backend")
|
||||
.runMapOnly(
|
||||
new DeleteProberDataMapper(getProberRoidSuffixes(), isDryRun, registryAdminClientId),
|
||||
ImmutableList.of(EppResourceInputs.createKeyInput(DomainBase.class)))
|
||||
.sendLinkToMapreduceConsole(response);
|
||||
}
|
||||
|
||||
private ImmutableSet<String> getProberRoidSuffixes() {
|
||||
checkArgument(
|
||||
!PRODUCTION.equals(RegistryEnvironment.get())
|
||||
|| tlds.stream().allMatch(tld -> tld.endsWith(".test")),
|
||||
"On production, can only work on TLDs that end with .test");
|
||||
ImmutableSet<String> deletableTlds =
|
||||
getTldsOfType(TldType.TEST)
|
||||
.stream()
|
||||
getTldsOfType(TldType.TEST).stream()
|
||||
.filter(tld -> tlds.isEmpty() ? tld.endsWith(".test") : tlds.contains(tld))
|
||||
.collect(toImmutableSet());
|
||||
checkArgument(
|
||||
@@ -110,10 +145,161 @@ public class DeleteProberDataAction implements Runnable {
|
||||
"If tlds are given, they must all exist and be TEST tlds. Given: %s, not found: %s",
|
||||
tlds,
|
||||
Sets.difference(tlds, deletableTlds));
|
||||
return deletableTlds
|
||||
.stream()
|
||||
.map(tld -> Registry.get(tld).getRoidSuffix())
|
||||
.collect(toImmutableSet());
|
||||
ImmutableSet<String> proberRoidSuffixes =
|
||||
deletableTlds.stream()
|
||||
.map(tld -> Registry.get(tld).getRoidSuffix())
|
||||
.collect(toImmutableSet());
|
||||
if (tm().isOfy()) {
|
||||
mrRunner
|
||||
.setJobName("Delete prober data")
|
||||
.setModuleName("backend")
|
||||
.runMapOnly(
|
||||
new DeleteProberDataMapper(proberRoidSuffixes, isDryRun, registryAdminRegistrarId),
|
||||
ImmutableList.of(EppResourceInputs.createKeyInput(DomainBase.class)))
|
||||
.sendLinkToMapreduceConsole(response);
|
||||
} else {
|
||||
runSqlJob(deletableTlds);
|
||||
}
|
||||
}
|
||||
|
||||
private void runSqlJob(ImmutableSet<String> deletableTlds) {
|
||||
AtomicInteger softDeletedDomains = new AtomicInteger();
|
||||
AtomicInteger hardDeletedDomains = new AtomicInteger();
|
||||
jpaTm().transact(() -> processDomains(deletableTlds, softDeletedDomains, hardDeletedDomains));
|
||||
logger.atInfo().log(
|
||||
"%s %d domains.",
|
||||
isDryRun ? "Would have soft-deleted" : "Soft-deleted", softDeletedDomains.get());
|
||||
logger.atInfo().log(
|
||||
"%s %d domains.",
|
||||
isDryRun ? "Would have hard-deleted" : "Hard-deleted", hardDeletedDomains.get());
|
||||
}
|
||||
|
||||
private void processDomains(
|
||||
ImmutableSet<String> deletableTlds,
|
||||
AtomicInteger softDeletedDomains,
|
||||
AtomicInteger hardDeletedDomains) {
|
||||
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 =
|
||||
jpaTm()
|
||||
.query(DOMAIN_QUERY_STRING, DomainBase.class)
|
||||
.setParameter("tlds", deletableTlds)
|
||||
.setParameter(
|
||||
"creationTimeCutoff", CreateAutoTimestamp.create(now.minus(DOMAIN_USED_DURATION)))
|
||||
.setParameter("nowMinusSoftDeleteDelay", now.minus(SOFT_DELETE_DELAY))
|
||||
.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) {
|
||||
DomainBase domain = (DomainBase) 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());
|
||||
}
|
||||
|
||||
private void processDomain(
|
||||
DomainBase domain,
|
||||
ImmutableList.Builder<String> domainRepoIdsToHardDelete,
|
||||
ImmutableList.Builder<String> hostNamesToHardDelete,
|
||||
AtomicInteger softDeletedDomains,
|
||||
AtomicInteger hardDeletedDomains) {
|
||||
// If the domain is still active, that means that the prober encountered a failure and did not
|
||||
// successfully soft-delete the domain (thus leaving its DNS entry published). We soft-delete
|
||||
// it now so that the DNS entry can be handled. The domain will then be hard-deleted the next
|
||||
// time the job is run.
|
||||
if (EppResourceUtils.isActive(domain, tm().getTransactionTime())) {
|
||||
if (isDryRun) {
|
||||
logger.atInfo().log(
|
||||
"Would soft-delete the active domain: %s (%s)",
|
||||
domain.getDomainName(), domain.getRepoId());
|
||||
} else {
|
||||
softDeleteDomain(domain, registryAdminRegistrarId, dnsQueue);
|
||||
}
|
||||
softDeletedDomains.incrementAndGet();
|
||||
} else {
|
||||
if (isDryRun) {
|
||||
logger.atInfo().log(
|
||||
"Would hard-delete the non-active domain: %s (%s) and its dependents",
|
||||
domain.getDomainName(), domain.getRepoId());
|
||||
} else {
|
||||
domainRepoIdsToHardDelete.add(domain.getRepoId());
|
||||
hostNamesToHardDelete.addAll(domain.getSubordinateHosts());
|
||||
}
|
||||
hardDeletedDomains.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
private void hardDeleteDomainsAndHosts(
|
||||
ImmutableList<String> domainRepoIds, ImmutableList<String> hostNames) {
|
||||
jpaTm()
|
||||
.query("DELETE FROM Host WHERE fullyQualifiedHostName IN :hostNames")
|
||||
.setParameter("hostNames", hostNames)
|
||||
.executeUpdate();
|
||||
jpaTm()
|
||||
.query("DELETE FROM BillingEvent WHERE domainRepoId IN :repoIds")
|
||||
.setParameter("repoIds", domainRepoIds)
|
||||
.executeUpdate();
|
||||
jpaTm()
|
||||
.query("DELETE FROM BillingRecurrence WHERE domainRepoId IN :repoIds")
|
||||
.setParameter("repoIds", domainRepoIds)
|
||||
.executeUpdate();
|
||||
jpaTm()
|
||||
.query("DELETE FROM BillingCancellation WHERE domainRepoId IN :repoIds")
|
||||
.setParameter("repoIds", domainRepoIds)
|
||||
.executeUpdate();
|
||||
jpaTm()
|
||||
.query("DELETE FROM DomainHistory WHERE domainRepoId IN :repoIds")
|
||||
.setParameter("repoIds", domainRepoIds)
|
||||
.executeUpdate();
|
||||
jpaTm()
|
||||
.query("DELETE FROM PollMessage WHERE domainRepoId IN :repoIds")
|
||||
.setParameter("repoIds", domainRepoIds)
|
||||
.executeUpdate();
|
||||
jpaTm()
|
||||
.query("DELETE FROM Domain WHERE repoId IN :repoIds")
|
||||
.setParameter("repoIds", domainRepoIds)
|
||||
.executeUpdate();
|
||||
}
|
||||
|
||||
// Take a DNS queue + admin registrar id as input so that it can be called from the mapper as well
|
||||
private static void softDeleteDomain(
|
||||
DomainBase domain, String registryAdminRegistrarId, DnsQueue localDnsQueue) {
|
||||
DomainBase deletedDomain =
|
||||
domain.asBuilder().setDeletionTime(tm().getTransactionTime()).setStatusValues(null).build();
|
||||
DomainHistory historyEntry =
|
||||
new DomainHistory.Builder()
|
||||
.setDomain(domain)
|
||||
.setType(DOMAIN_DELETE)
|
||||
.setModificationTime(tm().getTransactionTime())
|
||||
.setBySuperuser(true)
|
||||
.setReason("Deletion of prober data")
|
||||
.setRegistrarId(registryAdminRegistrarId)
|
||||
.build();
|
||||
// Note that we don't bother handling grace periods, billing events, pending transfers, poll
|
||||
// messages, or auto-renews because those will all be hard-deleted the next time the job runs
|
||||
// anyway.
|
||||
tm().putAllWithoutBackup(ImmutableList.of(deletedDomain, historyEntry));
|
||||
// updating foreign keys is a no-op in SQL
|
||||
updateForeignKeyIndexDeletionTime(deletedDomain);
|
||||
localDnsQueue.addDomainRefreshTask(deletedDomain.getDomainName());
|
||||
}
|
||||
|
||||
/** Provides the map method that runs for each existing DomainBase entity. */
|
||||
@@ -122,32 +308,17 @@ public class DeleteProberDataAction implements Runnable {
|
||||
private static final DnsQueue dnsQueue = DnsQueue.create();
|
||||
private static final long serialVersionUID = -7724537393697576369L;
|
||||
|
||||
/**
|
||||
* The maximum amount of time we allow a prober domain to be in use.
|
||||
*
|
||||
* In practice, the prober's connection will time out well before this duration. This includes a
|
||||
* decent buffer.
|
||||
*
|
||||
*/
|
||||
private static final Duration DOMAIN_USED_DURATION = Duration.standardHours(1);
|
||||
|
||||
/**
|
||||
* The minimum amount of time we want a domain to be "soft deleted".
|
||||
*
|
||||
* The domain has to remain soft deleted for at least enough time for the DNS task to run and
|
||||
* remove it from DNS itself. This is probably on the order of minutes.
|
||||
*/
|
||||
private static final Duration SOFT_DELETE_DELAY = Duration.standardHours(1);
|
||||
|
||||
private final ImmutableSet<String> proberRoidSuffixes;
|
||||
private final Boolean isDryRun;
|
||||
private final String registryAdminClientId;
|
||||
private final String registryAdminRegistrarId;
|
||||
|
||||
public DeleteProberDataMapper(
|
||||
ImmutableSet<String> proberRoidSuffixes, Boolean isDryRun, String registryAdminClientId) {
|
||||
ImmutableSet<String> proberRoidSuffixes,
|
||||
Boolean isDryRun,
|
||||
String registryAdminRegistrarId) {
|
||||
this.proberRoidSuffixes = proberRoidSuffixes;
|
||||
this.isDryRun = isDryRun;
|
||||
this.registryAdminClientId = registryAdminClientId;
|
||||
this.registryAdminRegistrarId = registryAdminRegistrarId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -203,7 +374,7 @@ public class DeleteProberDataAction implements Runnable {
|
||||
logger.atInfo().log(
|
||||
"Would soft-delete the active domain: %s (%s)", domainName, domainKey);
|
||||
} else {
|
||||
softDeleteDomain(domain);
|
||||
tm().transact(() -> softDeleteDomain(domain, registryAdminRegistrarId, dnsQueue));
|
||||
}
|
||||
getContext().incrementCounter("domains soft-deleted");
|
||||
return;
|
||||
@@ -223,8 +394,7 @@ public class DeleteProberDataAction implements Runnable {
|
||||
tm().transact(
|
||||
() -> {
|
||||
// This ancestor query selects all descendant HistoryEntries, BillingEvents,
|
||||
// PollMessages,
|
||||
// and TLD-specific entities, as well as the domain itself.
|
||||
// PollMessages, and TLD-specific entities, as well as the domain itself.
|
||||
List<Key<Object>> domainAndDependentKeys =
|
||||
auditedOfy().load().ancestor(domainKey).keys().list();
|
||||
ImmutableSet<Key<?>> allKeys =
|
||||
@@ -243,32 +413,5 @@ public class DeleteProberDataAction implements Runnable {
|
||||
getContext().incrementCounter("domains hard-deleted");
|
||||
getContext().incrementCounter("total entities hard-deleted", entitiesDeleted);
|
||||
}
|
||||
|
||||
private void softDeleteDomain(final DomainBase domain) {
|
||||
tm().transactNew(
|
||||
() -> {
|
||||
DomainBase deletedDomain =
|
||||
domain
|
||||
.asBuilder()
|
||||
.setDeletionTime(tm().getTransactionTime())
|
||||
.setStatusValues(null)
|
||||
.build();
|
||||
DomainHistory historyEntry =
|
||||
new DomainHistory.Builder()
|
||||
.setDomain(domain)
|
||||
.setType(DOMAIN_DELETE)
|
||||
.setModificationTime(tm().getTransactionTime())
|
||||
.setBySuperuser(true)
|
||||
.setReason("Deletion of prober data")
|
||||
.setClientId(registryAdminClientId)
|
||||
.build();
|
||||
// Note that we don't bother handling grace periods, billing events, pending
|
||||
// transfers, poll messages, or auto-renews because these will all be hard-deleted
|
||||
// the next time the mapreduce runs anyway.
|
||||
tm().putAll(deletedDomain, historyEntry);
|
||||
updateForeignKeyIndexDeletionTime(deletedDomain);
|
||||
dnsQueue.addDomainRefreshTask(deletedDomain.getDomainName());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,7 +324,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
|
||||
DomainHistory historyEntry =
|
||||
new DomainHistory.Builder()
|
||||
.setBySuperuser(false)
|
||||
.setClientId(recurring.getClientId())
|
||||
.setRegistrarId(recurring.getRegistrarId())
|
||||
.setModificationTime(tm().getTransactionTime())
|
||||
.setDomain(tm().loadByKey(domainKey))
|
||||
.setPeriod(Period.create(1, YEARS))
|
||||
@@ -354,7 +354,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
|
||||
syntheticOneTimesBuilder.add(
|
||||
new OneTime.Builder()
|
||||
.setBillingTime(billingTime)
|
||||
.setClientId(recurring.getClientId())
|
||||
.setRegistrarId(recurring.getRegistrarId())
|
||||
.setCost(renewCost)
|
||||
.setEventTime(eventTime)
|
||||
.setFlags(union(recurring.getFlags(), Flag.SYNTHETIC))
|
||||
|
||||
@@ -203,11 +203,11 @@ public class RelockDomainAction implements Runnable {
|
||||
"Domain %s has a pending transfer.",
|
||||
domainName);
|
||||
checkArgument(
|
||||
domain.getCurrentSponsorClientId().equals(oldLock.getRegistrarId()),
|
||||
domain.getCurrentSponsorRegistrarId().equals(oldLock.getRegistrarId()),
|
||||
"Domain %s has been transferred from registrar %s to registrar %s since the unlock.",
|
||||
domainName,
|
||||
oldLock.getRegistrarId(),
|
||||
domain.getCurrentSponsorClientId());
|
||||
domain.getCurrentSponsorRegistrarId());
|
||||
}
|
||||
|
||||
private void handleNonRetryableFailure(RegistryLock oldLock, Throwable t) {
|
||||
@@ -293,7 +293,7 @@ public class RelockDomainAction implements Runnable {
|
||||
|
||||
private ImmutableSet<InternetAddress> getEmailRecipients(String registrarId) {
|
||||
Registrar registrar =
|
||||
Registrar.loadByClientIdCached(registrarId)
|
||||
Registrar.loadByRegistrarIdCached(registrarId)
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new IllegalStateException(String.format("Unknown registrar %s", registrarId)));
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
// 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.batch;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
|
||||
import static org.apache.http.HttpStatus.SC_OK;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.flows.certs.CertificateChecker;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.model.registrar.RegistrarContact.Type;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.SendEmailService;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import javax.mail.internet.AddressException;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
|
||||
/** An action that sends notification emails to registrars whose certificates are expiring soon. */
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
path = SendExpiringCertificateNotificationEmailAction.PATH,
|
||||
auth = Auth.AUTH_INTERNAL_OR_ADMIN)
|
||||
public class SendExpiringCertificateNotificationEmailAction implements Runnable {
|
||||
public static final String PATH = "/_dr/task/sendExpiringCertificateNotificationEmail";
|
||||
/**
|
||||
* Used as an offset when storing the last notification email sent date.
|
||||
*
|
||||
* <p>This is used to handle edges cases when the update happens in between the day switch. For
|
||||
* instance,if the job starts at 2:00 am every day and it finishes at 2:03 of the same day, then
|
||||
* next day at 2am, the date difference will be less than a day, which will lead to the date
|
||||
* difference between two successive email sent date being the expected email interval days + 1;
|
||||
*/
|
||||
protected static final Duration UPDATE_TIME_OFFSET = Duration.standardMinutes(10);
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd");
|
||||
|
||||
private final CertificateChecker certificateChecker;
|
||||
private final String expirationWarningEmailBodyText;
|
||||
private final SendEmailService sendEmailService;
|
||||
private final String expirationWarningEmailSubjectText;
|
||||
private final InternetAddress gSuiteOutgoingEmailAddress;
|
||||
private final Response response;
|
||||
|
||||
@Inject
|
||||
public SendExpiringCertificateNotificationEmailAction(
|
||||
@Config("expirationWarningEmailBodyText") String expirationWarningEmailBodyText,
|
||||
@Config("expirationWarningEmailSubjectText") String expirationWarningEmailSubjectText,
|
||||
@Config("gSuiteOutgoingEmailAddress") InternetAddress gSuiteOutgoingEmailAddress,
|
||||
SendEmailService sendEmailService,
|
||||
CertificateChecker certificateChecker,
|
||||
Response response) {
|
||||
this.certificateChecker = certificateChecker;
|
||||
this.expirationWarningEmailSubjectText = expirationWarningEmailSubjectText;
|
||||
this.sendEmailService = sendEmailService;
|
||||
this.gSuiteOutgoingEmailAddress = gSuiteOutgoingEmailAddress;
|
||||
this.expirationWarningEmailBodyText = expirationWarningEmailBodyText;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||
try {
|
||||
sendNotificationEmails();
|
||||
response.setStatus(SC_OK);
|
||||
} catch (Exception e) {
|
||||
logger.atWarning().withCause(e).log(
|
||||
"Exception thrown when sending expiring certificate notification emails.");
|
||||
response.setStatus(SC_INTERNAL_SERVER_ERROR);
|
||||
response.setPayload(String.format("Exception thrown with cause: %s", e));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of registrars that should receive expiring notification emails. There are two
|
||||
* certificates that should be considered (the main certificate and failOver certificate). The
|
||||
* registrars should receive notifications if one of the certificate checks returns true.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
ImmutableList<RegistrarInfo> getRegistrarsWithExpiringCertificates() {
|
||||
logger.atInfo().log(
|
||||
"Getting a list of registrars that should receive expiring notification emails.");
|
||||
return Streams.stream(Registrar.loadAllCached())
|
||||
.map(
|
||||
registrar ->
|
||||
RegistrarInfo.create(
|
||||
registrar,
|
||||
registrar.getClientCertificate().isPresent()
|
||||
&& certificateChecker.shouldReceiveExpiringNotification(
|
||||
registrar.getLastExpiringCertNotificationSentDate(),
|
||||
registrar.getClientCertificate().get()),
|
||||
registrar.getFailoverClientCertificate().isPresent()
|
||||
&& certificateChecker.shouldReceiveExpiringNotification(
|
||||
registrar.getLastExpiringFailoverCertNotificationSentDate(),
|
||||
registrar.getFailoverClientCertificate().get())))
|
||||
.filter(
|
||||
registrarInfo ->
|
||||
registrarInfo.isCertExpiring() || registrarInfo.isFailOverCertExpiring())
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a notification email to the registrar regarding the expiring certificate and returns true
|
||||
* if it's sent successfully.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean sendNotificationEmail(
|
||||
Registrar registrar,
|
||||
DateTime lastExpiringCertNotificationSentDate,
|
||||
CertificateType certificateType,
|
||||
Optional<String> certificate) {
|
||||
if (!certificate.isPresent()
|
||||
|| !certificateChecker.shouldReceiveExpiringNotification(
|
||||
lastExpiringCertNotificationSentDate, certificate.get())) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
ImmutableSet<InternetAddress> recipients = getEmailAddresses(registrar, Type.TECH);
|
||||
Date expirationDate = certificateChecker.getCertificate(certificate.get()).getNotAfter();
|
||||
logger.atInfo().log(
|
||||
"Registrar %s should receive an email that its %s SSL certificate will expire on %s.",
|
||||
registrar.getRegistrarName(),
|
||||
certificateType.getDisplayName(),
|
||||
expirationDate.toString());
|
||||
if (recipients.isEmpty()) {
|
||||
logger.atWarning().log(
|
||||
"Registrar %s contains no email addresses to receive notification email.",
|
||||
registrar.getRegistrarName());
|
||||
return false;
|
||||
}
|
||||
sendEmailService.sendEmail(
|
||||
EmailMessage.newBuilder()
|
||||
.setFrom(gSuiteOutgoingEmailAddress)
|
||||
.setSubject(expirationWarningEmailSubjectText)
|
||||
.setBody(
|
||||
getEmailBody(
|
||||
registrar.getRegistrarName(),
|
||||
certificateType,
|
||||
expirationDate,
|
||||
registrar.getRegistrarId()))
|
||||
.setRecipients(recipients)
|
||||
.setCcs(getEmailAddresses(registrar, Type.ADMIN))
|
||||
.build());
|
||||
/*
|
||||
* A duration time offset is used here to ensure that date comparison between two
|
||||
* successive dates is always greater than 1 day. This date is set as last updated date,
|
||||
* for applicable certificate.
|
||||
*/
|
||||
updateLastNotificationSentDate(
|
||||
registrar,
|
||||
DateTime.now(UTC).minusMinutes((int) UPDATE_TIME_OFFSET.getStandardMinutes()),
|
||||
certificateType);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(
|
||||
String.format(
|
||||
"Failed to send expiring certificate notification email to registrar %s.",
|
||||
registrar.getRegistrarName()));
|
||||
}
|
||||
}
|
||||
|
||||
/** Updates the last notification sent date in database. */
|
||||
@VisibleForTesting
|
||||
void updateLastNotificationSentDate(
|
||||
Registrar registrar, DateTime now, CertificateType certificateType) {
|
||||
try {
|
||||
tm().transact(
|
||||
() -> {
|
||||
Registrar.Builder newRegistrar = tm().loadByEntity(registrar).asBuilder();
|
||||
switch (certificateType) {
|
||||
case PRIMARY:
|
||||
newRegistrar.setLastExpiringCertNotificationSentDate(now);
|
||||
tm().put(newRegistrar.build());
|
||||
logger.atInfo().log(
|
||||
"Updated last notification email sent date to %s for %s certificate of "
|
||||
+ "registrar %s.",
|
||||
DATE_FORMATTER.print(now),
|
||||
certificateType.getDisplayName(),
|
||||
registrar.getRegistrarName());
|
||||
break;
|
||||
case FAILOVER:
|
||||
newRegistrar.setLastExpiringFailoverCertNotificationSentDate(now);
|
||||
tm().put(newRegistrar.build());
|
||||
logger.atInfo().log(
|
||||
"Updated last notification email sent date to %s for %s certificate of "
|
||||
+ "registrar %s.",
|
||||
DATE_FORMATTER.print(now),
|
||||
certificateType.getDisplayName(),
|
||||
registrar.getRegistrarName());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Unsupported certificate type: %s being passed in when updating "
|
||||
+ "the last notification sent date to registrar %s.",
|
||||
certificateType.toString(), registrar.getRegistrarName()));
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(
|
||||
String.format(
|
||||
"Failed to update the last notification sent date to Registrar %s for the %s "
|
||||
+ "certificate.",
|
||||
registrar.getRegistrarName(), certificateType.getDisplayName()));
|
||||
}
|
||||
}
|
||||
|
||||
/** Sends notification emails to registrars with expiring certificates. */
|
||||
@VisibleForTesting
|
||||
int sendNotificationEmails() {
|
||||
int emailsSent = 0;
|
||||
for (RegistrarInfo registrarInfo : getRegistrarsWithExpiringCertificates()) {
|
||||
Registrar registrar = registrarInfo.registrar();
|
||||
if (registrarInfo.isCertExpiring()) {
|
||||
sendNotificationEmail(
|
||||
registrar,
|
||||
registrar.getLastExpiringCertNotificationSentDate(),
|
||||
CertificateType.PRIMARY,
|
||||
registrar.getClientCertificate());
|
||||
emailsSent++;
|
||||
}
|
||||
if (registrarInfo.isFailOverCertExpiring()) {
|
||||
sendNotificationEmail(
|
||||
registrar,
|
||||
registrar.getLastExpiringFailoverCertNotificationSentDate(),
|
||||
CertificateType.FAILOVER,
|
||||
registrar.getFailoverClientCertificate());
|
||||
emailsSent++;
|
||||
}
|
||||
}
|
||||
logger.atInfo().log(
|
||||
"Attempted to send %d expiring certificate notification emails.", emailsSent);
|
||||
return emailsSent;
|
||||
}
|
||||
|
||||
/** Returns a list of email addresses of the registrar that should receive a notification email */
|
||||
@VisibleForTesting
|
||||
ImmutableSet<InternetAddress> getEmailAddresses(Registrar registrar, Type contactType) {
|
||||
ImmutableSortedSet<RegistrarContact> contacts = registrar.getContactsOfType(contactType);
|
||||
ImmutableSet.Builder<InternetAddress> recipientEmails = new ImmutableSet.Builder<>();
|
||||
for (RegistrarContact contact : contacts) {
|
||||
try {
|
||||
recipientEmails.add(new InternetAddress(contact.getEmailAddress()));
|
||||
} catch (AddressException e) {
|
||||
logger.atWarning().withCause(e).log(
|
||||
"Registrar Contact email address %s of Registrar %s is invalid; skipping.",
|
||||
contact.getEmailAddress(), registrar.getRegistrarName());
|
||||
}
|
||||
}
|
||||
return recipientEmails.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates email content by taking registrar name, certificate type and expiration date as
|
||||
* parameters.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@SuppressWarnings("lgtm[java/dereferenced-value-may-be-null]")
|
||||
String getEmailBody(
|
||||
String registrarName, CertificateType type, Date expirationDate, String registrarId) {
|
||||
checkArgumentNotNull(expirationDate, "Expiration date cannot be null");
|
||||
checkArgumentNotNull(type, "Certificate type cannot be null");
|
||||
checkArgumentNotNull(registrarId, "Registrar Id cannot be null");
|
||||
return String.format(
|
||||
expirationWarningEmailBodyText,
|
||||
registrarName,
|
||||
type.getDisplayName(),
|
||||
DATE_FORMATTER.print(new DateTime(expirationDate)),
|
||||
registrarId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Certificate types for X509Certificate.
|
||||
*
|
||||
* <p><b>Note:</b> These types are only used to indicate the type of expiring certificate in
|
||||
* notification emails.
|
||||
*/
|
||||
protected enum CertificateType {
|
||||
PRIMARY("primary"),
|
||||
FAILOVER("fail-over");
|
||||
|
||||
private final String displayName;
|
||||
|
||||
CertificateType(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
public abstract static class RegistrarInfo {
|
||||
static RegistrarInfo create(
|
||||
Registrar registrar, boolean isCertExpiring, boolean isFailOverCertExpiring) {
|
||||
return new AutoValue_SendExpiringCertificateNotificationEmailAction_RegistrarInfo(
|
||||
registrar, isCertExpiring, isFailOverCertExpiring);
|
||||
}
|
||||
|
||||
public abstract Registrar registrar();
|
||||
|
||||
public abstract boolean isCertExpiring();
|
||||
|
||||
public abstract boolean isFailOverCertExpiring();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Streams;
|
||||
import google.registry.backup.AppEngineEnvironment;
|
||||
import google.registry.beam.common.RegistryQuery.CriteriaQuerySupplier;
|
||||
import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.model.UpdateAutoTimestamp.DisableAutoUpdateResource;
|
||||
import google.registry.model.ofy.ObjectifyService;
|
||||
import google.registry.model.replay.SqlEntity;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
@@ -274,6 +276,12 @@ 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();
|
||||
}
|
||||
@@ -294,6 +302,10 @@ public final class RegistryJpaIO {
|
||||
return toBuilder().jpaConverter(jpaConverter).build();
|
||||
}
|
||||
|
||||
public Write<T> disableUpdateAutoTimestamp() {
|
||||
return toBuilder().withUpdateAutoTimestamp(false).build();
|
||||
}
|
||||
|
||||
abstract Builder<T> toBuilder();
|
||||
|
||||
@Override
|
||||
@@ -310,7 +322,7 @@ public final class RegistryJpaIO {
|
||||
GroupIntoBatches.<Integer, T>ofSize(batchSize()).withShardedKey())
|
||||
.apply(
|
||||
"Write in batch for " + name(),
|
||||
ParDo.of(new SqlBatchWriter<>(name(), jpaConverter())));
|
||||
ParDo.of(new SqlBatchWriter<>(name(), jpaConverter(), withUpdateAutoTimestamp())));
|
||||
}
|
||||
|
||||
static <T> Builder<T> builder() {
|
||||
@@ -318,7 +330,8 @@ public final class RegistryJpaIO {
|
||||
.name(DEFAULT_NAME)
|
||||
.batchSize(DEFAULT_BATCH_SIZE)
|
||||
.shards(DEFAULT_SHARDS)
|
||||
.jpaConverter(x -> x);
|
||||
.jpaConverter(x -> x)
|
||||
.withUpdateAutoTimestamp(true);
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
@@ -332,6 +345,8 @@ public final class RegistryJpaIO {
|
||||
|
||||
abstract Builder<T> jpaConverter(SerializableFunction<T, Object> jpaConverter);
|
||||
|
||||
abstract Builder<T> withUpdateAutoTimestamp(boolean withUpdateAutoTimestamp);
|
||||
|
||||
abstract Write<T> build();
|
||||
}
|
||||
}
|
||||
@@ -340,10 +355,13 @@ 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) {
|
||||
SqlBatchWriter(
|
||||
String type, SerializableFunction<T, Object> jpaConverter, boolean withAutoTimestamp) {
|
||||
counter = Metrics.counter("SQL_WRITE", type);
|
||||
this.jpaConverter = jpaConverter;
|
||||
this.withAutoTimestamp = withAutoTimestamp;
|
||||
}
|
||||
|
||||
@Setup
|
||||
@@ -358,6 +376,16 @@ public final class RegistryJpaIO {
|
||||
|
||||
@ProcessElement
|
||||
public void processElement(@Element KV<ShardedKey<Integer>, Iterable<T>> kv) {
|
||||
if (withAutoTimestamp) {
|
||||
actuallyProcessElement(kv);
|
||||
return;
|
||||
}
|
||||
try (DisableAutoUpdateResource disable = UpdateAutoTimestamp.disableAutoUpdate()) {
|
||||
actuallyProcessElement(kv);
|
||||
}
|
||||
}
|
||||
|
||||
private void actuallyProcessElement(@Element KV<ShardedKey<Integer>, Iterable<T>> kv) {
|
||||
try (AppEngineEnvironment env = new AppEngineEnvironment()) {
|
||||
ImmutableList<Object> entities =
|
||||
Streams.stream(kv.getValue())
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.beam.common;
|
||||
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
@@ -28,6 +29,15 @@ import javax.persistence.criteria.CriteriaQuery;
|
||||
|
||||
/** Interface for query instances used by {@link RegistryJpaIO.Read}. */
|
||||
public interface RegistryQuery<T> extends Serializable {
|
||||
|
||||
/**
|
||||
* Number of JPA entities to fetch in each batch during a query.
|
||||
*
|
||||
* <p>With Hibernate, for result streaming to work, a query's fetchSize property must be set to a
|
||||
* non-zero value.
|
||||
*/
|
||||
int QUERY_FETCH_SIZE = 1000;
|
||||
|
||||
Stream<T> stream();
|
||||
|
||||
interface CriteriaQuerySupplier<T> extends Supplier<CriteriaQuery<T>>, Serializable {}
|
||||
@@ -49,6 +59,7 @@ public interface RegistryQuery<T> extends Serializable {
|
||||
if (parameters != null) {
|
||||
parameters.forEach(query::setParameter);
|
||||
}
|
||||
JpaTransactionManager.setQueryFetchSize(query, QUERY_FETCH_SIZE);
|
||||
@SuppressWarnings("unchecked")
|
||||
Stream<T> resultStream = query.getResultStream();
|
||||
return nativeQuery ? resultStream : resultStream.map(e -> detach(entityManager, e));
|
||||
@@ -64,11 +75,14 @@ public interface RegistryQuery<T> extends Serializable {
|
||||
static <T> RegistryQuery<T> createQuery(
|
||||
String jpql, @Nullable Map<String, Object> parameters, Class<T> clazz) {
|
||||
return () -> {
|
||||
TypedQuery<T> query = jpaTm().query(jpql, clazz);
|
||||
// TODO(b/193662898): switch to jpaTm().query() when it can properly detach loaded entities.
|
||||
EntityManager entityManager = jpaTm().getEntityManager();
|
||||
TypedQuery<T> query = entityManager.createQuery(jpql, clazz);
|
||||
if (parameters != null) {
|
||||
parameters.forEach(query::setParameter);
|
||||
}
|
||||
return query.getResultStream();
|
||||
JpaTransactionManager.setQueryFetchSize(query, QUERY_FETCH_SIZE);
|
||||
return query.getResultStream().map(e -> detach(entityManager, e));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -82,7 +96,13 @@ public interface RegistryQuery<T> extends Serializable {
|
||||
* @param <T> Type of each row in the result set.
|
||||
*/
|
||||
static <T> RegistryQuery<T> createQuery(CriteriaQuerySupplier<T> criteriaQuery) {
|
||||
return () -> jpaTm().query(criteriaQuery.get()).getResultStream();
|
||||
return () -> {
|
||||
// TODO(b/193662898): switch to jpaTm().query() when it can properly detach loaded entities.
|
||||
EntityManager entityManager = jpaTm().getEntityManager();
|
||||
TypedQuery<T> query = entityManager.createQuery(criteriaQuery.get());
|
||||
JpaTransactionManager.setQueryFetchSize(query, QUERY_FETCH_SIZE);
|
||||
return query.getResultStream().map(e -> detach(entityManager, e));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +128,10 @@ public interface RegistryQuery<T> extends Serializable {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
entityManager.detach(object);
|
||||
// TODO(b/193662898): choose detach() or clear() based on the type of transaction.
|
||||
// For context, EntityManager.detach() does not remove all metadata about loaded entities.
|
||||
// See b/193925312 or https://hibernate.atlassian.net/browse/HHH-14735 for details.
|
||||
entityManager.clear();
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Not an entity. Do nothing.
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import google.registry.backup.VersionedEntity;
|
||||
import google.registry.beam.common.RegistryJpaIO;
|
||||
import google.registry.beam.initsql.Transforms.RemoveDomainBaseForeignKeys;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
@@ -62,6 +63,7 @@ import org.joda.time.DateTime;
|
||||
* <ol>
|
||||
* <li>{@link Registry}: Assumes that {@code PremiumList} and {@code ReservedList} have been set
|
||||
* up in the SQL database.
|
||||
* <li>{@link Cursor}: Logically can depend on {@code Registry}, but without foreign key.
|
||||
* <li>{@link Registrar}: Logically depends on {@code Registry}, Foreign key not modeled yet.
|
||||
* <li>{@link ContactResource}: references {@code Registrar}
|
||||
* <li>{@link RegistrarContact}: references {@code Registrar}.
|
||||
@@ -101,7 +103,11 @@ public class InitSqlPipeline implements Serializable {
|
||||
*/
|
||||
private static final ImmutableList<Class<?>> PHASE_ONE_ORDERED =
|
||||
ImmutableList.of(
|
||||
Registry.class, Registrar.class, ContactResource.class, RegistrarContact.class);
|
||||
Registry.class,
|
||||
Cursor.class,
|
||||
Registrar.class,
|
||||
ContactResource.class,
|
||||
RegistrarContact.class);
|
||||
|
||||
/**
|
||||
* Datastore kinds to be written to the SQL database after the cleansed version of {@link
|
||||
@@ -219,7 +225,8 @@ public class InitSqlPipeline implements Serializable {
|
||||
.withName(transformId)
|
||||
.withBatchSize(options.getSqlWriteBatchSize())
|
||||
.withShards(options.getSqlWriteShards())
|
||||
.withJpaConverter(Transforms::convertVersionedEntityToSqlEntity));
|
||||
.withJpaConverter(Transforms::convertVersionedEntityToSqlEntity)
|
||||
.disableUpdateAutoTimestamp());
|
||||
}
|
||||
|
||||
private static ImmutableList<String> toKindStrings(Collection<Class<?>> entityClasses) {
|
||||
|
||||
@@ -125,7 +125,7 @@ public class InvoicingPipeline implements Serializable {
|
||||
oneTime.getId(),
|
||||
DateTimeUtils.toZonedDateTime(oneTime.getBillingTime(), ZoneId.of("UTC")),
|
||||
DateTimeUtils.toZonedDateTime(oneTime.getEventTime(), ZoneId.of("UTC")),
|
||||
registrar.getClientId(),
|
||||
registrar.getRegistrarId(),
|
||||
registrar.getBillingIdentifier().toString(),
|
||||
registrar.getPoNumber().orElse(""),
|
||||
DomainNameUtils.getTldFromDomainName(oneTime.getTargetId()),
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.apache.avro.generic.GenericRecord;
|
||||
import org.apache.beam.sdk.io.gcp.bigquery.SchemaAndRecord;
|
||||
|
||||
/**
|
||||
* A POJO representing a single subdomain, parsed from a {@code SchemaAndRecord}.
|
||||
* A POJO representing a domain name and associated info, parsed from a {@code SchemaAndRecord}.
|
||||
*
|
||||
* <p>This is a trivially serializable class that allows Beam to transform the results of a Bigquery
|
||||
* query into a standard Java representation, giving us the type guarantees and ease of manipulation
|
||||
@@ -33,28 +33,31 @@ import org.apache.beam.sdk.io.gcp.bigquery.SchemaAndRecord;
|
||||
* function.
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class Subdomain implements Serializable {
|
||||
public abstract class DomainNameInfo implements Serializable {
|
||||
|
||||
private static final ImmutableList<String> FIELD_NAMES =
|
||||
ImmutableList.of("domainName", "domainRepoId", "registrarId", "registrarEmailAddress");
|
||||
|
||||
/** Returns the fully qualified domain name. */
|
||||
abstract String domainName();
|
||||
|
||||
/** Returns the domain repo ID (the primary key of the domain table). */
|
||||
abstract String domainRepoId();
|
||||
|
||||
/** Returns the registrar ID of the associated registrar for this domain. */
|
||||
abstract String registrarId();
|
||||
|
||||
/** Returns the email address of the registrar associated with this domain. */
|
||||
abstract String registrarEmailAddress();
|
||||
|
||||
/**
|
||||
* Constructs a {@link Subdomain} from an Apache Avro {@code SchemaAndRecord}.
|
||||
* Constructs a {@link DomainNameInfo} from an Apache Avro {@code SchemaAndRecord}.
|
||||
*
|
||||
* @see <a
|
||||
* href=http://avro.apache.org/docs/1.7.7/api/java/org/apache/avro/generic/GenericData.Record.html>
|
||||
* Apache AVRO GenericRecord</a>
|
||||
*/
|
||||
static Subdomain parseFromRecord(SchemaAndRecord schemaAndRecord) {
|
||||
static DomainNameInfo parseFromRecord(SchemaAndRecord schemaAndRecord) {
|
||||
checkFieldsNotNull(FIELD_NAMES, schemaAndRecord);
|
||||
GenericRecord record = schemaAndRecord.getRecord();
|
||||
return create(
|
||||
@@ -65,18 +68,15 @@ public abstract class Subdomain implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a concrete {@link Subdomain}.
|
||||
* Creates a concrete {@link DomainNameInfo}.
|
||||
*
|
||||
* <p>This should only be used outside this class for testing- instances of {@link Subdomain}
|
||||
* <p>This should only be used outside this class for testing- instances of {@link DomainNameInfo}
|
||||
* should otherwise come from {@link #parseFromRecord}.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static Subdomain create(
|
||||
String domainName,
|
||||
String domainRepoId,
|
||||
String registrarId,
|
||||
String registrarEmailAddress) {
|
||||
return new AutoValue_Subdomain(
|
||||
static DomainNameInfo create(
|
||||
String domainName, String domainRepoId, String registrarId, String registrarEmailAddress) {
|
||||
return new AutoValue_DomainNameInfo(
|
||||
domainName, domainRepoId, registrarId, registrarEmailAddress);
|
||||
}
|
||||
}
|
||||
@@ -55,13 +55,14 @@ public class SafeBrowsingTransforms {
|
||||
"https://safebrowsing.googleapis.com/v4/threatMatches:find";
|
||||
|
||||
/**
|
||||
* {@link DoFn} mapping a {@link Subdomain} to its evaluation report from SafeBrowsing.
|
||||
* {@link DoFn} mapping a {@link DomainNameInfo} to its evaluation report from SafeBrowsing.
|
||||
*
|
||||
* <p>Refer to the Lookup API documentation for the request/response format and other details.
|
||||
*
|
||||
* @see <a href=https://developers.google.com/safe-browsing/v4/lookup-api>Lookup API</a>
|
||||
*/
|
||||
static class EvaluateSafeBrowsingFn extends DoFn<Subdomain, KV<Subdomain, ThreatMatch>> {
|
||||
static class EvaluateSafeBrowsingFn
|
||||
extends DoFn<DomainNameInfo, KV<DomainNameInfo, ThreatMatch>> {
|
||||
|
||||
/**
|
||||
* Max number of urls we can check in a single query.
|
||||
@@ -74,10 +75,11 @@ public class SafeBrowsingTransforms {
|
||||
private final String apiKey;
|
||||
|
||||
/**
|
||||
* Maps a subdomain's {@code fullyQualifiedDomainName} to its corresponding {@link Subdomain} to
|
||||
* facilitate batching SafeBrowsing API requests.
|
||||
* Maps a domain name's {@code fullyQualifiedDomainName} to its corresponding {@link
|
||||
* DomainNameInfo} to facilitate batching SafeBrowsing API requests.
|
||||
*/
|
||||
private final Map<String, Subdomain> subdomainBuffer = new LinkedHashMap<>(BATCH_SIZE);
|
||||
private final Map<String, DomainNameInfo> domainNameInfoBuffer =
|
||||
new LinkedHashMap<>(BATCH_SIZE);
|
||||
|
||||
/**
|
||||
* Provides the HTTP client we use to interact with the SafeBrowsing API.
|
||||
@@ -119,37 +121,38 @@ public class SafeBrowsingTransforms {
|
||||
closeableHttpClientSupplier = clientSupplier;
|
||||
}
|
||||
|
||||
/** Evaluates any buffered {@link Subdomain} objects upon completing the bundle. */
|
||||
/** Evaluates any buffered {@link DomainNameInfo} objects upon completing the bundle. */
|
||||
@FinishBundle
|
||||
public void finishBundle(FinishBundleContext context) {
|
||||
if (!subdomainBuffer.isEmpty()) {
|
||||
ImmutableSet<KV<Subdomain, ThreatMatch>> results = evaluateAndFlush();
|
||||
if (!domainNameInfoBuffer.isEmpty()) {
|
||||
ImmutableSet<KV<DomainNameInfo, ThreatMatch>> results = evaluateAndFlush();
|
||||
results.forEach((kv) -> context.output(kv, Instant.now(), GlobalWindow.INSTANCE));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Buffers {@link Subdomain} objects until we reach the batch size, then bulk-evaluate the URLs
|
||||
* with the SafeBrowsing API.
|
||||
* Buffers {@link DomainNameInfo} objects until we reach the batch size, then bulk-evaluate the
|
||||
* URLs with the SafeBrowsing API.
|
||||
*/
|
||||
@ProcessElement
|
||||
public void processElement(ProcessContext context) {
|
||||
Subdomain subdomain = context.element();
|
||||
subdomainBuffer.put(subdomain.domainName(), subdomain);
|
||||
if (subdomainBuffer.size() >= BATCH_SIZE) {
|
||||
ImmutableSet<KV<Subdomain, ThreatMatch>> results = evaluateAndFlush();
|
||||
DomainNameInfo domainNameInfo = context.element();
|
||||
domainNameInfoBuffer.put(domainNameInfo.domainName(), domainNameInfo);
|
||||
if (domainNameInfoBuffer.size() >= BATCH_SIZE) {
|
||||
ImmutableSet<KV<DomainNameInfo, ThreatMatch>> results = evaluateAndFlush();
|
||||
results.forEach(context::output);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates all {@link Subdomain} objects in the buffer and returns a list of key-value pairs
|
||||
* from {@link Subdomain} to its SafeBrowsing report.
|
||||
* Evaluates all {@link DomainNameInfo} objects in the buffer and returns a list of key-value
|
||||
* pairs from {@link DomainNameInfo} to its SafeBrowsing report.
|
||||
*
|
||||
* <p>If a {@link Subdomain} is safe according to the API, it will not emit a report.
|
||||
* <p>If a {@link DomainNameInfo} is safe according to the API, it will not emit a report.
|
||||
*/
|
||||
private ImmutableSet<KV<Subdomain, ThreatMatch>> evaluateAndFlush() {
|
||||
ImmutableSet.Builder<KV<Subdomain, ThreatMatch>> resultBuilder = new ImmutableSet.Builder<>();
|
||||
private ImmutableSet<KV<DomainNameInfo, ThreatMatch>> evaluateAndFlush() {
|
||||
ImmutableSet.Builder<KV<DomainNameInfo, ThreatMatch>> resultBuilder =
|
||||
new ImmutableSet.Builder<>();
|
||||
try {
|
||||
URIBuilder uriBuilder = new URIBuilder(SAFE_BROWSING_URL);
|
||||
// Add the API key param
|
||||
@@ -174,7 +177,7 @@ public class SafeBrowsingTransforms {
|
||||
throw new RuntimeException("Caught parsing exception, failing pipeline.", e);
|
||||
} finally {
|
||||
// Flush the buffer
|
||||
subdomainBuffer.clear();
|
||||
domainNameInfoBuffer.clear();
|
||||
}
|
||||
return resultBuilder.build();
|
||||
}
|
||||
@@ -183,7 +186,7 @@ public class SafeBrowsingTransforms {
|
||||
private JSONObject createRequestBody() throws JSONException {
|
||||
// Accumulate all domain names to evaluate.
|
||||
JSONArray threatArray = new JSONArray();
|
||||
for (String fullyQualifiedDomainName : subdomainBuffer.keySet()) {
|
||||
for (String fullyQualifiedDomainName : domainNameInfoBuffer.keySet()) {
|
||||
threatArray.put(new JSONObject().put("url", fullyQualifiedDomainName));
|
||||
}
|
||||
// Construct the JSON request body
|
||||
@@ -211,7 +214,7 @@ public class SafeBrowsingTransforms {
|
||||
*/
|
||||
private void processResponse(
|
||||
CloseableHttpResponse response,
|
||||
ImmutableSet.Builder<KV<Subdomain, ThreatMatch>> resultBuilder)
|
||||
ImmutableSet.Builder<KV<DomainNameInfo, ThreatMatch>> resultBuilder)
|
||||
throws JSONException, IOException {
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if (statusCode != SC_OK) {
|
||||
@@ -226,16 +229,17 @@ public class SafeBrowsingTransforms {
|
||||
if (responseBody.length() == 0) {
|
||||
logger.atInfo().log("Response was empty, no threats detected");
|
||||
} else {
|
||||
// Emit all Subdomains with their API results.
|
||||
// Emit all DomainNameInfos with their API results.
|
||||
JSONArray threatMatches = responseBody.getJSONArray("matches");
|
||||
for (int i = 0; i < threatMatches.length(); i++) {
|
||||
JSONObject match = threatMatches.getJSONObject(i);
|
||||
String url = match.getJSONObject("threat").getString("url");
|
||||
Subdomain subdomain = subdomainBuffer.get(url);
|
||||
DomainNameInfo domainNameInfo = domainNameInfoBuffer.get(url);
|
||||
resultBuilder.add(
|
||||
KV.of(
|
||||
subdomain,
|
||||
ThreatMatch.create(match.getString("threatType"), subdomain.domainName())));
|
||||
domainNameInfo,
|
||||
ThreatMatch.create(
|
||||
match.getString("threatType"), domainNameInfo.domainName())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,20 +100,20 @@ public class Spec11Pipeline implements Serializable {
|
||||
|
||||
void setupPipeline(Pipeline pipeline) {
|
||||
options.setIsolationOverride(TransactionIsolationLevel.TRANSACTION_READ_COMMITTED);
|
||||
PCollection<Subdomain> domains =
|
||||
PCollection<DomainNameInfo> domains =
|
||||
options.getDatabase().equals("DATASTORE")
|
||||
? readFromBigQuery(options, pipeline)
|
||||
: readFromCloudSql(pipeline);
|
||||
|
||||
PCollection<KV<Subdomain, ThreatMatch>> threatMatches =
|
||||
PCollection<KV<DomainNameInfo, ThreatMatch>> threatMatches =
|
||||
domains.apply("Run through SafeBrowsing API", ParDo.of(safeBrowsingFn));
|
||||
|
||||
saveToSql(threatMatches, options);
|
||||
saveToGcs(threatMatches, options);
|
||||
}
|
||||
|
||||
static PCollection<Subdomain> readFromCloudSql(Pipeline pipeline) {
|
||||
Read<Object[], Subdomain> read =
|
||||
static PCollection<DomainNameInfo> readFromCloudSql(Pipeline pipeline) {
|
||||
Read<Object[], DomainNameInfo> read =
|
||||
RegistryJpaIO.read(
|
||||
"select d, r.emailAddress from Domain d join Registrar r on"
|
||||
+ " d.currentSponsorClientId = r.clientIdentifier where r.type = 'REAL'"
|
||||
@@ -124,62 +124,63 @@ public class Spec11Pipeline implements Serializable {
|
||||
return pipeline.apply("Read active domains from Cloud SQL", read);
|
||||
}
|
||||
|
||||
static PCollection<Subdomain> readFromBigQuery(Spec11PipelineOptions options, Pipeline pipeline) {
|
||||
static PCollection<DomainNameInfo> readFromBigQuery(
|
||||
Spec11PipelineOptions options, Pipeline pipeline) {
|
||||
return pipeline.apply(
|
||||
"Read active domains from BigQuery",
|
||||
BigQueryIO.read(Subdomain::parseFromRecord)
|
||||
BigQueryIO.read(DomainNameInfo::parseFromRecord)
|
||||
.fromQuery(
|
||||
SqlTemplate.create(getQueryFromFile(Spec11Pipeline.class, "subdomains.sql"))
|
||||
SqlTemplate.create(getQueryFromFile(Spec11Pipeline.class, "domain_name_infos.sql"))
|
||||
.put("PROJECT_ID", options.getProject())
|
||||
.put("DATASTORE_EXPORT_DATASET", "latest_datastore_export")
|
||||
.put("REGISTRAR_TABLE", "Registrar")
|
||||
.put("DOMAIN_BASE_TABLE", "DomainBase")
|
||||
.build())
|
||||
.withCoder(SerializableCoder.of(Subdomain.class))
|
||||
.withCoder(SerializableCoder.of(DomainNameInfo.class))
|
||||
.usingStandardSql()
|
||||
.withoutValidation()
|
||||
.withTemplateCompatibility());
|
||||
}
|
||||
|
||||
private static Subdomain parseRow(Object[] row) {
|
||||
private static DomainNameInfo parseRow(Object[] row) {
|
||||
DomainBase domainBase = (DomainBase) row[0];
|
||||
String emailAddress = (String) row[1];
|
||||
if (emailAddress == null) {
|
||||
emailAddress = "";
|
||||
}
|
||||
return Subdomain.create(
|
||||
return DomainNameInfo.create(
|
||||
domainBase.getDomainName(),
|
||||
domainBase.getRepoId(),
|
||||
domainBase.getCurrentSponsorClientId(),
|
||||
domainBase.getCurrentSponsorRegistrarId(),
|
||||
emailAddress);
|
||||
}
|
||||
|
||||
static void saveToSql(
|
||||
PCollection<KV<Subdomain, ThreatMatch>> threatMatches, Spec11PipelineOptions options) {
|
||||
PCollection<KV<DomainNameInfo, ThreatMatch>> threatMatches, Spec11PipelineOptions options) {
|
||||
String transformId = "Spec11 Threat Matches";
|
||||
LocalDate date = LocalDate.parse(options.getDate(), ISODateTimeFormat.date());
|
||||
threatMatches.apply(
|
||||
"Write to Sql: " + transformId,
|
||||
RegistryJpaIO.<KV<Subdomain, ThreatMatch>>write()
|
||||
RegistryJpaIO.<KV<DomainNameInfo, ThreatMatch>>write()
|
||||
.withName(transformId)
|
||||
.withBatchSize(options.getSqlWriteBatchSize())
|
||||
.withShards(options.getSqlWriteShards())
|
||||
.withJpaConverter(
|
||||
(kv) -> {
|
||||
Subdomain subdomain = kv.getKey();
|
||||
DomainNameInfo domainNameInfo = kv.getKey();
|
||||
return new Spec11ThreatMatch.Builder()
|
||||
.setThreatTypes(
|
||||
ImmutableSet.of(ThreatType.valueOf(kv.getValue().threatType())))
|
||||
.setCheckDate(date)
|
||||
.setDomainName(subdomain.domainName())
|
||||
.setDomainRepoId(subdomain.domainRepoId())
|
||||
.setRegistrarId(subdomain.registrarId())
|
||||
.setDomainName(domainNameInfo.domainName())
|
||||
.setDomainRepoId(domainNameInfo.domainRepoId())
|
||||
.setRegistrarId(domainNameInfo.registrarId())
|
||||
.build();
|
||||
}));
|
||||
}
|
||||
|
||||
static void saveToGcs(
|
||||
PCollection<KV<Subdomain, ThreatMatch>> threatMatches, Spec11PipelineOptions options) {
|
||||
PCollection<KV<DomainNameInfo, ThreatMatch>> threatMatches, Spec11PipelineOptions options) {
|
||||
threatMatches
|
||||
.apply(
|
||||
"Map registrar ID to email/ThreatMatch pair",
|
||||
@@ -187,7 +188,7 @@ public class Spec11Pipeline implements Serializable {
|
||||
TypeDescriptors.kvs(
|
||||
TypeDescriptors.strings(), TypeDescriptor.of(EmailAndThreatMatch.class)))
|
||||
.via(
|
||||
(KV<Subdomain, ThreatMatch> kv) ->
|
||||
(KV<DomainNameInfo, ThreatMatch> kv) ->
|
||||
KV.of(
|
||||
kv.getKey().registrarId(),
|
||||
EmailAndThreatMatch.create(
|
||||
@@ -198,15 +199,15 @@ public class Spec11Pipeline implements Serializable {
|
||||
MapElements.into(TypeDescriptors.strings())
|
||||
.via(
|
||||
(KV<String, Iterable<EmailAndThreatMatch>> kv) -> {
|
||||
String clientId = kv.getKey();
|
||||
String registrarId = kv.getKey();
|
||||
checkArgument(
|
||||
kv.getValue().iterator().hasNext(),
|
||||
String.format(
|
||||
"Registrar with ID %s had no corresponding threats", clientId));
|
||||
"Registrar with ID %s had no corresponding threats", registrarId));
|
||||
String email = kv.getValue().iterator().next().email();
|
||||
JSONObject output = new JSONObject();
|
||||
try {
|
||||
output.put(REGISTRAR_CLIENT_ID_FIELD, clientId);
|
||||
output.put(REGISTRAR_CLIENT_ID_FIELD, registrarId);
|
||||
output.put(REGISTRAR_EMAIL_FIELD, email);
|
||||
JSONArray threatMatchArray = new JSONArray();
|
||||
for (EmailAndThreatMatch emailAndThreatMatch : kv.getValue()) {
|
||||
@@ -230,7 +231,7 @@ public class Spec11Pipeline implements Serializable {
|
||||
options.getReportingBucketUrl(),
|
||||
getSpec11ReportFilePath(LocalDate.parse(options.getDate()))))
|
||||
.withoutSharding()
|
||||
.withHeader("Map from registrar email / name to detected subdomain threats:"));
|
||||
.withHeader("Map from registrar email / name to detected domain name threats:"));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
// 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.config;
|
||||
|
||||
import com.google.api.gax.core.FixedCredentialsProvider;
|
||||
import com.google.cloud.tasks.v2.CloudTasksClient;
|
||||
import com.google.cloud.tasks.v2.CloudTasksSettings;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.DefaultCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.CloudTasksUtils;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import google.registry.util.Retrier;
|
||||
import java.io.IOException;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* A {@link Module} that provides {@link CloudTasksUtils}.
|
||||
*
|
||||
* <p>The class itself cannot be annotated as {@code Inject} because its requested dependencies use
|
||||
* the {@link Config} qualifier which is not available in the {@code util} package.
|
||||
*/
|
||||
@Module
|
||||
public abstract class CloudTasksUtilsModule {
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
public static CloudTasksUtils provideCloudTasksUtils(
|
||||
@Config("projectId") String projectId,
|
||||
@Config("locationId") String locationId,
|
||||
// Use a provider so that we can use try-with-resources with the client, which implements
|
||||
// Autocloseable.
|
||||
Provider<CloudTasksClient> clientProvider,
|
||||
Retrier retrier) {
|
||||
return new CloudTasksUtils(retrier, projectId, locationId, clientProvider);
|
||||
}
|
||||
|
||||
@Provides
|
||||
public static CloudTasksClient provideCloudTasksClient(
|
||||
@DefaultCredential GoogleCredentialsBundle credentials) {
|
||||
try {
|
||||
return CloudTasksClient.create(
|
||||
CloudTasksSettings.newBuilder()
|
||||
.setCredentialsProvider(
|
||||
FixedCredentialsProvider.create(credentials.getGoogleCredentials()))
|
||||
.build());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,12 @@ public final class RegistryConfig {
|
||||
return config.appEngine.projectId;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("locationId")
|
||||
public static String provideLocationId(RegistryConfigSettings config) {
|
||||
return config.appEngine.locationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* The filename of the logo to be displayed in the header of the registrar console.
|
||||
*
|
||||
@@ -1132,8 +1138,8 @@ public final class RegistryConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the clientId of the registrar that admins are automatically logged in as if they
|
||||
* aren't otherwise associated with one.
|
||||
* Returns the ID of the registrar that admins are automatically logged in as if they aren't
|
||||
* otherwise associated with one.
|
||||
*/
|
||||
@Provides
|
||||
@Config("registryAdminClientId")
|
||||
|
||||
@@ -45,6 +45,7 @@ public class RegistryConfigSettings {
|
||||
/** Configuration options that apply to the entire App Engine project. */
|
||||
public static class AppEngine {
|
||||
public String projectId;
|
||||
public String locationId;
|
||||
public boolean isLocal;
|
||||
public String defaultServiceUrl;
|
||||
public String backendServiceUrl;
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
appEngine:
|
||||
# Globally unique App Engine project ID
|
||||
projectId: registry-project-id
|
||||
# Location of the App engine project, note that us-central1 and europe-west1 are special in that
|
||||
# they are used without the trailing number in App Engine commands and Google Cloud Console.
|
||||
# See: https://cloud.google.com/appengine/docs/locations
|
||||
locationId: registry-location-id
|
||||
|
||||
# whether to use local/test credentials when connecting to the servers
|
||||
isLocal: true
|
||||
@@ -452,12 +456,36 @@ sslCertificateValidation:
|
||||
# The minimum number of days between two successive expiring notification emails.
|
||||
expirationWarningIntervalDays: 15
|
||||
# Text for expiring certificate notification email subject.
|
||||
expirationWarningEmailSubjectText: Certificate Expring Within 30 Days.
|
||||
expirationWarningEmailSubjectText: "[Important] Expiring SSL certificate for Google Registry EPP connection"
|
||||
# Text for expiring certificate notification email body that accepts 3 parameters:
|
||||
# registrar name, certificate type, and expiration date, respectively.
|
||||
expirationWarningEmailBodyText: |
|
||||
Hello Registrar %s,
|
||||
The %s certificate is expiring on %s.
|
||||
Dear %1$s,
|
||||
|
||||
We would like to inform you that your %2$s SSL certificate will expire at %3$s. Please take note that using expired certificates will prevent successful Registry login.
|
||||
|
||||
Kindly update your production account certificate within the support console using the following steps:
|
||||
|
||||
1. Navigate to support.registry.google and login using your %4$s@registry.google credentials.
|
||||
* If this is your first time logging in, you will be prompted to reset your password, so please keep your new password safe.
|
||||
* If you are already logged in with some other Google account(s) but not your %4$s@registry.google account, you need to click on
|
||||
“Add Account” and login using your %4$s@registry.google credentials.
|
||||
2. Select “Settings > Security” from the left navigation bar.
|
||||
3. Click “Edit” on the top left corner.
|
||||
4. Enter your full certificate string (including lines -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----) in the box.
|
||||
5. Click “Save”. If there are validation issues with the form, you will be prompted to fix them and click “Save” again.
|
||||
|
||||
A failover SSL certificate can also be added in order to prevent connection issues once your main certificate expires. Connecting with either of the certificates will work with our production EPP server.
|
||||
|
||||
Further information about our EPP connection requirements can be found in section 9.2 in the updated Technical Guide in your Google Drive folder.
|
||||
|
||||
Note that account certificate changes take a few minutes to become effective and that the existing connections will remain unaffected by the change.
|
||||
|
||||
If you also would like to update your OT&E account certificate, please send an email from your primary or technical contact to registry-support@google.com and include the full certificate string (including lines -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----).
|
||||
|
||||
Regards,
|
||||
Google Registry
|
||||
|
||||
# The minimum number of bits an RSA key must contain.
|
||||
minimumRsaKeyLength: 2048
|
||||
# The ECDSA curves that are allowed for public keys.
|
||||
|
||||
@@ -14,14 +14,10 @@
|
||||
|
||||
package google.registry.cron;
|
||||
|
||||
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
|
||||
import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Predicates.in;
|
||||
import static com.google.common.base.Predicates.not;
|
||||
import static com.google.common.base.Strings.nullToEmpty;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.Iterables.getFirst;
|
||||
import static com.google.common.collect.Multimaps.filterKeys;
|
||||
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
|
||||
import static google.registry.cron.CronModule.ENDPOINT_PARAM;
|
||||
@@ -36,21 +32,24 @@ import static google.registry.model.tld.Registry.TldType.REAL;
|
||||
import static google.registry.model.tld.Registry.TldType.TEST;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
import com.google.appengine.api.taskqueue.Queue;
|
||||
import com.google.appengine.api.taskqueue.TaskHandle;
|
||||
import com.google.appengine.api.taskqueue.TaskOptions;
|
||||
import com.google.cloud.tasks.v2.Task;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.protobuf.Timestamp;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.ParameterMap;
|
||||
import google.registry.request.RequestParameters;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.util.TaskQueueUtils;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.CloudTasksUtils;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
@@ -105,7 +104,8 @@ public final class TldFanoutAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@Inject TaskQueueUtils taskQueueUtils;
|
||||
@Inject Clock clock;
|
||||
@Inject CloudTasksUtils cloudTasksUtils;
|
||||
@Inject Response response;
|
||||
@Inject @Parameter(ENDPOINT_PARAM) String endpoint;
|
||||
@Inject @Parameter(QUEUE_PARAM) String queue;
|
||||
@@ -115,7 +115,9 @@ public final class TldFanoutAction implements Runnable {
|
||||
@Inject @Parameter(EXCLUDE_PARAM) ImmutableSet<String> excludes;
|
||||
@Inject @Parameter(JITTER_SECONDS_PARAM) Optional<Integer> jitterSeconds;
|
||||
@Inject @ParameterMap ImmutableListMultimap<String, String> params;
|
||||
@Inject TldFanoutAction() {}
|
||||
|
||||
@Inject
|
||||
TldFanoutAction() {}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -126,8 +128,7 @@ public final class TldFanoutAction implements Runnable {
|
||||
runInEmpty || forEachTestTld || forEachRealTld,
|
||||
"At least one of runInEmpty, forEachTestTld, forEachRealTld must be given");
|
||||
checkArgument(
|
||||
!(runInEmpty && !excludes.isEmpty()),
|
||||
"Can't specify 'exclude' with 'runInEmpty'");
|
||||
!(runInEmpty && !excludes.isEmpty()), "Can't specify 'exclude' with 'runInEmpty'");
|
||||
ImmutableSet<String> tlds =
|
||||
runInEmpty
|
||||
? ImmutableSet.of("")
|
||||
@@ -137,7 +138,6 @@ public final class TldFanoutAction implements Runnable {
|
||||
.filter(not(in(excludes)))
|
||||
.collect(toImmutableSet());
|
||||
Multimap<String, String> flowThruParams = filterKeys(params, not(in(CONTROL_PARAMS)));
|
||||
Queue taskQueue = getQueue(queue);
|
||||
StringBuilder outputPayload =
|
||||
new StringBuilder(
|
||||
String.format("OK: Launched the following %d tasks in queue %s\n", tlds.size(), queue));
|
||||
@@ -146,33 +146,41 @@ public final class TldFanoutAction implements Runnable {
|
||||
logger.atWarning().log("No TLDs to fan-out!");
|
||||
}
|
||||
for (String tld : tlds) {
|
||||
TaskOptions taskOptions = createTaskOptions(tld, flowThruParams);
|
||||
TaskHandle taskHandle = taskQueueUtils.enqueue(taskQueue, taskOptions);
|
||||
Task task = createTask(tld, flowThruParams);
|
||||
Task createdTask = cloudTasksUtils.enqueue(queue, task);
|
||||
outputPayload.append(
|
||||
String.format(
|
||||
"- Task: '%s', tld: '%s', endpoint: '%s'\n",
|
||||
taskHandle.getName(), tld, taskOptions.getUrl()));
|
||||
createdTask.getName(), tld, createdTask.getAppEngineHttpRequest().getRelativeUri()));
|
||||
logger.atInfo().log(
|
||||
"Task: '%s', tld: '%s', endpoint: '%s'", taskHandle.getName(), tld, taskOptions.getUrl());
|
||||
"Task: '%s', tld: '%s', endpoint: '%s'",
|
||||
createdTask.getName(), tld, createdTask.getAppEngineHttpRequest().getRelativeUri());
|
||||
}
|
||||
response.setContentType(PLAIN_TEXT_UTF_8);
|
||||
response.setPayload(outputPayload.toString());
|
||||
}
|
||||
|
||||
private TaskOptions createTaskOptions(String tld, Multimap<String, String> params) {
|
||||
TaskOptions options =
|
||||
withUrl(endpoint)
|
||||
.countdownMillis(
|
||||
jitterSeconds
|
||||
.map(seconds -> random.nextInt((int) SECONDS.toMillis(seconds)))
|
||||
.orElse(0));
|
||||
private Task createTask(String tld, Multimap<String, String> params) {
|
||||
if (!tld.isEmpty()) {
|
||||
options.param(RequestParameters.PARAM_TLD, tld);
|
||||
params = ArrayListMultimap.create(params);
|
||||
params.put(RequestParameters.PARAM_TLD, tld);
|
||||
}
|
||||
for (String param : params.keySet()) {
|
||||
// TaskOptions.param() does not accept null values.
|
||||
options.param(param, nullToEmpty(getFirst(params.get(param), null)));
|
||||
}
|
||||
return options;
|
||||
Instant scheduleTime =
|
||||
Instant.ofEpochMilli(
|
||||
clock
|
||||
.nowUtc()
|
||||
.plusMillis(
|
||||
jitterSeconds
|
||||
.map(seconds -> random.nextInt((int) SECONDS.toMillis(seconds)))
|
||||
.orElse(0))
|
||||
.getMillis());
|
||||
return Task.newBuilder(
|
||||
CloudTasksUtils.createPostTask(endpoint, Service.BACKEND.toString(), params))
|
||||
.setScheduleTime(
|
||||
Timestamp.newBuilder()
|
||||
.setSeconds(scheduleTime.getEpochSecond())
|
||||
.setNanos(scheduleTime.getNano())
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,12 +31,12 @@ package google.registry.dns.writer;
|
||||
public interface DnsWriter {
|
||||
|
||||
/**
|
||||
* Loads {@code domainName} from Datastore and publishes its NS/DS records to the DNS server.
|
||||
* Loads {@code domainName} from the database and publishes its NS/DS records to the DNS server.
|
||||
* Replaces existing records for the exact name supplied with an NS record for each name server
|
||||
* and a DS record for each delegation signer stored in the registry for the supplied domain name.
|
||||
* If the domain is deleted or is in a "non-publish" state then any existing records are deleted.
|
||||
*
|
||||
* This must NOT actually perform any action, instead it should stage the action so that it's
|
||||
* <p>This must NOT actually perform any action, instead it should stage the action so that it's
|
||||
* performed when {@link #commit()} is called.
|
||||
*
|
||||
* @param domainName the fully qualified domain name, with no trailing dot
|
||||
@@ -44,14 +44,14 @@ public interface DnsWriter {
|
||||
void publishDomain(String domainName);
|
||||
|
||||
/**
|
||||
* Loads {@code hostName} from Datastore and publishes its A/AAAA glue records to the DNS server,
|
||||
* if it is used as an in-bailiwick nameserver. Orphaned glue records are prohibited. Replaces
|
||||
* existing records for the exact name supplied, with an A or AAAA record (as appropriate) for
|
||||
* each address stored in the registry, for the supplied host name. If the host is deleted then
|
||||
* the existing records are deleted. Assumes that this method will only be called for in-bailiwick
|
||||
* hosts. The registry does not have addresses for other hosts.
|
||||
* Loads {@code hostName} from the database and publishes its A/AAAA glue records to the DNS
|
||||
* server, if it is used as an in-bailiwick nameserver. Orphaned glue records are prohibited.
|
||||
* Replaces existing records for the exact name supplied, with an A or AAAA record (as
|
||||
* appropriate) for each address stored in the registry, for the supplied host name. If the host
|
||||
* is deleted then the existing records are deleted. Assumes that this method will only be called
|
||||
* for in-bailiwick hosts. The registry does not have addresses for other hosts.
|
||||
*
|
||||
* This must NOT actually perform any action, instead it should stage the action so that it's
|
||||
* <p>This must NOT actually perform any action, instead it should stage the action so that it's
|
||||
* performed when {@link #commit()} is called.
|
||||
*
|
||||
* @param hostName the fully qualified host name, with no trailing dot
|
||||
|
||||
@@ -355,6 +355,12 @@
|
||||
<url-pattern>/_dr/task/deleteExpiredDomains</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Background action to send notification emails to registrars with expiring certificate. -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>backend-servlet</servlet-name>
|
||||
<url-pattern>/_dr/task/sendExpiringCertificateNotificationEmail</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Mapreduce to import contacts from escrow file -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>backend-servlet</servlet-name>
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
It also enqueues a new task to wait on the completion of that job and then load the resulting
|
||||
snapshot into bigquery.
|
||||
</description>
|
||||
<!--
|
||||
<!- -
|
||||
Keep google.registry.export.CheckBackupAction.MAXIMUM_BACKUP_RUNNING_TIME less than
|
||||
this interval. - ->
|
||||
<schedule>every day 06:00</schedule>
|
||||
|
||||
@@ -193,6 +193,15 @@
|
||||
<target>backend</target>
|
||||
</cron>
|
||||
|
||||
<cron>
|
||||
<url><![CDATA[/_dr/task/sendExpiringCertificateNotificationEmail]]></url>
|
||||
<description>
|
||||
This job runs an action that sends emails to partners if their certificates are expiring soon.
|
||||
</description>
|
||||
<schedule>every day 04:30</schedule>
|
||||
<target>backend</target>
|
||||
</cron>
|
||||
|
||||
<cron>
|
||||
<url><![CDATA[/_dr/cron/fanout?queue=export-snapshot&endpoint=/_dr/task/backupDatastore&runInEmpty]]></url>
|
||||
<description>
|
||||
@@ -330,4 +339,13 @@
|
||||
<schedule>every day 15:00</schedule>
|
||||
<target>backend</target>
|
||||
</cron>
|
||||
|
||||
<cron>
|
||||
<url><![CDATA[/_dr/cron/fanout?queue=replay-commit-logs-to-sql&endpoint=/_dr/task/replayCommitLogsToSql&runInEmpty]]></url>
|
||||
<description>
|
||||
Replays recent commit logs from Datastore to the SQL secondary backend.
|
||||
</description>
|
||||
<schedule>every 3 minutes</schedule>
|
||||
<target>backend</target>
|
||||
</cron>
|
||||
</cronentries>
|
||||
|
||||
@@ -168,6 +168,15 @@
|
||||
<target>backend</target>
|
||||
</cron>
|
||||
|
||||
<cron>
|
||||
<url><![CDATA[/_dr/task/sendExpiringCertificateNotificationEmail]]></url>
|
||||
<description>
|
||||
This job runs an action that sends emails to partners if their certificates are expiring soon.
|
||||
</description>
|
||||
<schedule>every day 04:30</schedule>
|
||||
<target>backend</target>
|
||||
</cron>
|
||||
|
||||
<cron>
|
||||
<url><![CDATA[/_dr/cron/fanout?queue=export-snapshot&endpoint=/_dr/task/backupDatastore&runInEmpty]]></url>
|
||||
<description>
|
||||
|
||||
@@ -19,7 +19,7 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
import static google.registry.util.RegistrarUtils.normalizeClientId;
|
||||
import static google.registry.util.RegistrarUtils.normalizeRegistrarId;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
@@ -96,16 +96,15 @@ public final class SyncGroupMembersAction implements Runnable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Google Groups email address for the given registrar clientId and
|
||||
* RegistrarContact.Type
|
||||
* Returns the Google Groups email address for the given registrar ID and RegistrarContact.Type.
|
||||
*/
|
||||
public static String getGroupEmailAddressForContactType(
|
||||
String clientId, RegistrarContact.Type type, String gSuiteDomainName) {
|
||||
// Take the registrar's clientId, make it lowercase, and remove all characters that aren't
|
||||
String registrarId, RegistrarContact.Type type, String gSuiteDomainName) {
|
||||
// Take the registrar's ID, make it lowercase, and remove all characters that aren't
|
||||
// alphanumeric, hyphens, or underscores.
|
||||
return String.format(
|
||||
"%s-%s-contacts@%s",
|
||||
normalizeClientId(clientId), type.getDisplayName(), gSuiteDomainName);
|
||||
normalizeRegistrarId(registrarId), type.getDisplayName(), gSuiteDomainName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,7 +149,8 @@ public final class SyncGroupMembersAction implements Runnable {
|
||||
|
||||
/**
|
||||
* Parses the results from Google Groups for each registrar, setting the dirty flag to false in
|
||||
* Datastore for the calls that succeeded and accumulating the errors for the calls that failed.
|
||||
* the database for the calls that succeeded and accumulating the errors for the calls that
|
||||
* failed.
|
||||
*/
|
||||
private static List<Throwable> getErrorsAndUpdateFlagsForSuccesses(
|
||||
ImmutableMap<Registrar, Optional<Throwable>> results) {
|
||||
@@ -175,8 +175,8 @@ public final class SyncGroupMembersAction implements Runnable {
|
||||
long totalAdded = 0;
|
||||
long totalRemoved = 0;
|
||||
for (final RegistrarContact.Type type : RegistrarContact.Type.values()) {
|
||||
groupKey = getGroupEmailAddressForContactType(
|
||||
registrar.getClientId(), type, gSuiteDomainName);
|
||||
groupKey =
|
||||
getGroupEmailAddressForContactType(registrar.getRegistrarId(), type, gSuiteDomainName);
|
||||
Set<String> currentMembers = groupsConnection.getMembersOfGroup(groupKey);
|
||||
Set<String> desiredMembers =
|
||||
registrarContacts
|
||||
@@ -195,11 +195,13 @@ public final class SyncGroupMembersAction implements Runnable {
|
||||
}
|
||||
logger.atInfo().log(
|
||||
"Successfully synced contacts for registrar %s: added %d and removed %d",
|
||||
registrar.getClientId(), totalAdded, totalRemoved);
|
||||
registrar.getRegistrarId(), totalAdded, totalRemoved);
|
||||
} catch (IOException e) {
|
||||
// Package up exception and re-throw with attached additional relevant info.
|
||||
String msg = String.format("Couldn't sync contacts for registrar %s to group %s",
|
||||
registrar.getClientId(), groupKey);
|
||||
String msg =
|
||||
String.format(
|
||||
"Couldn't sync contacts for registrar %s to group %s",
|
||||
registrar.getRegistrarId(), groupKey);
|
||||
throw new RuntimeException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ import javax.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* Class for synchronizing all {@link Registrar} Datastore objects to a Google Spreadsheet.
|
||||
* Class for synchronizing all {@link Registrar} objects to a Google Spreadsheet.
|
||||
*
|
||||
* @see SyncRegistrarsSheetAction
|
||||
*/
|
||||
@@ -82,7 +82,7 @@ class SyncRegistrarsSheet {
|
||||
new Ordering<Registrar>() {
|
||||
@Override
|
||||
public int compare(Registrar left, Registrar right) {
|
||||
return left.getClientId().compareTo(right.getClientId());
|
||||
return left.getRegistrarId().compareTo(right.getRegistrarId());
|
||||
}
|
||||
}.immutableSortedCopy(Registrar.loadAllCached()).stream()
|
||||
.filter(
|
||||
@@ -116,7 +116,7 @@ class SyncRegistrarsSheet {
|
||||
// and you'll need to remove deleted columns probably like a week after
|
||||
// deployment.
|
||||
//
|
||||
builder.put("clientIdentifier", convert(registrar.getClientId()));
|
||||
builder.put("clientIdentifier", convert(registrar.getRegistrarId()));
|
||||
builder.put("registrarName", convert(registrar.getRegistrarName()));
|
||||
builder.put("state", convert(registrar.getState()));
|
||||
builder.put("ianaIdentifier", convert(registrar.getIanaIdentifier()));
|
||||
|
||||
@@ -61,7 +61,7 @@ public final class EppController {
|
||||
boolean isDryRun,
|
||||
boolean isSuperuser,
|
||||
byte[] inputXmlBytes) {
|
||||
eppMetricBuilder.setClientId(Optional.ofNullable(sessionMetadata.getClientId()));
|
||||
eppMetricBuilder.setRegistrarId(Optional.ofNullable(sessionMetadata.getRegistrarId()));
|
||||
try {
|
||||
EppInput eppInput;
|
||||
try {
|
||||
@@ -76,7 +76,7 @@ public final class EppController {
|
||||
JSONValue.toJSONString(
|
||||
ImmutableMap.<String, Object>of(
|
||||
"clientId",
|
||||
nullToEmpty(sessionMetadata.getClientId()),
|
||||
nullToEmpty(sessionMetadata.getRegistrarId()),
|
||||
"resultCode",
|
||||
e.getResult().getCode().code,
|
||||
"resultMessage",
|
||||
|
||||
@@ -88,7 +88,7 @@ public class EppMetrics {
|
||||
String eppStatusCode =
|
||||
metric.getStatus().isPresent() ? String.valueOf(metric.getStatus().get().code) : "";
|
||||
eppRequestsByRegistrar.increment(
|
||||
metric.getCommandName().orElse(""), metric.getClientId().orElse(""), eppStatusCode);
|
||||
metric.getCommandName().orElse(""), metric.getRegistrarId().orElse(""), eppStatusCode);
|
||||
eppRequestsByTld.increment(
|
||||
metric.getCommandName().orElse(""), metric.getTld().orElse(""), eppStatusCode);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,10 @@ public class EppToolAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/epptool";
|
||||
|
||||
@Inject @Parameter("clientId") String clientId;
|
||||
@Inject
|
||||
@Parameter("clientId")
|
||||
String registrarId;
|
||||
|
||||
@Inject @Parameter("superuser") boolean isSuperuser;
|
||||
@Inject @Parameter("dryRun") boolean isDryRun;
|
||||
@Inject @Parameter("xml") String xml;
|
||||
@@ -49,8 +52,7 @@ public class EppToolAction implements Runnable {
|
||||
public void run() {
|
||||
eppRequestHandler.executeEpp(
|
||||
new StatelessRequestSessionMetadata(
|
||||
clientId,
|
||||
ProtocolDefinition.getVisibleServiceExtensionUris()),
|
||||
registrarId, ProtocolDefinition.getVisibleServiceExtensionUris()),
|
||||
new PasswordOnlyTransportCredentials(),
|
||||
EppRequestSource.TOOL,
|
||||
isDryRun,
|
||||
|
||||
@@ -26,7 +26,7 @@ import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.flows.EppException.CommandUseErrorException;
|
||||
import google.registry.flows.EppException.SyntaxErrorException;
|
||||
import google.registry.flows.EppException.UnimplementedExtensionException;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.exceptions.OnlyToolCanPassMetadataException;
|
||||
import google.registry.flows.exceptions.UnauthorizedForSuperuserExtensionException;
|
||||
@@ -55,7 +55,7 @@ public final class ExtensionManager {
|
||||
|
||||
@Inject EppInput eppInput;
|
||||
@Inject SessionMetadata sessionMetadata;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject Class<? extends Flow> flowClass;
|
||||
@Inject EppRequestSource eppRequestSource;
|
||||
@@ -101,7 +101,7 @@ public final class ExtensionManager {
|
||||
}
|
||||
logger.atInfo().log(
|
||||
"Client %s is attempting to run %s without declaring URIs %s on login",
|
||||
clientId, flowClass.getSimpleName(), undeclaredUris);
|
||||
registrarId, flowClass.getSimpleName(), undeclaredUris);
|
||||
}
|
||||
|
||||
private static final ImmutableSet<EppRequestSource> ALLOWED_METADATA_EPP_REQUEST_SOURCES =
|
||||
|
||||
@@ -164,11 +164,11 @@ public class FlowModule {
|
||||
|
||||
@Provides
|
||||
@FlowScope
|
||||
@ClientId
|
||||
static String provideClientId(SessionMetadata sessionMetadata) {
|
||||
// Treat a missing clientId as null so we can always inject a non-null value. All we do with the
|
||||
// clientId is log it (as "") or detect its absence, both of which work fine with empty.
|
||||
return Strings.nullToEmpty(sessionMetadata.getClientId());
|
||||
@RegistrarId
|
||||
static String provideRegistrarId(SessionMetadata sessionMetadata) {
|
||||
// Treat a missing registrarId as null so we can always inject a non-null value. All we do with
|
||||
// the registrarId is log it (as "") or detect its absence, both of which work fine with empty.
|
||||
return Strings.nullToEmpty(sessionMetadata.getRegistrarId());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -220,14 +220,14 @@ public class FlowModule {
|
||||
Trid trid,
|
||||
byte[] inputXmlBytes,
|
||||
boolean isSuperuser,
|
||||
String clientId,
|
||||
String registrarId,
|
||||
EppInput eppInput) {
|
||||
builder
|
||||
.setModificationTime(tm().getTransactionTime())
|
||||
.setTrid(trid)
|
||||
.setXmlBytes(inputXmlBytes)
|
||||
.setBySuperuser(isSuperuser)
|
||||
.setClientId(clientId);
|
||||
.setRegistrarId(registrarId);
|
||||
Optional<MetadataExtension> metadataExtension =
|
||||
eppInput.getSingleExtension(MetadataExtension.class);
|
||||
metadataExtension.ifPresent(
|
||||
@@ -249,10 +249,10 @@ public class FlowModule {
|
||||
Trid trid,
|
||||
@InputXml byte[] inputXmlBytes,
|
||||
@Superuser boolean isSuperuser,
|
||||
@ClientId String clientId,
|
||||
@RegistrarId String registrarId,
|
||||
EppInput eppInput) {
|
||||
return makeHistoryEntryBuilder(
|
||||
new ContactHistory.Builder(), trid, inputXmlBytes, isSuperuser, clientId, eppInput);
|
||||
new ContactHistory.Builder(), trid, inputXmlBytes, isSuperuser, registrarId, eppInput);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,10 +266,10 @@ public class FlowModule {
|
||||
Trid trid,
|
||||
@InputXml byte[] inputXmlBytes,
|
||||
@Superuser boolean isSuperuser,
|
||||
@ClientId String clientId,
|
||||
@RegistrarId String registrarId,
|
||||
EppInput eppInput) {
|
||||
return makeHistoryEntryBuilder(
|
||||
new HostHistory.Builder(), trid, inputXmlBytes, isSuperuser, clientId, eppInput);
|
||||
new HostHistory.Builder(), trid, inputXmlBytes, isSuperuser, registrarId, eppInput);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,10 +283,10 @@ public class FlowModule {
|
||||
Trid trid,
|
||||
@InputXml byte[] inputXmlBytes,
|
||||
@Superuser boolean isSuperuser,
|
||||
@ClientId String clientId,
|
||||
@RegistrarId String registrarId,
|
||||
EppInput eppInput) {
|
||||
return makeHistoryEntryBuilder(
|
||||
new DomainHistory.Builder(), trid, inputXmlBytes, isSuperuser, clientId, eppInput);
|
||||
new DomainHistory.Builder(), trid, inputXmlBytes, isSuperuser, registrarId, eppInput);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -322,7 +322,7 @@ public class FlowModule {
|
||||
/** Dagger qualifier for registrar client id. */
|
||||
@Qualifier
|
||||
@Documented
|
||||
public @interface ClientId {}
|
||||
public @interface RegistrarId {}
|
||||
|
||||
/** Dagger qualifier for the target id (foreign key) for single resource flows. */
|
||||
@Qualifier
|
||||
|
||||
@@ -23,8 +23,8 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.InputXml;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.eppinput.EppInput;
|
||||
@@ -45,7 +45,7 @@ public class FlowReporter {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@Inject Trid trid;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @InputXml byte[] inputXmlBytes;
|
||||
@Inject EppInput eppInput;
|
||||
@Inject Class<? extends Flow> flowClass;
|
||||
@@ -64,7 +64,7 @@ public class FlowReporter {
|
||||
JSONValue.toJSONString(
|
||||
new ImmutableMap.Builder<String, Object>()
|
||||
.put("serverTrid", trid.getServerTransactionId())
|
||||
.put("clientId", clientId)
|
||||
.put("clientId", registrarId)
|
||||
.put("commandType", eppInput.getCommandType())
|
||||
.put("resourceType", eppInput.getResourceType().orElse(""))
|
||||
.put("flowClassName", flowClass.getSimpleName())
|
||||
|
||||
@@ -19,9 +19,9 @@ import static google.registry.xml.XmlTransformer.prettyPrint;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.DryRun;
|
||||
import google.registry.flows.FlowModule.InputXml;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.Transactional;
|
||||
import google.registry.flows.session.LoginFlow;
|
||||
@@ -38,7 +38,7 @@ public class FlowRunner {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject TransportCredentials credentials;
|
||||
@Inject EppRequestSource eppRequestSource;
|
||||
@Inject Provider<Flow> flowProvider;
|
||||
@@ -59,7 +59,7 @@ public class FlowRunner {
|
||||
logger.atInfo().log(
|
||||
COMMAND_LOG_FORMAT,
|
||||
trid.getServerTransactionId(),
|
||||
clientId,
|
||||
registrarId,
|
||||
sessionMetadata,
|
||||
prettyXml.replace("\n", "\n\t"),
|
||||
credentials,
|
||||
@@ -74,8 +74,8 @@ public class FlowRunner {
|
||||
if (!isTransactional) {
|
||||
EppOutput eppOutput = EppOutput.create(flowProvider.get().run());
|
||||
if (flowClass.equals(LoginFlow.class)) {
|
||||
// In LoginFlow, clientId isn't known until after the flow executes, so save it then.
|
||||
eppMetricBuilder.setClientId(sessionMetadata.getClientId());
|
||||
// In LoginFlow, registrarId isn't known until after the flow executes, so save it then.
|
||||
eppMetricBuilder.setRegistrarId(sessionMetadata.getRegistrarId());
|
||||
}
|
||||
return eppOutput;
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ public final class FlowUtils {
|
||||
private FlowUtils() {}
|
||||
|
||||
/** Validate that there is a logged in client. */
|
||||
public static void validateClientIsLoggedIn(String clientId) throws EppException {
|
||||
if (clientId.isEmpty()) {
|
||||
public static void validateRegistrarIsLoggedIn(String registrarId) throws EppException {
|
||||
if (registrarId.isEmpty()) {
|
||||
throw new NotLoggedInException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import javax.servlet.http.HttpSession;
|
||||
/** A metadata class that is a wrapper around {@link HttpSession}. */
|
||||
public class HttpSessionMetadata implements SessionMetadata {
|
||||
|
||||
private static final String CLIENT_ID = "CLIENT_ID";
|
||||
private static final String REGISTRAR_ID = "REGISTRAR_ID";
|
||||
private static final String SERVICE_EXTENSIONS = "SERVICE_EXTENSIONS";
|
||||
private static final String FAILED_LOGIN_ATTEMPTS = "FAILED_LOGIN_ATTEMPTS";
|
||||
|
||||
@@ -41,8 +41,8 @@ public class HttpSessionMetadata implements SessionMetadata {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientId() {
|
||||
return (String) session.getAttribute(CLIENT_ID);
|
||||
public String getRegistrarId() {
|
||||
return (String) session.getAttribute(REGISTRAR_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -57,8 +57,8 @@ public class HttpSessionMetadata implements SessionMetadata {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClientId(String clientId) {
|
||||
session.setAttribute(CLIENT_ID, clientId);
|
||||
public void setRegistrarId(String registrarId) {
|
||||
session.setAttribute(REGISTRAR_ID, registrarId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -79,7 +79,7 @@ public class HttpSessionMetadata implements SessionMetadata {
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(getClass())
|
||||
.add("clientId", getClientId())
|
||||
.add("clientId", getRegistrarId())
|
||||
.add("failedLoginAttempts", getFailedLoginAttempts())
|
||||
.add("serviceExtensionUris", Joiner.on('.').join(nullToEmpty(getServiceExtensionUris())))
|
||||
.toString();
|
||||
|
||||
@@ -69,10 +69,10 @@ public final class ResourceFlowUtils {
|
||||
*/
|
||||
private static final int FAILFAST_CHECK_COUNT = 5;
|
||||
|
||||
/** Check that the given clientId corresponds to the owner of given resource. */
|
||||
public static void verifyResourceOwnership(String myClientId, EppResource resource)
|
||||
/** Check that the given registrarId corresponds to the owner of given resource. */
|
||||
public static void verifyResourceOwnership(String myRegistrarId, EppResource resource)
|
||||
throws EppException {
|
||||
if (!myClientId.equals(resource.getPersistedCurrentSponsorClientId())) {
|
||||
if (!myRegistrarId.equals(resource.getPersistedCurrentSponsorRegistrarId())) {
|
||||
throw new ResourceNotOwnedException();
|
||||
}
|
||||
}
|
||||
@@ -138,8 +138,8 @@ public final class ResourceFlowUtils {
|
||||
}
|
||||
|
||||
public static <R extends EppResource & ResourceWithTransferData> void verifyTransferInitiator(
|
||||
String clientId, R resource) throws NotTransferInitiatorException {
|
||||
if (!resource.getTransferData().getGainingClientId().equals(clientId)) {
|
||||
String registrarId, R resource) throws NotTransferInitiatorException {
|
||||
if (!resource.getTransferData().getGainingRegistrarId().equals(registrarId)) {
|
||||
throw new NotTransferInitiatorException();
|
||||
}
|
||||
}
|
||||
@@ -155,12 +155,12 @@ public final class ResourceFlowUtils {
|
||||
}
|
||||
|
||||
public static <R extends EppResource> void verifyResourceDoesNotExist(
|
||||
Class<R> clazz, String targetId, DateTime now, String clientId) throws EppException {
|
||||
Class<R> clazz, String targetId, DateTime now, String registrarId) throws EppException {
|
||||
VKey<R> key = loadAndGetKey(clazz, targetId, now);
|
||||
if (key != null) {
|
||||
R resource = tm().loadByKey(key);
|
||||
// These are similar exceptions, but we can track them internally as log-based metrics.
|
||||
if (Objects.equals(clientId, resource.getPersistedCurrentSponsorClientId())) {
|
||||
if (Objects.equals(registrarId, resource.getPersistedCurrentSponsorRegistrarId())) {
|
||||
throw new ResourceAlreadyExistsForThisClientException(targetId);
|
||||
} else {
|
||||
throw new ResourceCreateContentionException(targetId);
|
||||
|
||||
@@ -26,13 +26,13 @@ public interface SessionMetadata {
|
||||
*/
|
||||
void invalidate();
|
||||
|
||||
String getClientId();
|
||||
String getRegistrarId();
|
||||
|
||||
Set<String> getServiceExtensionUris();
|
||||
|
||||
int getFailedLoginAttempts();
|
||||
|
||||
void setClientId(String clientId);
|
||||
void setRegistrarId(String registrarId);
|
||||
|
||||
void setServiceExtensionUris(Set<String> serviceExtensionUris);
|
||||
|
||||
|
||||
@@ -25,12 +25,12 @@ import java.util.Set;
|
||||
/** A read-only {@link SessionMetadata} that doesn't support login/logout. */
|
||||
public class StatelessRequestSessionMetadata implements SessionMetadata {
|
||||
|
||||
private final String clientId;
|
||||
private final String registrarId;
|
||||
private final ImmutableSet<String> serviceExtensionUris;
|
||||
|
||||
public StatelessRequestSessionMetadata(
|
||||
String clientId, ImmutableSet<String> serviceExtensionUris) {
|
||||
this.clientId = checkNotNull(clientId);
|
||||
String registrarId, ImmutableSet<String> serviceExtensionUris) {
|
||||
this.registrarId = checkNotNull(registrarId);
|
||||
this.serviceExtensionUris = checkNotNull(serviceExtensionUris);
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ public class StatelessRequestSessionMetadata implements SessionMetadata {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
public String getRegistrarId() {
|
||||
return registrarId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,7 +55,7 @@ public class StatelessRequestSessionMetadata implements SessionMetadata {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClientId(String clientId) {
|
||||
public void setRegistrarId(String registrarId) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class StatelessRequestSessionMetadata implements SessionMetadata {
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(getClass())
|
||||
.add("clientId", getClientId())
|
||||
.add("clientId", getRegistrarId())
|
||||
.add("failedLoginAttempts", getFailedLoginAttempts())
|
||||
.add("serviceExtensionUris", Joiner.on('.').join(nullToEmpty(getServiceExtensionUris())))
|
||||
.toString();
|
||||
|
||||
@@ -97,7 +97,7 @@ public class TlsCredentials implements TransportCredentials {
|
||||
if (ipAddressAllowList.isEmpty()) {
|
||||
logger.atInfo().log(
|
||||
"Skipping IP allow list check because %s doesn't have an IP allow list.",
|
||||
registrar.getClientId());
|
||||
registrar.getRegistrarId());
|
||||
return;
|
||||
}
|
||||
// In the rare unexpected case that the client inet address wasn't passed along at all, then
|
||||
@@ -113,7 +113,7 @@ public class TlsCredentials implements TransportCredentials {
|
||||
logger.atInfo().log(
|
||||
"Authentication error: IP address %s is not allow-listed for registrar %s; allow list is:"
|
||||
+ " %s",
|
||||
clientInetAddr, registrar.getClientId(), ipAddressAllowList);
|
||||
clientInetAddr, registrar.getRegistrarId(), ipAddressAllowList);
|
||||
throw new BadRegistrarIpAddressException();
|
||||
}
|
||||
|
||||
@@ -132,7 +132,8 @@ public class TlsCredentials implements TransportCredentials {
|
||||
// Check that the request included the certificate hash
|
||||
if (!clientCertificateHash.isPresent()) {
|
||||
logger.atInfo().log(
|
||||
"Request from registrar %s did not include X-SSL-Certificate.", registrar.getClientId());
|
||||
"Request from registrar %s did not include X-SSL-Certificate.",
|
||||
registrar.getRegistrarId());
|
||||
throw new MissingRegistrarCertificateException();
|
||||
}
|
||||
// Check if the certificate hash is equal to the one on file for the registrar.
|
||||
@@ -141,7 +142,7 @@ public class TlsCredentials implements TransportCredentials {
|
||||
logger.atWarning().log(
|
||||
"Non-matching certificate hash (%s) for %s, wanted either %s or %s.",
|
||||
clientCertificateHash,
|
||||
registrar.getClientId(),
|
||||
registrar.getRegistrarId(),
|
||||
registrar.getClientCertificateHash(),
|
||||
registrar.getFailoverClientCertificateHash());
|
||||
throw new BadRegistrarCertificateException();
|
||||
@@ -156,7 +157,7 @@ public class TlsCredentials implements TransportCredentials {
|
||||
} catch (InsecureCertificateException e) {
|
||||
logger.atWarning().log(
|
||||
"Registrar certificate used for %s does not meet certificate requirements: %s",
|
||||
registrar.getClientId(), e.getMessage());
|
||||
registrar.getRegistrarId(), e.getMessage());
|
||||
throw new CertificateContainsSecurityViolationsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import java.security.interfaces.ECPublicKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.Date;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
|
||||
import org.bouncycastle.jce.ECNamedCurveTable;
|
||||
@@ -228,7 +227,7 @@ public class CertificateChecker {
|
||||
|
||||
/** Returns whether the client should receive a notification email. */
|
||||
public boolean shouldReceiveExpiringNotification(
|
||||
@Nullable DateTime lastExpiringNotificationSentDate, String certificateStr) {
|
||||
DateTime lastExpiringNotificationSentDate, String certificateStr) {
|
||||
X509Certificate certificate = getCertificate(certificateStr);
|
||||
DateTime now = clock.nowUtc();
|
||||
// expiration date is one day after lastValidDate
|
||||
@@ -238,13 +237,13 @@ public class CertificateChecker {
|
||||
}
|
||||
/*
|
||||
* Client should receive a notification if :
|
||||
* 1) client has never received notification and the certificate has entered
|
||||
* the expiring period, OR
|
||||
* 1) client has never received notification (lastExpiringNotificationSentDate is initially
|
||||
* set to START_OF_TIME) and the certificate has entered the expiring period, OR
|
||||
* 2) client has received notification but the interval between now and
|
||||
* lastExpiringNotificationSentDate is greater than expirationWarningIntervalDays.
|
||||
*/
|
||||
return !lastValidDate.after(now.plusDays(expirationWarningDays).toDate())
|
||||
&& (lastExpiringNotificationSentDate == null
|
||||
&& (lastExpiringNotificationSentDate.equals(START_OF_TIME)
|
||||
|| !lastExpiringNotificationSentDate
|
||||
.plusDays(expirationWarningIntervalDays)
|
||||
.toDate()
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
|
||||
import static google.registry.model.EppResourceUtils.checkResourcesExist;
|
||||
|
||||
@@ -24,7 +24,7 @@ import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.model.contact.ContactCommand.Check;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
@@ -47,7 +47,7 @@ import javax.inject.Inject;
|
||||
public final class ContactCheckFlow implements Flow {
|
||||
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject Clock clock;
|
||||
@Inject @Config("maxChecks") int maxChecks;
|
||||
@@ -57,7 +57,7 @@ public final class ContactCheckFlow implements Flow {
|
||||
@Override
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
ImmutableList<String> targetIds = ((Check) resourceCommand).getTargetIds();
|
||||
verifyTargetIdCount(targetIds, maxChecks);
|
||||
ImmutableSet<String> existingIds =
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist;
|
||||
import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo;
|
||||
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
|
||||
@@ -27,7 +27,7 @@ import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
@@ -60,7 +60,7 @@ public final class ContactCreateFlow implements TransactionalFlow {
|
||||
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject ContactHistory.Builder historyBuilder;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
@@ -71,16 +71,16 @@ public final class ContactCreateFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
Create command = (Create) resourceCommand;
|
||||
DateTime now = tm().getTransactionTime();
|
||||
verifyResourceDoesNotExist(ContactResource.class, targetId, now, clientId);
|
||||
verifyResourceDoesNotExist(ContactResource.class, targetId, now, registrarId);
|
||||
ContactResource newContact =
|
||||
new ContactResource.Builder()
|
||||
.setContactId(targetId)
|
||||
.setAuthInfo(command.getAuthInfo())
|
||||
.setCreationClientId(clientId)
|
||||
.setPersistedCurrentSponsorClientId(clientId)
|
||||
.setCreationRegistrarId(registrarId)
|
||||
.setPersistedCurrentSponsorRegistrarId(registrarId)
|
||||
.setRepoId(createRepoId(allocateId(), roidSuffix))
|
||||
.setFaxNumber(command.getFax())
|
||||
.setVoiceNumber(command.getVoice())
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.checkLinkedDomains;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||
@@ -31,7 +31,7 @@ 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.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
@@ -75,7 +75,7 @@ public final class ContactDeleteFlow implements TransactionalFlow {
|
||||
StatusValue.SERVER_DELETE_PROHIBITED);
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject Trid trid;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@@ -91,21 +91,21 @@ public final class ContactDeleteFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
checkLinkedDomains(targetId, now, ContactResource.class, DomainBase::getReferencedContacts);
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
if (!isSuperuser) {
|
||||
verifyResourceOwnership(clientId, existingContact);
|
||||
verifyResourceOwnership(registrarId, existingContact);
|
||||
}
|
||||
Type historyEntryType;
|
||||
Code resultCode;
|
||||
ContactResource newContact;
|
||||
if (tm().isOfy()) {
|
||||
asyncTaskEnqueuer.enqueueAsyncDelete(
|
||||
existingContact, tm().getTransactionTime(), clientId, trid, isSuperuser);
|
||||
existingContact, tm().getTransactionTime(), registrarId, trid, isSuperuser);
|
||||
newContact = existingContact.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build();
|
||||
historyEntryType = Type.CONTACT_PENDING_DELETE;
|
||||
resultCode = SUCCESS_WITH_ACTION_PENDING;
|
||||
@@ -113,7 +113,7 @@ public final class ContactDeleteFlow implements TransactionalFlow {
|
||||
// Handle pending transfers on contact deletion.
|
||||
newContact =
|
||||
existingContact.getStatusValues().contains(StatusValue.PENDING_TRANSFER)
|
||||
? denyPendingTransfer(existingContact, SERVER_CANCELLED, now, clientId)
|
||||
? denyPendingTransfer(existingContact, SERVER_CANCELLED, now, registrarId)
|
||||
: existingContact;
|
||||
// Wipe out PII on contact deletion.
|
||||
newContact =
|
||||
|
||||
@@ -73,7 +73,7 @@ public class ContactFlowUtils {
|
||||
DateTime now,
|
||||
Key<ContactHistory> contactHistoryKey) {
|
||||
return new PollMessage.OneTime.Builder()
|
||||
.setClientId(transferData.getGainingClientId())
|
||||
.setRegistrarId(transferData.getGainingRegistrarId())
|
||||
.setEventTime(transferData.getPendingTransferExpirationTime())
|
||||
.setMsg(transferData.getTransferStatus().getMessage())
|
||||
.setResponseData(
|
||||
@@ -92,7 +92,7 @@ public class ContactFlowUtils {
|
||||
static PollMessage createLosingTransferPollMessage(
|
||||
String targetId, TransferData transferData, Key<ContactHistory> contactHistoryKey) {
|
||||
return new PollMessage.OneTime.Builder()
|
||||
.setClientId(transferData.getLosingClientId())
|
||||
.setRegistrarId(transferData.getLosingRegistrarId())
|
||||
.setEventTime(transferData.getPendingTransferExpirationTime())
|
||||
.setMsg(transferData.getTransferStatus().getMessage())
|
||||
.setResponseData(ImmutableList.of(createTransferResponse(targetId, transferData)))
|
||||
@@ -105,8 +105,8 @@ public class ContactFlowUtils {
|
||||
String targetId, TransferData transferData) {
|
||||
return new ContactTransferResponse.Builder()
|
||||
.setContactId(targetId)
|
||||
.setGainingClientId(transferData.getGainingClientId())
|
||||
.setLosingClientId(transferData.getLosingClientId())
|
||||
.setGainingRegistrarId(transferData.getGainingRegistrarId())
|
||||
.setLosingRegistrarId(transferData.getLosingRegistrarId())
|
||||
.setPendingTransferExpirationTime(transferData.getPendingTransferExpirationTime())
|
||||
.setTransferRequestTime(transferData.getTransferRequestTime())
|
||||
.setTransferStatus(transferData.getTransferStatus())
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||
import static google.registry.model.EppResourceUtils.isLinked;
|
||||
@@ -23,7 +23,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
@@ -54,7 +54,7 @@ public final class ContactInfoFlow implements Flow {
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject Clock clock;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@@ -67,13 +67,13 @@ public final class ContactInfoFlow implements Flow {
|
||||
public final EppResponse run() throws EppException {
|
||||
DateTime now = clock.nowUtc();
|
||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
ContactResource contact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
if (!isSuperuser) {
|
||||
verifyResourceOwnership(clientId, contact);
|
||||
verifyResourceOwnership(registrarId, contact);
|
||||
}
|
||||
boolean includeAuthInfo =
|
||||
clientId.equals(contact.getCurrentSponsorClientId()) || authInfo.isPresent();
|
||||
registrarId.equals(contact.getCurrentSponsorRegistrarId()) || authInfo.isPresent();
|
||||
ImmutableSet.Builder<StatusValue> statusValues = new ImmutableSet.Builder<>();
|
||||
statusValues.addAll(contact.getStatusValues());
|
||||
if (isLinked(contact.createVKey(), now)) {
|
||||
@@ -89,10 +89,10 @@ public final class ContactInfoFlow implements Flow {
|
||||
.setVoiceNumber(contact.getVoiceNumber())
|
||||
.setFaxNumber(contact.getFaxNumber())
|
||||
.setEmailAddress(contact.getEmailAddress())
|
||||
.setCurrentSponsorClientId(contact.getCurrentSponsorClientId())
|
||||
.setCreationClientId(contact.getCreationClientId())
|
||||
.setCurrentSponsorClientId(contact.getCurrentSponsorRegistrarId())
|
||||
.setCreationClientId(contact.getCreationRegistrarId())
|
||||
.setCreationTime(contact.getCreationTime())
|
||||
.setLastEppUpdateClientId(contact.getLastEppUpdateClientId())
|
||||
.setLastEppUpdateClientId(contact.getLastEppUpdateRegistrarId())
|
||||
.setLastEppUpdateTime(contact.getLastEppUpdateTime())
|
||||
.setLastTransferTime(contact.getLastTransferTime())
|
||||
.setAuthInfo(includeAuthInfo ? contact.getAuthInfo() : null)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
@@ -29,7 +29,7 @@ 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.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
@@ -64,7 +64,7 @@ public final class ContactTransferApproveFlow implements TransactionalFlow {
|
||||
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject ContactHistory.Builder historyBuilder;
|
||||
@@ -79,12 +79,12 @@ public final class ContactTransferApproveFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
verifyHasPendingTransfer(existingContact);
|
||||
verifyResourceOwnership(clientId, existingContact);
|
||||
verifyResourceOwnership(registrarId, existingContact);
|
||||
ContactResource newContact =
|
||||
approvePendingTransfer(existingContact, TransferStatus.CLIENT_APPROVED, now);
|
||||
ContactHistory contactHistory =
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
@@ -29,7 +29,7 @@ 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.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
@@ -65,7 +65,7 @@ public final class ContactTransferCancelFlow implements TransactionalFlow {
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject ContactHistory.Builder historyBuilder;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
@@ -75,14 +75,14 @@ public final class ContactTransferCancelFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
verifyHasPendingTransfer(existingContact);
|
||||
verifyTransferInitiator(clientId, existingContact);
|
||||
verifyTransferInitiator(registrarId, existingContact);
|
||||
ContactResource newContact =
|
||||
denyPendingTransfer(existingContact, TransferStatus.CLIENT_CANCELLED, now, clientId);
|
||||
denyPendingTransfer(existingContact, TransferStatus.CLIENT_CANCELLED, now, registrarId);
|
||||
ContactHistory contactHistory =
|
||||
historyBuilder.setType(CONTACT_TRANSFER_CANCEL).setContact(newContact).build();
|
||||
// Create a poll message for the losing client.
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
||||
@@ -22,7 +22,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createTransferRespo
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.flows.exceptions.NoTransferHistoryToQueryException;
|
||||
@@ -55,7 +55,7 @@ public final class ContactTransferQueryFlow implements Flow {
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject Clock clock;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
@@ -64,7 +64,7 @@ public final class ContactTransferQueryFlow implements Flow {
|
||||
@Override
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
ContactResource contact =
|
||||
loadAndVerifyExistence(ContactResource.class, targetId, clock.nowUtc());
|
||||
verifyOptionalAuthInfo(authInfo, contact);
|
||||
@@ -76,8 +76,8 @@ public final class ContactTransferQueryFlow implements Flow {
|
||||
// Note that the authorization info on the command (if present) has already been verified. If
|
||||
// it's present, then the other checks are unnecessary.
|
||||
if (!authInfo.isPresent()
|
||||
&& !clientId.equals(contact.getTransferData().getGainingClientId())
|
||||
&& !clientId.equals(contact.getTransferData().getLosingClientId())) {
|
||||
&& !registrarId.equals(contact.getTransferData().getGainingRegistrarId())
|
||||
&& !registrarId.equals(contact.getTransferData().getLosingRegistrarId())) {
|
||||
throw new NotAuthorizedToViewTransferException();
|
||||
}
|
||||
return responseBuilder
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
@@ -29,7 +29,7 @@ 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.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
@@ -63,7 +63,7 @@ public final class ContactTransferRejectFlow implements TransactionalFlow {
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject ContactHistory.Builder historyBuilder;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
@@ -73,14 +73,14 @@ public final class ContactTransferRejectFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
verifyHasPendingTransfer(existingContact);
|
||||
verifyResourceOwnership(clientId, existingContact);
|
||||
verifyResourceOwnership(registrarId, existingContact);
|
||||
ContactResource newContact =
|
||||
denyPendingTransfer(existingContact, TransferStatus.CLIENT_REJECTED, now, clientId);
|
||||
denyPendingTransfer(existingContact, TransferStatus.CLIENT_REJECTED, now, registrarId);
|
||||
ContactHistory contactHistory =
|
||||
historyBuilder.setType(CONTACT_TRANSFER_REJECT).setContact(newContact).build();
|
||||
PollMessage gainingPollMessage =
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfo;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoPresentForResourceTransfer;
|
||||
@@ -32,7 +32,7 @@ import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
@@ -80,7 +80,7 @@ public final class ContactTransferRequestFlow implements TransactionalFlow {
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String gainingClientId;
|
||||
@Inject @RegistrarId String gainingClientId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Config("contactAutomaticTransferLength") Duration automaticTransferLength;
|
||||
|
||||
@@ -93,7 +93,7 @@ public final class ContactTransferRequestFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(gainingClientId);
|
||||
validateRegistrarIsLoggedIn(gainingClientId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
verifyAuthInfoPresentForResourceTransfer(authInfo);
|
||||
@@ -102,7 +102,7 @@ public final class ContactTransferRequestFlow implements TransactionalFlow {
|
||||
if (TransferStatus.PENDING.equals(existingContact.getTransferData().getTransferStatus())) {
|
||||
throw new AlreadyPendingTransferException(targetId);
|
||||
}
|
||||
String losingClientId = existingContact.getCurrentSponsorClientId();
|
||||
String losingClientId = existingContact.getCurrentSponsorRegistrarId();
|
||||
// Verify that this client doesn't already sponsor this resource.
|
||||
if (gainingClientId.equals(losingClientId)) {
|
||||
throw new ObjectAlreadySponsoredException();
|
||||
@@ -114,8 +114,8 @@ public final class ContactTransferRequestFlow implements TransactionalFlow {
|
||||
new ContactTransferData.Builder()
|
||||
.setTransferRequestTime(now)
|
||||
.setTransferRequestTrid(trid)
|
||||
.setGainingClientId(gainingClientId)
|
||||
.setLosingClientId(losingClientId)
|
||||
.setGainingRegistrarId(gainingClientId)
|
||||
.setLosingRegistrarId(losingClientId)
|
||||
.setPendingTransferExpirationTime(transferExpirationTime)
|
||||
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
||||
.build();
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static com.google.common.collect.Sets.union;
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.checkSameValuesNotAddedAndRemoved;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyAllStatusesAreClientSettable;
|
||||
@@ -30,7 +30,7 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
@@ -79,7 +79,7 @@ public final class ContactUpdateFlow implements TransactionalFlow {
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject ContactHistory.Builder historyBuilder;
|
||||
@@ -90,7 +90,7 @@ public final class ContactUpdateFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
Update command = (Update) resourceCommand;
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
@@ -98,7 +98,7 @@ public final class ContactUpdateFlow implements TransactionalFlow {
|
||||
ImmutableSet<StatusValue> statusToRemove = command.getInnerRemove().getStatusValues();
|
||||
ImmutableSet<StatusValue> statusesToAdd = command.getInnerAdd().getStatusValues();
|
||||
if (!isSuperuser) { // The superuser can update any contact and set any status.
|
||||
verifyResourceOwnership(clientId, existingContact);
|
||||
verifyResourceOwnership(registrarId, existingContact);
|
||||
verifyAllStatusesAreClientSettable(union(statusesToAdd, statusToRemove));
|
||||
}
|
||||
verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
|
||||
@@ -125,17 +125,18 @@ public final class ContactUpdateFlow implements TransactionalFlow {
|
||||
builder.setInternationalizedPostalInfo(null);
|
||||
}
|
||||
}
|
||||
ContactResource newContact = builder
|
||||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateClientId(clientId)
|
||||
.setAuthInfo(preferFirst(change.getAuthInfo(), existingContact.getAuthInfo()))
|
||||
.setDisclose(preferFirst(change.getDisclose(), existingContact.getDisclose()))
|
||||
.setEmailAddress(preferFirst(change.getEmail(), existingContact.getEmailAddress()))
|
||||
.setFaxNumber(preferFirst(change.getFax(), existingContact.getFaxNumber()))
|
||||
.setVoiceNumber(preferFirst(change.getVoice(), existingContact.getVoiceNumber()))
|
||||
.addStatusValues(statusesToAdd)
|
||||
.removeStatusValues(statusToRemove)
|
||||
.build();
|
||||
ContactResource newContact =
|
||||
builder
|
||||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateRegistrarId(registrarId)
|
||||
.setAuthInfo(preferFirst(change.getAuthInfo(), existingContact.getAuthInfo()))
|
||||
.setDisclose(preferFirst(change.getDisclose(), existingContact.getDisclose()))
|
||||
.setEmailAddress(preferFirst(change.getEmail(), existingContact.getEmailAddress()))
|
||||
.setFaxNumber(preferFirst(change.getFax(), existingContact.getFaxNumber()))
|
||||
.setVoiceNumber(preferFirst(change.getVoice(), existingContact.getVoiceNumber()))
|
||||
.addStatusValues(statusesToAdd)
|
||||
.removeStatusValues(statusToRemove)
|
||||
.build();
|
||||
// If the resource is marked with clientUpdateProhibited, and this update did not clear that
|
||||
// status, then the update must be disallowed (unless a superuser is requesting the change).
|
||||
if (!isSuperuser
|
||||
|
||||
@@ -56,10 +56,10 @@ public class DomainCreateFlowCustomLogic extends BaseFlowCustomLogic {
|
||||
/**
|
||||
* A hook that runs before new entities are persisted, allowing them to be changed.
|
||||
*
|
||||
* <p>It returns the actual entity changes that should be persisted to Datastore. It is important
|
||||
* to be careful when changing the flow behavior for existing entities, because the core logic
|
||||
* across many different flows expects the existence of these entities and many of the fields on
|
||||
* them.
|
||||
* <p>It returns the actual entity changes that should be persisted to the database. It is
|
||||
* important to be careful when changing the flow behavior for existing entities, because the core
|
||||
* logic across many different flows expects the existence of these entities and many of the
|
||||
* fields on them.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public EntityChanges beforeSave(BeforeSaveParameters parameters) throws EppException {
|
||||
|
||||
@@ -54,10 +54,10 @@ public class DomainDeleteFlowCustomLogic extends BaseFlowCustomLogic {
|
||||
/**
|
||||
* A hook that runs before new entities are persisted, allowing them to be changed.
|
||||
*
|
||||
* <p>It returns the actual entity changes that should be persisted to Datastore. It is important
|
||||
* to be careful when changing the flow behavior for existing entities, because the core logic
|
||||
* across many different flows expects the existence of these entities and many of the fields on
|
||||
* them.
|
||||
* <p>It returns the actual entity changes that should be persisted to the database. It is
|
||||
* important to be careful when changing the flow behavior for existing entities, because the core
|
||||
* logic across many different flows expects the existence of these entities and many of the
|
||||
* fields on them.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public EntityChanges beforeSave(BeforeSaveParameters parameters) throws EppException {
|
||||
|
||||
@@ -55,10 +55,10 @@ public class DomainRenewFlowCustomLogic extends BaseFlowCustomLogic {
|
||||
/**
|
||||
* A hook that runs before new entities are persisted, allowing them to be changed.
|
||||
*
|
||||
* <p>It returns the actual entity changes that should be persisted to Datastore. It is important
|
||||
* to be careful when changing the flow behavior for existing entities, because the core logic
|
||||
* across many different flows expects the existence of these entities and many of the fields on
|
||||
* them.
|
||||
* <p>It returns the actual entity changes that should be persisted to the database. It is
|
||||
* important to be careful when changing the flow behavior for existing entities, because the core
|
||||
* logic across many different flows expects the existence of these entities and many of the
|
||||
* fields on them.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public EntityChanges beforeSave(BeforeSaveParameters parameters) throws EppException {
|
||||
|
||||
@@ -51,10 +51,10 @@ public class DomainUpdateFlowCustomLogic extends BaseFlowCustomLogic {
|
||||
/**
|
||||
* A hook that runs before new entities are persisted, allowing them to be changed.
|
||||
*
|
||||
* <p>It returns the actual entity changes that should be persisted to Datastore. It is important
|
||||
* to be careful when changing the flow behavior for existing entities, because the core logic
|
||||
* across many different flows expects the existence of these entities and many of the fields on
|
||||
* them.
|
||||
* <p>It returns the actual entity changes that should be persisted to the database. It is
|
||||
* important to be careful when changing the flow behavior for existing entities, because the core
|
||||
* logic across many different flows expects the existence of these entities and many of the
|
||||
* fields on them.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public EntityChanges beforeSave(BeforeSaveParameters parameters) throws EppException {
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.persistence.VKey;
|
||||
|
||||
/** A wrapper class that encapsulates Datastore entities to both save and delete. */
|
||||
/** A wrapper class that encapsulates database entities to both save and delete. */
|
||||
@AutoValue
|
||||
public abstract class EntityChanges {
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ package google.registry.flows.domain;
|
||||
import static com.google.common.base.Strings.emptyToNull;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.getReservationTypes;
|
||||
@@ -41,7 +41,7 @@ import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.flows.custom.DomainCheckFlowCustomLogic;
|
||||
@@ -113,7 +113,7 @@ public final class DomainCheckFlow implements Flow {
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject EppInput eppInput;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
|
||||
@Inject
|
||||
@Config("maxChecks")
|
||||
@@ -135,7 +135,7 @@ public final class DomainCheckFlow implements Flow {
|
||||
FeeCheckCommandExtension.class, LaunchCheckExtension.class, AllocationTokenExtension.class);
|
||||
flowCustomLogic.beforeValidation();
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
ImmutableList<String> domainNames = ((Check) resourceCommand).getTargetIds();
|
||||
verifyTargetIdCount(domainNames, maxChecks);
|
||||
DateTime now = clock.nowUtc();
|
||||
@@ -151,7 +151,7 @@ public final class DomainCheckFlow implements Flow {
|
||||
String tld = parsedDomain.parent().toString();
|
||||
boolean tldFirstTimeSeen = seenTlds.add(tld);
|
||||
if (tldFirstTimeSeen && !isSuperuser) {
|
||||
checkAllowedAccessToTld(clientId, tld);
|
||||
checkAllowedAccessToTld(registrarId, tld);
|
||||
verifyNotInPredelegation(Registry.get(tld), now);
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,7 @@ public final class DomainCheckFlow implements Flow {
|
||||
allocationTokenFlowUtils.checkDomainsWithToken(
|
||||
ImmutableList.copyOf(parsedDomains.values()),
|
||||
tokenExtension.getAllocationToken(),
|
||||
clientId,
|
||||
registrarId,
|
||||
now));
|
||||
|
||||
ImmutableList.Builder<DomainCheck> checksBuilder = new ImmutableList.Builder<>();
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateDomainName;
|
||||
@@ -31,7 +31,7 @@ import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.CommandUseErrorException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.model.domain.DomainCommand.Check;
|
||||
@@ -69,7 +69,7 @@ public final class DomainClaimsCheckFlow implements Flow {
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject EppInput eppInput;
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject Clock clock;
|
||||
@Inject @Config("maxChecks") int maxChecks;
|
||||
@@ -82,7 +82,7 @@ public final class DomainClaimsCheckFlow implements Flow {
|
||||
public EppResponse run() throws EppException {
|
||||
extensionManager.register(LaunchCheckExtension.class, AllocationTokenExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
if (eppInput.getSingleExtension(AllocationTokenExtension.class).isPresent()) {
|
||||
throw new DomainClaimsCheckNotAllowedWithAllocationTokens();
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public final class DomainClaimsCheckFlow implements Flow {
|
||||
// Only validate access to a TLD the first time it is encountered.
|
||||
if (seenTlds.add(tld)) {
|
||||
if (!isSuperuser) {
|
||||
checkAllowedAccessToTld(clientId, tld);
|
||||
checkAllowedAccessToTld(registrarId, tld);
|
||||
Registry registry = Registry.get(tld);
|
||||
DateTime now = clock.nowUtc();
|
||||
verifyNotInPredelegation(registry, now);
|
||||
|
||||
@@ -16,7 +16,7 @@ package google.registry.flows.domain;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.flows.FlowUtils.persistEntityChanges;
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.COLLISION_MESSAGE;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
||||
@@ -62,7 +62,7 @@ import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.CommandUseErrorException;
|
||||
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
@@ -204,7 +204,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject EppInput eppInput;
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject DomainHistory.Builder historyBuilder;
|
||||
@@ -226,15 +226,15 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
AllocationTokenExtension.class);
|
||||
flowCustomLogic.beforeValidation();
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
verifyRegistrarIsActive(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
verifyRegistrarIsActive(registrarId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DomainCommand.Create command = cloneAndLinkReferences((Create) resourceCommand, now);
|
||||
Period period = command.getPeriod();
|
||||
verifyUnitIsYears(period);
|
||||
int years = period.getValue();
|
||||
validateRegistrationPeriod(years);
|
||||
verifyResourceDoesNotExist(DomainBase.class, targetId, now, clientId);
|
||||
verifyResourceDoesNotExist(DomainBase.class, targetId, now, registrarId);
|
||||
// Validate that this is actually a legal domain name on a TLD that the registrar has access to.
|
||||
InternetDomainName domainName = validateDomainName(command.getFullyQualifiedDomainName());
|
||||
String domainLabel = domainName.parts().get(0);
|
||||
@@ -252,7 +252,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
}
|
||||
boolean isSunriseCreate = hasSignedMarks && (tldState == START_DATE_SUNRISE);
|
||||
Optional<AllocationToken> allocationToken =
|
||||
verifyAllocationTokenIfPresent(command, registry, clientId, now);
|
||||
verifyAllocationTokenIfPresent(command, registry, registrarId, now);
|
||||
boolean isAnchorTenant =
|
||||
isAnchorTenant(
|
||||
domainName, allocationToken, eppInput.getSingleExtension(MetadataExtension.class));
|
||||
@@ -261,7 +261,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
// notice without specifying a claims key, ignore the registry phase, and override blocks on
|
||||
// registering premium domains.
|
||||
if (!isSuperuser) {
|
||||
checkAllowedAccessToTld(clientId, registry.getTldStr());
|
||||
checkAllowedAccessToTld(registrarId, registry.getTldStr());
|
||||
boolean isValidReservedCreate = isValidReservedCreate(domainName, allocationToken);
|
||||
verifyIsGaOrIsSpecialCase(tldState, isAnchorTenant, isValidReservedCreate, hasSignedMarks);
|
||||
if (launchCreate.isPresent()) {
|
||||
@@ -276,7 +276,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
if (now.isBefore(registry.getClaimsPeriodEnd())) {
|
||||
verifyClaimsNoticeIfAndOnlyIfNeeded(domainName, hasSignedMarks, hasClaimsNotice);
|
||||
}
|
||||
verifyPremiumNameIsNotBlocked(targetId, now, clientId);
|
||||
verifyPremiumNameIsNotBlocked(targetId, now, registrarId);
|
||||
verifySignedMarkOnlyInSunrise(hasSignedMarks, tldState);
|
||||
}
|
||||
String signedMarkId = null;
|
||||
@@ -338,8 +338,8 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
: ImmutableSet.of();
|
||||
DomainBase domain =
|
||||
new DomainBase.Builder()
|
||||
.setCreationClientId(clientId)
|
||||
.setPersistedCurrentSponsorClientId(clientId)
|
||||
.setCreationRegistrarId(registrarId)
|
||||
.setPersistedCurrentSponsorRegistrarId(registrarId)
|
||||
.setRepoId(repoId)
|
||||
.setIdnTableName(validateDomainNameWithIdnTables(domainName))
|
||||
.setRegistrationExpirationTime(registrationExpirationTime)
|
||||
@@ -361,7 +361,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
buildDomainHistory(domain, registry, now, period, registry.getAddGracePeriodLength());
|
||||
if (reservationTypes.contains(NAME_COLLISION)) {
|
||||
entitiesToSave.add(
|
||||
createNameCollisionOneTimePollMessage(targetId, domainHistory, clientId, now));
|
||||
createNameCollisionOneTimePollMessage(targetId, domainHistory, registrarId, now));
|
||||
}
|
||||
entitiesToSave.add(
|
||||
domain,
|
||||
@@ -472,14 +472,14 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
|
||||
/** Verifies and returns the allocation token if one is specified, otherwise does nothing. */
|
||||
private Optional<AllocationToken> verifyAllocationTokenIfPresent(
|
||||
DomainCommand.Create command, Registry registry, String clientId, DateTime now)
|
||||
DomainCommand.Create command, Registry registry, String registrarId, DateTime now)
|
||||
throws EppException {
|
||||
Optional<AllocationTokenExtension> extension =
|
||||
eppInput.getSingleExtension(AllocationTokenExtension.class);
|
||||
return Optional.ofNullable(
|
||||
extension.isPresent()
|
||||
? allocationTokenFlowUtils.loadTokenAndValidateDomainCreate(
|
||||
command, extension.get().getAllocationToken(), registry, clientId, now)
|
||||
command, extension.get().getAllocationToken(), registry, registrarId, now)
|
||||
: null);
|
||||
}
|
||||
|
||||
@@ -524,7 +524,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
return new BillingEvent.OneTime.Builder()
|
||||
.setReason(Reason.CREATE)
|
||||
.setTargetId(targetId)
|
||||
.setClientId(clientId)
|
||||
.setRegistrarId(registrarId)
|
||||
.setPeriodYears(years)
|
||||
.setCost(feesAndCredits.getCreateCost())
|
||||
.setEventTime(now)
|
||||
@@ -545,7 +545,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
.setReason(Reason.RENEW)
|
||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||
.setTargetId(targetId)
|
||||
.setClientId(clientId)
|
||||
.setRegistrarId(registrarId)
|
||||
.setEventTime(registrationExpirationTime)
|
||||
.setRecurrenceEndTime(END_OF_TIME)
|
||||
.setParent(domainHistoryKey)
|
||||
@@ -556,7 +556,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
Key<DomainHistory> domainHistoryKey, DateTime registrationExpirationTime) {
|
||||
return new PollMessage.Autorenew.Builder()
|
||||
.setTargetId(targetId)
|
||||
.setClientId(clientId)
|
||||
.setRegistrarId(registrarId)
|
||||
.setEventTime(registrationExpirationTime)
|
||||
.setMsg("Domain was auto-renewed.")
|
||||
.setParentKey(domainHistoryKey)
|
||||
@@ -568,7 +568,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
return new BillingEvent.OneTime.Builder()
|
||||
.setReason(Reason.FEE_EARLY_ACCESS)
|
||||
.setTargetId(createBillingEvent.getTargetId())
|
||||
.setClientId(createBillingEvent.getClientId())
|
||||
.setRegistrarId(createBillingEvent.getRegistrarId())
|
||||
.setPeriodYears(1)
|
||||
.setCost(feesAndCredits.getEapCost())
|
||||
.setEventTime(createBillingEvent.getEventTime())
|
||||
@@ -579,9 +579,12 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
}
|
||||
|
||||
private static PollMessage.OneTime createNameCollisionOneTimePollMessage(
|
||||
String fullyQualifiedDomainName, HistoryEntry historyEntry, String clientId, DateTime now) {
|
||||
String fullyQualifiedDomainName,
|
||||
HistoryEntry historyEntry,
|
||||
String registrarId,
|
||||
DateTime now) {
|
||||
return new PollMessage.OneTime.Builder()
|
||||
.setClientId(clientId)
|
||||
.setRegistrarId(registrarId)
|
||||
.setEventTime(now)
|
||||
.setMsg(COLLISION_MESSAGE) // Remind the registrar of the name collision policy.
|
||||
.setResponseData(
|
||||
|
||||
@@ -18,7 +18,7 @@ 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.persistEntityChanges;
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
@@ -50,7 +50,7 @@ import google.registry.dns.DnsQueue;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.AssociationProhibitsOperationException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.SessionMetadata;
|
||||
@@ -124,7 +124,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
@Inject EppInput eppInput;
|
||||
@Inject SessionMetadata sessionMetadata;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject DomainHistory.Builder historyBuilder;
|
||||
@@ -141,7 +141,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
MetadataExtension.class, SecDnsCreateExtension.class, DomainDeleteSuperuserExtension.class);
|
||||
flowCustomLogic.beforeValidation();
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
// Loads the target resource if it exists
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
@@ -153,12 +153,12 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
DomainBase.Builder builder;
|
||||
if (existingDomain.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) {
|
||||
builder =
|
||||
denyPendingTransfer(existingDomain, TransferStatus.SERVER_CANCELLED, now, clientId)
|
||||
denyPendingTransfer(existingDomain, TransferStatus.SERVER_CANCELLED, now, registrarId)
|
||||
.asBuilder();
|
||||
} else {
|
||||
builder = existingDomain.asBuilder();
|
||||
}
|
||||
builder.setLastEppUpdateTime(now).setLastEppUpdateClientId(clientId);
|
||||
builder.setLastEppUpdateTime(now).setLastEppUpdateRegistrarId(registrarId);
|
||||
Duration redemptionGracePeriodLength = registry.getRedemptionGracePeriodLength();
|
||||
Duration pendingDeleteLength = registry.getPendingDeleteLength();
|
||||
Optional<DomainDeleteSuperuserExtension> domainDeleteSuperuserExtension =
|
||||
@@ -199,7 +199,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
GracePeriodStatus.REDEMPTION,
|
||||
existingDomain.getRepoId(),
|
||||
redemptionTime,
|
||||
clientId)));
|
||||
registrarId)));
|
||||
// Note: The expiration time is unchanged, so if it's before the new deletion time, there will
|
||||
// be a "phantom autorenew" where the expiration time advances. No poll message will be
|
||||
// produced (since we are ending the autorenew recurrences at "now" below) and the billing
|
||||
@@ -220,7 +220,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
// Send a second poll message immediately if the domain is being deleted asynchronously by a
|
||||
// registrar other than the sponsoring registrar (which will necessarily be a superuser).
|
||||
if (durationUntilDelete.isLongerThan(Duration.ZERO)
|
||||
&& !clientId.equals(existingDomain.getPersistedCurrentSponsorClientId())) {
|
||||
&& !registrarId.equals(existingDomain.getPersistedCurrentSponsorRegistrarId())) {
|
||||
entitiesToSave.add(
|
||||
createImmediateDeletePollMessage(existingDomain, domainHistoryKey, now, deletionTime));
|
||||
}
|
||||
@@ -292,9 +292,9 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
verifyNoDisallowedStatuses(existingDomain, DISALLOWED_STATUSES);
|
||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||
if (!isSuperuser) {
|
||||
verifyResourceOwnership(clientId, existingDomain);
|
||||
verifyResourceOwnership(registrarId, existingDomain);
|
||||
verifyNotInPredelegation(registry, now);
|
||||
checkAllowedAccessToTld(clientId, registry.getTld().toString());
|
||||
checkAllowedAccessToTld(registrarId, registry.getTld().toString());
|
||||
}
|
||||
if (!existingDomain.getSubordinateHosts().isEmpty()) {
|
||||
throw new DomainToDeleteHasHostsException();
|
||||
@@ -347,7 +347,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
: "Deleted by registry administrator.")
|
||||
: "Domain deleted.";
|
||||
return new PollMessage.OneTime.Builder()
|
||||
.setClientId(existingDomain.getCurrentSponsorClientId())
|
||||
.setRegistrarId(existingDomain.getCurrentSponsorRegistrarId())
|
||||
.setEventTime(deletionTime)
|
||||
.setMsg(message)
|
||||
.setResponseData(
|
||||
@@ -364,7 +364,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
DateTime now,
|
||||
DateTime deletionTime) {
|
||||
return new PollMessage.OneTime.Builder()
|
||||
.setClientId(existingDomain.getPersistedCurrentSponsorClientId())
|
||||
.setRegistrarId(existingDomain.getPersistedCurrentSponsorRegistrarId())
|
||||
.setEventTime(now)
|
||||
.setParentKey(domainHistoryKey)
|
||||
.setMsg(
|
||||
|
||||
@@ -285,8 +285,8 @@ public class DomainFlowUtils {
|
||||
}
|
||||
|
||||
/** Check if the registrar running the flow has access to the TLD in question. */
|
||||
public static void checkAllowedAccessToTld(String clientId, String tld) throws EppException {
|
||||
if (!Registrar.loadByClientIdCached(clientId).get().getAllowedTlds().contains(tld)) {
|
||||
public static void checkAllowedAccessToTld(String registrarId, String tld) throws EppException {
|
||||
if (!Registrar.loadByRegistrarIdCached(registrarId).get().getAllowedTlds().contains(tld)) {
|
||||
throw new DomainFlowUtils.NotAuthorizedForTldException(tld);
|
||||
}
|
||||
}
|
||||
@@ -464,10 +464,10 @@ public class DomainFlowUtils {
|
||||
* where it would not be allowed is if domain name is premium, and premium names are blocked by
|
||||
* this registrar.
|
||||
*/
|
||||
static void verifyPremiumNameIsNotBlocked(String domainName, DateTime priceTime, String clientId)
|
||||
throws EppException {
|
||||
static void verifyPremiumNameIsNotBlocked(
|
||||
String domainName, DateTime priceTime, String registrarId) throws EppException {
|
||||
if (isDomainPremium(domainName, priceTime)) {
|
||||
if (Registrar.loadByClientIdCached(clientId).get().getBlockPremiumNames()) {
|
||||
if (Registrar.loadByRegistrarIdCached(registrarId).get().getBlockPremiumNames()) {
|
||||
throw new PremiumNameBlockedException();
|
||||
}
|
||||
}
|
||||
@@ -495,7 +495,7 @@ public class DomainFlowUtils {
|
||||
.setReason(Reason.RENEW)
|
||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||
.setTargetId(domain.getDomainName())
|
||||
.setClientId(domain.getCurrentSponsorClientId())
|
||||
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
|
||||
.setEventTime(domain.getRegistrationExpirationTime());
|
||||
}
|
||||
|
||||
@@ -506,7 +506,7 @@ public class DomainFlowUtils {
|
||||
public static PollMessage.Autorenew.Builder newAutorenewPollMessage(DomainBase domain) {
|
||||
return new PollMessage.Autorenew.Builder()
|
||||
.setTargetId(domain.getDomainName())
|
||||
.setClientId(domain.getCurrentSponsorClientId())
|
||||
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
|
||||
.setEventTime(domain.getRegistrationExpirationTime())
|
||||
.setMsg("Domain was auto-renewed.");
|
||||
}
|
||||
@@ -896,9 +896,9 @@ public class DomainFlowUtils {
|
||||
* <p>Non-active registrars are not allowed to run operations that cost money, like domain creates
|
||||
* or renews.
|
||||
*/
|
||||
static void verifyRegistrarIsActive(String clientId)
|
||||
static void verifyRegistrarIsActive(String registrarId)
|
||||
throws RegistrarMustBeActiveForThisOperationException {
|
||||
Registrar registrar = Registrar.loadByClientIdCached(clientId).get();
|
||||
Registrar registrar = Registrar.loadByRegistrarIdCached(registrarId).get();
|
||||
if (registrar.getState() != State.ACTIVE) {
|
||||
throw new RegistrarMustBeActiveForThisOperationException();
|
||||
}
|
||||
@@ -1097,10 +1097,11 @@ public class DomainFlowUtils {
|
||||
} else {
|
||||
return jpaTm()
|
||||
.query(
|
||||
"FROM DomainHistory WHERE modificationTime >= :beginning "
|
||||
+ "ORDER BY modificationTime ASC",
|
||||
"FROM DomainHistory WHERE modificationTime >= :beginning AND domainRepoId = "
|
||||
+ ":repoId ORDER BY modificationTime ASC",
|
||||
DomainHistory.class)
|
||||
.setParameter("beginning", now.minus(maxSearchPeriod))
|
||||
.setParameter("repoId", domainBase.getRepoId())
|
||||
.getResultList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.addSecDnsExtensionIfPresent;
|
||||
@@ -30,7 +30,7 @@ import com.google.common.net.InternetDomainName;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.flows.custom.DomainInfoFlowCustomLogic;
|
||||
@@ -79,7 +79,7 @@ public final class DomainInfoFlow implements Flow {
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject EppInput eppInput;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject Clock clock;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
@@ -94,7 +94,7 @@ public final class DomainInfoFlow implements Flow {
|
||||
extensionManager.register(FeeInfoCommandExtensionV06.class);
|
||||
flowCustomLogic.beforeValidation();
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
DateTime now = clock.nowUtc();
|
||||
DomainBase domain = verifyExistence(
|
||||
DomainBase.class, targetId, loadByForeignKey(DomainBase.class, targetId, now));
|
||||
@@ -112,12 +112,12 @@ public final class DomainInfoFlow implements Flow {
|
||||
DomainInfoData.newBuilder()
|
||||
.setFullyQualifiedDomainName(domain.getDomainName())
|
||||
.setRepoId(domain.getRepoId())
|
||||
.setCurrentSponsorClientId(domain.getCurrentSponsorClientId())
|
||||
.setCurrentSponsorClientId(domain.getCurrentSponsorRegistrarId())
|
||||
.setRegistrant(
|
||||
transactIfJpaTm(() -> 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 (clientId.equals(domain.getCurrentSponsorClientId()) || authInfo.isPresent()) {
|
||||
if (registrarId.equals(domain.getCurrentSponsorRegistrarId()) || authInfo.isPresent()) {
|
||||
HostsRequest hostsRequest = ((Info) resourceCommand).getHostsRequest();
|
||||
infoBuilder
|
||||
.setStatusValues(domain.getStatusValues())
|
||||
@@ -126,9 +126,9 @@ public final class DomainInfoFlow implements Flow {
|
||||
.setNameservers(hostsRequest.requestDelegated() ? domain.loadNameserverHostNames() : null)
|
||||
.setSubordinateHosts(
|
||||
hostsRequest.requestSubordinate() ? domain.getSubordinateHosts() : null)
|
||||
.setCreationClientId(domain.getCreationClientId())
|
||||
.setCreationClientId(domain.getCreationRegistrarId())
|
||||
.setCreationTime(domain.getCreationTime())
|
||||
.setLastEppUpdateClientId(domain.getLastEppUpdateClientId())
|
||||
.setLastEppUpdateClientId(domain.getLastEppUpdateRegistrarId())
|
||||
.setLastEppUpdateTime(domain.getLastEppUpdateTime())
|
||||
.setRegistrationExpirationTime(domain.getRegistrationExpirationTime())
|
||||
.setLastTransferTime(domain.getLastTransferTime())
|
||||
|
||||
@@ -16,7 +16,7 @@ package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.persistEntityChanges;
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
@@ -39,7 +39,7 @@ import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
@@ -123,7 +123,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject EppInput eppInput;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject DomainHistory.Builder historyBuilder;
|
||||
@@ -137,8 +137,8 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
extensionManager.register(FeeRenewCommandExtension.class, MetadataExtension.class);
|
||||
flowCustomLogic.beforeValidation();
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
verifyRegistrarIsActive(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
verifyRegistrarIsActive(registrarId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
Renew command = (Renew) resourceCommand;
|
||||
// Loads the target resource if it exists
|
||||
@@ -182,7 +182,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
existingDomain
|
||||
.asBuilder()
|
||||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateClientId(clientId)
|
||||
.setLastEppUpdateRegistrarId(registrarId)
|
||||
.setRegistrationExpirationTime(newExpirationTime)
|
||||
.setAutorenewBillingEvent(newAutorenewEvent.createVKey())
|
||||
.setAutorenewPollMessage(newAutorenewPollMessage.createVKey())
|
||||
@@ -250,8 +250,8 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||
verifyNoDisallowedStatuses(existingDomain, RENEW_DISALLOWED_STATUSES);
|
||||
if (!isSuperuser) {
|
||||
verifyResourceOwnership(clientId, existingDomain);
|
||||
checkAllowedAccessToTld(clientId, existingDomain.getTld());
|
||||
verifyResourceOwnership(registrarId, existingDomain);
|
||||
checkAllowedAccessToTld(registrarId, existingDomain.getTld());
|
||||
}
|
||||
verifyUnitIsYears(command.getPeriod());
|
||||
// If the date they specify doesn't match the expiration, fail. (This is an idempotence check).
|
||||
@@ -266,7 +266,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
return new BillingEvent.OneTime.Builder()
|
||||
.setReason(Reason.RENEW)
|
||||
.setTargetId(targetId)
|
||||
.setClientId(clientId)
|
||||
.setRegistrarId(registrarId)
|
||||
.setPeriodYears(years)
|
||||
.setCost(renewCost)
|
||||
.setEventTime(now)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||
@@ -40,7 +40,7 @@ import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.CommandUseErrorException;
|
||||
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
@@ -116,7 +116,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject EppInput eppInput;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject DomainHistory.Builder historyBuilder;
|
||||
@@ -132,8 +132,8 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
MetadataExtension.class,
|
||||
RgpUpdateExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
verifyRegistrarIsActive(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
verifyRegistrarIsActive(registrarId);
|
||||
Update command = (Update) resourceCommand;
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
@@ -174,7 +174,12 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
.build();
|
||||
DomainBase newDomain =
|
||||
performRestore(
|
||||
existingDomain, newExpirationTime, autorenewEvent, autorenewPollMessage, now, clientId);
|
||||
existingDomain,
|
||||
newExpirationTime,
|
||||
autorenewEvent,
|
||||
autorenewPollMessage,
|
||||
now,
|
||||
registrarId);
|
||||
updateForeignKeyIndexDeletionTime(newDomain);
|
||||
DomainHistory domainHistory = buildDomainHistory(newDomain, now);
|
||||
entitiesToSave.add(newDomain, domainHistory, autorenewEvent, autorenewPollMessage);
|
||||
@@ -205,10 +210,10 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
DateTime now) throws EppException {
|
||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||
if (!isSuperuser) {
|
||||
verifyResourceOwnership(clientId, existingDomain);
|
||||
verifyResourceOwnership(registrarId, existingDomain);
|
||||
verifyNotReserved(InternetDomainName.from(targetId), false);
|
||||
verifyPremiumNameIsNotBlocked(targetId, now, clientId);
|
||||
checkAllowedAccessToTld(clientId, existingDomain.getTld());
|
||||
verifyPremiumNameIsNotBlocked(targetId, now, registrarId);
|
||||
checkAllowedAccessToTld(registrarId, existingDomain.getTld());
|
||||
}
|
||||
// No other changes can be specified on a restore request.
|
||||
if (!command.noChangesPresent()) {
|
||||
@@ -227,7 +232,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
BillingEvent.Recurring autorenewEvent,
|
||||
PollMessage.Autorenew autorenewPollMessage,
|
||||
DateTime now,
|
||||
String clientId) {
|
||||
String registrarId) {
|
||||
return existingDomain
|
||||
.asBuilder()
|
||||
.setRegistrationExpirationTime(newExpirationTime)
|
||||
@@ -241,7 +246,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
// it won't immediately be deleted again.
|
||||
.setAutorenewEndTime(Optional.empty())
|
||||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateClientId(clientId)
|
||||
.setLastEppUpdateRegistrarId(registrarId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -261,7 +266,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
Key<DomainHistory> domainHistoryKey, Money cost, DateTime now) {
|
||||
return new BillingEvent.OneTime.Builder()
|
||||
.setTargetId(targetId)
|
||||
.setClientId(clientId)
|
||||
.setRegistrarId(registrarId)
|
||||
.setEventTime(now)
|
||||
.setBillingTime(now)
|
||||
.setPeriodYears(1)
|
||||
|
||||
@@ -16,7 +16,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.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.computeExDateForApprovalTime;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
||||
@@ -40,7 +40,7 @@ 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.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
@@ -89,7 +89,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject DomainHistory.Builder historyBuilder;
|
||||
@@ -104,18 +104,18 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||
verifyHasPendingTransfer(existingDomain);
|
||||
verifyResourceOwnership(clientId, existingDomain);
|
||||
verifyResourceOwnership(registrarId, existingDomain);
|
||||
String tld = existingDomain.getTld();
|
||||
if (!isSuperuser) {
|
||||
checkAllowedAccessToTld(clientId, tld);
|
||||
checkAllowedAccessToTld(registrarId, tld);
|
||||
}
|
||||
DomainTransferData transferData = existingDomain.getTransferData();
|
||||
String gainingClientId = transferData.getGainingClientId();
|
||||
String gainingRegistrarId = transferData.getGainingRegistrarId();
|
||||
// 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.
|
||||
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
|
||||
@@ -127,7 +127,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
new BillingEvent.OneTime.Builder()
|
||||
.setReason(Reason.TRANSFER)
|
||||
.setTargetId(targetId)
|
||||
.setClientId(gainingClientId)
|
||||
.setRegistrarId(gainingRegistrarId)
|
||||
.setPeriodYears(1)
|
||||
.setCost(getDomainRenewCost(targetId, transferData.getTransferRequestTime(), 1))
|
||||
.setEventTime(now)
|
||||
@@ -162,7 +162,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
.setReason(Reason.RENEW)
|
||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||
.setTargetId(targetId)
|
||||
.setClientId(gainingClientId)
|
||||
.setRegistrarId(gainingRegistrarId)
|
||||
.setEventTime(newExpirationTime)
|
||||
.setRecurrenceEndTime(END_OF_TIME)
|
||||
.setParent(domainHistoryKey)
|
||||
@@ -171,7 +171,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
PollMessage.Autorenew gainingClientAutorenewPollMessage =
|
||||
new PollMessage.Autorenew.Builder()
|
||||
.setTargetId(targetId)
|
||||
.setClientId(gainingClientId)
|
||||
.setRegistrarId(gainingRegistrarId)
|
||||
.setEventTime(newExpirationTime)
|
||||
.setAutorenewEndTime(END_OF_TIME)
|
||||
.setMsg("Domain was auto-renewed.")
|
||||
@@ -206,10 +206,10 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
oneTime)))
|
||||
.orElseGet(ImmutableSet::of))
|
||||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateClientId(clientId)
|
||||
.setLastEppUpdateRegistrarId(registrarId)
|
||||
.build();
|
||||
Registry registry = Registry.get(existingDomain.getTld());
|
||||
DomainHistory domainHistory = buildDomainHistory(newDomain, registry, now, gainingClientId);
|
||||
DomainHistory domainHistory = buildDomainHistory(newDomain, registry, now, gainingRegistrarId);
|
||||
// Create a poll message for the gaining client.
|
||||
PollMessage gainingClientPollMessage =
|
||||
createGainingTransferPollMessage(
|
||||
@@ -232,7 +232,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
}
|
||||
|
||||
private DomainHistory buildDomainHistory(
|
||||
DomainBase newDomain, Registry registry, DateTime now, String gainingClientId) {
|
||||
DomainBase newDomain, Registry registry, DateTime now, String gainingRegistrarId) {
|
||||
ImmutableSet<DomainTransactionRecord> cancelingRecords =
|
||||
createCancelingRecords(
|
||||
newDomain,
|
||||
@@ -241,7 +241,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
ImmutableSet.of(TRANSFER_SUCCESSFUL));
|
||||
return historyBuilder
|
||||
.setType(DOMAIN_TRANSFER_APPROVE)
|
||||
.setOtherClientId(gainingClientId)
|
||||
.setOtherRegistrarId(gainingRegistrarId)
|
||||
.setDomain(newDomain)
|
||||
.setDomainTransactionRecords(
|
||||
union(
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
@@ -35,7 +35,7 @@ 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.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
@@ -76,7 +76,7 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject DomainHistory.Builder historyBuilder;
|
||||
@@ -87,24 +87,24 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||
verifyHasPendingTransfer(existingDomain);
|
||||
verifyTransferInitiator(clientId, existingDomain);
|
||||
verifyTransferInitiator(registrarId, existingDomain);
|
||||
if (!isSuperuser) {
|
||||
checkAllowedAccessToTld(clientId, existingDomain.getTld());
|
||||
checkAllowedAccessToTld(registrarId, existingDomain.getTld());
|
||||
}
|
||||
Registry registry = Registry.get(existingDomain.getTld());
|
||||
|
||||
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
|
||||
historyBuilder
|
||||
.setId(domainHistoryKey.getId())
|
||||
.setOtherClientId(existingDomain.getTransferData().getLosingClientId());
|
||||
.setOtherRegistrarId(existingDomain.getTransferData().getLosingRegistrarId());
|
||||
|
||||
DomainBase newDomain =
|
||||
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_CANCELLED, now, clientId);
|
||||
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_CANCELLED, now, registrarId);
|
||||
DomainHistory domainHistory = buildDomainHistory(newDomain, registry, now);
|
||||
tm().putAll(
|
||||
newDomain,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
import static google.registry.flows.domain.DomainTransferUtils.createTransferResponse;
|
||||
@@ -22,7 +22,7 @@ import static google.registry.flows.domain.DomainTransferUtils.createTransferRes
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.ResourceFlowUtils;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
@@ -59,7 +59,7 @@ public final class DomainTransferQueryFlow implements Flow {
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject Clock clock;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
@@ -68,7 +68,7 @@ public final class DomainTransferQueryFlow implements Flow {
|
||||
@Override
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
DateTime now = clock.nowUtc();
|
||||
DomainBase domain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, domain);
|
||||
@@ -81,8 +81,8 @@ public final class DomainTransferQueryFlow implements Flow {
|
||||
// Note that the authorization info on the command (if present) has already been verified. If
|
||||
// it's present, then the other checks are unnecessary.
|
||||
if (!authInfo.isPresent()
|
||||
&& !clientId.equals(transferData.getGainingClientId())
|
||||
&& !clientId.equals(transferData.getLosingClientId())) {
|
||||
&& !registrarId.equals(transferData.getGainingRegistrarId())
|
||||
&& !registrarId.equals(transferData.getLosingRegistrarId())) {
|
||||
throw new NotAuthorizedToViewTransferException();
|
||||
}
|
||||
DateTime newExpirationTime = null;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
@@ -37,7 +37,7 @@ 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.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
@@ -78,7 +78,7 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject DomainHistory.Builder historyBuilder;
|
||||
@@ -89,23 +89,23 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
Registry registry = Registry.get(existingDomain.getTld());
|
||||
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
|
||||
historyBuilder
|
||||
.setId(domainHistoryKey.getId())
|
||||
.setOtherClientId(existingDomain.getTransferData().getGainingClientId());
|
||||
.setOtherRegistrarId(existingDomain.getTransferData().getGainingRegistrarId());
|
||||
|
||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||
verifyHasPendingTransfer(existingDomain);
|
||||
verifyResourceOwnership(clientId, existingDomain);
|
||||
verifyResourceOwnership(registrarId, existingDomain);
|
||||
if (!isSuperuser) {
|
||||
checkAllowedAccessToTld(clientId, existingDomain.getTld());
|
||||
checkAllowedAccessToTld(registrarId, existingDomain.getTld());
|
||||
}
|
||||
DomainBase newDomain =
|
||||
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_REJECTED, now, clientId);
|
||||
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_REJECTED, now, registrarId);
|
||||
DomainHistory domainHistory = buildDomainHistory(newDomain, registry, now);
|
||||
tm().putAll(
|
||||
newDomain,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.createHistoryKey;
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.computeExDateForApprovalTime;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfo;
|
||||
@@ -41,7 +41,7 @@ import com.googlecode.objectify.Key;
|
||||
import google.registry.batch.AsyncTaskEnqueuer;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
@@ -125,7 +125,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject EppInput eppInput;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String gainingClientId;
|
||||
@Inject @RegistrarId String gainingClientId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject DomainHistory.Builder historyBuilder;
|
||||
@@ -142,7 +142,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
FeeTransferCommandExtension.class,
|
||||
MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(gainingClientId);
|
||||
validateRegistrarIsLoggedIn(gainingClientId);
|
||||
verifyRegistrarIsActive(gainingClientId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
@@ -174,7 +174,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
|
||||
historyBuilder
|
||||
.setId(domainHistoryKey.getId())
|
||||
.setOtherClientId(existingDomain.getCurrentSponsorClientId());
|
||||
.setOtherRegistrarId(existingDomain.getCurrentSponsorRegistrarId());
|
||||
DateTime automaticTransferTime =
|
||||
superuserExtension.isPresent()
|
||||
? now.plusDays(superuserExtension.get().getAutomaticTransferLength())
|
||||
@@ -207,8 +207,8 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
new DomainTransferData.Builder()
|
||||
.setTransferRequestTrid(trid)
|
||||
.setTransferRequestTime(now)
|
||||
.setGainingClientId(gainingClientId)
|
||||
.setLosingClientId(existingDomain.getCurrentSponsorClientId())
|
||||
.setGainingRegistrarId(gainingClientId)
|
||||
.setLosingRegistrarId(existingDomain.getCurrentSponsorRegistrarId())
|
||||
.setPendingTransferExpirationTime(automaticTransferTime)
|
||||
.setTransferredRegistrationExpirationTime(serverApproveNewExpirationTime),
|
||||
serverApproveEntities,
|
||||
@@ -231,7 +231,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
.setTransferData(pendingTransferData)
|
||||
.addStatusValue(StatusValue.PENDING_TRANSFER)
|
||||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateClientId(gainingClientId)
|
||||
.setLastEppUpdateRegistrarId(gainingClientId)
|
||||
.build();
|
||||
DomainHistory domainHistory = buildDomainHistory(newDomain, registry, now, period);
|
||||
|
||||
@@ -264,7 +264,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
throw new AlreadyPendingTransferException(targetId);
|
||||
}
|
||||
// Verify that this client doesn't already sponsor this resource.
|
||||
if (gainingClientId.equals(existingDomain.getCurrentSponsorClientId())) {
|
||||
if (gainingClientId.equals(existingDomain.getCurrentSponsorRegistrarId())) {
|
||||
throw new ObjectAlreadySponsoredException();
|
||||
}
|
||||
verifyTransferPeriod(period, superuserExtension);
|
||||
|
||||
@@ -108,7 +108,7 @@ public final class DomainTransferUtils {
|
||||
Key<DomainHistory> domainHistoryKey,
|
||||
DomainBase existingDomain,
|
||||
Trid trid,
|
||||
String gainingClientId,
|
||||
String gainingRegistrarId,
|
||||
Optional<Money> transferCost,
|
||||
DateTime now) {
|
||||
String targetId = existingDomain.getDomainName();
|
||||
@@ -117,8 +117,8 @@ public final class DomainTransferUtils {
|
||||
new DomainTransferData.Builder()
|
||||
.setTransferRequestTrid(trid)
|
||||
.setTransferRequestTime(now)
|
||||
.setGainingClientId(gainingClientId)
|
||||
.setLosingClientId(existingDomain.getCurrentSponsorClientId())
|
||||
.setGainingRegistrarId(gainingRegistrarId)
|
||||
.setLosingRegistrarId(existingDomain.getCurrentSponsorRegistrarId())
|
||||
.setPendingTransferExpirationTime(automaticTransferTime)
|
||||
.setTransferredRegistrationExpirationTime(serverApproveNewExpirationTime)
|
||||
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
||||
@@ -132,7 +132,7 @@ public final class DomainTransferUtils {
|
||||
automaticTransferTime,
|
||||
domainHistoryKey,
|
||||
targetId,
|
||||
gainingClientId,
|
||||
gainingRegistrarId,
|
||||
registry,
|
||||
cost)));
|
||||
createOptionalAutorenewCancellation(
|
||||
@@ -141,10 +141,10 @@ public final class DomainTransferUtils {
|
||||
return builder
|
||||
.add(
|
||||
createGainingClientAutorenewEvent(
|
||||
serverApproveNewExpirationTime, domainHistoryKey, targetId, gainingClientId))
|
||||
serverApproveNewExpirationTime, domainHistoryKey, targetId, gainingRegistrarId))
|
||||
.add(
|
||||
createGainingClientAutorenewPollMessage(
|
||||
serverApproveNewExpirationTime, domainHistoryKey, targetId, gainingClientId))
|
||||
serverApproveNewExpirationTime, domainHistoryKey, targetId, gainingRegistrarId))
|
||||
.add(
|
||||
createGainingTransferPollMessage(
|
||||
targetId,
|
||||
@@ -169,7 +169,7 @@ public final class DomainTransferUtils {
|
||||
DateTime now,
|
||||
Key<DomainHistory> domainHistoryKey) {
|
||||
return new PollMessage.OneTime.Builder()
|
||||
.setClientId(transferData.getGainingClientId())
|
||||
.setRegistrarId(transferData.getGainingRegistrarId())
|
||||
.setEventTime(transferData.getPendingTransferExpirationTime())
|
||||
.setMsg(transferData.getTransferStatus().getMessage())
|
||||
.setResponseData(
|
||||
@@ -191,7 +191,7 @@ public final class DomainTransferUtils {
|
||||
@Nullable DateTime extendedRegistrationExpirationTime,
|
||||
Key<DomainHistory> domainHistoryKey) {
|
||||
return new PollMessage.OneTime.Builder()
|
||||
.setClientId(transferData.getLosingClientId())
|
||||
.setRegistrarId(transferData.getLosingRegistrarId())
|
||||
.setEventTime(transferData.getPendingTransferExpirationTime())
|
||||
.setMsg(transferData.getTransferStatus().getMessage())
|
||||
.setResponseData(
|
||||
@@ -208,8 +208,8 @@ public final class DomainTransferUtils {
|
||||
@Nullable DateTime extendedRegistrationExpirationTime) {
|
||||
return new DomainTransferResponse.Builder()
|
||||
.setFullyQualifiedDomainName(targetId)
|
||||
.setGainingClientId(transferData.getGainingClientId())
|
||||
.setLosingClientId(transferData.getLosingClientId())
|
||||
.setGainingRegistrarId(transferData.getGainingRegistrarId())
|
||||
.setLosingRegistrarId(transferData.getLosingRegistrarId())
|
||||
.setPendingTransferExpirationTime(transferData.getPendingTransferExpirationTime())
|
||||
.setTransferRequestTime(transferData.getTransferRequestTime())
|
||||
.setTransferStatus(transferData.getTransferStatus())
|
||||
@@ -221,10 +221,10 @@ public final class DomainTransferUtils {
|
||||
DateTime serverApproveNewExpirationTime,
|
||||
Key<DomainHistory> domainHistoryKey,
|
||||
String targetId,
|
||||
String gainingClientId) {
|
||||
String gainingRegistrarId) {
|
||||
return new PollMessage.Autorenew.Builder()
|
||||
.setTargetId(targetId)
|
||||
.setClientId(gainingClientId)
|
||||
.setRegistrarId(gainingRegistrarId)
|
||||
.setEventTime(serverApproveNewExpirationTime)
|
||||
.setAutorenewEndTime(END_OF_TIME)
|
||||
.setMsg("Domain was auto-renewed.")
|
||||
@@ -236,12 +236,12 @@ public final class DomainTransferUtils {
|
||||
DateTime serverApproveNewExpirationTime,
|
||||
Key<DomainHistory> domainHistoryKey,
|
||||
String targetId,
|
||||
String gainingClientId) {
|
||||
String gainingRegistrarId) {
|
||||
return new BillingEvent.Recurring.Builder()
|
||||
.setReason(Reason.RENEW)
|
||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||
.setTargetId(targetId)
|
||||
.setClientId(gainingClientId)
|
||||
.setRegistrarId(gainingRegistrarId)
|
||||
.setEventTime(serverApproveNewExpirationTime)
|
||||
.setRecurrenceEndTime(END_OF_TIME)
|
||||
.setParent(domainHistoryKey)
|
||||
@@ -291,13 +291,13 @@ public final class DomainTransferUtils {
|
||||
DateTime automaticTransferTime,
|
||||
Key<DomainHistory> domainHistoryKey,
|
||||
String targetId,
|
||||
String gainingClientId,
|
||||
String gainingRegistrarId,
|
||||
Registry registry,
|
||||
Money transferCost) {
|
||||
return new BillingEvent.OneTime.Builder()
|
||||
.setReason(Reason.TRANSFER)
|
||||
.setTargetId(targetId)
|
||||
.setClientId(gainingClientId)
|
||||
.setRegistrarId(gainingRegistrarId)
|
||||
.setCost(transferCost)
|
||||
.setPeriodYears(1)
|
||||
.setEventTime(automaticTransferTime)
|
||||
|
||||
@@ -19,7 +19,7 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.Sets.symmetricDifference;
|
||||
import static com.google.common.collect.Sets.union;
|
||||
import static google.registry.flows.FlowUtils.persistEntityChanges;
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.checkSameValuesNotAddedAndRemoved;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyAllStatusesAreClientSettable;
|
||||
@@ -47,7 +47,7 @@ import com.google.common.net.InternetDomainName;
|
||||
import google.registry.dns.DnsQueue;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
@@ -139,7 +139,7 @@ public final class DomainUpdateFlow implements TransactionalFlow {
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject EppInput eppInput;
|
||||
@Inject Optional<AuthInfo> authInfo;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject DomainHistory.Builder historyBuilder;
|
||||
@@ -158,7 +158,7 @@ public final class DomainUpdateFlow implements TransactionalFlow {
|
||||
DomainUpdateSuperuserExtension.class);
|
||||
flowCustomLogic.beforeValidation();
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
Update command = cloneAndLinkReferences((Update) resourceCommand, now);
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
@@ -197,10 +197,10 @@ public final class DomainUpdateFlow implements TransactionalFlow {
|
||||
String tld = existingDomain.getTld();
|
||||
if (!isSuperuser) {
|
||||
verifyNoDisallowedStatuses(existingDomain, UPDATE_DISALLOWED_STATUSES);
|
||||
verifyResourceOwnership(clientId, existingDomain);
|
||||
verifyResourceOwnership(registrarId, existingDomain);
|
||||
verifyClientUpdateNotProhibited(command, existingDomain);
|
||||
verifyAllStatusesAreClientSettable(union(add.getStatusValues(), remove.getStatusValues()));
|
||||
checkAllowedAccessToTld(clientId, tld);
|
||||
checkAllowedAccessToTld(registrarId, tld);
|
||||
}
|
||||
Registry registry = Registry.get(tld);
|
||||
Optional<FeeUpdateCommandExtension> feeUpdate =
|
||||
@@ -244,7 +244,7 @@ public final class DomainUpdateFlow implements TransactionalFlow {
|
||||
secDnsUpdate.get())
|
||||
: domain.getDsData())
|
||||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateClientId(clientId)
|
||||
.setLastEppUpdateRegistrarId(registrarId)
|
||||
.addStatusValues(add.getStatusValues())
|
||||
.removeStatusValues(remove.getStatusValues())
|
||||
.addNameservers(add.getNameservers().stream().collect(toImmutableSet()))
|
||||
@@ -291,15 +291,16 @@ public final class DomainUpdateFlow implements TransactionalFlow {
|
||||
: symmetricDifference(existingDomain.getStatusValues(), newDomain.getStatusValues())) {
|
||||
if (statusValue.isChargedStatus()) {
|
||||
// Only charge once.
|
||||
return Optional.of(new BillingEvent.OneTime.Builder()
|
||||
.setReason(Reason.SERVER_STATUS)
|
||||
.setTargetId(targetId)
|
||||
.setClientId(clientId)
|
||||
.setCost(Registry.get(existingDomain.getTld()).getServerStatusChangeCost())
|
||||
.setEventTime(now)
|
||||
.setBillingTime(now)
|
||||
.setParent(historyEntry)
|
||||
.build());
|
||||
return Optional.of(
|
||||
new BillingEvent.OneTime.Builder()
|
||||
.setReason(Reason.SERVER_STATUS)
|
||||
.setTargetId(targetId)
|
||||
.setRegistrarId(registrarId)
|
||||
.setCost(Registry.get(existingDomain.getTld()).getServerStatusChangeCost())
|
||||
.setEventTime(now)
|
||||
.setBillingTime(now)
|
||||
.setParent(historyEntry)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class AllocationTokenCustomLogic {
|
||||
DomainCommand.Create command,
|
||||
AllocationToken token,
|
||||
Registry registry,
|
||||
String clientId,
|
||||
String registrarId,
|
||||
DateTime now)
|
||||
throws EppException {
|
||||
// Do nothing.
|
||||
@@ -47,7 +47,7 @@ public class AllocationTokenCustomLogic {
|
||||
public ImmutableMap<InternetDomainName, String> checkDomainsWithToken(
|
||||
ImmutableList<InternetDomainName> domainNames,
|
||||
AllocationToken token,
|
||||
String clientId,
|
||||
String registrarId,
|
||||
DateTime now) {
|
||||
// Do nothing.
|
||||
return Maps.toMap(domainNames, k -> "");
|
||||
|
||||
@@ -58,12 +58,19 @@ public class AllocationTokenFlowUtils {
|
||||
* for this request.
|
||||
*/
|
||||
public AllocationToken loadTokenAndValidateDomainCreate(
|
||||
DomainCommand.Create command, String token, Registry registry, String clientId, DateTime now)
|
||||
DomainCommand.Create command,
|
||||
String token,
|
||||
Registry registry,
|
||||
String registrarId,
|
||||
DateTime now)
|
||||
throws EppException {
|
||||
AllocationToken tokenEntity = loadToken(token);
|
||||
validateToken(
|
||||
InternetDomainName.from(command.getFullyQualifiedDomainName()), tokenEntity, clientId, now);
|
||||
return tokenCustomLogic.validateToken(command, tokenEntity, registry, clientId, now);
|
||||
InternetDomainName.from(command.getFullyQualifiedDomainName()),
|
||||
tokenEntity,
|
||||
registrarId,
|
||||
now);
|
||||
return tokenCustomLogic.validateToken(command, tokenEntity, registry, registrarId, now);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +81,7 @@ public class AllocationTokenFlowUtils {
|
||||
* validate have blank messages (i.e. no error).
|
||||
*/
|
||||
public AllocationTokenDomainCheckResults checkDomainsWithToken(
|
||||
List<InternetDomainName> domainNames, String token, String clientId, DateTime now) {
|
||||
List<InternetDomainName> domainNames, String token, String registrarId, DateTime now) {
|
||||
// If the token is completely invalid, return the error message for all domain names
|
||||
AllocationToken tokenEntity;
|
||||
try {
|
||||
@@ -91,7 +98,7 @@ public class AllocationTokenFlowUtils {
|
||||
ImmutableMap.Builder<InternetDomainName, String> resultsBuilder = new ImmutableMap.Builder<>();
|
||||
for (InternetDomainName domainName : domainNames) {
|
||||
try {
|
||||
validateToken(domainName, tokenEntity, clientId, now);
|
||||
validateToken(domainName, tokenEntity, registrarId, now);
|
||||
validDomainNames.add(domainName);
|
||||
} catch (EppException e) {
|
||||
resultsBuilder.put(domainName, e.getMessage());
|
||||
@@ -101,7 +108,7 @@ public class AllocationTokenFlowUtils {
|
||||
// For all valid domain names, run the custom logic and include the results
|
||||
resultsBuilder.putAll(
|
||||
tokenCustomLogic.checkDomainsWithToken(
|
||||
validDomainNames.build(), tokenEntity, clientId, now));
|
||||
validDomainNames.build(), tokenEntity, registrarId, now));
|
||||
return AllocationTokenDomainCheckResults.create(
|
||||
Optional.of(tokenEntity), resultsBuilder.build());
|
||||
}
|
||||
@@ -123,10 +130,10 @@ public class AllocationTokenFlowUtils {
|
||||
* @throws EppException if the token is invalid in any way
|
||||
*/
|
||||
private void validateToken(
|
||||
InternetDomainName domainName, AllocationToken token, String clientId, DateTime now)
|
||||
InternetDomainName domainName, AllocationToken token, String registrarId, DateTime now)
|
||||
throws EppException {
|
||||
if (!token.getAllowedRegistrarIds().isEmpty()
|
||||
&& !token.getAllowedRegistrarIds().contains(clientId)) {
|
||||
&& !token.getAllowedRegistrarIds().contains(registrarId)) {
|
||||
throw new AllocationTokenNotValidForRegistrarException();
|
||||
}
|
||||
if (!token.getAllowedTlds().isEmpty()
|
||||
@@ -149,7 +156,7 @@ public class AllocationTokenFlowUtils {
|
||||
private 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 Datastore load attempt fails.
|
||||
// an InvalidAllocationTokenException before the database load attempt fails.
|
||||
// See https://tools.ietf.org/html/draft-ietf-regext-allocation-token-04#section-2.1
|
||||
throw new InvalidAllocationTokenException();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.host;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
|
||||
import static google.registry.model.EppResourceUtils.checkResourcesExist;
|
||||
|
||||
@@ -24,7 +24,7 @@ import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.model.eppinput.ResourceCommand;
|
||||
import google.registry.model.eppoutput.CheckData.HostCheck;
|
||||
@@ -47,7 +47,7 @@ import javax.inject.Inject;
|
||||
public final class HostCheckFlow implements Flow {
|
||||
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject @Config("maxChecks") int maxChecks;
|
||||
@Inject Clock clock;
|
||||
@@ -57,7 +57,7 @@ public final class HostCheckFlow implements Flow {
|
||||
@Override
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
ImmutableList<String> hostnames = ((Check) resourceCommand).getTargetIds();
|
||||
verifyTargetIdCount(hostnames, maxChecks);
|
||||
ImmutableSet<String> existingIds =
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.host;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist;
|
||||
import static google.registry.flows.host.HostFlowUtils.lookupSuperordinateDomain;
|
||||
import static google.registry.flows.host.HostFlowUtils.validateHostName;
|
||||
@@ -34,7 +34,7 @@ import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
||||
import google.registry.flows.EppException.RequiredParameterMissingException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
@@ -84,7 +84,7 @@ public final class HostCreateFlow implements TransactionalFlow {
|
||||
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject HostHistory.Builder historyBuilder;
|
||||
@Inject DnsQueue dnsQueue;
|
||||
@@ -101,17 +101,17 @@ public final class HostCreateFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
Create command = (Create) resourceCommand;
|
||||
DateTime now = tm().getTransactionTime();
|
||||
verifyResourceDoesNotExist(HostResource.class, targetId, now, clientId);
|
||||
verifyResourceDoesNotExist(HostResource.class, targetId, now, registrarId);
|
||||
// The superordinate domain of the host object if creating an in-bailiwick host, or null if
|
||||
// creating an external host. This is looked up before we actually create the Host object so
|
||||
// we can detect error conditions earlier.
|
||||
Optional<DomainBase> superordinateDomain =
|
||||
lookupSuperordinateDomain(validateHostName(targetId), now);
|
||||
verifySuperordinateDomainNotInPendingDelete(superordinateDomain.orElse(null));
|
||||
verifySuperordinateDomainOwnership(clientId, superordinateDomain.orElse(null));
|
||||
verifySuperordinateDomainOwnership(registrarId, superordinateDomain.orElse(null));
|
||||
boolean willBeSubordinate = superordinateDomain.isPresent();
|
||||
boolean hasIpAddresses = !isNullOrEmpty(command.getInetAddresses());
|
||||
if (willBeSubordinate != hasIpAddresses) {
|
||||
@@ -122,8 +122,8 @@ public final class HostCreateFlow implements TransactionalFlow {
|
||||
}
|
||||
HostResource newHost =
|
||||
new HostResource.Builder()
|
||||
.setCreationClientId(clientId)
|
||||
.setPersistedCurrentSponsorClientId(clientId)
|
||||
.setCreationRegistrarId(registrarId)
|
||||
.setPersistedCurrentSponsorRegistrarId(registrarId)
|
||||
.setHostName(targetId)
|
||||
.setInetAddresses(command.getInetAddresses())
|
||||
.setRepoId(createRepoId(allocateId(), roidSuffix))
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.host;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.checkLinkedDomains;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||
@@ -29,7 +29,7 @@ import google.registry.batch.AsyncTaskEnqueuer;
|
||||
import google.registry.dns.DnsQueue;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
@@ -78,7 +78,7 @@ public final class HostDeleteFlow implements TransactionalFlow {
|
||||
private static final DnsQueue dnsQueue = DnsQueue.create();
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject Trid trid;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@@ -93,7 +93,7 @@ public final class HostDeleteFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
DateTime now = tm().getTransactionTime();
|
||||
validateHostName(targetId);
|
||||
checkLinkedDomains(targetId, now, HostResource.class, DomainBase::getNameservers);
|
||||
@@ -106,14 +106,14 @@ public final class HostDeleteFlow implements TransactionalFlow {
|
||||
existingHost.isSubordinate()
|
||||
? tm().loadByKey(existingHost.getSuperordinateDomain()).cloneProjectedAtTime(now)
|
||||
: existingHost;
|
||||
verifyResourceOwnership(clientId, owningResource);
|
||||
verifyResourceOwnership(registrarId, owningResource);
|
||||
}
|
||||
HistoryEntry.Type historyEntryType;
|
||||
Result.Code resultCode;
|
||||
HostResource newHost;
|
||||
if (tm().isOfy()) {
|
||||
asyncTaskEnqueuer.enqueueAsyncDelete(
|
||||
existingHost, tm().getTransactionTime(), clientId, trid, isSuperuser);
|
||||
existingHost, tm().getTransactionTime(), registrarId, trid, isSuperuser);
|
||||
newHost = existingHost.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build();
|
||||
historyEntryType = Type.HOST_PENDING_DELETE;
|
||||
resultCode = SUCCESS_WITH_ACTION_PENDING;
|
||||
|
||||
@@ -105,11 +105,11 @@ public class HostFlowUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/** Ensure that the superordinate domain is sponsored by the provided clientId. */
|
||||
static void verifySuperordinateDomainOwnership(
|
||||
String clientId, DomainBase superordinateDomain) throws EppException {
|
||||
/** Ensure that the superordinate domain is sponsored by the provided registrar ID. */
|
||||
static void verifySuperordinateDomainOwnership(String registrarId, DomainBase superordinateDomain)
|
||||
throws EppException {
|
||||
if (superordinateDomain != null
|
||||
&& !clientId.equals(superordinateDomain.getCurrentSponsorClientId())) {
|
||||
&& !registrarId.equals(superordinateDomain.getCurrentSponsorRegistrarId())) {
|
||||
throw new HostDomainNotOwnedException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.host;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.host.HostFlowUtils.validateHostName;
|
||||
import static google.registry.model.EppResourceUtils.isLinked;
|
||||
@@ -25,7 +25,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
@@ -53,7 +53,7 @@ import org.joda.time.DateTime;
|
||||
public final class HostInfoFlow implements Flow {
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject Clock clock;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
@@ -62,7 +62,7 @@ public final class HostInfoFlow implements Flow {
|
||||
@Override
|
||||
public EppResponse run() throws EppException {
|
||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
validateHostName(targetId);
|
||||
DateTime now = clock.nowUtc();
|
||||
HostResource host = loadAndVerifyExistence(HostResource.class, targetId, now);
|
||||
@@ -80,14 +80,14 @@ public final class HostInfoFlow implements Flow {
|
||||
transactIfJpaTm(
|
||||
() -> tm().loadByKey(host.getSuperordinateDomain()).cloneProjectedAtTime(now));
|
||||
hostInfoDataBuilder
|
||||
.setCurrentSponsorClientId(superordinateDomain.getCurrentSponsorClientId())
|
||||
.setCurrentSponsorClientId(superordinateDomain.getCurrentSponsorRegistrarId())
|
||||
.setLastTransferTime(host.computeLastTransferTime(superordinateDomain));
|
||||
if (superordinateDomain.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) {
|
||||
statusValues.add(StatusValue.PENDING_TRANSFER);
|
||||
}
|
||||
} else {
|
||||
hostInfoDataBuilder
|
||||
.setCurrentSponsorClientId(host.getPersistedCurrentSponsorClientId())
|
||||
.setCurrentSponsorClientId(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.getCreationClientId())
|
||||
.setCreationClientId(host.getCreationRegistrarId())
|
||||
.setCreationTime(host.getCreationTime())
|
||||
.setLastEppUpdateClientId(host.getLastEppUpdateClientId())
|
||||
.setLastEppUpdateClientId(host.getLastEppUpdateRegistrarId())
|
||||
.setLastEppUpdateTime(host.getLastEppUpdateTime())
|
||||
.build())
|
||||
.build();
|
||||
|
||||
@@ -16,7 +16,7 @@ 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.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.checkSameValuesNotAddedAndRemoved;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyAllStatusesAreClientSettable;
|
||||
@@ -39,7 +39,7 @@ import google.registry.flows.EppException.ObjectAlreadyExistsException;
|
||||
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
||||
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
@@ -113,7 +113,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @TargetId String targetId;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
@Inject HostHistory.Builder historyBuilder;
|
||||
@@ -126,7 +126,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
Update command = (Update) resourceCommand;
|
||||
Change change = command.getInnerChange();
|
||||
String suppliedNewHostName = change.getFullyQualifiedHostName();
|
||||
@@ -170,10 +170,10 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
// since external hosts store their own clientId. For subordinate hosts the canonical clientId
|
||||
// comes from the superordinate domain, but we might as well update the persisted value. For
|
||||
// non-superusers this is the flow clientId, but for superusers it might not be, so compute it.
|
||||
String newPersistedClientId =
|
||||
String newPersistedRegistrarId =
|
||||
newSuperordinateDomain.isPresent()
|
||||
? newSuperordinateDomain.get().getCurrentSponsorClientId()
|
||||
: owningResource.getPersistedCurrentSponsorClientId();
|
||||
? newSuperordinateDomain.get().getCurrentSponsorRegistrarId()
|
||||
: owningResource.getPersistedCurrentSponsorRegistrarId();
|
||||
HostResource newHost =
|
||||
existingHost
|
||||
.asBuilder()
|
||||
@@ -183,11 +183,11 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
.addInetAddresses(add.getInetAddresses())
|
||||
.removeInetAddresses(remove.getInetAddresses())
|
||||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateClientId(clientId)
|
||||
.setLastEppUpdateRegistrarId(registrarId)
|
||||
.setSuperordinateDomain(newSuperordinateDomainKey)
|
||||
.setLastSuperordinateChange(lastSuperordinateChange)
|
||||
.setLastTransferTime(lastTransferTime)
|
||||
.setPersistedCurrentSponsorClientId(newPersistedClientId)
|
||||
.setPersistedCurrentSponsorRegistrarId(newPersistedRegistrarId)
|
||||
.build();
|
||||
verifyHasIpsIffIsExternal(command, existingHost, newHost);
|
||||
ImmutableSet.Builder<ImmutableObject> entitiesToInsert = new ImmutableSet.Builder<>();
|
||||
@@ -217,12 +217,12 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
if (!isSuperuser) {
|
||||
// Verify that the host belongs to this registrar, either directly or because it is currently
|
||||
// subordinate to a domain owned by this registrar.
|
||||
verifyResourceOwnership(clientId, owningResource);
|
||||
verifyResourceOwnership(registrarId, owningResource);
|
||||
if (isHostRename && !existingHost.isSubordinate()) {
|
||||
throw new CannotRenameExternalHostException();
|
||||
}
|
||||
// Verify that the new superordinate domain belongs to this registrar.
|
||||
verifySuperordinateDomainOwnership(clientId, newSuperordinateDomain);
|
||||
verifySuperordinateDomainOwnership(registrarId, newSuperordinateDomain);
|
||||
ImmutableSet<StatusValue> statusesToAdd = command.getInnerAdd().getStatusValues();
|
||||
ImmutableSet<StatusValue> statusesToRemove = command.getInnerRemove().getStatusValues();
|
||||
// If the resource is marked with clientUpdateProhibited, and this update does not clear that
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows.poll;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.poll.PollFlowUtils.ackPollMessage;
|
||||
import static google.registry.flows.poll.PollFlowUtils.getPollMessageCount;
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_NO_MESSAGES;
|
||||
@@ -29,8 +29,8 @@ import google.registry.flows.EppException.ObjectDoesNotExistException;
|
||||
import google.registry.flows.EppException.ParameterValueSyntaxErrorException;
|
||||
import google.registry.flows.EppException.RequiredParameterMissingException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.PollMessageId;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.model.eppoutput.EppResponse;
|
||||
import google.registry.model.poll.MessageQueueInfo;
|
||||
@@ -58,15 +58,16 @@ import org.joda.time.DateTime;
|
||||
public class PollAckFlow implements TransactionalFlow {
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject @ClientId String clientId;
|
||||
@Inject @RegistrarId String registrarId;
|
||||
@Inject @PollMessageId String messageId;
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
|
||||
@Inject PollAckFlow() {}
|
||||
|
||||
@Override
|
||||
public final EppResponse run() throws EppException {
|
||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||
validateClientIsLoggedIn(clientId);
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
if (messageId.isEmpty()) {
|
||||
throw new MissingMessageIdException();
|
||||
}
|
||||
@@ -94,7 +95,7 @@ public class PollAckFlow implements TransactionalFlow {
|
||||
|
||||
// Make sure this client is authorized to ack this message. It could be that the message is
|
||||
// supposed to go to a different registrar.
|
||||
if (!clientId.equals(pollMessage.getClientId())) {
|
||||
if (!registrarId.equals(pollMessage.getRegistrarId())) {
|
||||
throw new NotAuthorizedToAckMessageException();
|
||||
}
|
||||
|
||||
@@ -107,7 +108,7 @@ public 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(clientId, now));
|
||||
int messageCount = tm().doTransactionless(() -> getPollMessageCount(registrarId, now));
|
||||
// Within the same transaction, Datastore will not reflect the updated count (potentially
|
||||
// reduced by one thanks to the acked poll message). SQL will, however, so we shouldn't reduce
|
||||
// the count in the SQL case.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user