mirror of
https://github.com/google/nomulus
synced 2026-06-09 16:33:02 +00:00
Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d3ccad3aa7 | |||
| dc9d9158d8 | |||
| 0daa89ae25 | |||
| d6bcdc241e | |||
| 487b695a10 | |||
| b5ef99a8f8 | |||
| dd4300fce7 | |||
| 844c47061b | |||
| dcceb0d49a | |||
| f72c6c3c80 | |||
| c645fe6766 | |||
| bf52a78e89 | |||
| 8ec16dca8d | |||
| 69cb852a9c | |||
| 6dee3d526e | |||
| 3ba6e7bd06 | |||
| 2e84cdfc4b | |||
| 77f998ee4b | |||
| c93248ec10 | |||
| 3ac179aead | |||
| 92f2f3274e | |||
| 57975898d5 | |||
| 86fefa9a03 | |||
| d143cc83a0 | |||
| df5f450435 | |||
| 89a44f176c | |||
| d2319b13fa | |||
| 77259f368d | |||
| 27b81ba898 | |||
| c7478fc52b | |||
| a68b1a12fd | |||
| ce791e8b97 | |||
| cf3f9603f7 | |||
| 4fd32c8b5c | |||
| 3488f95990 | |||
| 8e00f85f60 | |||
| 3cc8d83396 | |||
| 0a779612f6 | |||
| 545a03618b | |||
| bcdacc88d3 | |||
| 56b10ea136 | |||
| 9479e1e8b9 | |||
| 110bd9c057 | |||
| 2ae5aba7ff | |||
| b878e5acc1 | |||
| 4d0409c924 | |||
| 0292887cb9 | |||
| 464f6ba90a | |||
| 0ab0a8c2e6 | |||
| 2cc4e5fa94 | |||
| 47a890253e | |||
| b452b0628d | |||
| 5dfd96d26d | |||
| e2a673d914 | |||
| bf29d159f9 | |||
| e17cb52bf7 | |||
| 7352f9b4a6 | |||
| 5da48184f9 |
@@ -100,3 +100,9 @@ nomulus.iws
|
||||
node_modules/**
|
||||
!node_modules/soyutils_usegoog.js
|
||||
/repos/
|
||||
|
||||
# Compiled JS/CSS code
|
||||
core/**/registrar_bin*.js
|
||||
core/**/registrar_dbg*.js
|
||||
core/**/registrar_bin*.css
|
||||
core/**/registrar_dbg*.css
|
||||
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
# Copyright 2018 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.
|
||||
#
|
||||
# Collecting report files from a travis build to GCS requires setting the
|
||||
# "CREDZ" and "REPORT_GCS_BUCKET" environment variables in your travis
|
||||
# repository.
|
||||
#
|
||||
# The report destination can be any GCS path (e.g. "gcs://bucket-name/path").
|
||||
# You'll want to select "Display value in build log", otherwise travis will
|
||||
# hide the bucket name in the URL that is displayed.
|
||||
#
|
||||
# The CREDZ variable should be the contents of a json credentials file for
|
||||
# a service account with write access to the bucket, escaped for bash shell
|
||||
# usage (usually just wrapping it in single quotes should suffice).
|
||||
|
||||
language: java
|
||||
jdk:
|
||||
# Our builds fail against Oracle Java for reasons yet unknown.
|
||||
- openjdk8
|
||||
|
||||
# Caching options suggested by a random article.
|
||||
before_cache:
|
||||
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||
- rm -f $HOME/.gradle/caches/*/plugin-resolution/
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.gradle/caches/
|
||||
- $HOME/.gradle/wrapper/
|
||||
- $HOME/google-cloud-sdk/
|
||||
|
||||
# WebDriver tests need Chrome and ChromeDriver provisioned by the docker image
|
||||
services:
|
||||
- docker
|
||||
|
||||
env:
|
||||
global:
|
||||
# Disable fancy status information (looks bad on travis and exceeds logfile
|
||||
# quota)
|
||||
- TERM=dumb
|
||||
# Do not prompt for user input when using any SDK methods.
|
||||
- CLOUDSDK_CORE_DISABLE_PROMPTS=1
|
||||
|
||||
install:
|
||||
- |
|
||||
if [ ! -d $HOME/google-cloud-sdk/bin ]
|
||||
then
|
||||
# The install script errors if this directory already exists,
|
||||
# but Travis already creates it when we mark it as cached.
|
||||
rm -rf $HOME/google-cloud-sdk
|
||||
# The install script is overly verbose, which sometimes causes
|
||||
# problems on Travis, so ignore stdout.
|
||||
curl https://sdk.cloud.google.com | bash
|
||||
fi
|
||||
# This line is critical. We setup the SDK to take precedence in our
|
||||
# environment over the old SDK that is already on the machine.
|
||||
- source $HOME/google-cloud-sdk/path.bash.inc
|
||||
- gcloud components install app-engine-java
|
||||
- gcloud version
|
||||
|
||||
# Specialize gradle build to use an up-to-date gradle and the /gradle
|
||||
# directory.
|
||||
# The "travis_wait 45" lets our build spend up to 45 minutes without writing
|
||||
# output, instead of the default 10.
|
||||
# See notes on the CREDZ and REPORT_GCS_BUCKET environment variable in the
|
||||
# comments at the top of the file.
|
||||
script: echo "$CREDZ" >credz.json && chmod 755 ./gradlew && travis_wait 45 ./gradlew build --continue -P uploaderDestination="$REPORT_GCS_DESTINATION" -P uploaderCredentialsFile=credz.json -P uploaderMultithreadedUpload=yes -P mavenUrl=https://storage.googleapis.com/domain-registry-maven-repository/maven -P pluginsUrl=https://storage.googleapis.com/domain-registry-maven-repository/plugins
|
||||
@@ -1,8 +1,8 @@
|
||||
# Nomulus
|
||||
|
||||
| Internal Build | FOSS Build | License | Code Search |
|
||||
|----------------|------------|---------|-------------|
|
||||
|[](https://storage.googleapis.com/domain-registry-kokoro/index.html)|[](https://travis-ci.org/google/nomulus)|[](https://github.com/google/nomulus/blob/master/LICENSE)|[](https://sourcegraph.com/github.com/google/nomulus)|
|
||||
| Internal Build | FOSS Build | LGTM | License | Code Search |
|
||||
|----------------|------------|------|---------|-------------|
|
||||
|[](https://storage.googleapis.com/domain-registry-kokoro/internal/index.html)|[](https://storage.googleapis.com/domain-registry-kokoro/foss/index.html)|[](https://lgtm.com/projects/g/google/nomulus/alerts/)|[](https://github.com/google/nomulus/blob/master/LICENSE)|[](https://sourcegraph.com/github.com/google/nomulus)|
|
||||
|
||||

|
||||
|
||||
|
||||
+11
-18
@@ -12,25 +12,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
def environments = ['production', 'sandbox', 'alpha', 'crash']
|
||||
|
||||
def projects = ['production': 'domain-registry',
|
||||
'sandbox' : 'domain-registry-sandbox',
|
||||
'alpha' : 'domain-registry-alpha',
|
||||
'crash' : 'domain-registry-crash']
|
||||
|
||||
|
||||
def environment = rootProject.findProperty("environment")
|
||||
if (environment == null) {
|
||||
environment = 'production'
|
||||
}
|
||||
def gcpProject = projects[environment]
|
||||
if (gcpProject == null) {
|
||||
throw new GradleException("-Penvironment must be one of ${environments}.")
|
||||
}
|
||||
|
||||
apply from: "${rootDir.path}/projects.gradle"
|
||||
apply plugin: 'war'
|
||||
|
||||
def environment = rootProject.environment
|
||||
def gcpProject = rootProject.gcpProject
|
||||
|
||||
// Set this directory before applying the appengine plugin so that the
|
||||
// plugin will recognize this as an app-engine standard app (and also
|
||||
// obtains the appengine-web.xml from the correct location)
|
||||
@@ -75,6 +62,12 @@ if (project.path == ":services:default") {
|
||||
|
||||
appengine {
|
||||
deploy {
|
||||
// appengineDeployAll task requires the version to be set. So,
|
||||
// this config lets gcloud select a version name when deploying
|
||||
// to alpha or sandbox from our workstation.
|
||||
if (!rootProject.prodOrSandboxEnv) {
|
||||
version = 'GCLOUD_CONFIG'
|
||||
}
|
||||
projectId = gcpProject
|
||||
}
|
||||
}
|
||||
@@ -85,4 +78,4 @@ dependencies {
|
||||
|
||||
rootProject.deploy.dependsOn appengineDeployAll
|
||||
rootProject.stage.dependsOn appengineStage
|
||||
appengineDeploy.dependsOn rootProject.verifyDeployment
|
||||
appengineDeployAll.dependsOn rootProject.verifyDeployment
|
||||
|
||||
+111
-22
@@ -12,8 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
||||
import org.gradle.api.tasks.testing.logging.TestLogEvent
|
||||
|
||||
buildscript {
|
||||
if (project.disableDependencyLocking.toBoolean() == false) {
|
||||
if (rootProject.enableDependencyLocking.toBoolean()) {
|
||||
// Lock buildscript dependencies.
|
||||
configurations.classpath {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
@@ -37,13 +40,15 @@ plugins {
|
||||
id 'net.ltgt.apt' version '0.19' apply false
|
||||
id 'net.ltgt.errorprone' version '0.6.1'
|
||||
id 'checkstyle'
|
||||
id 'com.github.johnrengelman.shadow' version '5.0.0'
|
||||
id 'com.github.johnrengelman.shadow' version '5.1.0'
|
||||
|
||||
// NodeJs plugin
|
||||
id "com.moowork.node" version "1.2.0"
|
||||
|
||||
id 'idea'
|
||||
id 'com.diffplug.gradle.spotless' version '3.18.0'
|
||||
|
||||
id 'jacoco'
|
||||
}
|
||||
|
||||
wrapper {
|
||||
@@ -75,7 +80,7 @@ reportUploader {
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
apply from: 'dependency_license.gradle'
|
||||
apply from: 'dependency_lic.gradle'
|
||||
|
||||
// Custom task to run checkLicense in buildSrc, which is not triggered
|
||||
// by root project tasks. A shell task is used because buildSrc tasks
|
||||
@@ -90,11 +95,6 @@ tasks.build.dependsOn(tasks.checkLicense)
|
||||
|
||||
// Provide defaults for all of the project properties.
|
||||
|
||||
// showAllOutput: boolean. If true, dump all test output during the build.
|
||||
if (!project.hasProperty('showAllOutput')) {
|
||||
ext.showAllOutput = 'false'
|
||||
}
|
||||
|
||||
// Only do linting if the build is successful.
|
||||
gradleLint.autoLintAfterFailure = false
|
||||
|
||||
@@ -109,10 +109,10 @@ task deploy {
|
||||
|
||||
task verifyDeployment {
|
||||
group = 'deployment'
|
||||
description = 'Ensure that one can only deploy to alpha.'
|
||||
description = 'Ensure that one cannot deploy to production or sandbox.'
|
||||
doFirst {
|
||||
if (rootProject.findProperty("environment") != 'alpha') {
|
||||
throw new GradleException("Can only deploy to alpha.");
|
||||
if (rootProject.prodOrSandboxEnv) {
|
||||
throw new GradleException("Cannot deploy to production or sandbox.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -157,8 +157,8 @@ subprojects {
|
||||
attributes 'Main-Class': mainClass
|
||||
}
|
||||
zip64 = true
|
||||
classifier = null
|
||||
version = null
|
||||
classifier = ''
|
||||
archiveVersion = ''
|
||||
configurations = [project.configurations.runtimeClasspath]
|
||||
from project.sourceSets.main.output
|
||||
// Excludes signature files that accompany some dependency jars, like
|
||||
@@ -169,7 +169,7 @@ subprojects {
|
||||
}
|
||||
}
|
||||
|
||||
if (rootProject.disableDependencyLocking.toBoolean() == false) {
|
||||
if (rootProject.enableDependencyLocking.toBoolean()) {
|
||||
buildscript {
|
||||
// Lock buildscript dependencies.
|
||||
configurations.classpath {
|
||||
@@ -177,7 +177,7 @@ subprojects {
|
||||
}
|
||||
}
|
||||
// Lock application dependencies except for the gradle-license-report
|
||||
// plugin. See dependency_license.gradle for more information.
|
||||
// plugin. See dependency_lic.gradle for more information.
|
||||
configurations.findAll { it.name != 'dependencyLicenseReport' }.each {
|
||||
it.resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
@@ -236,13 +236,7 @@ subprojects {
|
||||
}
|
||||
}
|
||||
|
||||
if (project.name == 'util') return
|
||||
if (project.name == 'proxy') return
|
||||
if (project.name == 'core') return
|
||||
|
||||
test {
|
||||
testLogging.showStandardStreams = Boolean.parseBoolean(showAllOutput)
|
||||
}
|
||||
if (['util', 'proxy', 'core', 'prober'].contains(project.name)) return
|
||||
|
||||
ext.relativePath = "google/registry/${project.name}"
|
||||
|
||||
@@ -256,6 +250,35 @@ subprojects {
|
||||
}
|
||||
}
|
||||
|
||||
// If "-P verboseTestOutput=true" is passed in, configure all subprojects to dump all of their
|
||||
// output and final test status (pass/fail, errors) for each test class.
|
||||
//
|
||||
// Note that we can't do this in the main subprojects section above because that's evaluated before
|
||||
// the subproject build files and the test tasks haven't been defined yet. We have to do it from
|
||||
// the projectsEvaluted hook, which gets called after the subprojects are configured.
|
||||
if (verboseTestOutput.toBoolean()) {
|
||||
gradle.projectsEvaluated({
|
||||
subprojects {
|
||||
tasks.withType(Test) {
|
||||
testLogging {
|
||||
events TestLogEvent.FAILED, TestLogEvent.PASSED, TestLogEvent.SKIPPED,
|
||||
TestLogEvent.STANDARD_OUT, TestLogEvent.STANDARD_ERROR
|
||||
exceptionFormat TestExceptionFormat.FULL
|
||||
showExceptions true
|
||||
showCauses true
|
||||
showStackTraces true
|
||||
|
||||
afterSuite { desc, result ->
|
||||
println "Results: ${result.resultType}, " +
|
||||
"${result.successfulTestCount}/${result.testCount} tests " +
|
||||
"passed, ${result.failedTestCount} failures.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
task checkDependenciesDotGradle {
|
||||
def buildSrcDepsFile = File.createTempFile('buildSrc', 'deps')
|
||||
buildSrcDepsFile.deleteOnExit()
|
||||
@@ -301,3 +324,69 @@ def createGetBuildSrcDirectDepsTask(outputFileName) {
|
||||
"-PdependencyExportFile=${outputFileName}"
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.ext {
|
||||
|
||||
// Executes an arbitrary shell command in bash and returns all output
|
||||
// to stdout as a string. This method allows pipes in shell command.
|
||||
execInBash = { shellCommand, bashWorkingDir ->
|
||||
return new ByteArrayOutputStream().withStream { os ->
|
||||
exec {
|
||||
workingDir bashWorkingDir
|
||||
commandLine 'bash', '-c', "${shellCommand}"
|
||||
standardOutput os
|
||||
}
|
||||
return os
|
||||
}.toString().trim()
|
||||
}
|
||||
|
||||
invokeJavaDiffFormatScript = { action ->
|
||||
def scriptDir = rootDir.path.endsWith('buildSrc')
|
||||
? "${rootDir}/../java-format"
|
||||
: "${rootDir}/java-format"
|
||||
def workingDir = rootDir.path.endsWith('buildSrc')
|
||||
? "${rootDir}/.."
|
||||
: rootDir
|
||||
def formatDiffScript = "${scriptDir}/google-java-format-git-diff.sh"
|
||||
|
||||
return ext.execInBash(
|
||||
"${formatDiffScript} ${action}", "${workingDir}")
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if modified lines in Java source files need reformatting.
|
||||
// Note that this task checks modified Java files in the entire repository.
|
||||
task javaIncrementalFormatCheck {
|
||||
doLast {
|
||||
def checkResult = invokeJavaDiffFormatScript("check")
|
||||
if (checkResult == 'true') {
|
||||
throw new IllegalStateException(
|
||||
"Some Java files need to be reformatted. You may use the "
|
||||
+ "'javaIncrementalFormatDryRun' task to review\n "
|
||||
+ "the changes, or the 'javaIncrementalFormatApply' task "
|
||||
+ "to reformat.")
|
||||
} else if (checkResult != 'false') {
|
||||
throw new RuntimeException(
|
||||
"Failed to invoke format check script:\n" + checkResult)
|
||||
}
|
||||
println("Incremental Java format check ok.")
|
||||
}
|
||||
}
|
||||
|
||||
// Shows how modified lines in Java source files will change after formatting.
|
||||
// Note that this task checks modified Java files in the entire repository.
|
||||
task javaIncrementalFormatDryRun {
|
||||
doLast {
|
||||
println("${invokeJavaDiffFormatScript("show")}")
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if modified lines in Java source files need reformatting.
|
||||
// Note that this task processes modified Java files in the entire repository.
|
||||
task javaIncrementalFormatApply {
|
||||
doLast {
|
||||
invokeJavaDiffFormatScript("format")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.build.dependsOn(tasks.javaIncrementalFormatCheck)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
buildscript {
|
||||
if (rootProject.disableDependencyLocking.toBoolean() == false) {
|
||||
if (project.enableDependencyLocking.toBoolean()) {
|
||||
// Lock buildscript dependencies.
|
||||
configurations.classpath {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
@@ -32,7 +32,7 @@ plugins {
|
||||
id 'com.diffplug.gradle.spotless' version '3.18.0'
|
||||
}
|
||||
|
||||
if (rootProject.disableDependencyLocking.toBoolean() == false) {
|
||||
if (rootProject.enableDependencyLocking.toBoolean()) {
|
||||
// Lock application dependencies.
|
||||
dependencyLocking {
|
||||
lockAllConfigurations()
|
||||
@@ -52,7 +52,7 @@ repositories {
|
||||
}
|
||||
|
||||
apply from: '../dependencies.gradle'
|
||||
apply from: '../dependency_license.gradle'
|
||||
apply from: '../dependency_lic.gradle'
|
||||
apply from: '../java_common.gradle'
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -1 +1 @@
|
||||
disableDependencyLocking=false
|
||||
enableDependencyLocking=false
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
{
|
||||
"moduleLicense": "BSD"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD-2-Clause"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD 2-Clause License"
|
||||
},
|
||||
@@ -54,6 +57,9 @@
|
||||
{
|
||||
"moduleLicense": "BSD 3-Clause License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD 3-clause New License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The 3-Clause BSD License"
|
||||
},
|
||||
@@ -69,6 +75,9 @@
|
||||
{
|
||||
"moduleLicense": "BSD style"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD-2-Clause"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "New BSD License"
|
||||
},
|
||||
@@ -78,6 +87,9 @@
|
||||
{
|
||||
"moduleLicense": "The BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The PostgreSQL License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "CC0 1.0 Universal License"
|
||||
},
|
||||
@@ -99,6 +111,9 @@
|
||||
{
|
||||
"moduleLicense": "\\n Dual license consisting of the CDDL v1.1 and GPL v2\\n "
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Distribution License v. 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License - Version 1.0"
|
||||
},
|
||||
@@ -108,6 +123,9 @@
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License v1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Google App Engine Terms of Service"
|
||||
},
|
||||
@@ -117,12 +135,18 @@
|
||||
{
|
||||
"moduleLicense": "GNU GENERAL PUBLIC LICENSE, Version 2 + Classpath Exception"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU Library General Public License v2.1 or later"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GPL2 w/ CPE"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU Lesser Public License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU Library General Public License v2.1 or later"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The Go license"
|
||||
},
|
||||
@@ -156,6 +180,9 @@
|
||||
{
|
||||
"moduleLicense": "The MIT license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The PostgreSQL License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Mozilla Public License Version 2.0"
|
||||
},
|
||||
|
||||
@@ -78,7 +78,8 @@ PRESUBMITS = {
|
||||
r".*Copyright 20\d{2} The Nomulus Authors\. All Rights Reserved\.",
|
||||
("java", "js", "soy", "sql", "py", "sh", "gradle"), {
|
||||
".git", "/build/", "/generated/", "node_modules/",
|
||||
"JUnitBackports.java"
|
||||
"JUnitBackports.java", "registrar_bin.", "registrar_dbg.",
|
||||
"google-java-format-diff.py"
|
||||
}, REQUIRED):
|
||||
"File did not include the license header.",
|
||||
|
||||
@@ -148,7 +149,7 @@ PRESUBMITS = {
|
||||
PresubmitCheck(
|
||||
r".*(innerHTML|outerHTML)\s*(=|[+]=)([^=]|$)",
|
||||
"js",
|
||||
{"/node_modules/"},
|
||||
{"/node_modules/", "registrar_bin."},
|
||||
):
|
||||
"Do not assign directly to the dom. Use goog.dom.setTextContent to set"
|
||||
" to plain text, goog.dom.removeChildren to clear, or "
|
||||
@@ -156,14 +157,13 @@ PRESUBMITS = {
|
||||
PresubmitCheck(
|
||||
r".*console\.(log|info|warn|error)",
|
||||
"js",
|
||||
{"/node_modules/", "google/registry/ui/js/util.js"},
|
||||
{"/node_modules/", "google/registry/ui/js/util.js", "registrar_bin."},
|
||||
):
|
||||
"JavaScript files should not include console logging."
|
||||
}
|
||||
|
||||
|
||||
def get_files():
|
||||
result = []
|
||||
for root, dirnames, filenames in os.walk("."):
|
||||
for filename in filenames:
|
||||
yield os.path.join(root, filename)
|
||||
|
||||
+28
-5
@@ -53,15 +53,19 @@ def fragileTestPatterns = [
|
||||
// Test Datastore inexplicably aborts transaction.
|
||||
"google/registry/model/tmch/ClaimsListShardTest.*",
|
||||
// Creates large object (64MBytes), occasionally throws OOM error.
|
||||
"google/registry/model/server/KmsSecretRevisionTest.*"
|
||||
"google/registry/model/server/KmsSecretRevisionTest.*",
|
||||
"google/registry/tools/GenerateSqlSchemaCommandTest.*",
|
||||
"google/registry/webdriver/*",
|
||||
]
|
||||
|
||||
// Tests that fail when running Gradle in a docker container, e. g. when
|
||||
// building the release artifacts in Google Cloud Build.
|
||||
def dockerIncompatibleTestPatterns = [
|
||||
// The webdriver tests start headless Chrome in a Docker container,
|
||||
// resulting in Docker-in-Docker complications.
|
||||
// resulting in Docker-in-Docker complications. Likewise,
|
||||
// GenerateSqlSchemaCommandTest launches postgresql in a docker container.
|
||||
"google/registry/webdriver/*",
|
||||
"google/registry/tools/GenerateSqlSchemaCommandTest.*",
|
||||
// PathParameterTest includes tests which validate that file permissions are
|
||||
// respected. However when running in Docker the user is root by default, so
|
||||
// every file is read/write-able. There is no way to exclude specific test
|
||||
@@ -217,10 +221,12 @@ dependencies {
|
||||
compile deps['org.joda:joda-money']
|
||||
compile deps['org.json:json']
|
||||
testCompile deps['org.mortbay.jetty:jetty']
|
||||
runtimeOnly deps['org.postgresql:postgresql']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-api']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-chrome-driver']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-java']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-remote-driver']
|
||||
compile deps['org.testcontainers:postgresql']
|
||||
testCompile deps['org.testcontainers:selenium']
|
||||
compile deps['xerces:xmlParserAPIs']
|
||||
compile deps['xpp3:xpp3']
|
||||
@@ -247,8 +253,10 @@ dependencies {
|
||||
testCompile deps['org.hamcrest:hamcrest-all']
|
||||
testCompile deps['org.hamcrest:hamcrest-core']
|
||||
testCompile deps['org.hamcrest:hamcrest-library']
|
||||
compile deps['org.hibernate:hibernate-hikaricp']
|
||||
testCompile deps['junit:junit']
|
||||
testCompile deps['org.mockito:mockito-core']
|
||||
runtime deps['org.postgresql:postgresql']
|
||||
|
||||
// Indirect dependency found by undeclared-dependency check. Such
|
||||
// dependencies should go after all other compile and testCompile
|
||||
@@ -554,11 +562,12 @@ task fragileTest(type: Test) {
|
||||
exclude "**/*TestCase.*", "**/*TestSuite.*"
|
||||
include fragileTestPatterns
|
||||
|
||||
if (rootProject.findProperty("skipDockerIncompatibleTests") == "true") {
|
||||
exclude dockerIncompatibleTestPatterns
|
||||
}
|
||||
|
||||
// Run every test class in a freshly started process.
|
||||
forkEvery 1
|
||||
|
||||
// Uncomment to see test outputs in stdout.
|
||||
//testLogging.showStandardStreams = true
|
||||
}
|
||||
|
||||
task outcastTest(type: Test) {
|
||||
@@ -651,5 +660,19 @@ task buildToolImage(dependsOn: nomulus, type: Exec) {
|
||||
commandLine 'docker', 'build', '-t', 'nomulus-tool', '.'
|
||||
}
|
||||
|
||||
task copyJsFilesForTestServer(dependsOn: assemble, type: Copy) {
|
||||
// Unfortunately the test server relies on having some compiled JS/CSS
|
||||
// in place, so copy it over here
|
||||
from "${resourcesDir}/google/registry/ui/"
|
||||
include '**/*.js'
|
||||
include '**/*.css'
|
||||
into "${project.projectDir}/src/main/resources/google/registry/ui/"
|
||||
}
|
||||
|
||||
task runTestServer(dependsOn: copyJsFilesForTestServer, type: JavaExec) {
|
||||
main = 'google.registry.server.RegistryTestServerMain'
|
||||
classpath = sourceSets.test.runtimeClasspath
|
||||
}
|
||||
|
||||
project.build.dependsOn buildToolImage
|
||||
project.build.dependsOn ':stage'
|
||||
|
||||
@@ -19,6 +19,7 @@ import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl;
|
||||
import static google.registry.backup.ExportCommitLogDiffAction.LOWER_CHECKPOINT_TIME_PARAM;
|
||||
import static google.registry.backup.ExportCommitLogDiffAction.UPPER_CHECKPOINT_TIME_PARAM;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
@@ -63,7 +64,7 @@ public final class CommitLogCheckpointAction implements Runnable {
|
||||
final CommitLogCheckpoint checkpoint = strategy.computeCheckpoint();
|
||||
logger.atInfo().log(
|
||||
"Generated candidate checkpoint for time: %s", checkpoint.getCheckpointTime());
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
DateTime lastWrittenTime = CommitLogCheckpointRoot.loadRoot().getLastWrittenTime();
|
||||
|
||||
@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.mapreduce.MapreduceRunner.PARAM_DRY_RUN;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
|
||||
@@ -276,7 +277,7 @@ public final class DeleteOldCommitLogsAction implements Runnable {
|
||||
return;
|
||||
}
|
||||
|
||||
DeletionResult deletionResult = ofy().transactNew(() -> {
|
||||
DeletionResult deletionResult = tm().transactNew(() -> {
|
||||
CommitLogManifest manifest = ofy().load().key(manifestKey).now();
|
||||
// It is possible that the same manifestKey was run twice, if a shard had to be restarted
|
||||
// or some weird failure. If this happens, we want to exit immediately.
|
||||
|
||||
@@ -39,6 +39,7 @@ import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_DELETE;
|
||||
import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_DELETE_FAILURE;
|
||||
import static google.registry.model.reporting.HistoryEntry.Type.HOST_DELETE;
|
||||
import static google.registry.model.reporting.HistoryEntry.Type.HOST_DELETE_FAILURE;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.model.transfer.TransferStatus.SERVER_CANCELLED;
|
||||
import static java.math.RoundingMode.CEILING;
|
||||
import static java.util.concurrent.TimeUnit.DAYS;
|
||||
@@ -308,7 +309,7 @@ public class DeleteContactsAndHostsAction implements Runnable {
|
||||
final boolean hasNoActiveReferences = !Iterators.contains(values, true);
|
||||
logger.atInfo().log("Processing async deletion request for %s", deletionRequest.key());
|
||||
DeletionResult result =
|
||||
ofy()
|
||||
tm()
|
||||
.transactNew(
|
||||
() -> {
|
||||
DeletionResult deletionResult =
|
||||
@@ -329,7 +330,7 @@ public class DeleteContactsAndHostsAction implements Runnable {
|
||||
|
||||
private DeletionResult attemptToDeleteResource(
|
||||
DeletionRequest deletionRequest, boolean hasNoActiveReferences) {
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
EppResource resource =
|
||||
ofy().load().key(deletionRequest.key()).now().cloneProjectedAtTime(now);
|
||||
// Double-check transactionally that the resource is still active and in PENDING_DELETE.
|
||||
|
||||
@@ -19,6 +19,7 @@ import static google.registry.config.RegistryEnvironment.PRODUCTION;
|
||||
import static google.registry.mapreduce.MapreduceRunner.PARAM_DRY_RUN;
|
||||
import static google.registry.mapreduce.inputs.EppResourceInputs.createEntityInput;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
|
||||
import com.google.appengine.tools.mapreduce.Mapper;
|
||||
@@ -124,7 +125,7 @@ public class DeleteLoadTestDataAction implements Runnable {
|
||||
Key.create(EppResourceIndex.create(Key.create(resource)));
|
||||
final Key<? extends ForeignKeyIndex<?>> fki = ForeignKeyIndex.createKey(resource);
|
||||
int numEntitiesDeleted =
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
// This ancestor query selects all descendant entities.
|
||||
|
||||
@@ -23,6 +23,7 @@ import static google.registry.model.ResourceTransferUtils.updateForeignKeyIndexD
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.registry.Registries.getTldsOfType;
|
||||
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_DELETE;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.request.RequestParameters.PARAM_TLDS;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
@@ -219,7 +220,7 @@ public class DeleteProberDataAction implements Runnable {
|
||||
final Key<? extends ForeignKeyIndex<?>> fki = ForeignKeyIndex.createKey(domain);
|
||||
|
||||
int entitiesDeleted =
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
// This ancestor query selects all descendant HistoryEntries, BillingEvents,
|
||||
@@ -245,16 +246,16 @@ public class DeleteProberDataAction implements Runnable {
|
||||
}
|
||||
|
||||
private void softDeleteDomain(final DomainBase domain) {
|
||||
ofy().transactNew(() -> {
|
||||
tm().transactNew(() -> {
|
||||
DomainBase deletedDomain = domain
|
||||
.asBuilder()
|
||||
.setDeletionTime(ofy().getTransactionTime())
|
||||
.setDeletionTime(tm().getTransactionTime())
|
||||
.setStatusValues(null)
|
||||
.build();
|
||||
HistoryEntry historyEntry = new HistoryEntry.Builder()
|
||||
.setParent(domain)
|
||||
.setType(DOMAIN_DELETE)
|
||||
.setModificationTime(ofy().getTransactionTime())
|
||||
.setModificationTime(tm().getTransactionTime())
|
||||
.setBySuperuser(true)
|
||||
.setReason("Deletion of prober data")
|
||||
.setClientId(registryAdminClientId)
|
||||
|
||||
@@ -23,6 +23,7 @@ import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING;
|
||||
import static google.registry.model.domain.Period.Unit.YEARS;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_AUTORENEW;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
||||
import static google.registry.util.CollectionUtils.union;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
@@ -150,7 +151,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
|
||||
}
|
||||
int numBillingEventsSaved = 0;
|
||||
try {
|
||||
numBillingEventsSaved = ofy().transactNew(() -> {
|
||||
numBillingEventsSaved = tm().transactNew(() -> {
|
||||
ImmutableSet.Builder<OneTime> syntheticOneTimesBuilder =
|
||||
new ImmutableSet.Builder<>();
|
||||
final Registry tld = Registry.get(getTldFromDomainName(recurring.getTargetId()));
|
||||
@@ -183,20 +184,24 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
|
||||
HistoryEntry historyEntry = new HistoryEntry.Builder()
|
||||
.setBySuperuser(false)
|
||||
.setClientId(recurring.getClientId())
|
||||
.setModificationTime(ofy().getTransactionTime())
|
||||
.setModificationTime(tm().getTransactionTime())
|
||||
.setParent(domainKey)
|
||||
.setPeriod(Period.create(1, YEARS))
|
||||
.setReason("Domain autorenewal by ExpandRecurringBillingEventsAction")
|
||||
.setRequestedByRegistrar(false)
|
||||
.setType(DOMAIN_AUTORENEW)
|
||||
// Don't write a domain transaction record if the recurrence was ended prior to the
|
||||
// billing time (i.e. a domain was deleted during the autorenew grace period).
|
||||
.setDomainTransactionRecords(
|
||||
ImmutableSet.of(
|
||||
DomainTransactionRecord.create(
|
||||
tld.getTldStr(),
|
||||
// We report this when the autorenew grace period ends
|
||||
billingTime,
|
||||
TransactionReportField.netRenewsFieldFromYears(1),
|
||||
1)))
|
||||
recurring.getRecurrenceEndTime().isBefore(billingTime)
|
||||
? ImmutableSet.of()
|
||||
: ImmutableSet.of(
|
||||
DomainTransactionRecord.create(
|
||||
tld.getTldStr(),
|
||||
// We report this when the autorenew grace period ends
|
||||
billingTime,
|
||||
TransactionReportField.netRenewsFieldFromYears(1),
|
||||
1)))
|
||||
.build();
|
||||
historyEntriesBuilder.add(historyEntry);
|
||||
|
||||
@@ -308,7 +313,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
|
||||
logger.atInfo().log(
|
||||
"Recurring event expansion %s complete for billing event range [%s, %s).",
|
||||
isDryRun ? "(dry run) " : "", cursorTime, executionTime);
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
Cursor cursor = ofy().load().key(Cursor.createGlobalKey(RECURRING_BILLING)).now();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.batch;
|
||||
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.appengine.tools.mapreduce.Mapper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -69,7 +70,7 @@ public class ResaveAllEppResourcesAction implements Runnable {
|
||||
|
||||
@Override
|
||||
public final void map(final Key<EppResource> resourceKey) {
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
EppResource projectedResource =
|
||||
@@ -77,7 +78,7 @@ public class ResaveAllEppResourcesAction implements Runnable {
|
||||
.load()
|
||||
.key(resourceKey)
|
||||
.now()
|
||||
.cloneProjectedAtTime(ofy().getTransactionTime());
|
||||
.cloneProjectedAtTime(tm().getTransactionTime());
|
||||
ofy().save().entity(projectedResource).now();
|
||||
});
|
||||
getContext().incrementCounter(String.format("%s entities re-saved", resourceKey.getKind()));
|
||||
|
||||
@@ -18,6 +18,7 @@ import static google.registry.batch.AsyncTaskEnqueuer.PARAM_REQUESTED_TIME;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESAVE_TIMES;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
@@ -73,11 +74,11 @@ public class ResaveEntityAction implements Runnable {
|
||||
public void run() {
|
||||
logger.atInfo().log(
|
||||
"Re-saving entity %s which was enqueued at %s.", resourceKey, requestedTime);
|
||||
ofy().transact(() -> {
|
||||
tm().transact(() -> {
|
||||
ImmutableObject entity = ofy().load().key(resourceKey).now();
|
||||
ofy().save().entity(
|
||||
(entity instanceof EppResource)
|
||||
? ((EppResource) entity).cloneProjectedAtTime(ofy().getTransactionTime()) : entity
|
||||
? ((EppResource) entity).cloneProjectedAtTime(tm().getTransactionTime()) : entity
|
||||
);
|
||||
if (!resaveTimes.isEmpty()) {
|
||||
asyncTaskEnqueuer.enqueueAsyncResave(entity, requestedTime, resaveTimes);
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.config;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import dagger.Module;
|
||||
@@ -68,6 +69,29 @@ public abstract class CredentialModule {
|
||||
return GoogleCredentialsBundle.create(credential);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the default {@link GoogleCredential} from the Google Cloud runtime for G Suite
|
||||
* Drive API.
|
||||
* TODO(b/138195359): Deprecate this credential once we figure out how to use
|
||||
* {@link GoogleCredentials} for G Suite Drive API.
|
||||
*/
|
||||
@GSuiteDriveCredential
|
||||
@Provides
|
||||
@Singleton
|
||||
public static GoogleCredential provideGSuiteDriveCredential(
|
||||
@Config("defaultCredentialOauthScopes") ImmutableList<String> requiredScopes) {
|
||||
GoogleCredential credential;
|
||||
try {
|
||||
credential = GoogleCredential.getApplicationDefault();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (credential.createScopedRequired()) {
|
||||
credential = credential.createScoped(requiredScopes);
|
||||
}
|
||||
return credential;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a {@link GoogleCredentialsBundle} from the service account's JSON key file.
|
||||
*
|
||||
@@ -118,6 +142,13 @@ public abstract class CredentialModule {
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DefaultCredential {}
|
||||
|
||||
|
||||
/** Dagger qualifier for the credential for G Suite Drive API. */
|
||||
@Qualifier
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface GSuiteDriveCredential {}
|
||||
|
||||
/**
|
||||
* Dagger qualifier for a credential from a service account's JSON key, to be used in non-request
|
||||
* threads.
|
||||
|
||||
@@ -112,7 +112,7 @@ public final class RegistryConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* The product name of this specific registry. Used throughout the registrar console.
|
||||
* The product name of this specific registry. Used throughout the registrar console.
|
||||
*
|
||||
* @see google.registry.ui.server.registrar.ConsoleUiAction
|
||||
*/
|
||||
@@ -123,11 +123,11 @@ public final class RegistryConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the roid suffix to be used for the roids of all contacts and hosts. E.g. a value of
|
||||
* Returns the roid suffix to be used for the roids of all contacts and hosts. E.g. a value of
|
||||
* "ROID" would end up creating roids that look like "ABC123-ROID".
|
||||
*
|
||||
* @see <a href="http://www.iana.org/assignments/epp-repository-ids/epp-repository-ids.xhtml">
|
||||
* Extensible Provisioning Protocol (EPP) Repository Identifiers</a>
|
||||
* Extensible Provisioning Protocol (EPP) Repository Identifiers</a>
|
||||
*/
|
||||
@Provides
|
||||
@Config("contactAndHostRoidSuffix")
|
||||
@@ -136,7 +136,7 @@ public final class RegistryConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* The e-mail address for questions about integrating with the registry. Used in the
|
||||
* The e-mail address for questions about integrating with the registry. Used in the
|
||||
* "contact-us" section of the registrar console.
|
||||
*
|
||||
* @see google.registry.ui.server.registrar.ConsoleUiAction
|
||||
@@ -148,7 +148,7 @@ public final class RegistryConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* The e-mail address for general support. Used in the "contact-us" section of the registrar
|
||||
* The e-mail address for general support. Used in the "contact-us" section of the registrar
|
||||
* console.
|
||||
*
|
||||
* @see google.registry.ui.server.registrar.ConsoleUiAction
|
||||
@@ -160,7 +160,7 @@ public final class RegistryConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* The "From" e-mail address for announcements. Used in the "contact-us" section of the
|
||||
* The "From" e-mail address for announcements. Used in the "contact-us" section of the
|
||||
* registrar console.
|
||||
*
|
||||
* @see google.registry.ui.server.registrar.ConsoleUiAction
|
||||
@@ -172,7 +172,7 @@ public final class RegistryConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* The contact phone number. Used in the "contact-us" section of the registrar console.
|
||||
* The contact phone number. Used in the "contact-us" section of the registrar console.
|
||||
*
|
||||
* @see google.registry.ui.server.registrar.ConsoleUiAction
|
||||
*/
|
||||
@@ -894,9 +894,9 @@ public final class RegistryConfig {
|
||||
* @see google.registry.reporting.spec11.Spec11EmailUtils
|
||||
*/
|
||||
@Provides
|
||||
@Config("spec11ReplyToEmailAddress")
|
||||
public static InternetAddress provideSpec11ReplyToEmailAddress(RegistryConfigSettings config) {
|
||||
return parseEmailAddress(config.misc.spec11ReplyToEmailAddress);
|
||||
@Config("spec11OutgoingEmailAddress")
|
||||
public static InternetAddress provideSpec11OutgoingEmailAddress(RegistryConfigSettings config) {
|
||||
return parseEmailAddress(config.misc.spec11OutgoingEmailAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1040,8 +1040,8 @@ public final class RegistryConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* The global automatic transfer length for contacts. After this amount of time has
|
||||
* elapsed, the transfer is automatically approved.
|
||||
* The global automatic transfer length for contacts. After this amount of time has elapsed, the
|
||||
* transfer is automatically approved.
|
||||
*
|
||||
* @see google.registry.flows.contact.ContactTransferRequestFlow
|
||||
*/
|
||||
@@ -1196,7 +1196,7 @@ public final class RegistryConfig {
|
||||
/**
|
||||
* Provides the OAuth scopes that authentication logic should detect on access tokens.
|
||||
*
|
||||
* <p>This list should be a superset of the required OAuth scope set provided below. Note that
|
||||
* <p>This list should be a superset of the required OAuth scope set provided below. Note that
|
||||
* ideally, this setting would not be required and all scopes on an access token would be
|
||||
* detected automatically, but that is not the case due to the way {@code OAuthService} works.
|
||||
*
|
||||
@@ -1297,9 +1297,7 @@ public final class RegistryConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the App Engine project ID, which is based off the environment name.
|
||||
*/
|
||||
/** Returns the App Engine project ID, which is based off the environment name. */
|
||||
public static String getProjectId() {
|
||||
return CONFIG_SETTINGS.get().appEngine.projectId;
|
||||
}
|
||||
@@ -1451,20 +1449,51 @@ public final class RegistryConfig {
|
||||
return CONFIG_SETTINGS.get().registryPolicy.defaultRegistrarWhoisServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of {@code EppResourceIndex} buckets to be used.
|
||||
*/
|
||||
/** Returns the number of {@code EppResourceIndex} buckets to be used. */
|
||||
public static int getEppResourceIndexBucketCount() {
|
||||
return CONFIG_SETTINGS.get().datastore.eppResourceIndexBucketsNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base retry duration that gets doubled after each failure within {@code Ofy}.
|
||||
*/
|
||||
/** Returns the base retry duration that gets doubled after each failure within {@code Ofy}. */
|
||||
public static Duration getBaseOfyRetryDuration() {
|
||||
return Duration.millis(CONFIG_SETTINGS.get().datastore.baseOfyRetryMillis);
|
||||
}
|
||||
|
||||
/** Returns the default database transaction isolation. */
|
||||
public static String getHibernateConnectionIsolation() {
|
||||
return CONFIG_SETTINGS.get().hibernate.connectionIsolation;
|
||||
}
|
||||
|
||||
/** Returns true if hibernate.show_sql is enabled. */
|
||||
public static String getHibernateLogSqlQueries() {
|
||||
return CONFIG_SETTINGS.get().hibernate.logSqlQueries;
|
||||
}
|
||||
|
||||
/** Returns true if schema modification is allowed. */
|
||||
public static String getHibernateHbm2ddlAuto() {
|
||||
return CONFIG_SETTINGS.get().hibernate.hbm2ddlAuto;
|
||||
}
|
||||
|
||||
/** Returns the connection timeout for HikariCP. */
|
||||
public static String getHibernateHikariConnectionTimeout() {
|
||||
return CONFIG_SETTINGS.get().hibernate.hikariConnectionTimeout;
|
||||
}
|
||||
|
||||
/** Returns the minimum idle connections for HikariCP. */
|
||||
public static String getHibernateHikariMinimumIdle() {
|
||||
return CONFIG_SETTINGS.get().hibernate.hikariMinimumIdle;
|
||||
}
|
||||
|
||||
/** Returns the maximum pool size for HikariCP. */
|
||||
public static String getHibernateHikariMaximumPoolSize() {
|
||||
return CONFIG_SETTINGS.get().hibernate.hikariMaximumPoolSize;
|
||||
}
|
||||
|
||||
/** Returns the idle timeout for HikariCP. */
|
||||
public static String getHibernateHikariIdleTimeout() {
|
||||
return CONFIG_SETTINGS.get().hibernate.hikariIdleTimeout;
|
||||
}
|
||||
|
||||
/** Returns the roid suffix to be used for the roids of all contacts and hosts. */
|
||||
public static String getContactAndHostRoidSuffix() {
|
||||
return CONFIG_SETTINGS.get().registryPolicy.contactAndHostRoidSuffix;
|
||||
|
||||
@@ -25,6 +25,7 @@ public class RegistryConfigSettings {
|
||||
public CredentialOAuth credentialOAuth;
|
||||
public RegistryPolicy registryPolicy;
|
||||
public Datastore datastore;
|
||||
public Hibernate hibernate;
|
||||
public CloudDns cloudDns;
|
||||
public Caching caching;
|
||||
public IcannReporting icannReporting;
|
||||
@@ -105,6 +106,17 @@ public class RegistryConfigSettings {
|
||||
public int baseOfyRetryMillis;
|
||||
}
|
||||
|
||||
/** Configuration for Hibernate. */
|
||||
public static class Hibernate {
|
||||
public String connectionIsolation;
|
||||
public String logSqlQueries;
|
||||
public String hbm2ddlAuto;
|
||||
public String hikariConnectionTimeout;
|
||||
public String hikariMinimumIdle;
|
||||
public String hikariMaximumPoolSize;
|
||||
public String hikariIdleTimeout;
|
||||
}
|
||||
|
||||
/** Configuration for Apache Beam (Cloud Dataflow). */
|
||||
public static class Beam {
|
||||
public String defaultJobZone;
|
||||
@@ -173,7 +185,7 @@ public class RegistryConfigSettings {
|
||||
public static class Misc {
|
||||
public String sheetExportId;
|
||||
public String alertRecipientEmailAddress;
|
||||
public String spec11ReplyToEmailAddress;
|
||||
public String spec11OutgoingEmailAddress;
|
||||
public int asyncDeleteDelaySeconds;
|
||||
public int transientFailureRetries;
|
||||
}
|
||||
|
||||
@@ -191,6 +191,26 @@ datastore:
|
||||
# doubles after each failure).
|
||||
baseOfyRetryMillis: 100
|
||||
|
||||
hibernate:
|
||||
# Make 'SERIALIZABLE' the default isolation level to ensure correctness.
|
||||
#
|
||||
# Entities that are never involved in multi-table transactions may use optimistic
|
||||
# locks and a less strict isolation level. We may lower individual transaction's
|
||||
# isolation level using a framework-dependent method.
|
||||
#
|
||||
# Alternatively, if a use case calls for, we may also use a lower isolation level
|
||||
# but lock tables explicitly, either using framework-dependent API, or execute
|
||||
# "select table for update" statements directly.
|
||||
connectionIsolation: TRANSACTION_SERIALIZABLE
|
||||
# Whether to log all SQL queries to App Engine logs. Overridable at runtime.
|
||||
logSqlQueries: false
|
||||
|
||||
# Connection pool configurations.
|
||||
hikariConnectionTimeout: 20000
|
||||
hikariMinimumIdle: 0
|
||||
hikariMaximumPoolSize: 20
|
||||
hikariIdleTimeout: 300000
|
||||
|
||||
cloudDns:
|
||||
# Set both properties to null in Production.
|
||||
# The root url for the Cloud DNS API. Set this to a non-null value to
|
||||
@@ -357,9 +377,9 @@ misc:
|
||||
# Address we send alert summary emails to.
|
||||
alertRecipientEmailAddress: email@example.com
|
||||
|
||||
# Address to which the Spec 11 emails to registrars should be replied. This needs
|
||||
# to be a deliverable email address in case the registrars want to contact us.
|
||||
spec11ReplyToEmailAddress: reply-to@example.com
|
||||
# Address from which Spec 11 emails to registrars are sent. This needs
|
||||
# to be a deliverable email address to handle replies from registrars as well.
|
||||
spec11OutgoingEmailAddress: abuse@example.com
|
||||
|
||||
# How long to delay processing of asynchronous deletions. This should always
|
||||
# be longer than eppResourceCachingSeconds, to prevent deleted contacts or
|
||||
|
||||
@@ -13,11 +13,6 @@
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>backend-servlet</servlet-name>
|
||||
<url-pattern>/_dr/task/metrics</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- RDE -->
|
||||
|
||||
<!--
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
|
||||
package google.registry.export;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.services.drive.Drive;
|
||||
import dagger.Component;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule;
|
||||
import google.registry.config.CredentialModule.DefaultCredential;
|
||||
import google.registry.config.CredentialModule.GSuiteDriveCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryConfig.ConfigModule;
|
||||
import google.registry.storage.drive.DriveConnection;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/** Dagger module for Google {@link Drive} service connection objects. */
|
||||
@@ -32,13 +32,13 @@ public final class DriveModule {
|
||||
|
||||
@Provides
|
||||
static Drive provideDrive(
|
||||
@DefaultCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@GSuiteDriveCredential GoogleCredential googleCredential,
|
||||
@Config("projectId") String projectId) {
|
||||
|
||||
return new Drive.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
googleCredential.getTransport(),
|
||||
googleCredential.getJsonFactory(),
|
||||
googleCredential)
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package google.registry.export;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.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;
|
||||
@@ -163,7 +164,7 @@ public final class SyncGroupMembersAction implements Runnable {
|
||||
registrarsToSave.add(result.getKey().asBuilder().setContactsRequireSyncing(false).build());
|
||||
}
|
||||
}
|
||||
ofy().transactNew(() -> ofy().save().entities(registrarsToSave.build()));
|
||||
tm().transactNew(() -> ofy().save().entities(registrarsToSave.build()));
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import static google.registry.model.registrar.RegistrarContact.Type.LEGAL;
|
||||
import static google.registry.model.registrar.RegistrarContact.Type.MARKETING;
|
||||
import static google.registry.model.registrar.RegistrarContact.Type.TECH;
|
||||
import static google.registry.model.registrar.RegistrarContact.Type.WHOIS;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
@@ -152,7 +153,7 @@ class SyncRegistrarsSheet {
|
||||
return builder.build();
|
||||
})
|
||||
.collect(toImmutableList()));
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> ofy().save().entity(Cursor.createGlobal(SYNC_REGISTRAR_SHEET, executionTime)));
|
||||
}
|
||||
|
||||
@@ -62,24 +62,6 @@ public class EppMetrics {
|
||||
"count",
|
||||
LABEL_DESCRIPTORS_BY_TLD);
|
||||
|
||||
private static final EventMetric processingTimeByRegistrar =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newEventMetric(
|
||||
"/epp/processing_time",
|
||||
"EPP Processing Time By Registrar",
|
||||
"milliseconds",
|
||||
LABEL_DESCRIPTORS_BY_REGISTRAR,
|
||||
DEFAULT_FITTER);
|
||||
|
||||
private static final EventMetric processingTimeByTld =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newEventMetric(
|
||||
"/epp/processing_time_by_tld",
|
||||
"EPP Processing Time By TLD",
|
||||
"milliseconds",
|
||||
LABEL_DESCRIPTORS_BY_TLD,
|
||||
DEFAULT_FITTER);
|
||||
|
||||
private static final EventMetric requestTime =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newEventMetric(
|
||||
@@ -118,10 +100,7 @@ public class EppMetrics {
|
||||
long processingTime =
|
||||
metric.getEndTimestamp().getMillis() - metric.getStartTimestamp().getMillis();
|
||||
String commandName = metric.getCommandName().orElse("");
|
||||
processingTimeByRegistrar
|
||||
.record(processingTime, commandName, metric.getClientId().orElse(""), eppStatusCode);
|
||||
String tld = metric.getTld().orElse("");
|
||||
processingTimeByTld.record(processingTime, commandName, tld, eppStatusCode);
|
||||
requestTime.record(processingTime, commandName, getTrafficType(tld).toString(), eppStatusCode);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.flows;
|
||||
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.xml.XmlTransformer.prettyPrint;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
@@ -80,7 +80,7 @@ public class FlowRunner {
|
||||
return eppOutput;
|
||||
}
|
||||
try {
|
||||
return ofy()
|
||||
return tm()
|
||||
.transact(
|
||||
() -> {
|
||||
try {
|
||||
|
||||
@@ -23,7 +23,7 @@ import google.registry.model.registrar.Registrar;
|
||||
public class PasswordOnlyTransportCredentials implements TransportCredentials {
|
||||
@Override
|
||||
public void validate(Registrar r, String password) throws AuthenticationErrorException {
|
||||
if (!r.testPassword(password)) {
|
||||
if (!r.verifyPassword(password)) {
|
||||
throw new BadRegistrarPasswordException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||
import static google.registry.model.EppResourceUtils.queryForLinkedDomains;
|
||||
import static google.registry.model.index.ForeignKeyIndex.loadAndGetKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
@@ -77,7 +78,7 @@ public final class ResourceFlowUtils {
|
||||
final Function<DomainBase, ImmutableSet<?>> getPotentialReferences) throws EppException {
|
||||
// Enter a transactionless context briefly.
|
||||
EppException failfastException =
|
||||
ofy()
|
||||
tm()
|
||||
.doTransactionless(
|
||||
() -> {
|
||||
final ForeignKeyIndex<R> fki =
|
||||
|
||||
@@ -145,7 +145,7 @@ public class TlsCredentials implements TransportCredentials {
|
||||
|
||||
private void validatePassword(Registrar registrar, String password)
|
||||
throws BadRegistrarPasswordException {
|
||||
if (!registrar.testPassword(password)) {
|
||||
if (!registrar.verifyPassword(password)) {
|
||||
throw new BadRegistrarPasswordException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostal
|
||||
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
|
||||
import static google.registry.model.EppResourceUtils.createRepoId;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
@@ -71,7 +72,7 @@ public final class ContactCreateFlow implements TransactionalFlow {
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
Create command = (Create) resourceCommand;
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
verifyResourceDoesNotExist(ContactResource.class, targetId, now, clientId);
|
||||
ContactResource newContact =
|
||||
new ContactResource.Builder()
|
||||
|
||||
@@ -22,6 +22,7 @@ import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
@@ -84,7 +85,7 @@ public final class ContactDeleteFlow implements TransactionalFlow {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
failfastForAsyncDelete(targetId, now, ContactResource.class, DomainBase::getReferencedContacts);
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
|
||||
@@ -93,7 +94,7 @@ public final class ContactDeleteFlow implements TransactionalFlow {
|
||||
verifyResourceOwnership(clientId, existingContact);
|
||||
}
|
||||
asyncTaskEnqueuer.enqueueAsyncDelete(
|
||||
existingContact, ofy().getTransactionTime(), clientId, trid, isSuperuser);
|
||||
existingContact, tm().getTransactionTime(), clientId, trid, isSuperuser);
|
||||
ContactResource newContact =
|
||||
existingContact.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build();
|
||||
historyBuilder
|
||||
|
||||
@@ -23,6 +23,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createGainingTransf
|
||||
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
||||
import static google.registry.model.ResourceTransferUtils.approvePendingTransfer;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
@@ -78,7 +79,7 @@ public final class ContactTransferApproveFlow implements TransactionalFlow {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
verifyHasPendingTransfer(existingContact);
|
||||
|
||||
@@ -23,6 +23,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createLosingTransfe
|
||||
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
||||
import static google.registry.model.ResourceTransferUtils.denyPendingTransfer;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
@@ -74,7 +75,7 @@ public final class ContactTransferCancelFlow implements TransactionalFlow {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
verifyHasPendingTransfer(existingContact);
|
||||
|
||||
@@ -23,6 +23,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createGainingTransf
|
||||
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
||||
import static google.registry.model.ResourceTransferUtils.denyPendingTransfer;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
@@ -72,7 +73,7 @@ public final class ContactTransferRejectFlow implements TransactionalFlow {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
verifyHasPendingTransfer(existingContact);
|
||||
|
||||
@@ -24,6 +24,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createLosingTransfe
|
||||
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
@@ -91,7 +92,7 @@ public final class ContactTransferRequestFlow implements TransactionalFlow {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(gainingClientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
verifyAuthInfoPresentForResourceTransfer(authInfo);
|
||||
verifyAuthInfo(authInfo.get(), existingContact);
|
||||
|
||||
@@ -25,6 +25,7 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||
import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo;
|
||||
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
@@ -92,7 +93,7 @@ public final class ContactUpdateFlow implements TransactionalFlow {
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
Update command = (Update) resourceCommand;
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
ImmutableSet<StatusValue> statusToRemove = command.getInnerRemove().getStatusValues();
|
||||
|
||||
@@ -42,11 +42,11 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActi
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
||||
import static google.registry.model.EppResourceUtils.createDomainRepoId;
|
||||
import static google.registry.model.eppcommon.StatusValue.SERVER_HOLD;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY;
|
||||
import static google.registry.model.registry.Registry.TldState.QUIET_PERIOD;
|
||||
import static google.registry.model.registry.Registry.TldState.START_DATE_SUNRISE;
|
||||
import static google.registry.model.registry.label.ReservationType.NAME_COLLISION;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
||||
|
||||
@@ -221,7 +221,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
verifyRegistrarIsActive(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DomainCommand.Create command = cloneAndLinkReferences((Create) resourceCommand, now);
|
||||
Period period = command.getPeriod();
|
||||
verifyUnitIsYears(period);
|
||||
|
||||
@@ -34,6 +34,7 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PE
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.ADD_FIELDS;
|
||||
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.RENEW_FIELDS;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
import static google.registry.util.CollectionUtils.union;
|
||||
@@ -140,7 +141,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
flowCustomLogic.beforeValidation();
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
// Loads the target resource if it exists
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
Registry registry = Registry.get(existingDomain.getTld());
|
||||
|
||||
@@ -28,7 +28,7 @@ import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateRegistrationPeriod;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -137,7 +137,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
verifyRegistrarIsActive(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
Renew command = (Renew) resourceCommand;
|
||||
// Loads the target resource if it exists
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
|
||||
@@ -27,6 +27,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNo
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive;
|
||||
import static google.registry.model.ResourceTransferUtils.updateForeignKeyIndexDeletionTime;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -133,7 +134,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
validateClientIsLoggedIn(clientId);
|
||||
verifyRegistrarIsActive(clientId);
|
||||
Update command = (Update) resourceCommand;
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
FeesAndCredits feesAndCredits =
|
||||
pricingLogic.getRestorePrice(Registry.get(existingDomain.getTld()), targetId, now);
|
||||
|
||||
@@ -29,6 +29,7 @@ import static google.registry.model.ResourceTransferUtils.approvePendingTransfer
|
||||
import static google.registry.model.domain.DomainBase.extendRegistrationWithCap;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
||||
import static google.registry.util.CollectionUtils.union;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
@@ -102,7 +103,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||
verifyHasPendingTransfer(existingDomain);
|
||||
|
||||
@@ -27,6 +27,7 @@ import static google.registry.flows.domain.DomainTransferUtils.createTransferRes
|
||||
import static google.registry.model.ResourceTransferUtils.denyPendingTransfer;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -87,7 +88,7 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||
verifyHasPendingTransfer(existingDomain);
|
||||
|
||||
@@ -28,6 +28,7 @@ import static google.registry.model.ResourceTransferUtils.denyPendingTransfer;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_NACKED;
|
||||
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.CollectionUtils.union;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
|
||||
@@ -89,7 +90,7 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
Registry registry = Registry.get(existingDomain.getTld());
|
||||
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now);
|
||||
|
||||
@@ -32,6 +32,7 @@ import static google.registry.flows.domain.DomainTransferUtils.createTransferSer
|
||||
import static google.registry.model.domain.DomainBase.extendRegistrationWithCap;
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -143,7 +144,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(gainingClientId);
|
||||
verifyRegistrarIsActive(gainingClientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
Optional<DomainTransferRequestSuperuserExtension> superuserExtension =
|
||||
eppInput.getSingleExtension(DomainTransferRequestSuperuserExtension.class);
|
||||
|
||||
@@ -38,7 +38,7 @@ import static google.registry.flows.domain.DomainFlowUtils.validateRegistrantAll
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresent;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNotProhibited;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
@@ -154,7 +154,7 @@ public final class DomainUpdateFlow implements TransactionalFlow {
|
||||
flowCustomLogic.beforeValidation();
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
Update command = cloneAndLinkReferences((Update) resourceCommand, now);
|
||||
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
|
||||
verifyUpdateAllowed(command, existingDomain, now);
|
||||
|
||||
@@ -22,6 +22,7 @@ import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomain
|
||||
import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomainOwnership;
|
||||
import static google.registry.model.EppResourceUtils.createRepoId;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||
import static google.registry.util.CollectionUtils.union;
|
||||
|
||||
@@ -103,7 +104,7 @@ public final class HostCreateFlow implements TransactionalFlow {
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
Create command = (Create) resourceCommand;
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
verifyResourceDoesNotExist(HostResource.class, targetId, now, clientId);
|
||||
// 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
|
||||
|
||||
@@ -22,6 +22,7 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||
import static google.registry.flows.host.HostFlowUtils.validateHostName;
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
@@ -85,7 +86,7 @@ public final class HostDeleteFlow implements TransactionalFlow {
|
||||
extensionManager.register(MetadataExtension.class);
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
validateHostName(targetId);
|
||||
failfastForAsyncDelete(targetId, now, HostResource.class, DomainBase::getNameservers);
|
||||
HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now);
|
||||
@@ -101,7 +102,7 @@ public final class HostDeleteFlow implements TransactionalFlow {
|
||||
verifyResourceOwnership(clientId, owningResource);
|
||||
}
|
||||
asyncTaskEnqueuer.enqueueAsyncDelete(
|
||||
existingHost, ofy().getTransactionTime(), clientId, trid, isSuperuser);
|
||||
existingHost, tm().getTransactionTime(), clientId, trid, isSuperuser);
|
||||
HostResource newHost =
|
||||
existingHost.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build();
|
||||
historyBuilder
|
||||
|
||||
@@ -28,6 +28,7 @@ import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomain
|
||||
import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomainOwnership;
|
||||
import static google.registry.model.index.ForeignKeyIndex.loadAndGetKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -129,7 +130,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
Update command = (Update) resourceCommand;
|
||||
Change change = command.getInnerChange();
|
||||
String suppliedNewHostName = change.getFullyQualifiedHostName();
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
validateHostName(targetId);
|
||||
HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now);
|
||||
boolean isHostRename = suppliedNewHostName != null;
|
||||
@@ -271,7 +272,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
}
|
||||
// We must also enqueue updates for all domains that use this host as their nameserver so
|
||||
// that their NS records can be updated to point at the new name.
|
||||
asyncTaskEnqueuer.enqueueAsyncDnsRefresh(existingHost, ofy().getTransactionTime());
|
||||
asyncTaskEnqueuer.enqueueAsyncDnsRefresh(existingHost, tm().getTransactionTime());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_NO_MESSAG
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.poll.PollMessageExternalKeyConverter.makePollMessageExternalId;
|
||||
import static google.registry.model.poll.PollMessageExternalKeyConverter.parsePollMessageExternalId;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
@@ -78,7 +79,7 @@ public class PollAckFlow implements TransactionalFlow {
|
||||
throw new InvalidMessageIdException(messageId);
|
||||
}
|
||||
|
||||
final DateTime now = ofy().getTransactionTime();
|
||||
final DateTime now = tm().getTransactionTime();
|
||||
|
||||
// Load the message to be acked. If a message is queued to be delivered in the future, we treat
|
||||
// it as if it doesn't exist yet. Same for if the message ID year isn't the same as the actual
|
||||
@@ -124,7 +125,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 = ofy().doTransactionless(() -> getPollMessagesQuery(clientId, now).count());
|
||||
int messageCount = tm().doTransactionless(() -> getPollMessagesQuery(clientId, now).count());
|
||||
if (!includeAckedMessageInCount) {
|
||||
messageCount--;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.RDE_SSH_CLIE
|
||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.RDE_SSH_CLIENT_PUBLIC_STRING;
|
||||
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.SAFE_BROWSING_API_KEY;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
@@ -182,7 +183,7 @@ public final class KmsUpdater {
|
||||
*/
|
||||
private static void persistEncryptedValues(
|
||||
final ImmutableMap<String, EncryptResponse> encryptedValues) {
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
for (Map.Entry<String, EncryptResponse> entry : encryptedValues.entrySet()) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import static com.google.common.collect.Sets.union;
|
||||
import static google.registry.config.RegistryConfig.getEppResourceCachingDuration;
|
||||
import static google.registry.config.RegistryConfig.getEppResourceMaxCachedEntries;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
@@ -49,10 +50,13 @@ import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** An EPP entity object (i.e. a domain, contact, or host). */
|
||||
@MappedSuperclass
|
||||
public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
|
||||
/**
|
||||
@@ -61,8 +65,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
* <p>This is in the (\w|_){1,80}-\w{1,8} format specified by RFC 5730 for roidType.
|
||||
* @see <a href="https://tools.ietf.org/html/rfc5730">RFC 5730</a>
|
||||
*/
|
||||
@Id
|
||||
String repoId;
|
||||
@Id @javax.persistence.Id String repoId;
|
||||
|
||||
/** The ID of the registrar that is currently sponsoring this resource. */
|
||||
@Index
|
||||
@@ -84,8 +87,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
// Map the method to XML, not the field, because if we map the field (with an adaptor class) it
|
||||
// will never be omitted from the xml even if the timestamp inside creationTime is null and we
|
||||
// return null from the adaptor. (Instead it gets written as an empty tag.)
|
||||
@Index
|
||||
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
@Index @Transient CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
|
||||
/**
|
||||
* The time when this resource was or will be deleted.
|
||||
@@ -114,7 +116,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
DateTime lastEppUpdateTime;
|
||||
|
||||
/** Status values associated with this resource. */
|
||||
Set<StatusValue> status;
|
||||
@Transient Set<StatusValue> status;
|
||||
|
||||
/**
|
||||
* Sorted map of {@link DateTime} keys (modified time) to {@link CommitLogManifest} entries.
|
||||
@@ -325,13 +327,13 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
|
||||
@Override
|
||||
public EppResource load(Key<? extends EppResource> key) {
|
||||
return ofy().doTransactionless(() -> ofy().load().key(key).now());
|
||||
return tm().doTransactionless(() -> ofy().load().key(key).now());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Key<? extends EppResource>, EppResource> loadAll(
|
||||
Iterable<? extends Key<? extends EppResource>> keys) {
|
||||
return ofy().doTransactionless(() -> loadMultiple(keys));
|
||||
return tm().doTransactionless(() -> loadMultiple(keys));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY;
|
||||
import static google.registry.model.registry.Registry.TldState.START_DATE_SUNRISE;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -236,7 +237,7 @@ public final class OteAccountBuilder {
|
||||
*/
|
||||
public ImmutableMap<String, String> buildAndPersist() {
|
||||
// save all the entitiesl in a single transaction
|
||||
ofy().transact(this::saveAllEntities);
|
||||
tm().transact(this::saveAllEntities);
|
||||
return clientIdToTld;
|
||||
}
|
||||
|
||||
@@ -249,7 +250,7 @@ public final class OteAccountBuilder {
|
||||
|
||||
/** Saves all the OT&E entities we created. */
|
||||
private void saveAllEntities() {
|
||||
ofy().assertInTransaction();
|
||||
tm().assertInTransaction();
|
||||
|
||||
ImmutableList<Registry> registries = ImmutableList.of(sunriseTld, gaTld, eapTld);
|
||||
ImmutableList<RegistrarContact> contacts = contactsBuilder.build();
|
||||
|
||||
@@ -17,6 +17,7 @@ package google.registry.model.common;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.model.ofy.ObjectifyService.allocateId;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.common.base.Splitter;
|
||||
@@ -55,13 +56,13 @@ public class GaeUserIdConverter extends ImmutableObject {
|
||||
try {
|
||||
// Perform these operations in a transactionless context to avoid enlisting in some outer
|
||||
// transaction (if any).
|
||||
ofy().doTransactionless(() -> ofy().saveWithoutBackup().entity(gaeUserIdConverter).now());
|
||||
tm().doTransactionless(() -> ofy().saveWithoutBackup().entity(gaeUserIdConverter).now());
|
||||
|
||||
// The read must be done in its own transaction to avoid reading from the session cache.
|
||||
return ofy()
|
||||
return tm()
|
||||
.transactNew(() -> ofy().load().entity(gaeUserIdConverter).safe().user.getUserId());
|
||||
} finally {
|
||||
ofy().doTransactionless(() -> ofy().deleteWithoutBackup().entity(gaeUserIdConverter).now());
|
||||
tm().doTransactionless(() -> ofy().deleteWithoutBackup().entity(gaeUserIdConverter).now());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Interval;
|
||||
|
||||
@@ -83,6 +84,8 @@ import org.joda.time.Interval;
|
||||
*/
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@javax.persistence.Entity
|
||||
@javax.persistence.Table(name = "domain")
|
||||
@ExternalMessagingName("domain")
|
||||
public class DomainBase extends EppResource
|
||||
implements ForeignKeyedEppResource, ResourceWithTransferData {
|
||||
@@ -115,18 +118,17 @@ public class DomainBase extends EppResource
|
||||
String tld;
|
||||
|
||||
/** References to hosts that are the nameservers for the domain. */
|
||||
@Index
|
||||
Set<Key<HostResource>> nsHosts;
|
||||
@Index @Transient Set<Key<HostResource>> nsHosts;
|
||||
|
||||
/**
|
||||
* The union of the contacts visible via {@link #getContacts} and {@link #getRegistrant}.
|
||||
*
|
||||
* <p>These are stored in one field so that we can query across all contacts at once.
|
||||
*/
|
||||
Set<DesignatedContact> allContacts;
|
||||
@Transient Set<DesignatedContact> allContacts;
|
||||
|
||||
/** Authorization info (aka transfer secret) of the domain. */
|
||||
DomainAuthInfo authInfo;
|
||||
@Transient DomainAuthInfo authInfo;
|
||||
|
||||
/**
|
||||
* Data used to construct DS records for this domain.
|
||||
@@ -134,14 +136,13 @@ public class DomainBase extends EppResource
|
||||
* <p>This is {@literal @}XmlTransient because it needs to be returned under the "extension" tag
|
||||
* of an info response rather than inside the "infData" tag.
|
||||
*/
|
||||
Set<DelegationSignerData> dsData;
|
||||
@Transient Set<DelegationSignerData> dsData;
|
||||
|
||||
/**
|
||||
* The claims notice supplied when this application or domain was created, if there was one. It's
|
||||
* {@literal @}XmlTransient because it's not returned in an info response.
|
||||
*/
|
||||
@IgnoreSave(IfNull.class)
|
||||
LaunchNotice launchNotice;
|
||||
@IgnoreSave(IfNull.class) @Transient LaunchNotice launchNotice;
|
||||
|
||||
/**
|
||||
* Name of first IDN table associated with TLD that matched the characters in this domain label.
|
||||
@@ -152,7 +153,7 @@ public class DomainBase extends EppResource
|
||||
String idnTableName;
|
||||
|
||||
/** Fully qualified host names of this domain's active subordinate hosts. */
|
||||
Set<String> subordinateHosts;
|
||||
@Transient Set<String> subordinateHosts;
|
||||
|
||||
/** When this domain's registration will expire. */
|
||||
DateTime registrationExpirationTime;
|
||||
@@ -187,7 +188,7 @@ public class DomainBase extends EppResource
|
||||
Key<PollMessage.Autorenew> autorenewPollMessage;
|
||||
|
||||
/** The unexpired grace periods for this domain (some of which may not be active yet). */
|
||||
Set<GracePeriod> gracePeriods;
|
||||
@Transient Set<GracePeriod> gracePeriods;
|
||||
|
||||
/**
|
||||
* The id of the signed mark that was used to create this domain in sunrise.
|
||||
@@ -198,7 +199,7 @@ public class DomainBase extends EppResource
|
||||
String smdId;
|
||||
|
||||
/** Data about any pending or past transfers on this domain. */
|
||||
TransferData transferData;
|
||||
@Transient TransferData transferData;
|
||||
|
||||
/**
|
||||
* The time that this resource was last transferred.
|
||||
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
package google.registry.model.domain.fee;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName;
|
||||
import java.util.Locale;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlValue;
|
||||
|
||||
@@ -47,7 +47,7 @@ public class FeeExtensionCommandDescriptor extends ImmutableObject {
|
||||
|
||||
public CommandName getCommand() {
|
||||
// Require the xml string to be lowercase.
|
||||
if (command != null && CharMatcher.javaLowerCase().matchesAllOf(command)) {
|
||||
if (command != null && command.toLowerCase(Locale.ENGLISH).equals(command)) {
|
||||
try {
|
||||
return CommandName.valueOf(Ascii.toUpperCase(command));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
package google.registry.model.domain.fee12;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
@@ -83,7 +83,7 @@ public class FeeCheckCommandExtensionItemV12 extends FeeCheckCommandExtensionIte
|
||||
@Override
|
||||
public CommandName getCommandName() {
|
||||
// Require the xml string to be lowercase.
|
||||
if (commandName != null && CharMatcher.javaLowerCase().matchesAllOf(commandName)) {
|
||||
if (commandName != null && commandName.toLowerCase(Locale.ENGLISH).equals(commandName)) {
|
||||
try {
|
||||
return CommandName.valueOf(Ascii.toUpperCase(commandName));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import static com.google.common.collect.Maps.filterValues;
|
||||
import static google.registry.config.RegistryConfig.getEppResourceCachingDuration;
|
||||
import static google.registry.config.RegistryConfig.getEppResourceMaxCachedEntries;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.TypeUtils.instantiate;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
@@ -188,7 +189,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
|
||||
@Override
|
||||
public Optional<ForeignKeyIndex<?>> load(Key<ForeignKeyIndex<?>> key) {
|
||||
return Optional.ofNullable(ofy().doTransactionless(() -> ofy().load().key(key).now()));
|
||||
return Optional.ofNullable(tm().doTransactionless(() -> ofy().load().key(key).now()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -196,7 +197,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
Iterable<? extends Key<ForeignKeyIndex<?>>> keys) {
|
||||
ImmutableSet<Key<ForeignKeyIndex<?>>> typedKeys = ImmutableSet.copyOf(keys);
|
||||
Map<Key<ForeignKeyIndex<?>>, ForeignKeyIndex<?>> existingFkis =
|
||||
ofy().doTransactionless(() -> ofy().load().keys(typedKeys));
|
||||
tm().doTransactionless(() -> ofy().load().keys(typedKeys));
|
||||
// ofy() omits keys that don't have values in Datastore, so re-add them in
|
||||
// here with Optional.empty() values.
|
||||
return Maps.asMap(
|
||||
@@ -250,7 +251,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
public static <E extends EppResource> Map<String, ForeignKeyIndex<E>> loadCached(
|
||||
Class<E> clazz, Iterable<String> foreignKeys, final DateTime now) {
|
||||
if (!RegistryConfig.isEppResourceCachingEnabled()) {
|
||||
return ofy().doTransactionless(() -> load(clazz, foreignKeys, now));
|
||||
return tm().doTransactionless(() -> load(clazz, foreignKeys, now));
|
||||
}
|
||||
ImmutableList<Key<ForeignKeyIndex<?>>> fkiKeys =
|
||||
Streams.stream(foreignKeys)
|
||||
|
||||
@@ -28,10 +28,9 @@ import static google.registry.util.DateTimeUtils.isBeforeOrAt;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.VoidWork;
|
||||
import com.googlecode.objectify.Work;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.transaction.TransactionManager.Work;
|
||||
import google.registry.util.Clock;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@@ -40,7 +39,7 @@ import java.util.Set;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Wrapper for {@link Work} that associates a time with each attempt. */
|
||||
class CommitLoggedWork<R> extends VoidWork {
|
||||
class CommitLoggedWork<R> implements Runnable {
|
||||
|
||||
private final Work<R> work;
|
||||
private final Clock clock;
|
||||
@@ -74,8 +73,8 @@ class CommitLoggedWork<R> extends VoidWork {
|
||||
*/
|
||||
protected ImmutableSet<ImmutableObject> mutations = ImmutableSet.of();
|
||||
|
||||
/** Lifecycle marker to track whether {@link #vrun} has been called. */
|
||||
private boolean vrunCalled;
|
||||
/** Lifecycle marker to track whether {@link #run} has been called. */
|
||||
private boolean runCalled;
|
||||
|
||||
CommitLoggedWork(Work<R> work, Clock clock) {
|
||||
this.work = work;
|
||||
@@ -87,26 +86,26 @@ class CommitLoggedWork<R> extends VoidWork {
|
||||
}
|
||||
|
||||
boolean hasRun() {
|
||||
return vrunCalled;
|
||||
return runCalled;
|
||||
}
|
||||
|
||||
R getResult() {
|
||||
checkState(vrunCalled, "Cannot call getResult() before vrun()");
|
||||
checkState(runCalled, "Cannot call getResult() before run()");
|
||||
return result;
|
||||
}
|
||||
|
||||
CommitLogManifest getManifest() {
|
||||
checkState(vrunCalled, "Cannot call getManifest() before vrun()");
|
||||
checkState(runCalled, "Cannot call getManifest() before run()");
|
||||
return manifest;
|
||||
}
|
||||
|
||||
ImmutableSet<ImmutableObject> getMutations() {
|
||||
checkState(vrunCalled, "Cannot call getMutations() before vrun()");
|
||||
checkState(runCalled, "Cannot call getMutations() before run()");
|
||||
return mutations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void vrun() {
|
||||
public void run() {
|
||||
// The previous time will generally be null, except when using transactNew.
|
||||
TransactionInfo previous = Ofy.TRANSACTION_INFO.get();
|
||||
// Set the time to be used for "now" within the transaction.
|
||||
@@ -117,7 +116,7 @@ class CommitLoggedWork<R> extends VoidWork {
|
||||
} finally {
|
||||
Ofy.TRANSACTION_INFO.set(previous);
|
||||
}
|
||||
vrunCalled = true;
|
||||
runCalled = true;
|
||||
}
|
||||
|
||||
/** Records all mutations enrolled by this transaction to a {@link CommitLogManifest} entry. */
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.ofy;
|
||||
|
||||
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
|
||||
import google.registry.model.transaction.TransactionManager;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Datastore implementation of {@link TransactionManager}. */
|
||||
public class DatastoreTransactionManager implements TransactionManager {
|
||||
|
||||
private Ofy injectedOfy;
|
||||
|
||||
/** Constructs an instance. */
|
||||
public DatastoreTransactionManager(Ofy injectedOfy) {
|
||||
this.injectedOfy = injectedOfy;
|
||||
}
|
||||
|
||||
private Ofy getOfy() {
|
||||
return injectedOfy == null ? ofy() : injectedOfy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inTransaction() {
|
||||
return getOfy().inTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertInTransaction() {
|
||||
getOfy().assertInTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T transact(Work<T> work) {
|
||||
return getOfy().transact(work);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transact(Runnable work) {
|
||||
getOfy().transact(work);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T transactNew(Work<T> work) {
|
||||
return getOfy().transactNew(work);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transactNew(Runnable work) {
|
||||
getOfy().transactNew(work);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R transactNewReadOnly(Work<R> work) {
|
||||
return getOfy().transactNewReadOnly(work);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transactNewReadOnly(Runnable work) {
|
||||
getOfy().transactNewReadOnly(work);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R doTransactionless(Work<R> work) {
|
||||
return getOfy().doTransactionless(work);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateTime getTransactionTime() {
|
||||
return getOfy().getTransactionTime();
|
||||
}
|
||||
}
|
||||
@@ -32,13 +32,13 @@ import com.google.common.flogger.FluentLogger;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.Objectify;
|
||||
import com.googlecode.objectify.ObjectifyFactory;
|
||||
import com.googlecode.objectify.Work;
|
||||
import com.googlecode.objectify.cmd.Deleter;
|
||||
import com.googlecode.objectify.cmd.Loader;
|
||||
import com.googlecode.objectify.cmd.Saver;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.VirtualEntity;
|
||||
import google.registry.model.ofy.ReadOnlyWork.KillTransactionException;
|
||||
import google.registry.model.transaction.TransactionManager.Work;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.NonFinalForTesting;
|
||||
import google.registry.util.Sleeper;
|
||||
@@ -111,11 +111,11 @@ public class Ofy {
|
||||
ofy().clear();
|
||||
}
|
||||
|
||||
public boolean inTransaction() {
|
||||
boolean inTransaction() {
|
||||
return ofy().getTransaction() != null;
|
||||
}
|
||||
|
||||
public void assertInTransaction() {
|
||||
void assertInTransaction() {
|
||||
checkState(inTransaction(), "Must be called in a transaction");
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ public class Ofy {
|
||||
}
|
||||
|
||||
/** Execute a transaction. */
|
||||
public <R> R transact(Work<R> work) {
|
||||
<R> R transact(Work<R> work) {
|
||||
// If we are already in a transaction, don't wrap in a CommitLoggedWork.
|
||||
return inTransaction() ? work.run() : transactNew(work);
|
||||
}
|
||||
@@ -205,7 +205,7 @@ public class Ofy {
|
||||
* <p>This overload is used for transactions that don't return a value, formerly implemented using
|
||||
* VoidWork.
|
||||
*/
|
||||
public void transact(Runnable work) {
|
||||
void transact(Runnable work) {
|
||||
transact(
|
||||
() -> {
|
||||
work.run();
|
||||
@@ -214,7 +214,7 @@ public class Ofy {
|
||||
}
|
||||
|
||||
/** Pause the current transaction (if any) and complete this one before returning to it. */
|
||||
public <R> R transactNew(Work<R> work) {
|
||||
<R> R transactNew(Work<R> work) {
|
||||
// Wrap the Work in a CommitLoggedWork so that we can give transactions a frozen view of time
|
||||
// and maintain commit logs for them.
|
||||
return transactCommitLoggedWork(new CommitLoggedWork<>(work, getClock()));
|
||||
@@ -226,7 +226,7 @@ public class Ofy {
|
||||
* <p>This overload is used for transactions that don't return a value, formerly implemented using
|
||||
* VoidWork.
|
||||
*/
|
||||
public void transactNew(Runnable work) {
|
||||
void transactNew(Runnable work) {
|
||||
transactNew(
|
||||
() -> {
|
||||
work.run();
|
||||
@@ -246,7 +246,10 @@ public class Ofy {
|
||||
true;
|
||||
attempt++, sleepMillis *= 2) {
|
||||
try {
|
||||
ofy().transactNew(work);
|
||||
ofy().transactNew(() -> {
|
||||
work.run();
|
||||
return null;
|
||||
});
|
||||
return work.getResult();
|
||||
} catch (TransientFailureException
|
||||
| TimestampInversionException
|
||||
@@ -295,10 +298,13 @@ public class Ofy {
|
||||
}
|
||||
|
||||
/** A read-only transaction is useful to get strongly consistent reads at a shared timestamp. */
|
||||
public <R> R transactNewReadOnly(Work<R> work) {
|
||||
<R> R transactNewReadOnly(Work<R> work) {
|
||||
ReadOnlyWork<R> readOnlyWork = new ReadOnlyWork<>(work, getClock());
|
||||
try {
|
||||
ofy().transactNew(readOnlyWork);
|
||||
ofy().transactNew(() -> {
|
||||
readOnlyWork.run();
|
||||
return null;
|
||||
});
|
||||
} catch (TransientFailureException | DatastoreTimeoutException | DatastoreFailureException e) {
|
||||
// These are always retryable for a read-only operation.
|
||||
return transactNewReadOnly(work);
|
||||
@@ -309,7 +315,7 @@ public class Ofy {
|
||||
throw new AssertionError(); // How on earth did we get here?
|
||||
}
|
||||
|
||||
public void transactNewReadOnly(Runnable work) {
|
||||
void transactNewReadOnly(Runnable work) {
|
||||
transactNewReadOnly(
|
||||
() -> {
|
||||
work.run();
|
||||
@@ -318,7 +324,7 @@ public class Ofy {
|
||||
}
|
||||
|
||||
/** Execute some work in a transactionless context. */
|
||||
public <R> R doTransactionless(Work<R> work) {
|
||||
<R> R doTransactionless(Work<R> work) {
|
||||
try {
|
||||
com.googlecode.objectify.ObjectifyService.push(
|
||||
com.googlecode.objectify.ObjectifyService.ofy().transactionless());
|
||||
@@ -347,7 +353,7 @@ public class Ofy {
|
||||
}
|
||||
|
||||
/** Get the time associated with the start of this particular transaction attempt. */
|
||||
public DateTime getTransactionTime() {
|
||||
DateTime getTransactionTime() {
|
||||
assertInTransaction();
|
||||
return TRANSACTION_INFO.get().transactionTime;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.model.ofy;
|
||||
|
||||
import com.googlecode.objectify.Work;
|
||||
import google.registry.model.transaction.TransactionManager.Work;
|
||||
import google.registry.util.Clock;
|
||||
|
||||
/** Wrapper for {@link Work} that disallows mutations and fails the transaction at the end. */
|
||||
@@ -30,8 +30,8 @@ class ReadOnlyWork<R> extends CommitLoggedWork<R> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void vrun() {
|
||||
super.vrun();
|
||||
public void run() {
|
||||
super.run();
|
||||
throw new KillTransactionException();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import static com.google.common.base.Verify.verify;
|
||||
import static com.google.common.base.Verify.verifyNotNull;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.rde.RdeNamingUtils.makePartialName;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.base.VerifyException;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
@@ -70,7 +71,7 @@ public final class RdeRevision extends ImmutableObject {
|
||||
public static void saveRevision(String tld, DateTime date, RdeMode mode, int revision) {
|
||||
checkArgument(revision >= 0, "Negative revision: %s", revision);
|
||||
String triplet = makePartialName(tld, date, mode);
|
||||
ofy().assertInTransaction();
|
||||
tm().assertInTransaction();
|
||||
RdeRevision object = ofy().load().type(RdeRevision.class).id(triplet).now();
|
||||
if (revision == 0) {
|
||||
verify(object == null, "RdeRevision object already created: %s", object);
|
||||
|
||||
@@ -31,12 +31,14 @@ import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.registry.Registries.assertTldsExist;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy;
|
||||
import static google.registry.util.PasswordUtils.SALT_SUPPLIER;
|
||||
import static google.registry.util.PasswordUtils.hashPassword;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
import static google.registry.util.X509Utils.getCertificateHash;
|
||||
import static google.registry.util.X509Utils.loadCertificate;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.Comparator.comparing;
|
||||
import static java.util.function.Predicate.isEqual;
|
||||
|
||||
@@ -72,10 +74,6 @@ import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.registrar.Registrar.BillingAccountEntry.CurrencyMapper;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.util.CidrAddressBlock;
|
||||
import google.registry.util.NonFinalForTesting;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateParsingException;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
@@ -206,7 +204,7 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
||||
private static final Supplier<ImmutableMap<String, Registrar>> CACHE_BY_CLIENT_ID =
|
||||
memoizeWithShortExpiration(
|
||||
() ->
|
||||
ofy()
|
||||
tm()
|
||||
.doTransactionless(
|
||||
() -> Maps.uniqueIndex(loadAll(), Registrar::getClientId)));
|
||||
|
||||
@@ -408,14 +406,8 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
||||
*/
|
||||
boolean contactsRequireSyncing = true;
|
||||
|
||||
@NonFinalForTesting
|
||||
private static Supplier<byte[]> saltSupplier =
|
||||
() -> {
|
||||
// There are 32 bytes in a sha-256 hash, and the salt should generally be the same size.
|
||||
byte[] salt = new byte[32];
|
||||
new SecureRandom().nextBytes(salt);
|
||||
return salt;
|
||||
};
|
||||
/** Whether or not registry lock is allowed for this registrar. */
|
||||
boolean registryLockAllowed = false;
|
||||
|
||||
public String getClientId() {
|
||||
return clientIdentifier;
|
||||
@@ -544,6 +536,10 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
||||
return contactsRequireSyncing;
|
||||
}
|
||||
|
||||
public boolean isRegistryLockAllowed() {
|
||||
return registryLockAllowed;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
@@ -626,16 +622,6 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
||||
.build();
|
||||
}
|
||||
|
||||
private String hashPassword(String password) {
|
||||
try {
|
||||
return base64()
|
||||
.encode(MessageDigest.getInstance("SHA-256").digest((password + salt).getBytes(UTF_8)));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// All implementations of MessageDigest are required to support SHA-256.
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String checkValidPhoneNumber(String phoneNumber) {
|
||||
checkArgument(
|
||||
E164_PATTERN.matcher(phoneNumber).matches(),
|
||||
@@ -644,8 +630,8 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
||||
return phoneNumber;
|
||||
}
|
||||
|
||||
public boolean testPassword(String password) {
|
||||
return hashPassword(password).equals(passwordHash);
|
||||
public boolean verifyPassword(String password) {
|
||||
return hashPassword(password, salt).equals(passwordHash);
|
||||
}
|
||||
|
||||
public String getPhonePasscode() {
|
||||
@@ -880,8 +866,8 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
||||
checkArgument(
|
||||
Range.closed(6, 16).contains(nullToEmpty(password).length()),
|
||||
"Password must be 6-16 characters long.");
|
||||
getInstance().salt = base64().encode(saltSupplier.get());
|
||||
getInstance().passwordHash = getInstance().hashPassword(password);
|
||||
getInstance().salt = base64().encode(SALT_SUPPLIER.get());
|
||||
getInstance().passwordHash = hashPassword(password, getInstance().salt);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -894,6 +880,11 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRegistryLockAllowed(boolean registryLockAllowed) {
|
||||
getInstance().registryLockAllowed = registryLockAllowed;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Build the registrar, nullifying empty fields. */
|
||||
@Override
|
||||
public Registrar build() {
|
||||
|
||||
@@ -14,12 +14,18 @@
|
||||
|
||||
package google.registry.model.registrar;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.Sets.difference;
|
||||
import static com.google.common.io.BaseEncoding.base64;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.registrar.Registrar.checkValidEmail;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy;
|
||||
import static google.registry.util.PasswordUtils.SALT_SUPPLIER;
|
||||
import static google.registry.util.PasswordUtils.hashPassword;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import com.google.common.base.Enums;
|
||||
@@ -134,6 +140,21 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable {
|
||||
*/
|
||||
boolean visibleInDomainWhoisAsAbuse = false;
|
||||
|
||||
/**
|
||||
* Whether or not the contact is allowed to set their registry lock password through the registrar
|
||||
* console. This will be set to false on contact creation and when the user sets a password.
|
||||
*/
|
||||
boolean allowedToSetRegistryLockPassword = false;
|
||||
|
||||
/**
|
||||
* A hashed password that exists iff this contact is registry-lock-enabled. The hash is a base64
|
||||
* encoded SHA256 string.
|
||||
*/
|
||||
String registryLockPasswordHash;
|
||||
|
||||
/** Randomly generated hash salt. */
|
||||
String registryLockPasswordSalt;
|
||||
|
||||
public static ImmutableSet<Type> typesFromCSV(String csv) {
|
||||
return typesFromStrings(Arrays.asList(csv.split(",")));
|
||||
}
|
||||
@@ -154,7 +175,7 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable {
|
||||
*/
|
||||
public static void updateContacts(
|
||||
final Registrar registrar, final Set<RegistrarContact> contacts) {
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
ofy()
|
||||
@@ -212,19 +233,39 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable {
|
||||
return new Builder(clone(this));
|
||||
}
|
||||
|
||||
public boolean isAllowedToSetRegistryLockPassword() {
|
||||
return allowedToSetRegistryLockPassword;
|
||||
}
|
||||
|
||||
public boolean isRegistryLockAllowed() {
|
||||
return !isNullOrEmpty(registryLockPasswordHash) && !isNullOrEmpty(registryLockPasswordSalt);
|
||||
}
|
||||
|
||||
public boolean verifyRegistryLockPassword(String registryLockPassword) {
|
||||
if (isNullOrEmpty(registryLockPassword)
|
||||
|| isNullOrEmpty(registryLockPasswordSalt)
|
||||
|| isNullOrEmpty(registryLockPasswordHash)) {
|
||||
return false;
|
||||
}
|
||||
return hashPassword(registryLockPassword, registryLockPasswordSalt)
|
||||
.equals(registryLockPasswordHash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation that's human friendly.
|
||||
*
|
||||
* <p>The output will look something like this:<pre> {@code
|
||||
* <p>The output will look something like this:
|
||||
*
|
||||
* Some Person
|
||||
* person@example.com
|
||||
* Tel: +1.2125650666
|
||||
* Types: [ADMIN, WHOIS]
|
||||
* Visible in WHOIS as Admin contact: Yes
|
||||
* Visible in WHOIS as Technical contact: No
|
||||
* GAE-UserID: 1234567890
|
||||
* Registrar-Console access: Yes}</pre>
|
||||
* <pre>{@code
|
||||
* Some Person
|
||||
* person@example.com
|
||||
* Tel: +1.2125650666
|
||||
* Types: [ADMIN, WHOIS]
|
||||
* Visible in WHOIS as Admin contact: Yes
|
||||
* Visible in WHOIS as Technical contact: No
|
||||
* GAE-UserID: 1234567890
|
||||
* Registrar-Console access: Yes
|
||||
* }</pre>
|
||||
*/
|
||||
public String toStringMultilinePlainText() {
|
||||
StringBuilder result = new StringBuilder(256);
|
||||
@@ -272,6 +313,7 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable {
|
||||
.put("visibleInWhoisAsAdmin", visibleInWhoisAsAdmin)
|
||||
.put("visibleInWhoisAsTech", visibleInWhoisAsTech)
|
||||
.put("visibleInDomainWhoisAsAbuse", visibleInDomainWhoisAsAbuse)
|
||||
.put("allowedToSetRegistryLockPassword", allowedToSetRegistryLockPassword)
|
||||
.put("gaeUserId", gaeUserId)
|
||||
.build();
|
||||
}
|
||||
@@ -345,5 +387,27 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable {
|
||||
getInstance().gaeUserId = gaeUserId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAllowedToSetRegistryLockPassword(boolean allowedToSetRegistryLockPassword) {
|
||||
if (allowedToSetRegistryLockPassword) {
|
||||
getInstance().registryLockPasswordSalt = null;
|
||||
getInstance().registryLockPasswordHash = null;
|
||||
}
|
||||
getInstance().allowedToSetRegistryLockPassword = allowedToSetRegistryLockPassword;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRegistryLockPassword(String registryLockPassword) {
|
||||
checkArgument(
|
||||
getInstance().allowedToSetRegistryLockPassword,
|
||||
"Not allowed to set registry lock password for this contact");
|
||||
checkArgument(
|
||||
!isNullOrEmpty(registryLockPassword), "Registry lock password was null or empty");
|
||||
getInstance().registryLockPasswordSalt = base64().encode(SALT_SUPPLIER.get());
|
||||
getInstance().registryLockPasswordHash =
|
||||
hashPassword(registryLockPassword, getInstance().registryLockPasswordSalt);
|
||||
getInstance().allowedToSetRegistryLockPassword = false;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import static com.google.common.collect.Maps.filterValues;
|
||||
import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
@@ -52,7 +53,7 @@ public final class Registries {
|
||||
private static Supplier<ImmutableMap<String, TldType>> createFreshCache() {
|
||||
return memoizeWithShortExpiration(
|
||||
() ->
|
||||
ofy()
|
||||
tm()
|
||||
.doTransactionless(
|
||||
() -> {
|
||||
ImmutableMap.Builder<String, TldType> builder =
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.google.common.base.Predicates.not;
|
||||
import static google.registry.config.RegistryConfig.getSingletonCacheRefreshDuration;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
@@ -222,7 +223,7 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
// Enter a transactionless context briefly; we don't want to enroll every TLD in a
|
||||
// transaction that might be wrapping this call.
|
||||
return Optional.ofNullable(
|
||||
ofy()
|
||||
tm()
|
||||
.doTransactionless(
|
||||
() -> ofy()
|
||||
.load()
|
||||
|
||||
@@ -22,6 +22,7 @@ import static google.registry.config.RegistryConfig.getStaticPremiumListMaxCache
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.allocateId;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
@@ -150,7 +151,7 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
|
||||
new CacheLoader<String, PremiumList>() {
|
||||
@Override
|
||||
public PremiumList load(final String name) {
|
||||
return ofy().doTransactionless(() -> loadPremiumList(name));
|
||||
return tm().doTransactionless(() -> loadPremiumList(name));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -174,7 +175,7 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
|
||||
new CacheLoader<Key<PremiumListRevision>, PremiumListRevision>() {
|
||||
@Override
|
||||
public PremiumListRevision load(final Key<PremiumListRevision> revisionKey) {
|
||||
return ofy().doTransactionless(() -> ofy().load().key(revisionKey).now());
|
||||
return tm().doTransactionless(() -> ofy().load().key(revisionKey).now());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -214,7 +215,7 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
|
||||
new CacheLoader<Key<PremiumListEntry>, Optional<PremiumListEntry>>() {
|
||||
@Override
|
||||
public Optional<PremiumListEntry> load(final Key<PremiumListEntry> entryKey) {
|
||||
return ofy()
|
||||
return tm()
|
||||
.doTransactionless(() -> Optional.ofNullable(ofy().load().key(entryKey).now()));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -27,6 +27,7 @@ import static google.registry.model.registry.label.DomainLabelMetrics.PremiumLis
|
||||
import static google.registry.model.registry.label.PremiumList.cachePremiumListEntries;
|
||||
import static google.registry.model.registry.label.PremiumList.cachePremiumListRevisions;
|
||||
import static google.registry.model.registry.label.PremiumList.cachePremiumLists;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
@@ -151,12 +152,12 @@ public final class PremiumListUtils {
|
||||
|
||||
// Save the new child entities in a series of transactions.
|
||||
for (final List<PremiumListEntry> batch : partition(parentedEntries, TRANSACTION_BATCH_SIZE)) {
|
||||
ofy().transactNew(() -> ofy().save().entities(batch));
|
||||
tm().transactNew(() -> ofy().save().entities(batch));
|
||||
}
|
||||
|
||||
// Save the new PremiumList and revision itself.
|
||||
PremiumList updated = ofy().transactNew(() -> {
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
PremiumList updated = tm().transactNew(() -> {
|
||||
DateTime now = tm().getTransactionTime();
|
||||
// Assert that the premium list hasn't been changed since we started this process.
|
||||
PremiumList existing = ofy().load()
|
||||
.type(PremiumList.class)
|
||||
@@ -201,7 +202,7 @@ public final class PremiumListUtils {
|
||||
|
||||
/** Deletes the PremiumList and all of its child entities. */
|
||||
public static void deletePremiumList(final PremiumList premiumList) {
|
||||
ofy().transactNew(() -> ofy().delete().entity(premiumList));
|
||||
tm().transactNew(() -> ofy().delete().entity(premiumList));
|
||||
deleteRevisionAndEntriesOfPremiumList(premiumList);
|
||||
cachePremiumLists.invalidate(premiumList.getName());
|
||||
}
|
||||
@@ -214,9 +215,9 @@ public final class PremiumListUtils {
|
||||
partition(
|
||||
ofy().load().type(PremiumListEntry.class).ancestor(premiumList.revisionKey).keys(),
|
||||
TRANSACTION_BATCH_SIZE)) {
|
||||
ofy().transactNew(() -> ofy().delete().keys(batch));
|
||||
tm().transactNew(() -> ofy().delete().keys(batch));
|
||||
}
|
||||
ofy().transactNew(() -> ofy().delete().key(premiumList.getRevisionKey()));
|
||||
tm().transactNew(() -> ofy().delete().key(premiumList.getRevisionKey()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.model.server;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.isAtOrAfter;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
@@ -176,10 +177,10 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
// access to resources like GCS that can't be transactionally rolled back. Therefore, the lock
|
||||
// must be definitively acquired before it is used, even when called inside another transaction.
|
||||
AcquireResult acquireResult =
|
||||
ofy()
|
||||
tm()
|
||||
.transactNew(
|
||||
() -> {
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
|
||||
// Checking if an unexpired lock still exists - if so, the lock can't be acquired.
|
||||
Lock lock = ofy().load().type(Lock.class).id(lockId).now();
|
||||
@@ -217,7 +218,7 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
/** Release the lock. */
|
||||
public void release() {
|
||||
// Just use the default clock because we aren't actually doing anything that will use the clock.
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
// To release a lock, check that no one else has already obtained it and if not
|
||||
@@ -231,7 +232,7 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
logger.atInfo().log("Deleting lock: %s", lockId);
|
||||
ofy().deleteWithoutBackup().entity(Lock.this);
|
||||
lockMetrics.recordRelease(
|
||||
resourceName, tld, new Duration(acquiredTime, ofy().getTransactionTime()));
|
||||
resourceName, tld, new Duration(acquiredTime, tm().getTransactionTime()));
|
||||
} else {
|
||||
logger.atSevere().log(
|
||||
"The lock we acquired was transferred to someone else before we"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.model.server;
|
||||
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
@@ -54,7 +55,7 @@ public class ServerSecret extends CrossTldSingleton {
|
||||
return secret;
|
||||
}
|
||||
// Slow path - transactionally create a new ServerSecret (once per app setup).
|
||||
return ofy().transact(() -> {
|
||||
return tm().transact(() -> {
|
||||
// Check again for an existing secret within the transaction to avoid races.
|
||||
ServerSecret secret1 = ofy().load().entity(new ServerSecret()).now();
|
||||
if (secret1 == null) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.allocateId;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
|
||||
|
||||
@@ -92,7 +93,7 @@ public class SignedMarkRevocationList extends ImmutableObject {
|
||||
private static final Supplier<SignedMarkRevocationList> CACHE =
|
||||
memoizeWithShortExpiration(
|
||||
() ->
|
||||
ofy()
|
||||
tm()
|
||||
.transactNewReadOnly(
|
||||
() -> {
|
||||
Iterable<SignedMarkRevocationList> shards =
|
||||
@@ -150,7 +151,7 @@ public class SignedMarkRevocationList extends ImmutableObject {
|
||||
|
||||
/** Save this list to Datastore in sharded form. Returns {@code this}. */
|
||||
public SignedMarkRevocationList save() {
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
ofy()
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.google.common.base.Verify.verify;
|
||||
import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
|
||||
import static google.registry.model.ofy.ObjectifyService.allocateId;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
@@ -111,7 +112,7 @@ public class ClaimsListShard extends ImmutableObject {
|
||||
Concurrent.transform(
|
||||
shardKeys,
|
||||
key ->
|
||||
ofy()
|
||||
tm()
|
||||
.transactNewReadOnly(
|
||||
() -> {
|
||||
ClaimsListShard claimsListShard = ofy().load().key(key).now();
|
||||
@@ -188,7 +189,7 @@ public class ClaimsListShard extends ImmutableObject {
|
||||
Concurrent.transform(
|
||||
CollectionUtils.partitionMap(labelsToKeys, shardSize),
|
||||
(final ImmutableMap<String, String> labelsToKeysShard) ->
|
||||
ofy()
|
||||
tm()
|
||||
.transactNew(
|
||||
() -> {
|
||||
ClaimsListShard shard = create(creationTime, labelsToKeysShard);
|
||||
@@ -199,7 +200,7 @@ public class ClaimsListShard extends ImmutableObject {
|
||||
}));
|
||||
|
||||
// Persist the new revision, thus causing the newly created shards to go live.
|
||||
ofy()
|
||||
tm()
|
||||
.transactNew(
|
||||
() -> {
|
||||
verify(
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.model.tmch;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
@@ -48,11 +49,11 @@ public final class TmchCrl extends CrossTldSingleton {
|
||||
* and actually newer than the one currently in Datastore.
|
||||
*/
|
||||
public static void set(final String crl, final String url) {
|
||||
ofy()
|
||||
tm()
|
||||
.transactNew(
|
||||
() -> {
|
||||
TmchCrl tmchCrl = new TmchCrl();
|
||||
tmchCrl.updated = ofy().getTransactionTime();
|
||||
tmchCrl.updated = tm().getTransactionTime();
|
||||
tmchCrl.crl = checkNotNull(crl, "crl");
|
||||
tmchCrl.url = checkNotNull(url, "url");
|
||||
ofy().saveWithoutBackup().entity(tmchCrl);
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.transaction;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* This interface defines the methods to execute database operations with or without a transaction.
|
||||
*/
|
||||
public interface TransactionManager {
|
||||
|
||||
/** This functional interface defines a method to execute a work and return the result. */
|
||||
@FunctionalInterface
|
||||
interface Work<R> {
|
||||
R run();
|
||||
}
|
||||
|
||||
/** Returns {@code true} if the caller is in a transaction.
|
||||
*
|
||||
* <p>Note that this function is kept for backward compatibility. We will review the use case
|
||||
* later when adding the cloud sql implementation.
|
||||
*/
|
||||
boolean inTransaction();
|
||||
|
||||
/** Throws {@link IllegalStateException} if the caller is not in a transaction.
|
||||
*
|
||||
* <p>Note that this function is kept for backward compatibility. We will review the use case
|
||||
* later when adding the cloud sql implementation.
|
||||
*/
|
||||
void assertInTransaction();
|
||||
|
||||
/** Executes the work in a transaction and returns the result. */
|
||||
<T> T transact(Work<T> work);
|
||||
|
||||
/** Executes the work in a transaction. */
|
||||
void transact(Runnable work);
|
||||
|
||||
/** Pauses the current transaction (if any), executes the work in a new transaction
|
||||
* and returns the result.
|
||||
*
|
||||
* <p>Note that this function is kept for backward compatibility. We will review the use case
|
||||
* later when adding the cloud sql implementation.
|
||||
*/
|
||||
<T> T transactNew(Work<T> work);
|
||||
|
||||
/** Pauses the current transaction (if any) and executes the work in a new transaction.
|
||||
*
|
||||
* <p>Note that this function is kept for backward compatibility. We will review the use case
|
||||
* later when adding the cloud sql implementation.
|
||||
*/
|
||||
void transactNew(Runnable work);
|
||||
|
||||
/** Executes the work in a read-only transaction and returns the result.
|
||||
*
|
||||
* <p>Note that this function is kept for backward compatibility. We will review the use case
|
||||
* later when adding the cloud sql implementation.
|
||||
*/
|
||||
<R> R transactNewReadOnly(Work<R> work);
|
||||
|
||||
/** Executes the work in a read-only transaction.
|
||||
*
|
||||
* <p>Note that this function is kept for backward compatibility. We will review the use case
|
||||
* later when adding the cloud sql implementation.
|
||||
*/
|
||||
void transactNewReadOnly(Runnable work);
|
||||
|
||||
/** Executes the work in a transactionless context. */
|
||||
<R> R doTransactionless(Work<R> work);
|
||||
|
||||
/** Returns the time associated with the start of this particular transaction attempt. */
|
||||
DateTime getTransactionTime();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.transaction;
|
||||
|
||||
import google.registry.model.ofy.DatastoreTransactionManager;
|
||||
|
||||
/** Factory class to create {@link TransactionManager} instance. */
|
||||
public class TransactionManagerFactory {
|
||||
|
||||
private static final TransactionManager TM = createTransactionManager();
|
||||
|
||||
private TransactionManagerFactory() {}
|
||||
|
||||
private static TransactionManager createTransactionManager() {
|
||||
// TODO: Conditionally returns the corresponding implementation once we have
|
||||
// CloudSqlTransactionManager
|
||||
return new DatastoreTransactionManager(null);
|
||||
}
|
||||
|
||||
/** Returns {@link TransactionManager} instance. */
|
||||
public static TransactionManager tm() {
|
||||
|
||||
return TM;
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -17,6 +17,7 @@ package google.registry.model.translators;
|
||||
import static com.google.common.base.MoreObjects.firstNonNull;
|
||||
import static google.registry.config.RegistryConfig.getCommitLogDatastoreRetention;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
@@ -62,7 +63,7 @@ public final class CommitLogRevisionsTranslatorFactory
|
||||
@Override
|
||||
ImmutableSortedMap<DateTime, Key<CommitLogManifest>> transformBeforeSave(
|
||||
ImmutableSortedMap<DateTime, Key<CommitLogManifest>> revisions) {
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
DateTime threshold = now.minus(getCommitLogDatastoreRetention());
|
||||
DateTime preThresholdTime = firstNonNull(revisions.floorKey(threshold), START_OF_TIME);
|
||||
return new ImmutableSortedMap.Builder<DateTime, Key<CommitLogManifest>>(Ordering.natural())
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@
|
||||
package google.registry.model.translators;
|
||||
|
||||
import static com.google.common.base.MoreObjects.firstNonNull;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
@@ -46,7 +46,7 @@ public class CreateAutoTimestampTranslatorFactory
|
||||
/** Save a timestamp, setting it to the current time if it did not have a previous value. */
|
||||
@Override
|
||||
public Date saveValue(CreateAutoTimestamp pojoValue) {
|
||||
return firstNonNull(pojoValue.getTimestamp(), ofy().getTransactionTime()).toDate();
|
||||
return firstNonNull(pojoValue.getTimestamp(), tm().getTransactionTime()).toDate();
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.model.translators;
|
||||
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import google.registry.model.UpdateAutoTimestamp;
|
||||
@@ -46,7 +46,7 @@ public class UpdateAutoTimestampTranslatorFactory
|
||||
/** Save a timestamp, setting it to the current time. */
|
||||
@Override
|
||||
public Date saveValue(UpdateAutoTimestamp pojoValue) {
|
||||
return ofy().getTransactionTime().toDate();
|
||||
return tm().getTransactionTime().toDate();
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.persistence;
|
||||
|
||||
import static google.registry.config.RegistryConfig.getHibernateConnectionIsolation;
|
||||
import static google.registry.config.RegistryConfig.getHibernateHikariConnectionTimeout;
|
||||
import static google.registry.config.RegistryConfig.getHibernateHikariIdleTimeout;
|
||||
import static google.registry.config.RegistryConfig.getHibernateHikariMaximumPoolSize;
|
||||
import static google.registry.config.RegistryConfig.getHibernateHikariMinimumIdle;
|
||||
import static google.registry.config.RegistryConfig.getHibernateLogSqlQueries;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Persistence;
|
||||
import org.hibernate.cfg.Environment;
|
||||
|
||||
/** Factory class to provide {@link EntityManagerFactory} instance. */
|
||||
public class EntityManagerFactoryProvider {
|
||||
// This name must be the same as the one defined in persistence.xml.
|
||||
public static final String PERSISTENCE_UNIT_NAME = "nomulus";
|
||||
public static final String HIKARI_CONNECTION_TIMEOUT = "hibernate.hikari.connectionTimeout";
|
||||
public static final String HIKARI_MINIMUM_IDLE = "hibernate.hikari.minimumIdle";
|
||||
public static final String HIKARI_MAXIMUM_POOL_SIZE = "hibernate.hikari.maximumPoolSize";
|
||||
public static final String HIKARI_IDLE_TIMEOUT = "hibernate.hikari.idleTimeout";
|
||||
|
||||
private static ImmutableMap<String, String> getDefaultProperties() {
|
||||
ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
|
||||
|
||||
properties.put(Environment.DRIVER, "org.postgresql.Driver");
|
||||
properties.put(
|
||||
Environment.CONNECTION_PROVIDER,
|
||||
"org.hibernate.hikaricp.internal.HikariCPConnectionProvider");
|
||||
// Whether to automatically validate and export schema DDL to the database when the
|
||||
// SessionFactory is created. Setting it to 'none' to turn off the feature.
|
||||
properties.put(Environment.HBM2DDL_AUTO, "none");
|
||||
|
||||
properties.put(Environment.ISOLATION, getHibernateConnectionIsolation());
|
||||
properties.put(Environment.SHOW_SQL, getHibernateLogSqlQueries());
|
||||
properties.put(HIKARI_CONNECTION_TIMEOUT, getHibernateHikariConnectionTimeout());
|
||||
properties.put(HIKARI_MINIMUM_IDLE, getHibernateHikariMinimumIdle());
|
||||
properties.put(HIKARI_MAXIMUM_POOL_SIZE, getHibernateHikariMaximumPoolSize());
|
||||
properties.put(HIKARI_IDLE_TIMEOUT, getHibernateHikariIdleTimeout());
|
||||
return properties.build();
|
||||
}
|
||||
|
||||
/** Constructs the {@link EntityManagerFactory} instance. */
|
||||
public static EntityManagerFactory create(String jdbcUrl, String username, String password) {
|
||||
ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
|
||||
properties.putAll(getDefaultProperties());
|
||||
properties.put(Environment.URL, jdbcUrl);
|
||||
properties.put(Environment.USER, username);
|
||||
properties.put(Environment.PASS, password);
|
||||
return Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME, properties.build());
|
||||
}
|
||||
}
|
||||
@@ -47,13 +47,6 @@ public class RdapHelpAction extends RdapActionBase {
|
||||
}
|
||||
|
||||
private Notice createHelpNotice() {
|
||||
String linkValue = rdapJsonFormatter.makeRdapServletRelativeUrl("help");
|
||||
Link.Builder linkBuilder =
|
||||
Link.builder()
|
||||
.setValue(linkValue)
|
||||
.setRel("alternate")
|
||||
.setHref(RDAP_HELP_LINK)
|
||||
.setType("text/html");
|
||||
return Notice.builder()
|
||||
.setTitle("RDAP Help")
|
||||
.setDescription(
|
||||
@@ -68,13 +61,19 @@ public class RdapHelpAction extends RdapActionBase {
|
||||
"entities?fn=XXXX",
|
||||
"entities?handle=XXXX",
|
||||
"help/XXXX")
|
||||
.addLink(linkBuilder.build())
|
||||
.addLink(
|
||||
Link.builder().setHref(RDAP_HELP_LINK).setRel("alternate").setType("text/html").build())
|
||||
.addLink(
|
||||
Link.builder()
|
||||
.setHref(rdapJsonFormatter.makeRdapServletRelativeUrl("help"))
|
||||
.setRel("self")
|
||||
.setType("application/rdap+json")
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpResponse getJsonObjectForResource(
|
||||
String pathSearchString, boolean isHeadRequest) {
|
||||
public HelpResponse getJsonObjectForResource(String pathSearchString, boolean isHeadRequest) {
|
||||
if (pathSearchString.isEmpty() || pathSearchString.equals("/")) {
|
||||
return HelpResponse.create(Optional.of(createHelpNotice()));
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ public class RdapIcannStandardInformation {
|
||||
+ " https://icann.org/epp")
|
||||
.addLink(
|
||||
Link.builder()
|
||||
.setValue("https://icann.org/epp")
|
||||
.setRel("alternate")
|
||||
.setHref("https://icann.org/epp")
|
||||
.setType("text/html")
|
||||
@@ -59,7 +58,6 @@ public class RdapIcannStandardInformation {
|
||||
"URL of the ICANN RDDS Inaccuracy Complaint Form: https://www.icann.org/wicf")
|
||||
.addLink(
|
||||
Link.builder()
|
||||
.setValue("https://www.icann.org/wicf")
|
||||
.setRel("alternate")
|
||||
.setHref("https://www.icann.org/wicf")
|
||||
.setType("text/html")
|
||||
@@ -145,8 +143,6 @@ public class RdapIcannStandardInformation {
|
||||
.setType(Remark.Type.OBJECT_REDACTED_AUTHORIZATION)
|
||||
.addLink(
|
||||
Link.builder()
|
||||
.setValue(
|
||||
"https://github.com/google/nomulus/blob/master/docs/rdap.md#authentication")
|
||||
.setRel("alternate")
|
||||
.setHref(
|
||||
"https://github.com/google/nomulus/blob/master/docs/rdap.md#authentication")
|
||||
|
||||
@@ -228,20 +228,25 @@ public class RdapJsonFormatter {
|
||||
/** Creates the TOS notice that is added to every reply. */
|
||||
Notice createTosNotice() {
|
||||
String linkValue = makeRdapServletRelativeUrl("help", RdapHelpAction.TOS_PATH);
|
||||
Link.Builder linkBuilder = Link.builder()
|
||||
.setValue(linkValue);
|
||||
if (rdapTosStaticUrl == null) {
|
||||
linkBuilder.setRel("self").setHref(linkValue).setType("application/rdap+json");
|
||||
} else {
|
||||
Link selfLink =
|
||||
Link.builder().setRel("self").setHref(linkValue).setType("application/rdap+json").build();
|
||||
|
||||
Notice.Builder noticeBuilder =
|
||||
Notice.builder()
|
||||
.setTitle("RDAP Terms of Service")
|
||||
.setDescription(rdapTos)
|
||||
.addLink(selfLink);
|
||||
if (rdapTosStaticUrl != null) {
|
||||
URI htmlBaseURI = URI.create(fullServletPath);
|
||||
URI htmlUri = htmlBaseURI.resolve(rdapTosStaticUrl);
|
||||
linkBuilder.setRel("alternate").setHref(htmlUri.toString()).setType("text/html");
|
||||
noticeBuilder.addLink(
|
||||
Link.builder()
|
||||
.setRel("alternate")
|
||||
.setHref(htmlUri.toString())
|
||||
.setType("text/html")
|
||||
.build());
|
||||
}
|
||||
return Notice.builder()
|
||||
.setTitle("RDAP Terms of Service")
|
||||
.setDescription(rdapTos)
|
||||
.addLink(linkBuilder.build())
|
||||
.build();
|
||||
return noticeBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,7 +319,6 @@ public class RdapJsonFormatter {
|
||||
.add(
|
||||
Link.builder()
|
||||
.setHref(href)
|
||||
.setValue(href)
|
||||
.setRel("related")
|
||||
.setType("application/rdap+json")
|
||||
.build());
|
||||
@@ -1078,7 +1082,6 @@ public class RdapJsonFormatter {
|
||||
private Link makeSelfLink(String type, String name) {
|
||||
String url = makeRdapServletRelativeUrl(type, name);
|
||||
return Link.builder()
|
||||
.setValue(url)
|
||||
.setRel("self")
|
||||
.setHref(url)
|
||||
.setType("application/rdap+json")
|
||||
|
||||
@@ -17,6 +17,7 @@ package google.registry.rdap;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.api.client.http.GenericUrl;
|
||||
@@ -92,27 +93,23 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
@Inject
|
||||
UpdateRegistrarRdapBaseUrlsAction() {}
|
||||
|
||||
private String loginAndGetId(HttpRequestFactory requestFactory, String tld) {
|
||||
try {
|
||||
logger.atInfo().log("Logging in to MoSAPI");
|
||||
HttpRequest request =
|
||||
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGIN_URL, tld)));
|
||||
request.getHeaders().setBasicAuthentication(String.format("%s_ry", tld), password);
|
||||
HttpResponse response = request.execute();
|
||||
private String loginAndGetId(HttpRequestFactory requestFactory, String tld) throws IOException {
|
||||
logger.atInfo().log("Logging in to MoSAPI");
|
||||
HttpRequest request =
|
||||
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGIN_URL, tld)));
|
||||
request.getHeaders().setBasicAuthentication(String.format("%s_ry", tld), password);
|
||||
HttpResponse response = request.execute();
|
||||
|
||||
Optional<HttpCookie> idCookie =
|
||||
HttpCookie.parse(response.getHeaders().getFirstHeaderStringValue("Set-Cookie")).stream()
|
||||
.filter(cookie -> cookie.getName().equals(COOKIE_ID))
|
||||
.findAny();
|
||||
checkState(
|
||||
idCookie.isPresent(),
|
||||
"Didn't get the ID cookie from the login response. Code: %s, headers: %s",
|
||||
response.getStatusCode(),
|
||||
response.getHeaders());
|
||||
return idCookie.get().getValue();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Error logging in to MoSAPI server: " + e.getMessage(), e);
|
||||
}
|
||||
Optional<HttpCookie> idCookie =
|
||||
HttpCookie.parse(response.getHeaders().getFirstHeaderStringValue("Set-Cookie")).stream()
|
||||
.filter(cookie -> cookie.getName().equals(COOKIE_ID))
|
||||
.findAny();
|
||||
checkState(
|
||||
idCookie.isPresent(),
|
||||
"Didn't get the ID cookie from the login response. Code: %s, headers: %s",
|
||||
response.getStatusCode(),
|
||||
response.getHeaders());
|
||||
return idCookie.get().getValue();
|
||||
}
|
||||
|
||||
private void logout(HttpRequestFactory requestFactory, String id, String tld) {
|
||||
@@ -128,13 +125,13 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaIdWithTld(String tld) {
|
||||
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
|
||||
String id = loginAndGetId(requestFactory, tld);
|
||||
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaIdWithTld(
|
||||
String tld, String id, HttpRequestFactory requestFactory) {
|
||||
String content;
|
||||
try {
|
||||
HttpRequest request =
|
||||
requestFactory.buildGetRequest(new GenericUrl(String.format(LIST_URL, tld)));
|
||||
request.getHeaders().setAcceptEncoding("identity");
|
||||
request.getHeaders().setCookie(String.format("%s=%s", COOKIE_ID, id));
|
||||
HttpResponse response = request.execute();
|
||||
|
||||
@@ -173,11 +170,22 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
checkArgument(!tlds.isEmpty(), "There must exist at least one REAL TLD.");
|
||||
Throwable finalThrowable = null;
|
||||
for (String tld : tlds) {
|
||||
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
|
||||
String id;
|
||||
try {
|
||||
return getRdapBaseUrlsPerIanaIdWithTld(tld);
|
||||
id = loginAndGetId(requestFactory, tld);
|
||||
} catch (Throwable e) {
|
||||
// Login failures are bad but not unexpected for certain TLDs. We shouldn't store those
|
||||
// but rather should only store useful Throwables.
|
||||
logger.atWarning().log("Error logging in to MoSAPI server: " + e.getMessage());
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
return getRdapBaseUrlsPerIanaIdWithTld(tld, id, requestFactory);
|
||||
} catch (Throwable throwable) {
|
||||
logger.atWarning().log(String
|
||||
.format("Error retrieving RDAP urls with TLD %s: %s", tld, throwable.getMessage()));
|
||||
logger.atWarning().log(
|
||||
String.format(
|
||||
"Error retrieving RDAP urls with TLD %s: %s", tld, throwable.getMessage()));
|
||||
finalThrowable = throwable;
|
||||
}
|
||||
}
|
||||
@@ -190,7 +198,7 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
ImmutableSetMultimap<String, String> ianaToBaseUrls = getRdapBaseUrlsPerIanaId();
|
||||
|
||||
for (Key<Registrar> registrarKey : ofy().load().type(Registrar.class).keys()) {
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
Registrar registrar = ofy().load().key(registrarKey).now();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.rde;
|
||||
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.model.common.Cursor;
|
||||
@@ -98,7 +99,7 @@ class EscrowTaskRunner {
|
||||
task.runWithLock(nextRequiredRun);
|
||||
DateTime nextRun = nextRequiredRun.plus(interval);
|
||||
logger.atInfo().log("Rolling cursor forward to %s.", nextRun);
|
||||
ofy().transact(() -> ofy().save().entity(Cursor.create(cursorType, nextRun, registry)));
|
||||
tm().transact(() -> ofy().save().entity(Cursor.create(cursorType, nextRun, registry)));
|
||||
return null;
|
||||
};
|
||||
String lockName = String.format("EscrowTaskRunner %s", task.getClass().getSimpleName());
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.rde;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
|
||||
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
@@ -106,7 +107,7 @@ public final class PendingDepositChecker {
|
||||
final Registry registry,
|
||||
final CursorType cursorType,
|
||||
final DateTime initialValue) {
|
||||
return ofy()
|
||||
return tm()
|
||||
.transact(
|
||||
() -> {
|
||||
Cursor cursor = ofy().load().key(Cursor.createKey(cursorType, registry)).now();
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static google.registry.model.common.Cursor.getCursorTimeOrStartOfTime;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.appengine.tools.cloudstorage.GcsFilename;
|
||||
@@ -202,7 +203,7 @@ public final class RdeStagingReducer extends Reducer<PendingDeposit, DepositFrag
|
||||
logger.atInfo().log("Manual operation; not advancing cursor or enqueuing upload task");
|
||||
return;
|
||||
}
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
Registry registry = Registry.get(tld);
|
||||
|
||||
@@ -22,6 +22,7 @@ import static google.registry.model.common.Cursor.CursorType.RDE_UPLOAD_SFTP;
|
||||
import static google.registry.model.common.Cursor.getCursorTimeOrStartOfTime;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.rde.RdeMode.FULL;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
|
||||
import static java.util.Arrays.asList;
|
||||
@@ -169,11 +170,11 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
|
||||
() -> upload(xmlFilename, xmlLength, watermark, name), JSchException.class);
|
||||
logger.atInfo().log(
|
||||
"Updating RDE cursor '%s' for TLD '%s' following successful upload.", RDE_UPLOAD_SFTP, tld);
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
Cursor updatedSftpCursor =
|
||||
Cursor.create(RDE_UPLOAD_SFTP, ofy().getTransactionTime(), Registry.get(tld));
|
||||
Cursor.create(RDE_UPLOAD_SFTP, tm().getTransactionTime(), Registry.get(tld));
|
||||
ofy().save().entity(updatedSftpCursor);
|
||||
});
|
||||
response.setContentType(PLAIN_TEXT_UTF_8);
|
||||
|
||||
@@ -22,6 +22,7 @@ import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import com.google.appengine.tools.cloudstorage.GcsFilename;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.io.ByteStreams;
|
||||
@@ -38,6 +39,7 @@ import google.registry.util.Retrier;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Copy all registrar detail reports in a given bucket's subdirectory from GCS to Drive. */
|
||||
@@ -95,6 +97,8 @@ public final class CopyDetailReportsAction implements Runnable {
|
||||
response.setPayload(String.format("Failure, encountered %s", e.getMessage()));
|
||||
return;
|
||||
}
|
||||
ImmutableMap.Builder<String, Throwable> copyErrorsBuilder =
|
||||
new ImmutableMap.Builder<String, Throwable>();
|
||||
for (String detailReportName : detailReportObjectNames) {
|
||||
// The standard report format is "invoice_details_yyyy-MM_registrarId_tld.csv
|
||||
// TODO(larryruili): Determine a safer way of enforcing this.
|
||||
@@ -117,7 +121,7 @@ public final class CopyDetailReportsAction implements Runnable {
|
||||
try (InputStream input =
|
||||
gcsUtils.openInputStream(
|
||||
new GcsFilename(billingBucket, invoiceDirectoryPrefix + detailReportName))) {
|
||||
driveConnection.createFile(
|
||||
driveConnection.createOrUpdateFile(
|
||||
detailReportName,
|
||||
MediaType.CSV_UTF_8,
|
||||
driveFolderId,
|
||||
@@ -129,15 +133,31 @@ public final class CopyDetailReportsAction implements Runnable {
|
||||
},
|
||||
IOException.class);
|
||||
} catch (Throwable e) {
|
||||
emailUtils.sendAlertEmail(
|
||||
String alertMessage =
|
||||
String.format(
|
||||
"Warning: CopyDetailReportsAction failed.\nEncountered: %s on file: %s",
|
||||
getRootCause(e).getMessage(), detailReportName));
|
||||
throw e;
|
||||
"Warning: CopyDetailReportsAction failed for registrar %s.\n"
|
||||
+ "Encountered: %s on file: %s",
|
||||
registrarId, getRootCause(e).getMessage(), detailReportName);
|
||||
copyErrorsBuilder.put(registrarId, e);
|
||||
logger.atSevere().withCause(e).log(alertMessage);
|
||||
}
|
||||
}
|
||||
response.setStatus(SC_OK);
|
||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||
response.setPayload("Copied detail reports.");
|
||||
StringBuilder payload = new StringBuilder().append("Copied detail reports.\n");
|
||||
ImmutableMap<String, Throwable> copyErrors = copyErrorsBuilder.build();
|
||||
if (!copyErrors.isEmpty()) {
|
||||
payload.append("The following errors were encountered:\n");
|
||||
payload.append(
|
||||
copyErrors.entrySet().stream()
|
||||
.map(
|
||||
entrySet ->
|
||||
String.format(
|
||||
"Registrar: %s\nError: %s\n",
|
||||
entrySet.getKey(), entrySet.getValue().getMessage()))
|
||||
.collect(Collectors.joining()));
|
||||
}
|
||||
response.setPayload(payload.toString());
|
||||
emailUtils.sendAlertEmail(payload.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,22 +59,19 @@ public class Spec11EmailUtils {
|
||||
private final SendEmailService emailService;
|
||||
private final InternetAddress outgoingEmailAddress;
|
||||
private final InternetAddress alertRecipientAddress;
|
||||
private final InternetAddress spec11ReplyToAddress;
|
||||
private final ImmutableList<String> spec11WebResources;
|
||||
private final String registryName;
|
||||
|
||||
@Inject
|
||||
Spec11EmailUtils(
|
||||
SendEmailService emailService,
|
||||
@Config("gSuiteOutgoingEmailAddress") InternetAddress outgoingEmailAddress,
|
||||
@Config("alertRecipientEmailAddress") InternetAddress alertRecipientAddress,
|
||||
@Config("spec11ReplyToEmailAddress") InternetAddress spec11ReplyToAddress,
|
||||
@Config("spec11OutgoingEmailAddress") InternetAddress spec11OutgoingEmailAddress,
|
||||
@Config("spec11WebResources") ImmutableList<String> spec11WebResources,
|
||||
@Config("registryName") String registryName) {
|
||||
this.emailService = emailService;
|
||||
this.outgoingEmailAddress = outgoingEmailAddress;
|
||||
this.outgoingEmailAddress = spec11OutgoingEmailAddress;
|
||||
this.alertRecipientAddress = alertRecipientAddress;
|
||||
this.spec11ReplyToAddress = spec11ReplyToAddress;
|
||||
this.spec11WebResources = spec11WebResources;
|
||||
this.registryName = registryName;
|
||||
}
|
||||
@@ -149,7 +146,7 @@ public class Spec11EmailUtils {
|
||||
.setContentType(MediaType.HTML_UTF_8)
|
||||
.setFrom(outgoingEmailAddress)
|
||||
.addRecipient(getEmailAddressForRegistrar(registrarThreatMatches.clientId()))
|
||||
.setBcc(spec11ReplyToAddress)
|
||||
.setBcc(outgoingEmailAddress)
|
||||
.build());
|
||||
}
|
||||
|
||||
@@ -172,7 +169,7 @@ public class Spec11EmailUtils {
|
||||
ImmutableMap.of(
|
||||
"date", date.toString(),
|
||||
"registry", registryName,
|
||||
"replyToEmail", spec11ReplyToAddress.getAddress(),
|
||||
"replyToEmail", outgoingEmailAddress.getAddress(),
|
||||
"threats", threatMatchMap,
|
||||
"resources", spec11WebResources);
|
||||
renderer.setData(data);
|
||||
|
||||
@@ -16,12 +16,17 @@ package google.registry.request;
|
||||
|
||||
import static com.google.monitoring.metrics.EventMetric.DEFAULT_FITTER;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.monitoring.metrics.EventMetric;
|
||||
import com.google.monitoring.metrics.LabelDescriptor;
|
||||
import com.google.monitoring.metrics.MetricRegistryImpl;
|
||||
import google.registry.request.auth.AuthLevel;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
class RequestMetrics {
|
||||
@@ -50,7 +55,7 @@ class RequestMetrics {
|
||||
Duration duration, String path, Action.Method method, AuthLevel authLevel, boolean success) {
|
||||
requestDurationMetric.record(
|
||||
duration.getMillis(),
|
||||
path,
|
||||
truncatePath(path),
|
||||
String.valueOf(method),
|
||||
String.valueOf(authLevel),
|
||||
String.valueOf(success));
|
||||
@@ -58,4 +63,15 @@ class RequestMetrics {
|
||||
"Action called for path=%s, method=%s, authLevel=%s, success=%s. Took: %.3fs",
|
||||
path, method, authLevel, success, duration.getMillis() / 1000d);
|
||||
}
|
||||
|
||||
private static String truncatePath(String path) {
|
||||
// We want to bucket RDAP requests by type to use less metric space,
|
||||
// e.g. "/rdap/domains" rather than "/rdap/domains/foo.tld"
|
||||
if (path.startsWith("/rdap")) {
|
||||
List<String> splitPath = Splitter.on("/").omitEmptyStrings().splitToList(path);
|
||||
return Streams.stream(Iterables.limit(splitPath, 2))
|
||||
.collect(Collectors.joining("/", "/", "/"));
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.schema.tmch;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* A list of TMCH claims labels and their associated claims keys.
|
||||
*
|
||||
* <p>Note that the primary key of this entity is {@link #revisionId}, which is auto-generated by
|
||||
* the database. So, if a retry of insertion happens after the previous attempt unexpectedly
|
||||
* succeeds, we will end up with having two exact same claims list with only different {@link
|
||||
* #revisionId}. However, this is not an actual problem because we only use the claims list with
|
||||
* highest {@link #revisionId}.
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "ClaimsList")
|
||||
public class ClaimsList {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "revision_id")
|
||||
private Long revisionId;
|
||||
|
||||
@Column(name = "creation_timestamp", nullable = false)
|
||||
private ZonedDateTime creationTimestamp;
|
||||
|
||||
@ElementCollection
|
||||
@CollectionTable(
|
||||
name = "ClaimsEntry",
|
||||
joinColumns = @JoinColumn(name = "revision_id", referencedColumnName = "revision_id"))
|
||||
@MapKeyColumn(name = "domain_label", nullable = false)
|
||||
@Column(name = "claim_key", nullable = false)
|
||||
private Map<String, String> labelsToKeys;
|
||||
|
||||
private ClaimsList(ZonedDateTime creationTimestamp, Map<String, String> labelsToKeys) {
|
||||
this.creationTimestamp = creationTimestamp;
|
||||
this.labelsToKeys = labelsToKeys;
|
||||
}
|
||||
|
||||
// Hibernate requires this default constructor.
|
||||
private ClaimsList() {}
|
||||
|
||||
/** Constructs a {@link ClaimsList} object. */
|
||||
public static ClaimsList create(
|
||||
ZonedDateTime creationTimestamp, Map<String, String> labelsToKeys) {
|
||||
return new ClaimsList(creationTimestamp, labelsToKeys);
|
||||
}
|
||||
|
||||
/** Returns the revision id of this claims list, or throws exception if it is null. */
|
||||
public Long getRevisionId() {
|
||||
checkState(
|
||||
revisionId != null, "revisionId is null because it is not persisted in the database");
|
||||
return revisionId;
|
||||
}
|
||||
|
||||
/** Returns the creation time of this claims list. */
|
||||
public ZonedDateTime getCreationTimestamp() {
|
||||
return creationTimestamp;
|
||||
}
|
||||
|
||||
/** Returns an {@link Map} mapping domain label to its lookup key. */
|
||||
public Map<String, String> getLabelsToKeys() {
|
||||
return labelsToKeys;
|
||||
}
|
||||
|
||||
/** Returns the claim key for a given domain if there is one, empty otherwise. */
|
||||
public Optional<String> getClaimKey(String label) {
|
||||
return Optional.ofNullable(labelsToKeys.get(label));
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,10 @@ public class DriveConnection {
|
||||
/**
|
||||
* Creates a file with the given parent.
|
||||
*
|
||||
* <p>If a file with the same path already exists, a duplicate is created. If overwriting the
|
||||
* existing file is the desired behavior, use {@link #createOrUpdateFile(String, MediaType,
|
||||
* String, byte[])} instead.
|
||||
*
|
||||
* @returns the file id.
|
||||
*/
|
||||
public String createFile(String title, MediaType mimeType, String parentFolderId, byte[] bytes)
|
||||
|
||||
@@ -16,7 +16,7 @@ package google.registry.tmch;
|
||||
|
||||
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.appengine.api.taskqueue.TaskOptions;
|
||||
import com.google.appengine.api.taskqueue.TaskOptions.Method;
|
||||
@@ -47,7 +47,7 @@ public final class LordnTaskUtils {
|
||||
* Enqueues a task in the LORDN queue representing a line of CSV for LORDN export.
|
||||
*/
|
||||
public static void enqueueDomainBaseTask(DomainBase domain) {
|
||||
ofy().assertInTransaction();
|
||||
tm().assertInTransaction();
|
||||
// This method needs to use ofy transactionTime as the DomainBase's creationTime because
|
||||
// CreationTime isn't yet populated when this method is called during the resource flow.
|
||||
String tld = domain.getTld();
|
||||
@@ -55,12 +55,12 @@ public final class LordnTaskUtils {
|
||||
getQueue(QUEUE_SUNRISE).add(TaskOptions.Builder
|
||||
.withTag(tld)
|
||||
.method(Method.PULL)
|
||||
.payload(getCsvLineForSunriseDomain(domain, ofy().getTransactionTime())));
|
||||
.payload(getCsvLineForSunriseDomain(domain, tm().getTransactionTime())));
|
||||
} else {
|
||||
getQueue(QUEUE_CLAIMS).add(TaskOptions.Builder
|
||||
.withTag(tld)
|
||||
.method(Method.PULL)
|
||||
.payload(getCsvLineForClaimsDomain(domain, ofy().getTransactionTime())));
|
||||
.payload(getCsvLineForClaimsDomain(domain, tm().getTransactionTime())));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.flows.poll.PollFlowUtils.getPollMessagesQuery;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.poll.PollMessageExternalKeyConverter.makePollMessageExternalId;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
@@ -85,7 +86,7 @@ final class AckPollMessagesCommand implements CommandWithRemoteApi {
|
||||
public void run() {
|
||||
QueryKeys<PollMessage> query = getPollMessagesQuery(clientId, clock.nowUtc()).keys();
|
||||
for (List<Key<PollMessage>> keys : Iterables.partition(query, BATCH_SIZE)) {
|
||||
ofy()
|
||||
tm()
|
||||
.transact(
|
||||
() -> {
|
||||
// Load poll messages and filter to just those of interest.
|
||||
|
||||
@@ -52,7 +52,7 @@ final class CreateAnchorTenantCommand extends MutatingEppToolCommand {
|
||||
|
||||
@Parameter(
|
||||
names = {"--contact"},
|
||||
description = "Contact ID for the request. This will be used for registrant, admin contact,"
|
||||
description = "Contact ID for the request. This will be used for registrant, admin contact, "
|
||||
+ "and tech contact.",
|
||||
required = true)
|
||||
private String contact;
|
||||
|
||||
@@ -234,6 +234,13 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
|
||||
arity = 1)
|
||||
private Boolean contactsRequireSyncing;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
names = "--registry_lock_allowed",
|
||||
description = "Whether this registrar is allowed to use registry lock",
|
||||
arity = 1)
|
||||
private Boolean registryLockAllowed;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
names = "--drive_folder_id",
|
||||
@@ -393,6 +400,7 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
|
||||
}
|
||||
Optional.ofNullable(blockPremiumNames).ifPresent(builder::setBlockPremiumNames);
|
||||
Optional.ofNullable(contactsRequireSyncing).ifPresent(builder::setContactsRequireSyncing);
|
||||
Optional.ofNullable(registryLockAllowed).ifPresent(builder::setRegistryLockAllowed);
|
||||
Optional.ofNullable(phonePasscode).ifPresent(builder::setPhonePasscode);
|
||||
Optional.ofNullable(icannReferralEmail).ifPresent(builder::setIcannReferralEmail);
|
||||
Optional.ofNullable(whoisServer).ifPresent(builder::setWhoisServer);
|
||||
|
||||
@@ -19,7 +19,6 @@ import static google.registry.util.CollectionUtils.findDuplicates;
|
||||
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -255,7 +254,7 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
|
||||
tld,
|
||||
canonicalizeDomainName(tld));
|
||||
checkArgument(
|
||||
!CharMatcher.javaDigit().matches(tld.charAt(0)),
|
||||
!Character.isDigit(tld.charAt(0)),
|
||||
"TLDs cannot begin with a number");
|
||||
Registry oldRegistry = getOldRegistry(tld);
|
||||
// TODO(b/26901539): Add a flag to set the pricing engine once we have more than one option.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user