1
0
mirror of https://github.com/google/nomulus synced 2026-06-09 16:33:02 +00:00

Compare commits

..

20 Commits

Author SHA1 Message Date
Michael Muller 8a045aedd0 Disambiguate naming of VKey.create() overloads (#513)
* Disambiguate naming of VKey.create() overloads

It was discovered in the course of trying to convert the larger codebase
to VKey.create() calls that method overloading isn't a very effective
discriminator in cases where "Object" is one of the distinguishing
argument types:-)

Convert the two specialized create() methods to createOfy() and
createSql() so that (at least in the former case) we'll get a
compile-time error if we aim to create a VKey for an Ofy key from an
object of the incorrect type.
2020-03-12 16:13:12 -04:00
gbrodman 560bec1e83 Add a RelockDomainAction for future auto-relocks (#485)
* Add a RelockAction and reference to relocks in RegistryLocks

* Respond to CR

- refactor the request param exception logging a bit
- don't log an error if the domain was already locked, just skip

* Save a relock for all locks (if possible)

* derp

* Long -> long + remove unnecessary transact

* semantic merge conflict woo

* fix another semantic merge conflict
2020-03-12 16:02:27 -04:00
Lai Jiang 3e7ea75b6f Use cs.opensource.google for code search (#512)
* Use cs.opensource.google for code search

* Change logo size

* Make texts in the table center-aligned
2020-03-12 14:06:04 -04:00
Weimin Yu 6ed7e00b00 Update SqlIntegrationTestSuite (#510)
* Update SqlIntegrationTestSuite

Edited Javadoc to emphasize that suite members should be DAO tests.

Removed functional tests from the suite. They do not benefit much
from running against different schemas when the entities they use
are already covered by DAO tests.

Added DomainBaseSqlTest to the suite, which tests DomainBase.
2020-03-11 14:11:53 -04:00
Michael Muller 6e1231233e Create a nom_build wrapper script (#508)
* Create a nom_build wrapper script

nom_build is a wrapper around ./gradlew.  It's purpose is to help us
deal with properties.  The main problem that it is trying to solve is
that when properties are specified using -P, we don't get an error if
the property we specify isn't correct.  As a result, a user or a build
agent can launch a build with unintended parameters.

nom_build consolidates all of the properties that we define into a
python script where the properties are translated to flags (actual
gradlew flags are also proxied).  It also generates the property file
and warns the user if the current properties file is out of sync with
the script and includes documentation on each of the properties.
2020-03-10 16:32:14 -04:00
Shicong Huang 3098048fdb Enable Cloud SQL when Datastore is enabled for unit test (#502)
* Enable Cloud SQL when Datastore is enabled for unit test

* Add explanation for why add a ETA field in GenerateEscrowDepositCommand

* Fix line length

* Ignore membershipt test but bring back test suite

* Fix tiny issue
2020-03-10 12:26:25 -04:00
gbrodman f2846fc914 Gray out the password field for admins (#506)
* Gray out the password field for admins

We don't check it for admins since it's not necessary, so ignore it

* Remove the field entirely
2020-03-10 11:30:20 -04:00
gbrodman 499237ac57 Listen to the user hitting enter in the lock/unlock modal input fields (#505)
* Listen to the user hitting enter in the lock/unlock modal input fields

Listen to both, just in case one or the other is disabled

* Don't require that the element exist
2020-03-10 11:22:57 -04:00
Weimin Yu 6bd50421bc Fix broken builds when Maven Central is used (#509)
* Fix broken builds when Maven Central is used

Gradle 6.2.1 apparently introduces a behavior change wrt boolean
expression: empty string used to eval to false, but now evals to
true.

Pre Gradle 6.2.1, root project's Gradle properties apparently were
not set to buildSrc. Now they are passed on to buildSrc -- mavenUrl
in buildSrc changes from null to "".

Both changes break the project when mavenUrl and/or pluginsUrl are
not set on command line.

Also added junit.jupiter-api as testCompile dependencies to projects.
This is a directly used dependency, whose absence causes a Lint
warning.
2020-03-10 11:21:03 -04:00
sarahcaseybot dbdd2b4491 Add Lock dual write (#496)
* Add Lock dual write

* wrap calls in DB transaction
2020-03-09 11:13:46 -04:00
gbrodman f83f8f92a3 Show locks in the case where you have an expired unlock request (#507)
* Show locks in the case where you have an expired unlock request
2020-03-06 22:00:42 -05:00
gbrodman 28d3af0ee9 Change the wording on the lock-not-enabled page (#504)
* Change the wording on the lock-not-enabled page

* fix the screenshot
2020-03-06 16:15:11 -05:00
Lai Jiang 08a6a333ad Upgrade to Gradle 6.2.1 (#501) 2020-03-05 18:47:25 -05:00
Shicong Huang adafab60c4 Add common CRUD operations to TransactionManager (#487)
* Add BasicDao

* Refactor RegistrarDao to extend BasicDao

* Introduce VKey and rewrite BasicDao

* Move CRUD methods to TransactionManager

* Refactor code to simplify the way to get id from entity and sqlKey

* Assert in transaction

* Fix broken test

* Change methods name
2020-03-05 14:03:03 -05:00
gbrodman fec806ef8b Handle both ways the UI passes in booleans (#500)
* Handle both ways the UI passes in booleans

* fix the JS test

* Quote the value
2020-03-02 12:49:09 -05:00
gbrodman e8ff4081a9 Show pending locks in the locked-domains table (#495)
* Show pending locks in the locked-domains table

* asdf

* fix the tests

* including pending unlocks in the table

* fix the screenshot test
2020-02-28 13:57:33 -05:00
Ben McIlwain 9283cd263f Always validate domain name on allocation token (#498)
* Always validate domain name on allocation token

This is in response to a client-reported error, where they accidentally sent the
wrong domain name on a domain create that included an allocation token. What
should have happened (and that now happens as of this commit) is an error being
thrown that the allocation token does not match the domain name being created.
What happened instead was that, since the incorrectly submitted domain name was
not reserved, the create succeeded (as it would for all creates of unreserved
domains in GA) and the allocation token was redeemed, which is not what you'd
expect.

* Fix tests to reflect changed check behavior
2020-02-27 16:48:37 -05:00
gbrodman 429bc8e6d2 Set focus correctly in lock modal (#499) 2020-02-27 13:20:10 -05:00
gbrodman fc0a9160b2 Create methods to administratively (un)lock domains (#494)
* Refactor DomainLockUtils methods to take a time rather than a clock

* Add administratively (un)lock methods

* Responses to CR

- Javadoc changes
- Method renames
- Variable renames

* Refactor lock methods to use JPA transaction time

* Remove clock, use Datastore transaction time

* Properly use Datastore transaction time, batched

* Continue to throw exceptions on invalid domains

* DAO writes should be in a transaction

* Assume in-transaction for all RLDao methods

* clean up test

* Fix more tests

* add comment
2020-02-26 17:11:16 -05:00
Ben McIlwain 3cd0b4d5e5 Upgrade Gradle license report plugin to latest version (1.13) (#492)
* Upgrade Gradle license report plugin to latest version (1.13)
2020-02-25 15:04:56 -05:00
306 changed files with 4345 additions and 2573 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
# Nomulus
| Internal Build | FOSS Build | LGTM | License | Code Search |
|----------------|------------|------|---------|-------------|
|[![Build Status for Google Registry internal build](https://storage.googleapis.com/domain-registry-kokoro/internal/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/internal/index.html)|[![Build Status for the open source build](https://storage.googleapis.com/domain-registry-kokoro/foss/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/foss/index.html)|[![Total alerts](https://img.shields.io/lgtm/alerts/g/google/nomulus.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/google/nomulus/alerts/)|[![License for this repo](https://img.shields.io/github/license/google/nomulus.svg)](https://github.com/google/nomulus/blob/master/LICENSE)|[![Link to Source Graph](https://sourcegraph.com/.assets/img/sourcegraph-light-head-logo.svg)](https://sourcegraph.com/github.com/google/nomulus)|
|:--------------:|:----------:|:----:|:-------:|:-----------:|
|[![Build Status for Google Registry internal build](https://storage.googleapis.com/domain-registry-kokoro/internal/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/internal/index.html)|[![Build Status for the open source build](https://storage.googleapis.com/domain-registry-kokoro/foss/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/foss/index.html)|[![Total alerts](https://img.shields.io/lgtm/alerts/g/google/nomulus.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/google/nomulus/alerts/)|[![License for this repo](https://img.shields.io/github/license/google/nomulus.svg)](https://github.com/google/nomulus/blob/master/LICENSE)|[![Link to Code Search](https://www.gstatic.com/devopsconsole/images/oss/favicons/oss-32x32.png)](https://cs.opensource.google/nomulus/nomulus)|
![Nomulus logo](./nomulus-logo.png)
+3 -3
View File
@@ -169,10 +169,10 @@ allprojects {
if (project.name == 'services') return
repositories {
if (rootProject.mavenUrl) {
if (!mavenUrl.isEmpty()) {
maven {
println "Java dependencies: Using repo $pluginsUrl..."
url rootProject.mavenUrl
println "Java dependencies: Using repo ${mavenUrl}..."
url mavenUrl
}
} else {
println "Java dependencies: Using Maven Central..."
+6 -3
View File
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import static com.google.common.base.Strings.isNullOrEmpty;
buildscript {
if (project.enableDependencyLocking.toBoolean()) {
// Lock buildscript dependencies.
@@ -40,13 +42,13 @@ if (rootProject.enableDependencyLocking.toBoolean()) {
}
repositories {
if (project.ext.properties.mavenUrl == null) {
println "Plugin dependencies: Using Maven central..."
if (isNullOrEmpty(project.ext.properties.mavenUrl)) {
println "Java dependencies: Using Maven central..."
mavenCentral()
google()
} else {
maven {
println "Plugin dependencies: Using repo ${mavenUrl}..."
println "Java dependencies: Using repo ${mavenUrl}..."
url mavenUrl
}
}
@@ -82,6 +84,7 @@ dependencies {
testCompile deps['com.google.truth:truth']
testCompile deps['com.google.truth.extensions:truth-java8-extension']
testCompile deps['junit:junit']
testCompile deps['org.junit.jupiter:junit-jupiter-api']
testCompile deps['org.junit.jupiter:junit-jupiter-engine']
testCompile deps['org.junit.vintage:junit-vintage-engine']
testCompile deps['org.mockito:mockito-core']
@@ -5,14 +5,14 @@ antlr:antlr:2.7.7
com.google.code.findbugs:jsr305:3.0.2
com.google.errorprone:error_prone_annotations:2.3.2
com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.0-jre
com.google.guava:guava:28.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.j2objc:j2objc-annotations:1.3
com.puppycrawl.tools:checkstyle:8.24
com.puppycrawl.tools:checkstyle:8.27
commons-beanutils:commons-beanutils:1.9.4
commons-collections:commons-collections:3.2.2
info.picocli:picocli:4.0.3
net.sf.saxon:Saxon-HE:9.9.1-4
info.picocli:picocli:4.1.1
net.sf.saxon:Saxon-HE:9.9.1-5
org.antlr:antlr4-runtime:4.7.2
org.checkerframework:checker-qual:2.8.1
org.codehaus.mojo:animal-sniffer-annotations:1.17
org.codehaus.mojo:animal-sniffer-annotations:1.18
+1
View File
@@ -62,6 +62,7 @@ dependencies {
testingCompile deps['io.github.java-diff-utils:java-diff-utils']
testCompile deps['junit:junit']
testCompile deps['org.junit.jupiter:junit-jupiter-api']
testCompile deps['org.junit.jupiter:junit-jupiter-engine']
testCompile deps['org.junit.vintage:junit-vintage-engine']
}
@@ -5,14 +5,14 @@ antlr:antlr:2.7.7
com.google.code.findbugs:jsr305:3.0.2
com.google.errorprone:error_prone_annotations:2.3.2
com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.0-jre
com.google.guava:guava:28.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.j2objc:j2objc-annotations:1.3
com.puppycrawl.tools:checkstyle:8.24
com.puppycrawl.tools:checkstyle:8.27
commons-beanutils:commons-beanutils:1.9.4
commons-collections:commons-collections:3.2.2
info.picocli:picocli:4.0.3
net.sf.saxon:Saxon-HE:9.9.1-4
info.picocli:picocli:4.1.1
net.sf.saxon:Saxon-HE:9.9.1-5
org.antlr:antlr4-runtime:4.7.2
org.checkerframework:checker-qual:2.8.1
org.codehaus.mojo:animal-sniffer-annotations:1.17
org.codehaus.mojo:animal-sniffer-annotations:1.18
+327
View File
@@ -0,0 +1,327 @@
# Copyright 2020 The Nomulus Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Script to generate dr-build and the properties file.
"""
import argparse
import attr
import io
import os
import subprocess
import sys
from typing import List, Union
@attr.s(auto_attribs=True)
class Property:
name : str = ''
desc : str = ''
default : str = ''
constraints : type = str
def validate(self, value: str):
"""Verify that "value" is appropriate for the property."""
if type is bool:
if value not in ('true', 'false'):
raise ValidationError('value of {self.name} must be "true" or '
'"false".')
@attr.s(auto_attribs=True)
class GradleFlag:
flags : Union[str, List[str]]
desc : str
has_arg : bool = False
PROPERTIES_HEADER = """\
# This file defines properties used by the gradle build. It must be kept in
# sync with config/nom_build.py.
#
# To regenerate, run config/nom_build.py --generate-gradle-properties
#
# To view property descriptions (which are command line flags for
# nom_build), run config/nom_build.py --help.
#
# DO NOT EDIT THIS FILE BY HAND
org.gradle.jvmargs=-Xmx1024m
"""
# Define all of our special gradle properties here.
PROPERTIES = [
Property('mavenUrl',
'URL to use for the main maven repository (defaults to maven '
'central). This can be http(s) or a "gcs" repo.'),
Property('pluginsUrl',
'URL to use for the gradle plugins repository (defaults to maven '
'central, see also mavenUrl'),
Property('uploaderDestination',
'Location to upload test reports to. Normally this should be a '
'GCS url (see also uploaderCredentialsFile)'),
Property('uploaderCredentialsFile',
'json credentials file to use to upload test reports.'),
Property('uploaderMultithreadedUpload',
'Whether to enable multithread upload.'),
Property('verboseTestOutput',
'If true, show all test output in near-realtime.',
'false',
bool),
Property('flowDocsFile',
'Output filename for the flowDocsTool command.'),
Property('enableDependencyLocking',
'Enables dependency locking.',
'true',
bool),
Property('enableCrossReferencing',
'generate metadata during java compile (used for kythe source '
'reference generation).',
'false'),
Property('testFilter',
'Comma separated list of test patterns, if specified run only '
'these.'),
Property('environment', 'GAE Environment for deployment and staging.'),
# Cloud SQL properties
Property('dbServer',
'A registry environment name (e.g., "alpha") or a host[:port] '
'string'),
Property('dbName',
'Database name to use in connection.',
'postgres'),
Property('dbUser', 'Database user name for use in connection'),
Property('dbPassword', 'Database password for use in connection'),
Property('publish_repo',
'Maven repository that hosts the Cloud SQL schema jar and the '
'registry server test jars. Such jars are needed for '
'server/schema integration tests. Please refer to <a '
'href="./integration/README.md">integration project</a> for more '
'information.'),
Property('schema_version',
'The nomulus version tag of the schema for use in a database'
'integration test.'),
Property('nomulus_version',
'The version of nomulus to test against in a database '
'integration test.'),
]
GRADLE_FLAGS = [
GradleFlag(['-a', '--no-rebuild'],
'Do not rebuild project dependencies.'),
GradleFlag(['-b', '--build-file'], 'Specify the build file.', True),
GradleFlag(['--build-cache'],
'Enables the Gradle build cache. Gradle will try to reuse '
'outputs from previous builds.'),
GradleFlag(['-c', '--settings-file'], 'Specify the settings file.', True),
GradleFlag(['--configure-on-demand'],
'Configure necessary projects only. Gradle will attempt to '
'reduce configuration time for large multi-project builds. '
'[incubating]'),
GradleFlag(['--console'],
'Specifies which type of console output to generate. Values '
"are 'plain', 'auto' (default), 'rich' or 'verbose'.",
True),
GradleFlag(['--continue'], 'Continue task execution after a task failure.'),
GradleFlag(['-D', '--system-prop'],
'Set system property of the JVM (e.g. -Dmyprop=myvalue).',
True),
GradleFlag(['-d', '--debug'],
'Log in debug mode (includes normal stacktrace).'),
GradleFlag(['--daemon'],
'Uses the Gradle Daemon to run the build. Starts the Daemon '
'if not running.'),
GradleFlag(['--foreground'], 'Starts the Gradle Daemon in the foreground.'),
GradleFlag(['-g', '--gradle-user-home'],
'Specifies the gradle user home directory.',
True),
GradleFlag(['-I', '--init-script'], 'Specify an initialization script.',
True),
GradleFlag(['-i', '--info'], 'Set log level to info.'),
GradleFlag(['--include-build'],
'Include the specified build in the composite.',
True),
GradleFlag(['-m', '--dry-run'],
'Run the builds with all task actions disabled.'),
GradleFlag(['--max-workers'],
'Configure the number of concurrent workers Gradle is '
'allowed to use.',
True),
GradleFlag(['--no-build-cache'], 'Disables the Gradle build cache.'),
GradleFlag(['--no-configure-on-demand'],
'Disables the use of configuration on demand. [incubating]'),
GradleFlag(['--no-daemon'],
'Do not use the Gradle daemon to run the build. Useful '
'occasionally if you have configured Gradle to always run '
'with the daemon by default.'),
GradleFlag(['--no-parallel'],
'Disables parallel execution to build projects.'),
GradleFlag(['--no-scan'],
'Disables the creation of a build scan. For more information '
'about build scans, please visit '
'https://gradle.com/build-scans.'),
GradleFlag(['--offline'],
'Execute the build without accessing network resources.'),
GradleFlag(['-P', '--project-prop'],
'Set project property for the build script (e.g. '
'-Pmyprop=myvalue).',
True),
GradleFlag(['-p', '--project-dir'],
'Specifies the start directory for Gradle. Defaults to '
'current directory.'),
GradleFlag(['--parallel'],
'Build projects in parallel. Gradle will attempt to '
'determine the optimal number of executor threads to use.'),
GradleFlag(['--priority'],
'Specifies the scheduling priority for the Gradle daemon and '
"all processes launched by it. Values are 'normal' (default) "
"or 'low' [incubating]",
True),
GradleFlag(['--profile'],
'Profile build execution time and generates a report in the '
'<build_dir>/reports/profile directory.'),
GradleFlag(['--project-cache-dir'],
'Specify the project-specific cache directory. Defaults to '
'.gradle in the root project directory.',
True),
GradleFlag(['-q', '--quiet'], 'Log errors only.'),
GradleFlag(['--refresh-dependencies'], 'Refresh the state of dependencies.'),
GradleFlag(['--rerun-tasks'], 'Ignore previously cached task results.'),
GradleFlag(['-S', '--full-stacktrace'],
'Print out the full (very verbose) stacktrace for all '
'exceptions.'),
GradleFlag(['-s', '--stacktrace'],
'Print out the stacktrace for all exceptions.'),
GradleFlag(['--scan'],
'Creates a build scan. Gradle will emit a warning if the '
'build scan plugin has not been applied. '
'(https://gradle.com/build-scans)'),
GradleFlag(['--status'],
'Shows status of running and recently stopped Gradle '
'Daemon(s).'),
GradleFlag(['--stop'], 'Stops the Gradle Daemon if it is running.'),
GradleFlag(['-t', '--continuous'],
'Enables continuous build. Gradle does not exit and will '
're-execute tasks when task file inputs change.'),
GradleFlag(['--update-locks'],
'Perform a partial update of the dependency lock, letting '
'passed in module notations change version. [incubating]'),
GradleFlag(['-v', '--version'], 'Print version info.'),
GradleFlag(['-w', '--warn'], 'Set log level to warn.'),
GradleFlag(['--warning-mode'],
'Specifies which mode of warnings to generate. Values are '
"'all', 'fail', 'summary'(default) or 'none'",
True),
GradleFlag(['--write-locks'],
'Persists dependency resolution for locked configurations, '
'ignoring existing locking information if it exists '
'[incubating]'),
GradleFlag(['-x', '--exclude-task'],
'Specify a task to be excluded from execution.',
True),
]
def generate_gradle_properties() -> str:
"""Returns the expected contents of gradle.properties."""
out = io.StringIO()
out.write(PROPERTIES_HEADER)
for prop in PROPERTIES:
out.write(f'{prop.name}={prop.default}\n')
return out.getvalue()
def get_root() -> str:
"""Returns the root of the nomulus build tree."""
cur_dir = os.getcwd()
if not os.path.exists(os.path.join(cur_dir, '.git')) or \
not os.path.exists(os.path.join(cur_dir, 'core')) or \
not os.path.exists(os.path.join(cur_dir, 'gradle.properties')):
raise Exception('You must run this script from the root directory')
return cur_dir
def main(args):
parser = argparse.ArgumentParser('nom_build')
for prop in PROPERTIES:
parser.add_argument('--' + prop.name, default=prop.default,
help=prop.desc)
# Add Gradle flags. We set 'dest' to the first flag to get a name that is
# predictable for getattr (even though it will have a leading '-' and thus
# we can't use normal python attribute syntax to get it).
for flag in GRADLE_FLAGS:
if flag.has_arg:
parser.add_argument(*flag.flags, dest=flag.flags[0],
help=flag.desc)
else:
parser.add_argument(*flag.flags, dest=flag.flags[0],
help=flag.desc,
action='store_true')
# Add a flag to regenerate the gradle properties file.
parser.add_argument('--generate-gradle-properties',
help='Regenerate the gradle.properties file. This '
'file must be regenerated when changes are made to '
'config/nom_build.py, and should not be updated by '
'hand.',
action='store_true')
# Consume the remaining non-flag arguments.
parser.add_argument('non_flag_args', nargs='*')
# Parse command line arguments. Note that this exits the program and
# prints usage if either of the help options (-h, --help) are specified.
args = parser.parse_args(args)
gradle_properties = generate_gradle_properties()
root = get_root()
# If we're regenerating properties, do so and exit.
if args.generate_gradle_properties:
with open(f'{root}/gradle.properties', 'w') as dst:
dst.write(gradle_properties)
return
# Verify that the gradle properties file is what we expect it to be.
with open(f'{root}/gradle.properties') as src:
if src.read() != gradle_properties:
print('\033[33mWARNING:\033[0m Gradle properties out of sync '
'with nom_build. Run with --generate-gradle-properties '
'to regenerate.')
# Add properties to the gradle argument list.
gradle_command = [f'{root}/gradlew']
for prop in PROPERTIES:
arg_val = getattr(args, prop.name)
if arg_val != prop.default:
prop.validate(arg_val)
gradle_command.extend(['-P', f'{prop.name}={arg_val}'])
# Add Gradle flags to the gradle argument list.
for flag in GRADLE_FLAGS:
arg_val = getattr(args, flag.flags[0])
if arg_val:
gradle_command.append(flag.flags[-1])
if flag.has_arg:
gradle_command.append(arg_val)
# Add the non-flag args (we exclude the first, which is the command name
# itself) and run.
gradle_command.extend(args.non_flag_args[1:])
subprocess.call(gradle_command)
if __name__ == '__main__':
main(sys.argv)
+109
View File
@@ -0,0 +1,109 @@
# Copyright 2020 The Nomulus Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import io
import os
import unittest
from unittest import mock
import nom_build
import subprocess
FAKE_PROPERTIES = [
nom_build.Property('foo', 'help text'),
nom_build.Property('bar', 'more text', 'true', bool),
]
FAKE_PROP_CONTENTS = nom_build.PROPERTIES_HEADER + 'foo=\nbar=true\n'
PROPERTIES_FILENAME = '/tmp/rootdir/gradle.properties'
GRADLEW = '/tmp/rootdir/gradlew'
class FileFake(io.StringIO):
"""File fake that writes file contents to the dictionary on close."""
def __init__(self, contents_dict, filename):
self.dict = contents_dict
self.filename = filename
super(FileFake, self).__init__()
def close(self):
self.dict[self.filename] = self.getvalue()
super(FileFake, self).close()
class MyTest(unittest.TestCase):
def open_fake(self, filename, action='r'):
if action == 'r':
return io.StringIO(self.file_contents.get(filename, ''))
elif action == 'w':
result = self.file_contents[filename] = (
FileFake(self.file_contents, filename))
return result
else:
raise Exception(f'Unexpected action {action}')
def print_fake(self, data):
self.printed.append(data)
def setUp(self):
self.addCleanup(mock.patch.stopall)
self.exists_mock = mock.patch.object(os.path, 'exists').start()
self.getcwd_mock = mock.patch.object(os, 'getcwd').start()
self.getcwd_mock.return_value = '/tmp/rootdir'
self.open_mock = (
mock.patch.object(nom_build, 'open', self.open_fake).start())
self.print_mock = (
mock.patch.object(nom_build, 'print', self.print_fake).start())
self.call_mock = mock.patch.object(subprocess, 'call').start()
self.file_contents = {
# Prefil with the actual file contents.
PROPERTIES_FILENAME: nom_build.generate_gradle_properties()
}
self.printed = []
@mock.patch.object(nom_build, 'PROPERTIES', FAKE_PROPERTIES)
def test_property_generation(self):
self.assertEqual(nom_build.generate_gradle_properties(),
FAKE_PROP_CONTENTS)
@mock.patch.object(nom_build, 'PROPERTIES', FAKE_PROPERTIES)
def test_property_file_write(self):
nom_build.main(['nom_build', '--generate-gradle-properties'])
self.assertEqual(self.file_contents[PROPERTIES_FILENAME],
FAKE_PROP_CONTENTS)
def test_property_file_incorrect(self):
self.file_contents[PROPERTIES_FILENAME] = 'bad contents'
nom_build.main(['nom_build'])
self.assertIn('', self.printed[0])
def test_no_args(self):
nom_build.main(['nom_build'])
self.assertEqual(self.printed, [])
self.call_mock.assert_called_with([GRADLEW])
def test_property_calls(self):
nom_build.main(['nom_build', '--testFilter=foo'])
self.call_mock.assert_called_with([GRADLEW, '-P', 'testFilter=foo'])
def test_gradle_flags(self):
nom_build.main(['nom_build', '-d', '-b', 'foo'])
self.call_mock.assert_called_with([GRADLEW, '--build-file', 'foo',
'--debug'])
unittest.main()
Binary file not shown.
+3 -1
View File
@@ -300,6 +300,7 @@ dependencies {
testCompile deps['org.hamcrest:hamcrest-library']
compile deps['org.hibernate:hibernate-hikaricp']
testCompile deps['junit:junit']
testCompile deps['org.junit.jupiter:junit-jupiter-api']
testCompile deps['org.junit.jupiter:junit-jupiter-engine']
testCompile deps['org.junit.vintage:junit-vintage-engine']
testCompile deps['org.mockito:mockito-core']
@@ -869,7 +870,8 @@ test {
// Don't run any tests from this task, all testing gets done in the
// FilteringTest tasks.
exclude "**"
}.dependsOn(fragileTest, outcastTest, standardTest, registryToolIntegrationTest)
// TODO(weiminyu): Remove dependency on sqlIntegrationTest
}.dependsOn(fragileTest, outcastTest, standardTest, registryToolIntegrationTest, sqlIntegrationTest)
createUberJar('nomulus', 'nomulus', 'google.registry.tools.RegistryTool')
@@ -5,14 +5,14 @@ antlr:antlr:2.7.7
com.google.code.findbugs:jsr305:3.0.2
com.google.errorprone:error_prone_annotations:2.3.2
com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.0-jre
com.google.guava:guava:28.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.j2objc:j2objc-annotations:1.3
com.puppycrawl.tools:checkstyle:8.24
com.puppycrawl.tools:checkstyle:8.27
commons-beanutils:commons-beanutils:1.9.4
commons-collections:commons-collections:3.2.2
info.picocli:picocli:4.0.3
net.sf.saxon:Saxon-HE:9.9.1-4
info.picocli:picocli:4.1.1
net.sf.saxon:Saxon-HE:9.9.1-5
org.antlr:antlr4-runtime:4.7.2
org.checkerframework:checker-qual:2.8.1
org.codehaus.mojo:animal-sniffer-annotations:1.17
org.codehaus.mojo:animal-sniffer-annotations:1.18
+15 -16
View File
@@ -1,21 +1,20 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.0.23
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -85,22 +84,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -125,7 +124,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -147,10 +146,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -184,8 +183,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.10.0
@@ -1,21 +1,20 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.0.23
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -84,22 +83,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -124,7 +123,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
io.grpc:grpc-netty:1.17.1
@@ -145,10 +144,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -181,8 +180,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.10.0
+15 -16
View File
@@ -1,14 +1,13 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.0.23
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.github.jnr:jffi:1.2.17
@@ -19,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -96,22 +95,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -136,7 +135,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -158,10 +157,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -195,8 +194,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.10.0
@@ -1,14 +1,13 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.0.23
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.github.jnr:jffi:1.2.17
@@ -19,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -96,22 +95,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -136,7 +135,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -158,10 +157,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -194,8 +193,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.10.0
@@ -1,21 +1,20 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.0.23
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -85,22 +84,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -125,7 +124,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -147,10 +146,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -184,8 +183,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.10.0
@@ -1,21 +1,20 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.0.23
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -84,22 +83,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -124,7 +123,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
io.grpc:grpc-netty:1.17.1
@@ -145,10 +144,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -182,8 +181,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.10.0
@@ -1,21 +1,20 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.0.23
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -85,22 +84,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -125,7 +124,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -147,10 +146,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -184,8 +183,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.10.0
@@ -1,21 +1,20 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.0.23
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -85,22 +84,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -125,7 +124,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -147,10 +146,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -184,8 +183,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.10.0
+15 -16
View File
@@ -1,21 +1,20 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.0.23
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -85,22 +84,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -125,7 +124,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -147,10 +146,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -184,8 +183,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.10.0
@@ -1,14 +1,13 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.0.23
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.github.jnr:jffi:1.2.17
@@ -19,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -96,22 +95,22 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -136,7 +135,7 @@ io.dropwizard.metrics:metrics-core:3.1.2
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -158,10 +157,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -194,8 +193,8 @@ org.apache.beam:beam-vendor-grpc-1_21_0:0.1
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
org.apache.commons:commons-compress:1.19
org.apache.commons:commons-lang3:3.5
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.bouncycastle:bcpg-jdk15on:1.61
org.bouncycastle:bcprov-jdk15on:1.61
org.checkerframework:checker-qual:2.10.0
@@ -1,21 +1,20 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.33
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -87,11 +86,11 @@ com.google.guava:guava-testlib:28.2-jre
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
@@ -99,11 +98,11 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.7
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -134,7 +133,7 @@ io.github.classgraph:classgraph:4.8.52
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -156,10 +155,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -199,8 +198,8 @@ org.apache.commons:commons-lang3:3.8.1
org.apache.commons:commons-text:1.6
org.apache.ftpserver:ftplet-api:1.0.6
org.apache.ftpserver:ftpserver-core:1.0.6
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.mina:mina-core:2.0.4
org.apache.sshd:sshd-core:2.0.0
org.apache.sshd:sshd-scp:2.0.0
@@ -1,21 +1,20 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.33
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -86,11 +85,11 @@ com.google.guava:guava-testlib:28.2-jre
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
@@ -98,11 +97,11 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.7
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -133,7 +132,7 @@ io.github.classgraph:classgraph:4.8.52
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
io.grpc:grpc-netty:1.17.1
@@ -154,10 +153,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -197,8 +196,8 @@ org.apache.commons:commons-lang3:3.8.1
org.apache.commons:commons-text:1.6
org.apache.ftpserver:ftplet-api:1.0.6
org.apache.ftpserver:ftpserver-core:1.0.6
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.mina:mina-core:2.0.4
org.apache.sshd:sshd-core:2.0.0
org.apache.sshd:sshd-scp:2.0.0
@@ -1,14 +1,13 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.33
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.github.jnr:jffi:1.2.17
@@ -19,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -98,11 +97,11 @@ com.google.guava:guava-testlib:28.2-jre
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
@@ -110,11 +109,11 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.7
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -146,7 +145,7 @@ io.github.java-diff-utils:java-diff-utils:4.0
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -168,10 +167,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -211,8 +210,8 @@ org.apache.commons:commons-lang3:3.8.1
org.apache.commons:commons-text:1.6
org.apache.ftpserver:ftplet-api:1.0.6
org.apache.ftpserver:ftpserver-core:1.0.6
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.mina:mina-core:2.0.4
org.apache.sshd:sshd-core:2.0.0
org.apache.sshd:sshd-scp:2.0.0
@@ -1,14 +1,13 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
androidx.annotation:annotation:1.1.0
antlr:antlr:2.7.7
aopalliance:aopalliance:1.0
args4j:args4j:2.33
cglib:cglib-nodep:2.2
com.beust:jcommander:1.60
com.fasterxml.jackson.core:jackson-annotations:2.9.10
com.fasterxml.jackson.core:jackson-core:2.10.2
com.fasterxml.jackson.core:jackson-core:2.9.10
com.fasterxml.jackson.core:jackson-databind:2.9.10
com.fasterxml:classmate:1.3.4
com.github.jnr:jffi:1.2.17
@@ -19,11 +18,11 @@ com.github.jnr:jnr-ffi:2.1.9
com.github.jnr:jnr-posix:3.0.47
com.github.jnr:jnr-unixsocket:0.21
com.github.jnr:jnr-x86asm:1.0.2
com.google.api-client:google-api-client-appengine:1.30.8
com.google.api-client:google-api-client-appengine:1.29.0
com.google.api-client:google-api-client-jackson2:1.27.0
com.google.api-client:google-api-client-java6:1.27.0
com.google.api-client:google-api-client-servlet:1.30.8
com.google.api-client:google-api-client:1.30.8
com.google.api-client:google-api-client-servlet:1.29.0
com.google.api-client:google-api-client:1.29.2
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.44.0
com.google.api.grpc:grpc-google-cloud-bigtable-admin-v2:0.38.0
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
@@ -98,11 +97,11 @@ com.google.guava:guava-testlib:28.2-jre
com.google.guava:guava:28.2-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.gwt:gwt-user:2.8.2
com.google.http-client:google-http-client-appengine:1.34.1
com.google.http-client:google-http-client-jackson2:1.34.1
com.google.http-client:google-http-client-appengine:1.29.2
com.google.http-client:google-http-client-jackson2:1.30.1
com.google.http-client:google-http-client-jackson:1.20.0
com.google.http-client:google-http-client-protobuf:1.20.0
com.google.http-client:google-http-client:1.34.1
com.google.http-client:google-http-client:1.30.1
com.google.inject.extensions:guice-multibindings:4.1.0
com.google.inject:guice:4.1.0
com.google.j2objc:j2objc-annotations:1.3
@@ -110,11 +109,11 @@ com.google.jsinterop:jsinterop-annotations:1.0.2
com.google.monitoring-client:contrib:1.0.7
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client-appengine:1.30.5
com.google.oauth-client:google-oauth-client-appengine:1.29.0
com.google.oauth-client:google-oauth-client-java6:1.28.0
com.google.oauth-client:google-oauth-client-jetty:1.28.0
com.google.oauth-client:google-oauth-client-servlet:1.30.5
com.google.oauth-client:google-oauth-client:1.30.5
com.google.oauth-client:google-oauth-client-servlet:1.29.0
com.google.oauth-client:google-oauth-client:1.29.2
com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-5
com.google.protobuf:protobuf-java-util:3.6.1
com.google.protobuf:protobuf-java:3.6.1
@@ -146,7 +145,7 @@ io.github.java-diff-utils:java-diff-utils:4.0
io.grpc:grpc-all:1.17.1
io.grpc:grpc-alts:1.17.1
io.grpc:grpc-auth:1.17.1
io.grpc:grpc-context:1.22.1
io.grpc:grpc-context:1.19.0
io.grpc:grpc-core:1.17.1
io.grpc:grpc-grpclb:1.17.1
io.grpc:grpc-netty-shaded:1.17.1
@@ -168,10 +167,10 @@ io.netty:netty-handler:4.1.30.Final
io.netty:netty-resolver:4.1.30.Final
io.netty:netty-tcnative-boringssl-static:2.0.17.Final
io.netty:netty-transport:4.1.30.Final
io.opencensus:opencensus-api:0.24.0
io.opencensus:opencensus-api:0.21.0
io.opencensus:opencensus-contrib-grpc-metrics:0.17.0
io.opencensus:opencensus-contrib-grpc-util:0.17.0
io.opencensus:opencensus-contrib-http-util:0.24.0
io.opencensus:opencensus-contrib-http-util:0.21.0
it.unimi.dsi:fastutil:6.5.16
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
@@ -211,8 +210,8 @@ org.apache.commons:commons-lang3:3.8.1
org.apache.commons:commons-text:1.6
org.apache.ftpserver:ftplet-api:1.0.6
org.apache.ftpserver:ftpserver-core:1.0.6
org.apache.httpcomponents:httpclient:4.5.11
org.apache.httpcomponents:httpcore:4.4.13
org.apache.httpcomponents:httpclient:4.5.8
org.apache.httpcomponents:httpcore:4.4.11
org.apache.mina:mina-core:2.0.4
org.apache.sshd:sshd-core:2.0.0
org.apache.sshd:sshd-scp:2.0.0
@@ -21,6 +21,7 @@ import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_HOST_RENAME;
import static google.registry.request.RequestParameters.extractLongParameter;
import static google.registry.request.RequestParameters.extractOptionalBooleanParameter;
import static google.registry.request.RequestParameters.extractOptionalIntParameter;
import static google.registry.request.RequestParameters.extractOptionalParameter;
@@ -40,9 +41,7 @@ import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import org.joda.time.DateTime;
/**
* Dagger module for injecting common settings for batch actions.
*/
/** Dagger module for injecting common settings for batch actions. */
@Module
public class BatchModule {
@@ -94,6 +93,12 @@ public class BatchModule {
return extractSetOfDatetimeParameters(req, PARAM_RESAVE_TIMES);
}
@Provides
@Parameter("oldUnlockRevisionId")
static long provideOldUnlockRevisionId(HttpServletRequest req) {
return extractLongParameter(req, "oldUnlockRevisionId");
}
@Provides
@Named(QUEUE_ASYNC_ACTIONS)
static Queue provideAsyncActionsPushQueue() {
@@ -0,0 +1,167 @@
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.batch;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.request.Action.Method.POST;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.model.domain.DomainBase;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.registry.RegistryLockDao;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.schema.domain.RegistryLock;
import google.registry.tools.DomainLockUtils;
import google.registry.util.DateTimeUtils;
import javax.inject.Inject;
/**
* Task that relocks a previously-Registry-Locked domain after some predetermined period of time.
*/
@Action(
service = Action.Service.BACKEND,
path = RelockDomainAction.PATH,
method = POST,
automaticallyPrintOk = true,
auth = Auth.AUTH_INTERNAL_OR_ADMIN)
public class RelockDomainAction implements Runnable {
public static final String PATH = "/_dr/task/relockDomain";
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final long oldUnlockRevisionId;
private final DomainLockUtils domainLockUtils;
private final Response response;
@Inject
public RelockDomainAction(
@Parameter("oldUnlockRevisionId") long oldUnlockRevisionId,
DomainLockUtils domainLockUtils,
Response response) {
this.oldUnlockRevisionId = oldUnlockRevisionId;
this.domainLockUtils = domainLockUtils;
this.response = response;
}
@Override
public void run() {
jpaTm().transact(this::relockDomain);
}
private void relockDomain() {
RegistryLock oldLock;
try {
oldLock =
RegistryLockDao.getByRevisionId(oldUnlockRevisionId)
.orElseThrow(
() ->
new IllegalArgumentException(
String.format("Unknown revision ID %d", oldUnlockRevisionId)));
DomainBase domain =
ofy()
.load()
.type(DomainBase.class)
.id(oldLock.getRepoId())
.now()
.cloneProjectedAtTime(jpaTm().getTransactionTime());
if (domain.getStatusValues().containsAll(REGISTRY_LOCK_STATUSES)
|| oldLock.getRelock() != null) {
// The domain was manually locked, so we shouldn't worry about relocking
String message =
String.format(
"Domain %s is already manually relocked, skipping automated relock.",
domain.getFullyQualifiedDomainName());
logger.atInfo().log(message);
// SC_NO_CONTENT (204) skips retry -- see the comment below
response.setStatus(SC_NO_CONTENT);
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
response.setPayload(message);
return;
}
verifyDomainAndLockState(oldLock, domain);
} catch (Throwable t) {
/* If there's a bad verification code or the domain is in a bad state, we won't want to retry.
* AppEngine will retry on non-2xx error codes, so we return SC_NO_CONTENT (204) to avoid it.
*
* See https://cloud.google.com/appengine/docs/standard/java/taskqueue/push/retrying-tasks
* for more details on retry behavior. */
logger.atWarning().withCause(t).log(
"Exception when attempting to relock domain with old revision ID %d.",
oldUnlockRevisionId);
response.setStatus(SC_NO_CONTENT);
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
response.setPayload(String.format("Relock failed: %s", t.getMessage()));
return;
}
applyRelock(oldLock);
}
private void applyRelock(RegistryLock oldLock) {
try {
domainLockUtils.administrativelyApplyLock(
oldLock.getDomainName(),
oldLock.getRegistrarId(),
oldLock.getRegistrarPocId(),
oldLock.isSuperuser());
logger.atInfo().log("Relocked domain %s.", oldLock.getDomainName());
response.setStatus(SC_OK);
} catch (Throwable t) {
// Any errors that occur here are unexpected, so we should retry. Return a non-2xx
// error code to get AppEngine to retry
logger.atSevere().withCause(t).log(
"Exception when attempting to relock domain %s.", oldLock.getDomainName());
response.setStatus(SC_INTERNAL_SERVER_ERROR);
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
response.setPayload(String.format("Relock failed: %s", t.getMessage()));
}
}
private void verifyDomainAndLockState(RegistryLock oldLock, DomainBase domain) {
// Domain shouldn't be deleted or have a pending transfer/delete
String domainName = domain.getFullyQualifiedDomainName();
checkArgument(
!DateTimeUtils.isAtOrAfter(jpaTm().getTransactionTime(), domain.getDeletionTime()),
"Domain %s has been deleted",
domainName);
ImmutableSet<StatusValue> statusValues = domain.getStatusValues();
checkArgument(
!statusValues.contains(StatusValue.PENDING_DELETE),
"Domain %s has a pending delete",
domainName);
checkArgument(
!statusValues.contains(StatusValue.PENDING_TRANSFER),
"Domain %s has a pending transfer",
domainName);
checkArgument(
domain.getCurrentSponsorClientId().equals(oldLock.getRegistrarId()),
"Domain %s has been transferred from registrar %s to registrar %s since the unlock",
domainName,
oldLock.getRegistrarId(),
domain.getCurrentSponsorClientId());
}
}
@@ -120,6 +120,8 @@ import org.joda.time.Duration;
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForDomainException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException}
@@ -41,7 +41,7 @@ import org.joda.time.DateTime;
/** Utility functions for dealing with {@link AllocationToken}s in domain flows. */
public class AllocationTokenFlowUtils {
final AllocationTokenCustomLogic tokenCustomLogic;
private final AllocationTokenCustomLogic tokenCustomLogic;
@Inject
AllocationTokenFlowUtils(AllocationTokenCustomLogic tokenCustomLogic) {
@@ -60,7 +60,8 @@ public class AllocationTokenFlowUtils {
DomainCommand.Create command, String token, Registry registry, String clientId, DateTime now)
throws EppException {
AllocationToken tokenEntity = loadToken(token);
validateToken(tokenEntity, clientId, registry.getTldStr(), now);
validateToken(
InternetDomainName.from(command.getFullyQualifiedDomainName()), tokenEntity, clientId, now);
return tokenCustomLogic.validateToken(command, tokenEntity, registry, clientId, now);
}
@@ -89,7 +90,7 @@ public class AllocationTokenFlowUtils {
ImmutableMap.Builder<InternetDomainName, String> resultsBuilder = new ImmutableMap.Builder<>();
for (InternetDomainName domainName : domainNames) {
try {
validateToken(tokenEntity, clientId, domainName.parent().toString(), now);
validateToken(domainName, tokenEntity, clientId, now);
validDomainNames.add(domainName);
} catch (EppException e) {
resultsBuilder.put(domainName, e.getMessage());
@@ -120,14 +121,20 @@ public class AllocationTokenFlowUtils {
*
* @throws EppException if the token is invalid in any way
*/
private void validateToken(AllocationToken token, String clientId, String tld, DateTime now)
private void validateToken(
InternetDomainName domainName, AllocationToken token, String clientId, DateTime now)
throws EppException {
if (!token.getAllowedClientIds().isEmpty() && !token.getAllowedClientIds().contains(clientId)) {
throw new AllocationTokenNotValidForRegistrarException();
}
if (!token.getAllowedTlds().isEmpty() && !token.getAllowedTlds().contains(tld)) {
if (!token.getAllowedTlds().isEmpty()
&& !token.getAllowedTlds().contains(domainName.parent().toString())) {
throw new AllocationTokenNotValidForTldException();
}
if (token.getDomainName().isPresent()
&& !token.getDomainName().get().equals(domainName.toString())) {
throw new AllocationTokenNotValidForDomainException();
}
// Tokens without status transitions will just have a single-entry NOT_STARTED map, so only
// check the status transitions map if it's non-trivial.
if (token.getTokenStatusTransitions().size() > 1
@@ -159,22 +166,30 @@ public class AllocationTokenFlowUtils {
/** The allocation token is not currently valid. */
public static class AllocationTokenNotInPromotionException
extends StatusProhibitsOperationException {
public AllocationTokenNotInPromotionException() {
AllocationTokenNotInPromotionException() {
super("Alloc token not in promo period");
}
}
/** The allocation token is not valid for this TLD. */
public static class AllocationTokenNotValidForTldException
extends AssociationProhibitsOperationException {
public AllocationTokenNotValidForTldException() {
AllocationTokenNotValidForTldException() {
super("Alloc token invalid for TLD");
}
}
/** The allocation token is not valid for this domain. */
public static class AllocationTokenNotValidForDomainException
extends AssociationProhibitsOperationException {
AllocationTokenNotValidForDomainException() {
super("Alloc token invalid for domain");
}
}
/** The allocation token is not valid for this registrar. */
public static class AllocationTokenNotValidForRegistrarException
extends AssociationProhibitsOperationException {
public AllocationTokenNotValidForRegistrarException() {
AllocationTokenNotValidForRegistrarException() {
super("Alloc token invalid for client");
}
}
@@ -182,14 +197,14 @@ public class AllocationTokenFlowUtils {
/** The allocation token was already redeemed. */
public static class AlreadyRedeemedAllocationTokenException
extends AssociationProhibitsOperationException {
public AlreadyRedeemedAllocationTokenException() {
AlreadyRedeemedAllocationTokenException() {
super("Alloc token was already redeemed");
}
}
/** The allocation token is invalid. */
public static class InvalidAllocationTokenException extends AuthorizationErrorException {
public InvalidAllocationTokenException() {
InvalidAllocationTokenException() {
super("The allocation token is invalid");
}
}
@@ -16,7 +16,11 @@ package google.registry.model.ofy;
import static google.registry.model.ofy.ObjectifyService.ofy;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import google.registry.persistence.VKey;
import google.registry.persistence.transaction.TransactionManager;
import java.util.Optional;
import java.util.function.Supplier;
import org.joda.time.DateTime;
@@ -83,4 +87,64 @@ public class DatastoreTransactionManager implements TransactionManager {
public DateTime getTransactionTime() {
return getOfy().getTransactionTime();
}
@Override
public void saveNew(Object entity) {
throw new UnsupportedOperationException("Not available in the Datastore transaction manager");
}
@Override
public void saveAllNew(ImmutableCollection<?> entities) {
throw new UnsupportedOperationException("Not available in the Datastore transaction manager");
}
@Override
public void saveNewOrUpdate(Object entity) {
throw new UnsupportedOperationException("Not available in the Datastore transaction manager");
}
@Override
public void saveNewOrUpdateAll(ImmutableCollection<?> entities) {
throw new UnsupportedOperationException("Not available in the Datastore transaction manager");
}
@Override
public void update(Object entity) {
throw new UnsupportedOperationException("Not available in the Datastore transaction manager");
}
@Override
public void updateAll(ImmutableCollection<?> entities) {
throw new UnsupportedOperationException("Not available in the Datastore transaction manager");
}
@Override
public boolean checkExists(Object entity) {
throw new UnsupportedOperationException("Not available in the Datastore transaction manager");
}
@Override
public <T> boolean checkExists(VKey<T> key) {
throw new UnsupportedOperationException("Not available in the Datastore transaction manager");
}
@Override
public <T> Optional<T> load(VKey<T> key) {
throw new UnsupportedOperationException("Not available in the Datastore transaction manager");
}
@Override
public <T> ImmutableList<T> loadAll(Class<T> clazz) {
throw new UnsupportedOperationException("Not available in the Datastore transaction manager");
}
@Override
public <T> int delete(VKey<T> key) {
throw new UnsupportedOperationException("Not available in the Datastore transaction manager");
}
@Override
public <T> void assertDelete(VKey<T> key) {
throw new UnsupportedOperationException("Not available in the Datastore transaction manager");
}
}
@@ -25,90 +25,105 @@ import javax.persistence.EntityManager;
/** Data access object for {@link google.registry.schema.domain.RegistryLock}. */
public final class RegistryLockDao {
/**
* Returns the most recent version of the {@link RegistryLock} referred to by the verification
* code (there may be two instances of the same code in the database--one after lock object
* creation and one after verification.
*/
/** Returns the {@link RegistryLock} referred to by this revision ID, or empty if none exists. */
public static Optional<RegistryLock> getByRevisionId(long revisionId) {
jpaTm().assertInTransaction();
return Optional.ofNullable(jpaTm().getEntityManager().find(RegistryLock.class, revisionId));
}
/** Returns the most recent version of the {@link RegistryLock} referred to by the code. */
public static Optional<RegistryLock> getByVerificationCode(String verificationCode) {
return jpaTm()
.transact(
() -> {
EntityManager em = jpaTm().getEntityManager();
Long revisionId =
em.createQuery(
"SELECT MAX(revisionId) FROM RegistryLock WHERE verificationCode ="
+ " :verificationCode",
Long.class)
.setParameter("verificationCode", verificationCode)
.getSingleResult();
return Optional.ofNullable(revisionId)
.map(revision -> em.find(RegistryLock.class, revision));
});
jpaTm().assertInTransaction();
EntityManager em = jpaTm().getEntityManager();
Long revisionId =
em.createQuery(
"SELECT MAX(revisionId) FROM RegistryLock WHERE verificationCode ="
+ " :verificationCode",
Long.class)
.setParameter("verificationCode", verificationCode)
.getSingleResult();
return Optional.ofNullable(revisionId).map(revision -> em.find(RegistryLock.class, revision));
}
/** Returns all lock objects that this registrar has created. */
public static ImmutableList<RegistryLock> getLockedDomainsByRegistrarId(String registrarId) {
return jpaTm()
.transact(
() ->
ImmutableList.copyOf(
jpaTm()
.getEntityManager()
.createQuery(
"SELECT lock FROM RegistryLock lock WHERE"
+ " lock.registrarId = :registrarId "
+ "AND lock.lockCompletionTimestamp IS NOT NULL "
+ "AND lock.unlockCompletionTimestamp IS NULL",
RegistryLock.class)
.setParameter("registrarId", registrarId)
.getResultList()));
/** Returns all lock objects that this registrar has created, including pending locks. */
public static ImmutableList<RegistryLock> getLocksByRegistrarId(String registrarId) {
jpaTm().assertInTransaction();
return ImmutableList.copyOf(
jpaTm()
.getEntityManager()
.createQuery(
"SELECT lock FROM RegistryLock lock WHERE lock.registrarId = :registrarId"
+ " AND lock.unlockCompletionTimestamp IS NULL",
RegistryLock.class)
.setParameter("registrarId", registrarId)
.getResultList());
}
/**
* Returns the most recent lock object for a given domain specified by repo ID, or empty if this
* domain hasn't been locked before.
* Returns the most recent lock object for a given domain specified by repo ID.
*
* <p>Returns empty if this domain hasn't been locked before.
*/
public static Optional<RegistryLock> getMostRecentByRepoId(String repoId) {
jpaTm().assertInTransaction();
return jpaTm()
.transact(
() ->
jpaTm()
.getEntityManager()
.createQuery(
"SELECT lock FROM RegistryLock lock WHERE lock.repoId = :repoId"
+ " ORDER BY lock.revisionId DESC",
RegistryLock.class)
.setParameter("repoId", repoId)
.setMaxResults(1)
.getResultStream()
.findFirst());
.getEntityManager()
.createQuery(
"SELECT lock FROM RegistryLock lock WHERE lock.repoId = :repoId"
+ " ORDER BY lock.revisionId DESC",
RegistryLock.class)
.setParameter("repoId", repoId)
.setMaxResults(1)
.getResultStream()
.findFirst();
}
/**
* Returns the most recent verified lock object for a given domain specified by repo ID, or empty
* if no lock has ever been finalized for this domain. This is different from {@link
* #getMostRecentByRepoId(String)} in that it only returns verified locks.
* Returns the most recent verified lock object for a given domain specified by repo ID.
*
* <p>Returns empty if no lock has ever been finalized for this domain. This is different from
* {@link #getMostRecentByRepoId(String)} in that it only returns verified locks.
*/
public static Optional<RegistryLock> getMostRecentVerifiedLockByRepoId(String repoId) {
jpaTm().assertInTransaction();
return jpaTm()
.transact(
() ->
jpaTm()
.getEntityManager()
.createQuery(
"SELECT lock FROM RegistryLock lock WHERE lock.repoId = :repoId AND"
+ " lock.lockCompletionTimestamp IS NOT NULL ORDER BY lock.revisionId"
+ " DESC",
RegistryLock.class)
.setParameter("repoId", repoId)
.setMaxResults(1)
.getResultStream()
.findFirst());
.getEntityManager()
.createQuery(
"SELECT lock FROM RegistryLock lock WHERE lock.repoId = :repoId AND"
+ " lock.lockCompletionTimestamp IS NOT NULL AND"
+ " lock.unlockCompletionTimestamp IS NULL ORDER BY lock.revisionId"
+ " DESC",
RegistryLock.class)
.setParameter("repoId", repoId)
.setMaxResults(1)
.getResultStream()
.findFirst();
}
/**
* Returns the most recent verified unlock for a given domain specified by repo ID.
*
* <p>Returns empty if no unlock has ever been finalized for this domain. This is different from
* {@link #getMostRecentByRepoId(String)} in that it only returns verified unlocks.
*/
public static Optional<RegistryLock> getMostRecentVerifiedUnlockByRepoId(String repoId) {
jpaTm().assertInTransaction();
return jpaTm()
.getEntityManager()
.createQuery(
"SELECT lock FROM RegistryLock lock WHERE lock.repoId = :repoId AND"
+ " lock.unlockCompletionTimestamp IS NOT NULL ORDER BY lock.revisionId"
+ " DESC",
RegistryLock.class)
.setParameter("repoId", repoId)
.setMaxResults(1)
.getResultStream()
.findFirst();
}
public static RegistryLock save(RegistryLock registryLock) {
jpaTm().assertInTransaction();
checkNotNull(registryLock, "Null registry lock cannot be saved");
return jpaTm().transact(() -> jpaTm().getEntityManager().merge(registryLock));
return jpaTm().getEntityManager().merge(registryLock);
}
}
@@ -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.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.isAtOrAfter;
@@ -28,6 +29,7 @@ import com.googlecode.objectify.annotation.Id;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.NotBackedUp;
import google.registry.model.annotations.NotBackedUp.Reason;
import google.registry.schema.server.LockDao;
import google.registry.util.RequestStatusChecker;
import google.registry.util.RequestStatusCheckerImpl;
import java.io.Serializable;
@@ -177,8 +179,7 @@ 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 =
tm()
.transactNew(
tm().transactNew(
() -> {
DateTime now = tm().getTransactionTime();
@@ -207,6 +208,31 @@ public class Lock extends ImmutableObject implements Serializable {
// contention) and
// don't need to be backed up.
ofy().saveWithoutBackup().entity(newLock);
// create and save the lock to Cloud SQL
try {
jpaTm()
.transact(
() -> {
google.registry.schema.server.Lock cloudSqlLock =
google.registry.schema.server.Lock.create(
resourceName,
Optional.ofNullable(tld).orElse("GLOBAL"),
requestStatusChecker.getLogId(),
now,
leaseLength);
// cloudSqlLock should not already exist in Cloud SQL, but call delete
// just in case
// TODO: Remove this delete once dual read is added
LockDao.delete(
resourceName, Optional.ofNullable(tld).orElse("GLOBAL"));
LockDao.saveNew(cloudSqlLock);
});
} catch (Exception e) {
logger.atSevere().withCause(e).log(
"Error saving lock to Cloud SQL: %s", newLock);
}
return AcquireResult.create(now, lock, newLock, lockState);
});
@@ -218,8 +244,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.
tm()
.transact(
tm().transact(
() -> {
// To release a lock, check that no one else has already obtained it and if not
// delete it. If the lock in Datastore was different then this lock is gone already;
@@ -231,6 +256,19 @@ public class Lock extends ImmutableObject implements Serializable {
// lock.
logger.atInfo().log("Deleting lock: %s", lockId);
ofy().deleteWithoutBackup().entity(Lock.this);
// Remove the lock from Cloud SQL
try {
jpaTm()
.transact(
() ->
LockDao.delete(
resourceName, Optional.ofNullable(tld).orElse("GLOBAL")));
} catch (Exception e) {
logger.atSevere().withCause(e).log(
"Error deleting lock from Cloud SQL: %s", loadedLock);
}
lockMetrics.recordRelease(
resourceName, tld, new Duration(acquiredTime, tm().getTransactionTime()));
} else {
@@ -26,6 +26,7 @@ import google.registry.batch.DeleteLoadTestDataAction;
import google.registry.batch.DeleteProberDataAction;
import google.registry.batch.ExpandRecurringBillingEventsAction;
import google.registry.batch.RefreshDnsOnHostRenameAction;
import google.registry.batch.RelockDomainAction;
import google.registry.batch.ResaveAllEppResourcesAction;
import google.registry.batch.ResaveEntityAction;
import google.registry.cron.CommitLogFanoutAction;
@@ -140,6 +141,7 @@ interface BackendRequestComponent {
RdeReporter rdeReporter();
RefreshDnsAction refreshDnsAction();
RefreshDnsOnHostRenameAction refreshDnsOnHostRenameAction();
RelockDomainAction relockDomainAction();
ResaveAllEppResourcesAction resaveAllEppResourcesAction();
ResaveEntityAction resaveEntityAction();
SyncGroupMembersAction syncGroupMembersAction();
@@ -0,0 +1,68 @@
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.persistence;
import google.registry.model.ImmutableObject;
/**
* VKey is an abstraction that encapsulates the key concept.
*
* <p>A VKey instance must contain both the JPA primary key for the referenced entity class and the
* objectify key for the object.
*/
public class VKey<T> extends ImmutableObject {
// The primary key for the referenced entity.
private Object primaryKey;
// The objectify key for the referenced entity.
private com.googlecode.objectify.Key<T> ofyKey;
private Class<? extends T> kind;
private VKey(Class<? extends T> kind, com.googlecode.objectify.Key<T> ofyKey, Object primaryKey) {
this.kind = kind;
this.ofyKey = ofyKey;
this.primaryKey = primaryKey;
}
public static <T> VKey<T> create(
Class<? extends T> kind, com.googlecode.objectify.Key<T> ofyKey, Object primaryKey) {
return new VKey(kind, ofyKey, primaryKey);
}
public static <T> VKey<T> createSql(Class<? extends T> kind, Object primaryKey) {
return new VKey(kind, null, primaryKey);
}
public static <T> VKey<T> createOfy(
Class<? extends T> kind, com.googlecode.objectify.Key<T> ofyKey) {
return new VKey(kind, ofyKey, null);
}
public Class<? extends T> getKind() {
return this.kind;
}
/** Returns the SQL primary key. */
public Object getSqlKey() {
return this.primaryKey;
}
/** Returns the objectify key. */
public com.googlecode.objectify.Key<T> getOfyKey() {
return this.ofyKey;
}
}
@@ -18,6 +18,7 @@ import javax.persistence.EntityManager;
/** Sub-interface of {@link TransactionManager} which defines JPA related methods. */
public interface JpaTransactionManager extends TransactionManager {
/** Returns the {@link EntityManager} for the current request. */
EntityManager getEntityManager();
}
@@ -14,13 +14,28 @@
package google.registry.persistence.transaction;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import static java.util.stream.Collectors.joining;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import google.registry.persistence.VKey;
import google.registry.util.Clock;
import java.lang.reflect.Field;
import java.util.Optional;
import java.util.function.Supplier;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.SingularAttribute;
import org.joda.time.DateTime;
/** Implementation of {@link JpaTransactionManager} for JPA compatible database. */
@@ -142,6 +157,180 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
return txnInfo.transactionTime;
}
@Override
public void saveNew(Object entity) {
checkArgumentNotNull(entity, "entity must be specified");
assertInTransaction();
getEntityManager().persist(entity);
}
@Override
public void saveAllNew(ImmutableCollection<?> entities) {
checkArgumentNotNull(entities, "entities must be specified");
assertInTransaction();
entities.forEach(this::saveNew);
}
@Override
public void saveNewOrUpdate(Object entity) {
checkArgumentNotNull(entity, "entity must be specified");
assertInTransaction();
getEntityManager().merge(entity);
}
@Override
public void saveNewOrUpdateAll(ImmutableCollection<?> entities) {
checkArgumentNotNull(entities, "entities must be specified");
assertInTransaction();
entities.forEach(this::saveNewOrUpdate);
}
@Override
public void update(Object entity) {
checkArgumentNotNull(entity, "entity must be specified");
assertInTransaction();
checkArgument(checkExists(entity), "Given entity does not exist");
getEntityManager().merge(entity);
}
@Override
public void updateAll(ImmutableCollection<?> entities) {
checkArgumentNotNull(entities, "entities must be specified");
assertInTransaction();
entities.forEach(this::update);
}
@Override
public <T> boolean checkExists(VKey<T> key) {
checkArgumentNotNull(key, "key must be specified");
EntityType<?> entityType = getEntityType(key.getKind());
ImmutableSet<EntityId> entityIds = getEntityIdsFromSqlKey(entityType, key.getSqlKey());
return checkExists(entityType.getName(), entityIds);
}
@Override
public boolean checkExists(Object entity) {
checkArgumentNotNull(entity, "entity must be specified");
EntityType<?> entityType = getEntityType(entity.getClass());
ImmutableSet<EntityId> entityIds = getEntityIdsFromEntity(entityType, entity);
return checkExists(entityType.getName(), entityIds);
}
private boolean checkExists(String entityName, ImmutableSet<EntityId> entityIds) {
assertInTransaction();
TypedQuery<Integer> query =
getEntityManager()
.createQuery(
String.format("SELECT 1 FROM %s WHERE %s", entityName, getAndClause(entityIds)),
Integer.class)
.setMaxResults(1);
entityIds.forEach(entityId -> query.setParameter(entityId.name, entityId.value));
return query.getResultList().size() > 0;
}
@Override
public <T> Optional<T> load(VKey<T> key) {
checkArgumentNotNull(key, "key must be specified");
assertInTransaction();
return Optional.ofNullable(getEntityManager().find(key.getKind(), key.getSqlKey()));
}
@Override
public <T> ImmutableList<T> loadAll(Class<T> clazz) {
checkArgumentNotNull(clazz, "clazz must be specified");
assertInTransaction();
return ImmutableList.copyOf(
getEntityManager()
.createQuery(
String.format("SELECT entity FROM %s entity", getEntityType(clazz).getName()),
clazz)
.getResultList());
}
@Override
public <T> int delete(VKey<T> key) {
checkArgumentNotNull(key, "key must be specified");
assertInTransaction();
EntityType<?> entityType = getEntityType(key.getKind());
ImmutableSet<EntityId> entityIds = getEntityIdsFromSqlKey(entityType, key.getSqlKey());
String sql =
String.format("DELETE FROM %s WHERE %s", entityType.getName(), getAndClause(entityIds));
Query query = getEntityManager().createQuery(sql);
entityIds.forEach(entityId -> query.setParameter(entityId.name, entityId.value));
return query.executeUpdate();
}
@Override
public <T> void assertDelete(VKey<T> key) {
if (delete(key) != 1) {
throw new IllegalArgumentException(
String.format("Error deleting the entity of the key: %s", key.getSqlKey()));
}
}
private <T> EntityType<T> getEntityType(Class<T> clazz) {
return emf.getMetamodel().entity(clazz);
}
private static class EntityId {
private String name;
private Object value;
private EntityId(String name, Object value) {
this.name = name;
this.value = value;
}
}
private static ImmutableSet<EntityId> getEntityIdsFromEntity(
EntityType<?> entityType, Object entity) {
if (entityType.hasSingleIdAttribute()) {
String idName = entityType.getDeclaredId(entityType.getIdType().getJavaType()).getName();
Object idValue = getFieldValue(entity, idName);
return ImmutableSet.of(new EntityId(idName, idValue));
} else {
return getEntityIdsFromIdContainer(entityType, entity);
}
}
private static ImmutableSet<EntityId> getEntityIdsFromSqlKey(
EntityType<?> entityType, Object sqlKey) {
if (entityType.hasSingleIdAttribute()) {
String idName = entityType.getDeclaredId(entityType.getIdType().getJavaType()).getName();
return ImmutableSet.of(new EntityId(idName, sqlKey));
} else {
return getEntityIdsFromIdContainer(entityType, sqlKey);
}
}
private static ImmutableSet<EntityId> getEntityIdsFromIdContainer(
EntityType<?> entityType, Object idContainer) {
return entityType.getIdClassAttributes().stream()
.map(SingularAttribute::getName)
.map(
idName -> {
Object idValue = getFieldValue(idContainer, idName);
return new EntityId(idName, idValue);
})
.collect(toImmutableSet());
}
private String getAndClause(ImmutableSet<EntityId> entityIds) {
return entityIds.stream()
.map(entityId -> String.format("%s = :%s", entityId.name, entityId.name))
.collect(joining(" AND "));
}
private static Object getFieldValue(Object object, String fieldName) {
try {
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(object);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new IllegalArgumentException(e);
}
}
private static class TransactionInfo {
EntityManager entityManager;
boolean inTransaction = false;
@@ -14,6 +14,10 @@
package google.registry.persistence.transaction;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import google.registry.persistence.VKey;
import java.util.Optional;
import java.util.function.Supplier;
import org.joda.time.DateTime;
@@ -78,4 +82,40 @@ public interface TransactionManager {
/** Returns the time associated with the start of this particular transaction attempt. */
DateTime getTransactionTime();
/** Persists a new entity in the database, throws exception if the entity already exists. */
void saveNew(Object entity);
/** Persists all new entities in the database, throws exception if any entity already exists. */
void saveAllNew(ImmutableCollection<?> entities);
/** Persists a new entity or update the existing entity in the database. */
void saveNewOrUpdate(Object entity);
/** Persists all new entities or update the existing entities in the database. */
void saveNewOrUpdateAll(ImmutableCollection<?> entities);
/** Updates an entity in the database, throws exception if the entity does not exist. */
void update(Object entity);
/** Updates all entities in the database, throws exception if any entity does not exist. */
void updateAll(ImmutableCollection<?> entities);
/** Returns whether the given entity with same ID exists. */
boolean checkExists(Object entity);
/** Returns whether the entity of given key exists. */
<T> boolean checkExists(VKey<T> key);
/** Loads the entity by its id, returns empty if the entity doesn't exist. */
<T> Optional<T> load(VKey<T> key);
/** Loads all entities of the given type, returns empty if there is no such entity. */
<T> ImmutableList<T> loadAll(Class<T> clazz);
/** Deletes the entity by its id, returns the number of deleted entity. */
<T> int delete(VKey<T> key);
/** Deletes the entity by its id, throws exception if the entity is not deleted. */
<T> void assertDelete(VKey<T> key);
}
@@ -193,8 +193,7 @@ public class PublishSpec11ReportAction implements Runnable {
// Group by email address then flat-map all of the ThreatMatch objects together
return ImmutableMap.copyOf(
Maps.transformValues(
Multimaps.index(registrarThreatMatches, RegistrarThreatMatches::clientId)
.asMap(),
Multimaps.index(registrarThreatMatches, RegistrarThreatMatches::clientId).asMap(),
registrarThreatMatchesCollection ->
registrarThreatMatchesCollection.stream()
.flatMap(matches -> matches.threatMatches().stream())
@@ -44,11 +44,11 @@ public final class RequestParameters {
* method to yield the following results:
*
* <ul>
* <li>/foo?bar=hello → hello
* <li>/foo?bar=hello&bar=there → hello
* <li>/foo?bar= → 400 error (empty)
* <li>/foo?bar=&bar=there → 400 error (empty)
* <li>/foo → 400 error (absent)
* <li>/foo?bar=hello → hello
* <li>/foo?bar=hello&bar=there → hello
* <li>/foo?bar= → 400 error (empty)
* <li>/foo?bar=&bar=there → 400 error (empty)
* <li>/foo → 400 error (absent)
* </ul>
*
* @throws BadRequestException if request parameter is absent or empty
@@ -88,10 +88,27 @@ public final class RequestParameters {
* @throws BadRequestException if request parameter is absent, empty, or not a valid integer
*/
public static int extractIntParameter(HttpServletRequest req, String name) {
String stringParam = req.getParameter(name);
try {
return Integer.parseInt(nullToEmpty(req.getParameter(name)));
return Integer.parseInt(nullToEmpty(stringParam));
} catch (NumberFormatException e) {
throw new BadRequestException("Expected integer: " + name);
throw new BadRequestException(
String.format("Expected int for parameter %s but received %s", name, stringParam));
}
}
/**
* Returns first GET or POST parameter associated with {@code name} as a long.
*
* @throws BadRequestException if request parameter is absent, empty, or not a valid long
*/
public static long extractLongParameter(HttpServletRequest req, String name) {
String stringParam = req.getParameter(name);
try {
return Long.parseLong(nullToEmpty(stringParam));
} catch (NumberFormatException e) {
throw new BadRequestException(
String.format("Expected long for parameter %s but received %s", name, stringParam));
}
}
@@ -126,9 +143,7 @@ public final class RequestParameters {
if (parameter == null || parameter.isEmpty()) {
return ImmutableSet.of();
}
return Splitter.on(',')
.splitToList(parameter)
.stream()
return Splitter.on(',').splitToList(parameter).stream()
.filter(s -> !s.isEmpty())
.collect(toImmutableSet());
}
@@ -160,8 +175,8 @@ public final class RequestParameters {
* @throws BadRequestException if request parameter named {@code name} is absent, empty, or not
* equal to any of the values in {@code enumClass}
*/
public static <C extends Enum<C>>
C extractEnumParameter(HttpServletRequest req, Class<C> enumClass, String name) {
public static <C extends Enum<C>> C extractEnumParameter(
HttpServletRequest req, Class<C> enumClass, String name) {
return getEnumValue(enumClass, extractRequiredParameter(req, name), name);
}
@@ -216,9 +231,9 @@ public final class RequestParameters {
}
/**
* Returns first request parameter associated with {@code name} parsed as an
* <a href="https://goo.gl/pk5Q2k">ISO 8601</a> timestamp, e.g. {@code 1984-12-18TZ},
* {@code 2000-01-01T16:20:00Z}.
* Returns first request parameter associated with {@code name} parsed as an <a
* href="https://goo.gl/pk5Q2k">ISO 8601</a> timestamp, e.g. {@code 1984-12-18TZ}, {@code
* 2000-01-01T16:20:00Z}.
*
* @throws BadRequestException if request parameter named {@code name} is absent, empty, or could
* not be parsed as an ISO 8601 timestamp
@@ -233,9 +248,9 @@ public final class RequestParameters {
}
/**
* Returns first request parameter associated with {@code name} parsed as an
* <a href="https://goo.gl/pk5Q2k">ISO 8601</a> timestamp, e.g. {@code 1984-12-18TZ},
* {@code 2000-01-01T16:20:00Z}.
* Returns first request parameter associated with {@code name} parsed as an <a
* href="https://goo.gl/pk5Q2k">ISO 8601</a> timestamp, e.g. {@code 1984-12-18TZ}, {@code
* 2000-01-01T16:20:00Z}.
*
* @throws BadRequestException if request parameter is present but not a valid {@link DateTime}.
*/
@@ -262,8 +277,7 @@ public final class RequestParameters {
public static ImmutableSet<DateTime> extractSetOfDatetimeParameters(
HttpServletRequest req, String name) {
try {
return extractSetOfParameters(req, name)
.stream()
return extractSetOfParameters(req, name).stream()
.filter(not(String::isEmpty))
.map(DateTime::parse)
.collect(toImmutableSet());
@@ -23,16 +23,18 @@ import google.registry.model.Buildable;
import google.registry.model.CreateAutoTimestamp;
import google.registry.model.ImmutableObject;
import google.registry.model.UpdateAutoTimestamp;
import google.registry.util.Clock;
import google.registry.util.DateTimeUtils;
import java.time.ZonedDateTime;
import java.util.Optional;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.joda.time.DateTime;
@@ -124,6 +126,11 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
@Column(nullable = false)
private boolean isSuperuser;
/** The lock that undoes this lock, if this lock has been unlocked and the domain locked again. */
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "relockRevisionId", referencedColumnName = "revisionId")
private RegistryLock relock;
/** Time that this entity was last updated. */
private UpdateAutoTimestamp lastUpdateTimestamp;
@@ -180,22 +187,32 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
return revisionId;
}
/**
* The lock that undoes this lock, if this lock has been unlocked and the domain locked again.
*
* <p>Note: this is lazily loaded, so it may not be initialized if referenced outside of the
* transaction in which this lock is loaded.
*/
public RegistryLock getRelock() {
return relock;
}
public boolean isLocked() {
return lockCompletionTimestamp != null && unlockCompletionTimestamp == null;
}
/** Returns true iff the lock was requested >= 1 hour ago and has not been verified. */
public boolean isLockRequestExpired(Clock clock) {
public boolean isLockRequestExpired(DateTime now) {
return !getLockCompletionTimestamp().isPresent()
&& isBeforeOrAt(getLockRequestTimestamp(), clock.nowUtc().minusHours(1));
&& isBeforeOrAt(getLockRequestTimestamp(), now.minusHours(1));
}
/** Returns true iff the unlock was requested >= 1 hour ago and has not been verified. */
public boolean isUnlockRequestExpired(Clock clock) {
public boolean isUnlockRequestExpired(DateTime now) {
Optional<DateTime> unlockRequestTimestamp = getUnlockRequestTimestamp();
return unlockRequestTimestamp.isPresent()
&& !getUnlockCompletionTimestamp().isPresent()
&& isBeforeOrAt(unlockRequestTimestamp.get(), clock.nowUtc().minusHours(1));
&& isBeforeOrAt(unlockRequestTimestamp.get(), now.minusHours(1));
}
@Override
@@ -267,5 +284,10 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
getInstance().isSuperuser = isSuperuser;
return this;
}
public Builder setRelock(RegistryLock relock) {
getInstance().relock = relock;
return this;
}
}
}
@@ -1,73 +0,0 @@
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.schema.registrar;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import google.registry.model.registrar.Registrar;
import java.util.Optional;
/** Data access object for {@link Registrar}. */
public class RegistrarDao {
private RegistrarDao() {}
/** Persists a new or updates an existing registrar in Cloud SQL. */
public static void saveNew(Registrar registrar) {
checkArgumentNotNull(registrar, "registrar must be specified");
jpaTm().transact(() -> jpaTm().getEntityManager().persist(registrar));
}
/** Updates an existing registrar in Cloud SQL, throws excpetion if it does not exist. */
public static void update(Registrar registrar) {
checkArgumentNotNull(registrar, "registrar must be specified");
jpaTm()
.transact(
() -> {
checkArgument(
checkExists(registrar.getClientId()),
"A registrar of this id does not exist: %s.",
registrar.getClientId());
jpaTm().getEntityManager().merge(registrar);
});
}
/** Returns whether the registrar of the given id exists. */
public static boolean checkExists(String clientId) {
checkArgumentNotNull(clientId, "clientId must be specified");
return jpaTm()
.transact(
() ->
jpaTm()
.getEntityManager()
.createQuery(
"SELECT 1 FROM Registrar WHERE clientIdentifier = :clientIdentifier",
Integer.class)
.setParameter("clientIdentifier", clientId)
.setMaxResults(1)
.getResultList()
.size()
> 0);
}
/** Loads the registrar by its id, returns empty if it doesn't exist. */
public static Optional<Registrar> load(String clientId) {
checkArgumentNotNull(clientId, "clientId must be specified");
return Optional.ofNullable(
jpaTm().transact(() -> jpaTm().getEntityManager().find(Registrar.class, clientId)));
}
}
@@ -51,26 +51,29 @@ public class LockDao {
* else empty.
*/
public static Optional<Lock> load(String resourceName) {
checkArgumentNotNull(resourceName, "The resource name of the lock to load cannot be null");
return Optional.ofNullable(
jpaTm()
.transact(
() ->
jpaTm().getEntityManager().find(Lock.class, new LockId(resourceName, GLOBAL))));
return load(resourceName, GLOBAL);
}
/**
* Deletes the given {@link Lock} object from Cloud SQL. This method is idempotent and will simply
* return if the lock has already been deleted.
* Deletes the {@link Lock} object with the given resourceName and tld from Cloud SQL. This method
* is idempotent and will simply return if the lock has already been deleted.
*/
public static void delete(Lock lock) {
public static void delete(String resourceName, String tld) {
jpaTm()
.transact(
() -> {
Optional<Lock> loadedLock = load(lock.resourceName, lock.tld);
Optional<Lock> loadedLock = load(resourceName, tld);
if (loadedLock.isPresent()) {
jpaTm().getEntityManager().remove(loadedLock.get());
}
});
}
/**
* Deletes the global {@link Lock} object with the given resourceName from Cloud SQL. This method
* is idempotent and will simply return if the lock has already been deleted.
*/
public static void delete(String resourceName) {
delete(resourceName, GLOBAL);
}
}
@@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.collect.Iterables.getOnlyElement;
import static google.registry.model.registrar.Registrar.State.ACTIVE;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.tools.RegistryToolEnvironment.PRODUCTION;
import static google.registry.tools.RegistryToolEnvironment.SANDBOX;
import static google.registry.tools.RegistryToolEnvironment.UNITTEST;
@@ -32,7 +33,6 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import google.registry.config.RegistryEnvironment;
import google.registry.model.registrar.Registrar;
import google.registry.schema.registrar.RegistrarDao;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -72,7 +72,7 @@ final class CreateRegistrarCommand extends CreateOrUpdateRegistrarCommand
@Override
void saveToCloudSql(Registrar registrar) {
RegistrarDao.saveNew(registrar);
jpaTm().saveNew(registrar);
}
@Nullable
@@ -31,12 +31,12 @@ import google.registry.model.registry.Registry;
import google.registry.model.registry.RegistryLockDao;
import google.registry.model.reporting.HistoryEntry;
import google.registry.schema.domain.RegistryLock;
import google.registry.util.Clock;
import google.registry.util.StringGenerator;
import java.util.Optional;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Named;
import org.joda.time.DateTime;
/**
* Utility functions for validating and applying {@link RegistryLock}s.
@@ -56,13 +56,145 @@ public final class DomainLockUtils {
this.stringGenerator = stringGenerator;
}
public RegistryLock createRegistryLockRequest(
String domainName,
String registrarId,
@Nullable String registrarPocId,
boolean isAdmin,
Clock clock) {
DomainBase domainBase = getDomain(domainName, clock);
/**
* Creates and persists a lock request when requested by a user.
*
* <p>The lock will not be applied until {@link #verifyAndApplyLock} is called.
*/
public RegistryLock saveNewRegistryLockRequest(
String domainName, String registrarId, @Nullable String registrarPocId, boolean isAdmin) {
return jpaTm()
.transact(
() ->
RegistryLockDao.save(
createLockBuilder(domainName, registrarId, registrarPocId, isAdmin).build()));
}
/**
* Creates and persists an unlock request when requested by a user.
*
* <p>The unlock will not be applied until {@link #verifyAndApplyUnlock} is called.
*/
public RegistryLock saveNewRegistryUnlockRequest(
String domainName, String registrarId, boolean isAdmin) {
return jpaTm()
.transact(
() ->
RegistryLockDao.save(
createUnlockBuilder(domainName, registrarId, isAdmin).build()));
}
/** Verifies and applies the lock request previously requested by a user. */
public RegistryLock verifyAndApplyLock(String verificationCode, boolean isAdmin) {
return jpaTm()
.transact(
() -> {
DateTime now = jpaTm().getTransactionTime();
RegistryLock lock = getByVerificationCode(verificationCode);
checkArgument(
!lock.getLockCompletionTimestamp().isPresent(),
"Domain %s is already locked",
lock.getDomainName());
checkArgument(
!lock.isLockRequestExpired(now),
"The pending lock has expired; please try again");
checkArgument(
!lock.isSuperuser() || isAdmin, "Non-admin user cannot complete admin lock");
RegistryLock newLock =
RegistryLockDao.save(lock.asBuilder().setLockCompletionTimestamp(now).build());
setAsRelock(newLock);
tm().transact(() -> applyLockStatuses(newLock, now));
return newLock;
});
}
/** Verifies and applies the unlock request previously requested by a user. */
public RegistryLock verifyAndApplyUnlock(String verificationCode, boolean isAdmin) {
return jpaTm()
.transact(
() -> {
DateTime now = jpaTm().getTransactionTime();
RegistryLock lock = getByVerificationCode(verificationCode);
checkArgument(
!lock.getUnlockCompletionTimestamp().isPresent(),
"Domain %s is already unlocked",
lock.getDomainName());
checkArgument(
!lock.isUnlockRequestExpired(now),
"The pending unlock has expired; please try again");
checkArgument(
isAdmin || !lock.isSuperuser(), "Non-admin user cannot complete admin unlock");
RegistryLock newLock =
RegistryLockDao.save(lock.asBuilder().setUnlockCompletionTimestamp(now).build());
tm().transact(() -> removeLockStatuses(newLock, isAdmin, now));
return newLock;
});
}
/**
* Creates and applies a lock in one step -- this should only be used for admin actions, e.g.
* Nomulus tool commands or relocks.
*
* <p>Note: in the case of relocks, isAdmin is determined by the previous lock.
*/
public RegistryLock administrativelyApplyLock(
String domainName, String registrarId, @Nullable String registrarPocId, boolean isAdmin) {
return jpaTm()
.transact(
() -> {
DateTime now = jpaTm().getTransactionTime();
RegistryLock newLock =
RegistryLockDao.save(
createLockBuilder(domainName, registrarId, registrarPocId, isAdmin)
.setLockCompletionTimestamp(now)
.build());
tm().transact(() -> applyLockStatuses(newLock, now));
setAsRelock(newLock);
return newLock;
});
}
/**
* Creates and applies an unlock in one step -- this should only be used for admin actions, e.g.
* Nomulus tool commands.
*/
public RegistryLock administrativelyApplyUnlock(
String domainName, String registrarId, boolean isAdmin) {
return jpaTm()
.transact(
() -> {
DateTime now = jpaTm().getTransactionTime();
RegistryLock result =
RegistryLockDao.save(
createUnlockBuilder(domainName, registrarId, isAdmin)
.setUnlockCompletionTimestamp(now)
.build());
tm().transact(() -> removeLockStatuses(result, isAdmin, now));
return result;
});
}
private void setAsRelock(RegistryLock newLock) {
jpaTm()
.transact(
() ->
RegistryLockDao.getMostRecentVerifiedUnlockByRepoId(newLock.getRepoId())
.ifPresent(
oldLock ->
RegistryLockDao.save(oldLock.asBuilder().setRelock(newLock).build())));
}
private RegistryLock.Builder createLockBuilder(
String domainName, String registrarId, @Nullable String registrarPocId, boolean isAdmin) {
DateTime now = jpaTm().getTransactionTime();
DomainBase domainBase = getDomain(domainName, now);
verifyDomainNotLocked(domainBase);
// Multiple pending actions are not allowed
@@ -70,26 +202,24 @@ public final class DomainLockUtils {
.ifPresent(
previousLock ->
checkArgument(
previousLock.isLockRequestExpired(clock)
previousLock.isLockRequestExpired(now)
|| previousLock.getUnlockCompletionTimestamp().isPresent(),
"A pending or completed lock action already exists for %s",
previousLock.getDomainName()));
RegistryLock lock =
new RegistryLock.Builder()
.setVerificationCode(stringGenerator.createString(VERIFICATION_CODE_LENGTH))
.setDomainName(domainName)
.setRepoId(domainBase.getRepoId())
.setRegistrarId(registrarId)
.setRegistrarPocId(registrarPocId)
.isSuperuser(isAdmin)
.build();
return RegistryLockDao.save(lock);
return new RegistryLock.Builder()
.setVerificationCode(stringGenerator.createString(VERIFICATION_CODE_LENGTH))
.setDomainName(domainName)
.setRepoId(domainBase.getRepoId())
.setRegistrarId(registrarId)
.setRegistrarPocId(registrarPocId)
.isSuperuser(isAdmin);
}
public RegistryLock createRegistryUnlockRequest(
String domainName, String registrarId, boolean isAdmin, Clock clock) {
DomainBase domainBase = getDomain(domainName, clock);
private RegistryLock.Builder createUnlockBuilder(
String domainName, String registrarId, boolean isAdmin) {
DateTime now = jpaTm().getTransactionTime();
DomainBase domainBase = getDomain(domainName, now);
Optional<RegistryLock> lockOptional =
RegistryLockDao.getMostRecentVerifiedLockByRepoId(domainBase.getRepoId());
@@ -105,7 +235,7 @@ public final class DomainLockUtils {
new RegistryLock.Builder()
.setRepoId(domainBase.getRepoId())
.setDomainName(domainName)
.setLockCompletionTimestamp(clock.nowUtc())
.setLockCompletionTimestamp(now)
.setRegistrarId(registrarId));
} else {
verifyDomainLocked(domainBase);
@@ -117,7 +247,7 @@ public final class DomainLockUtils {
checkArgument(
lock.isLocked(), "Lock object for domain %s is not currently locked", domainName);
checkArgument(
!lock.getUnlockRequestTimestamp().isPresent() || lock.isUnlockRequestExpired(clock),
!lock.getUnlockRequestTimestamp().isPresent() || lock.isUnlockRequestExpired(now),
"A pending unlock action already exists for %s",
domainName);
checkArgument(
@@ -128,65 +258,11 @@ public final class DomainLockUtils {
!lock.isSuperuser(), "Non-admin user cannot unlock admin-locked domain %s", domainName);
newLockBuilder = lock.asBuilder();
}
RegistryLock newLock =
newLockBuilder
.setVerificationCode(stringGenerator.createString(VERIFICATION_CODE_LENGTH))
.isSuperuser(isAdmin)
.setUnlockRequestTimestamp(clock.nowUtc())
.setRegistrarId(registrarId)
.build();
return RegistryLockDao.save(newLock);
}
public RegistryLock verifyAndApplyLock(String verificationCode, boolean isAdmin, Clock clock) {
return jpaTm()
.transact(
() -> {
RegistryLock lock = getByVerificationCode(verificationCode);
checkArgument(
!lock.getLockCompletionTimestamp().isPresent(),
"Domain %s is already locked",
lock.getDomainName());
checkArgument(
!lock.isLockRequestExpired(clock),
"The pending lock has expired; please try again");
checkArgument(
!lock.isSuperuser() || isAdmin, "Non-admin user cannot complete admin lock");
RegistryLock newLock =
RegistryLockDao.save(
lock.asBuilder().setLockCompletionTimestamp(clock.nowUtc()).build());
tm().transact(() -> applyLockStatuses(newLock, clock));
return newLock;
});
}
public RegistryLock verifyAndApplyUnlock(String verificationCode, boolean isAdmin, Clock clock) {
return jpaTm()
.transact(
() -> {
RegistryLock lock = getByVerificationCode(verificationCode);
checkArgument(
!lock.getUnlockCompletionTimestamp().isPresent(),
"Domain %s is already unlocked",
lock.getDomainName());
checkArgument(
!lock.isUnlockRequestExpired(clock),
"The pending unlock has expired; please try again");
checkArgument(
isAdmin || !lock.isSuperuser(), "Non-admin user cannot complete admin unlock");
RegistryLock newLock =
RegistryLockDao.save(
lock.asBuilder().setUnlockCompletionTimestamp(clock.nowUtc()).build());
tm().transact(() -> removeLockStatuses(newLock, isAdmin, clock));
return newLock;
});
return newLockBuilder
.setVerificationCode(stringGenerator.createString(VERIFICATION_CODE_LENGTH))
.isSuperuser(isAdmin)
.setUnlockRequestTimestamp(now)
.setRegistrarId(registrarId);
}
private static void verifyDomainNotLocked(DomainBase domainBase) {
@@ -203,8 +279,8 @@ public final class DomainLockUtils {
domainBase.getFullyQualifiedDomainName());
}
private static DomainBase getDomain(String domainName, Clock clock) {
return loadByForeignKeyCached(DomainBase.class, domainName, clock.nowUtc())
private static DomainBase getDomain(String domainName, DateTime now) {
return loadByForeignKeyCached(DomainBase.class, domainName, now)
.orElseThrow(
() -> new IllegalArgumentException(String.format("Unknown domain %s", domainName)));
}
@@ -217,8 +293,8 @@ public final class DomainLockUtils {
String.format("Invalid verification code %s", verificationCode)));
}
private static void applyLockStatuses(RegistryLock lock, Clock clock) {
DomainBase domain = getDomain(lock.getDomainName(), clock);
private static void applyLockStatuses(RegistryLock lock, DateTime lockTime) {
DomainBase domain = getDomain(lock.getDomainName(), lockTime);
verifyDomainNotLocked(domain);
DomainBase newDomain =
@@ -227,11 +303,11 @@ public final class DomainLockUtils {
.setStatusValues(
ImmutableSet.copyOf(Sets.union(domain.getStatusValues(), REGISTRY_LOCK_STATUSES)))
.build();
saveEntities(newDomain, lock, clock);
saveEntities(newDomain, lock, lockTime, true);
}
private static void removeLockStatuses(RegistryLock lock, boolean isAdmin, Clock clock) {
DomainBase domain = getDomain(lock.getDomainName(), clock);
private static void removeLockStatuses(RegistryLock lock, boolean isAdmin, DateTime unlockTime) {
DomainBase domain = getDomain(lock.getDomainName(), unlockTime);
if (!isAdmin) {
verifyDomainLocked(domain);
}
@@ -243,18 +319,21 @@ public final class DomainLockUtils {
ImmutableSet.copyOf(
Sets.difference(domain.getStatusValues(), REGISTRY_LOCK_STATUSES)))
.build();
saveEntities(newDomain, lock, clock);
saveEntities(newDomain, lock, unlockTime, false);
}
private static void saveEntities(DomainBase domain, RegistryLock lock, Clock clock) {
String reason = "Lock or unlock of a domain through a RegistryLock operation";
private static void saveEntities(
DomainBase domain, RegistryLock lock, DateTime now, boolean isLock) {
String reason =
String.format(
"%s of a domain through a RegistryLock operation", isLock ? "Lock" : "Unlock");
HistoryEntry historyEntry =
new HistoryEntry.Builder()
.setClientId(domain.getCurrentSponsorClientId())
.setBySuperuser(lock.isSuperuser())
.setRequestedByRegistrar(!lock.isSuperuser())
.setType(HistoryEntry.Type.DOMAIN_UPDATE)
.setModificationTime(clock.nowUtc())
.setModificationTime(now)
.setParent(Key.create(domain))
.setReason(reason)
.build();
@@ -266,8 +345,8 @@ public final class DomainLockUtils {
.setTargetId(domain.getForeignKey())
.setClientId(domain.getCurrentSponsorClientId())
.setCost(Registry.get(domain.getTld()).getServerStatusChangeCost())
.setEventTime(clock.nowUtc())
.setBillingTime(clock.nowUtc())
.setEventTime(now)
.setBillingTime(now)
.setParent(historyEntry)
.build();
ofy().save().entity(oneTime);
@@ -28,11 +28,13 @@ import com.beust.jcommander.ParameterException;
import com.beust.jcommander.Parameters;
import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.common.annotations.VisibleForTesting;
import google.registry.model.rde.RdeMode;
import google.registry.rde.RdeStagingAction;
import google.registry.tools.params.DateTimeParameter;
import google.registry.util.AppEngineServiceUtils;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Named;
@@ -75,7 +77,16 @@ final class GenerateEscrowDepositCommand implements CommandWithRemoteApi {
private String outdir;
@Inject AppEngineServiceUtils appEngineServiceUtils;
@Inject @Named("rde-report") Queue queue;
@Inject
@Named("rde-report")
Queue queue;
// ETA is a required property for TaskOptions but we let the service to set it when submitting the
// task to the task queue. However, the local test service doesn't do that for us during the unit
// test, so we add this field here to let the unit test be able to inject the ETA to pass the
// test.
@VisibleForTesting Optional<Long> maybeEtaMillis = Optional.empty();
@Override
public void run() {
@@ -115,6 +126,9 @@ final class GenerateEscrowDepositCommand implements CommandWithRemoteApi {
if (revision != null) {
opts = opts.param(PARAM_REVISION, String.valueOf(revision));
}
if (maybeEtaMillis.isPresent()) {
opts = opts.etaMillis(maybeEtaMillis.get());
}
queue.add(opts);
}
}
@@ -22,7 +22,6 @@ import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import google.registry.model.domain.DomainBase;
import google.registry.model.eppcommon.StatusValue;
import google.registry.schema.domain.RegistryLock;
import org.joda.time.DateTime;
/**
@@ -36,35 +35,24 @@ public class LockDomainCommand extends LockOrUnlockDomainCommand {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@Override
protected ImmutableSet<String> getRelevantDomains() {
// Project all domains as of the same time so that argument order doesn't affect behavior.
DateTime now = clock.nowUtc();
ImmutableSet.Builder<String> relevantDomains = new ImmutableSet.Builder<>();
for (String domain : getDomains()) {
DomainBase domainBase =
loadByForeignKey(DomainBase.class, domain, now)
.orElseThrow(
() ->
new IllegalArgumentException(
String.format("Domain '%s' does not exist or is deleted", domain)));
ImmutableSet<StatusValue> statusesToAdd =
Sets.difference(REGISTRY_LOCK_STATUSES, domainBase.getStatusValues()).immutableCopy();
if (statusesToAdd.isEmpty()) {
logger.atInfo().log("Domain '%s' is already locked and needs no updates.", domain);
continue;
}
relevantDomains.add(domain);
protected boolean shouldApplyToDomain(String domain, DateTime now) {
DomainBase domainBase =
loadByForeignKey(DomainBase.class, domain, now)
.orElseThrow(
() ->
new IllegalArgumentException(
String.format("Domain '%s' does not exist or is deleted", domain)));
ImmutableSet<StatusValue> statusesToAdd =
Sets.difference(REGISTRY_LOCK_STATUSES, domainBase.getStatusValues()).immutableCopy();
if (statusesToAdd.isEmpty()) {
logger.atInfo().log("Domain '%s' is already locked and needs no updates.", domain);
return false;
}
return relevantDomains.build();
return true;
}
@Override
protected RegistryLock createLock(String domain) {
return domainLockUtils.createRegistryLockRequest(domain, clientId, null, true, clock);
}
@Override
protected void finalizeLockOrUnlockRequest(RegistryLock lock) {
domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), true, clock);
protected void createAndApplyRequest(String domain) {
domainLockUtils.administrativelyApplyLock(domain, clientId, null, true);
}
}
@@ -15,22 +15,22 @@
package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Iterables.partition;
import static google.registry.model.eppcommon.StatusValue.SERVER_DELETE_PROHIBITED;
import static google.registry.model.eppcommon.StatusValue.SERVER_TRANSFER_PROHIBITED;
import static google.registry.model.eppcommon.StatusValue.SERVER_UPDATE_PROHIBITED;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.findDuplicates;
import com.beust.jcommander.Parameter;
import com.google.common.base.Joiner;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.eppcommon.StatusValue;
import google.registry.schema.domain.RegistryLock;
import google.registry.util.Clock;
import java.util.List;
import javax.inject.Inject;
import org.joda.time.DateTime;
/** Shared base class for commands to registry lock or unlock a domain via EPP. */
public abstract class LockOrUnlockDomainCommand extends ConfirmingCommand
@@ -38,6 +38,8 @@ public abstract class LockOrUnlockDomainCommand extends ConfirmingCommand
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final int BATCH_SIZE = 10;
public static final ImmutableSet<StatusValue> REGISTRY_LOCK_STATUSES =
ImmutableSet.of(
SERVER_DELETE_PROHIBITED, SERVER_TRANSFER_PROHIBITED, SERVER_UPDATE_PROHIBITED);
@@ -55,12 +57,8 @@ public abstract class LockOrUnlockDomainCommand extends ConfirmingCommand
@Config("registryAdminClientId")
String registryAdminClientId;
@Inject Clock clock;
@Inject DomainLockUtils domainLockUtils;
protected ImmutableSet<String> relevantDomains = ImmutableSet.of();
protected ImmutableSet<String> getDomains() {
return ImmutableSet.copyOf(mainParameters);
}
@@ -75,34 +73,42 @@ public abstract class LockOrUnlockDomainCommand extends ConfirmingCommand
checkArgument(duplicates.isEmpty(), "Duplicate domain arguments found: '%s'", duplicates);
System.out.println(
"== ENSURE THAT YOU HAVE AUTHENTICATED THE REGISTRAR BEFORE RUNNING THIS COMMAND ==");
relevantDomains = getRelevantDomains();
}
@Override
protected String execute() {
int failures = 0;
for (String domain : relevantDomains) {
try {
RegistryLock lock = createLock(domain);
finalizeLockOrUnlockRequest(lock);
} catch (Throwable t) {
Throwable rootCause = Throwables.getRootCause(t);
logger.atSevere().withCause(rootCause).log("Error when (un)locking domain %s.", domain);
failures++;
}
}
if (failures == 0) {
return String.format("Successfully locked/unlocked %d domains.", relevantDomains.size());
} else {
return String.format(
"Successfully locked/unlocked %d domains with %d failures.",
relevantDomains.size() - failures, failures);
}
ImmutableSet.Builder<String> successfulDomainsBuilder = new ImmutableSet.Builder<>();
ImmutableSet.Builder<String> skippedDomainsBuilder = new ImmutableSet.Builder<>();
ImmutableSet.Builder<String> failedDomainsBuilder = new ImmutableSet.Builder<>();
partition(getDomains(), BATCH_SIZE)
.forEach(
batch ->
tm().transact(
() -> {
for (String domain : batch) {
if (shouldApplyToDomain(domain, tm().getTransactionTime())) {
try {
createAndApplyRequest(domain);
} catch (Throwable t) {
logger.atSevere().withCause(t).log(
"Error when (un)locking domain %s.", domain);
failedDomainsBuilder.add(domain);
}
successfulDomainsBuilder.add(domain);
} else {
skippedDomainsBuilder.add(domain);
}
}
}));
ImmutableSet<String> successfulDomains = successfulDomainsBuilder.build();
ImmutableSet<String> skippedDomains = skippedDomainsBuilder.build();
ImmutableSet<String> failedDomains = failedDomainsBuilder.build();
return String.format(
"Successfully locked/unlocked domains:\n%s\nSkipped domains:\n%s\nFailed domains:\n%s",
successfulDomains, skippedDomains, failedDomains);
}
protected abstract ImmutableSet<String> getRelevantDomains();
protected abstract boolean shouldApplyToDomain(String domain, DateTime now);
protected abstract RegistryLock createLock(String domain);
protected abstract void finalizeLockOrUnlockRequest(RegistryLock lock);
protected abstract void createAndApplyRequest(String domain);
}
@@ -22,7 +22,6 @@ import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import google.registry.model.domain.DomainBase;
import google.registry.model.eppcommon.StatusValue;
import google.registry.schema.domain.RegistryLock;
import org.joda.time.DateTime;
/**
@@ -36,35 +35,24 @@ public class UnlockDomainCommand extends LockOrUnlockDomainCommand {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@Override
protected ImmutableSet<String> getRelevantDomains() {
// Project all domains as of the same time so that argument order doesn't affect behavior.
DateTime now = clock.nowUtc();
ImmutableSet.Builder<String> relevantDomains = new ImmutableSet.Builder<>();
for (String domain : getDomains()) {
DomainBase domainBase =
loadByForeignKey(DomainBase.class, domain, now)
.orElseThrow(
() ->
new IllegalArgumentException(
String.format("Domain '%s' does not exist or is deleted", domain)));
ImmutableSet<StatusValue> statusesToRemove =
Sets.intersection(domainBase.getStatusValues(), REGISTRY_LOCK_STATUSES).immutableCopy();
if (statusesToRemove.isEmpty()) {
logger.atInfo().log("Domain '%s' is already unlocked and needs no updates.", domain);
continue;
}
relevantDomains.add(domain);
protected boolean shouldApplyToDomain(String domain, DateTime now) {
DomainBase domainBase =
loadByForeignKey(DomainBase.class, domain, now)
.orElseThrow(
() ->
new IllegalArgumentException(
String.format("Domain '%s' does not exist or is deleted", domain)));
ImmutableSet<StatusValue> statusesToRemove =
Sets.intersection(domainBase.getStatusValues(), REGISTRY_LOCK_STATUSES).immutableCopy();
if (statusesToRemove.isEmpty()) {
logger.atInfo().log("Domain '%s' is already unlocked and needs no updates.", domain);
return false;
}
return relevantDomains.build();
return true;
}
@Override
protected RegistryLock createLock(String domain) {
return domainLockUtils.createRegistryUnlockRequest(domain, clientId, true, clock);
}
@Override
protected void finalizeLockOrUnlockRequest(RegistryLock lock) {
domainLockUtils.verifyAndApplyUnlock(lock.getVerificationCode(), true, clock);
protected void createAndApplyRequest(String domain) {
domainLockUtils.administrativelyApplyUnlock(domain, clientId, true);
}
}
@@ -14,13 +14,13 @@
package google.registry.tools;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
import com.beust.jcommander.Parameters;
import google.registry.config.RegistryEnvironment;
import google.registry.model.registrar.Registrar;
import google.registry.schema.registrar.RegistrarDao;
import javax.annotation.Nullable;
/** Command to update a Registrar. */
@@ -53,6 +53,6 @@ final class UpdateRegistrarCommand extends CreateOrUpdateRegistrarCommand {
@Override
void saveToCloudSql(Registrar registrar) {
RegistrarDao.update(registrar);
jpaTm().update(registrar);
}
}
@@ -17,6 +17,7 @@ package google.registry.tools.javascrap;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import com.beust.jcommander.Parameter;
@@ -73,15 +74,14 @@ public class BackfillRegistryLocksCommand extends ConfirmingCommand
@Named("base58StringGenerator")
StringGenerator stringGenerator;
private DateTime now;
private ImmutableList<DomainBase> lockedDomains;
@Override
protected String prompt() {
checkArgument(
roids != null && !roids.isEmpty(), "Must provide non-empty domain_roids argument");
now = clock.nowUtc();
lockedDomains = getLockedDomainsWithoutLocks();
lockedDomains =
jpaTm().transact(() -> getLockedDomainsWithoutLocks(jpaTm().getTransactionTime()));
ImmutableList<String> lockedDomainNames =
lockedDomains.stream()
.map(DomainBase::getFullyQualifiedDomainName)
@@ -94,24 +94,30 @@ public class BackfillRegistryLocksCommand extends ConfirmingCommand
@Override
protected String execute() {
ImmutableSet.Builder<DomainBase> failedDomainsBuilder = new ImmutableSet.Builder<>();
for (DomainBase domainBase : lockedDomains) {
try {
RegistryLockDao.save(
new RegistryLock.Builder()
.isSuperuser(true)
.setRegistrarId(registryAdminClientId)
.setRepoId(domainBase.getRepoId())
.setDomainName(domainBase.getFullyQualifiedDomainName())
.setLockCompletionTimestamp(getLockCompletionTimestamp(domainBase, now))
.setVerificationCode(stringGenerator.createString(VERIFICATION_CODE_LENGTH))
.build());
} catch (Throwable t) {
logger.atSevere().withCause(t).log(
"Error when creating lock object for domain %s.",
domainBase.getFullyQualifiedDomainName());
failedDomainsBuilder.add(domainBase);
}
}
jpaTm()
.transact(
() -> {
for (DomainBase domainBase : lockedDomains) {
try {
RegistryLockDao.save(
new RegistryLock.Builder()
.isSuperuser(true)
.setRegistrarId(registryAdminClientId)
.setRepoId(domainBase.getRepoId())
.setDomainName(domainBase.getFullyQualifiedDomainName())
.setLockCompletionTimestamp(
getLockCompletionTimestamp(domainBase, jpaTm().getTransactionTime()))
.setVerificationCode(
stringGenerator.createString(VERIFICATION_CODE_LENGTH))
.build());
} catch (Throwable t) {
logger.atSevere().withCause(t).log(
"Error when creating lock object for domain %s.",
domainBase.getFullyQualifiedDomainName());
failedDomainsBuilder.add(domainBase);
}
}
});
ImmutableSet<DomainBase> failedDomains = failedDomainsBuilder.build();
if (failedDomains.isEmpty()) {
return String.format(
@@ -136,14 +142,16 @@ public class BackfillRegistryLocksCommand extends ConfirmingCommand
.orElse(now);
}
private ImmutableList<DomainBase> getLockedDomainsWithoutLocks() {
private ImmutableList<DomainBase> getLockedDomainsWithoutLocks(DateTime now) {
return ImmutableList.copyOf(
ofy().load()
ofy()
.load()
.keys(
roids.stream()
.map(roid -> Key.create(DomainBase.class, roid))
.collect(toImmutableList()))
.values().stream()
.values()
.stream()
.filter(d -> d.getDeletionTime().isAfter(now))
.filter(d -> d.getStatusValues().containsAll(REGISTRY_LOCK_STATUSES))
.filter(d -> !RegistryLockDao.getMostRecentByRepoId(d.getRepoId()).isPresent())
@@ -37,6 +37,7 @@ import google.registry.util.X509Utils;
import java.security.cert.CertificateParsingException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
@@ -204,8 +205,10 @@ public final class RegistrarFormFields {
public static final FormField<String, String> CONTACT_GAE_USER_ID_FIELD =
FormFields.NAME.asBuilderNamed("gaeUserId").build();
public static final FormField<Boolean, Boolean> CONTACT_ALLOWED_TO_SET_REGISTRY_LOCK_PASSWORD =
FormField.named("allowedToSetRegistryLockPassword", Boolean.class).build();
public static final FormField<Object, Boolean> CONTACT_ALLOWED_TO_SET_REGISTRY_LOCK_PASSWORD =
FormField.named("allowedToSetRegistryLockPassword", Object.class)
.transform(Boolean.class, b -> Boolean.valueOf(Objects.toString(b)))
.build();
public static final FormField<String, String> CONTACT_REGISTRY_LOCK_PASSWORD_FIELD =
FormFields.NAME.asBuilderNamed("registryLockPassword").build();
@@ -384,6 +387,8 @@ public final class RegistrarFormFields {
builder.setFaxNumber(CONTACT_FAX_NUMBER_FIELD.extractUntyped(args).orElse(null));
builder.setTypes(CONTACT_TYPES.extractUntyped(args).orElse(ImmutableSet.of()));
builder.setGaeUserId(CONTACT_GAE_USER_ID_FIELD.extractUntyped(args).orElse(null));
// The parser is inconsistent with whether it retrieves boolean values as strings or booleans.
// As a result, use a potentially-redundant converter that can deal with both.
builder.setAllowedToSetRegistryLockPassword(
CONTACT_ALLOWED_TO_SET_REGISTRY_LOCK_PASSWORD.extractUntyped(args).orElse(false));
@@ -16,6 +16,7 @@ package google.registry.ui.server.registrar;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.security.JsonResponseHelper.Status.SUCCESS;
import static google.registry.ui.server.registrar.RegistrarConsoleModule.PARAM_CLIENT_ID;
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
@@ -67,6 +68,8 @@ public final class RegistryLockGetAction implements JsonGetAction {
private static final String FULLY_QUALIFIED_DOMAIN_NAME_PARAM = "fullyQualifiedDomainName";
private static final String LOCKED_TIME_PARAM = "lockedTime";
private static final String LOCKED_BY_PARAM = "lockedBy";
private static final String IS_LOCK_PENDING_PARAM = "isLockPending";
private static final String IS_UNLOCK_PENDING_PARAM = "isUnlockPending";
private static final String USER_CAN_UNLOCK_PARAM = "userCanUnlock";
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@@ -151,20 +154,29 @@ public final class RegistryLockGetAction implements JsonGetAction {
private ImmutableList<ImmutableMap<String, ?>> getLockedDomains(
String clientId, boolean isAdmin) {
return RegistryLockDao.getLockedDomainsByRegistrarId(clientId).stream()
.map(lock -> lockToMap(lock, isAdmin))
.collect(toImmutableList());
return jpaTm()
.transact(
() ->
RegistryLockDao.getLocksByRegistrarId(clientId).stream()
.filter(lock -> !lock.isLockRequestExpired(jpaTm().getTransactionTime()))
.map(lock -> lockToMap(lock, isAdmin))
.collect(toImmutableList()));
}
private ImmutableMap<String, ?> lockToMap(RegistryLock lock, boolean isAdmin) {
return ImmutableMap.of(
FULLY_QUALIFIED_DOMAIN_NAME_PARAM,
lock.getDomainName(),
LOCKED_TIME_PARAM,
lock.getLockCompletionTimestamp().map(DateTime::toString).orElse(""),
LOCKED_BY_PARAM,
lock.isSuperuser() ? "admin" : lock.getRegistrarPocId(),
USER_CAN_UNLOCK_PARAM,
isAdmin || !lock.isSuperuser());
DateTime now = jpaTm().getTransactionTime();
return new ImmutableMap.Builder<String, Object>()
.put(FULLY_QUALIFIED_DOMAIN_NAME_PARAM, lock.getDomainName())
.put(
LOCKED_TIME_PARAM, lock.getLockCompletionTimestamp().map(DateTime::toString).orElse(""))
.put(LOCKED_BY_PARAM, lock.isSuperuser() ? "admin" : lock.getRegistrarPocId())
.put(IS_LOCK_PENDING_PARAM, !lock.getLockCompletionTimestamp().isPresent())
.put(
IS_UNLOCK_PENDING_PARAM,
lock.getUnlockRequestTimestamp().isPresent()
&& !lock.getUnlockCompletionTimestamp().isPresent()
&& !lock.isUnlockRequestExpired(now))
.put(USER_CAN_UNLOCK_PARAM, isAdmin || !lock.isSuperuser())
.build();
}
}
@@ -43,7 +43,6 @@ import google.registry.request.auth.UserAuthInfo;
import google.registry.schema.domain.RegistryLock;
import google.registry.security.JsonResponseHelper;
import google.registry.tools.DomainLockUtils;
import google.registry.util.Clock;
import google.registry.util.EmailMessage;
import google.registry.util.SendEmailService;
import java.net.URISyntaxException;
@@ -82,7 +81,6 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc
private final AuthResult authResult;
private final AuthenticatedRegistrarAccessor registrarAccessor;
private final SendEmailService sendEmailService;
private final Clock clock;
private final DomainLockUtils domainLockUtils;
private final InternetAddress gSuiteOutgoingEmailAddress;
@@ -92,14 +90,12 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc
AuthResult authResult,
AuthenticatedRegistrarAccessor registrarAccessor,
SendEmailService sendEmailService,
Clock clock,
DomainLockUtils domainLockUtils,
@Config("gSuiteOutgoingEmailAddress") InternetAddress gSuiteOutgoingEmailAddress) {
this.jsonActionRunner = jsonActionRunner;
this.authResult = authResult;
this.registrarAccessor = registrarAccessor;
this.sendEmailService = sendEmailService;
this.clock = clock;
this.domainLockUtils = domainLockUtils;
this.gSuiteOutgoingEmailAddress = gSuiteOutgoingEmailAddress;
}
@@ -138,14 +134,13 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc
() -> {
RegistryLock registryLock =
postInput.isLock
? domainLockUtils.createRegistryLockRequest(
? domainLockUtils.saveNewRegistryLockRequest(
postInput.fullyQualifiedDomainName,
postInput.clientId,
userEmail,
isAdmin,
clock)
: domainLockUtils.createRegistryUnlockRequest(
postInput.fullyQualifiedDomainName, postInput.clientId, isAdmin, clock);
isAdmin)
: domainLockUtils.saveNewRegistryUnlockRequest(
postInput.fullyQualifiedDomainName, postInput.clientId, isAdmin);
sendVerificationEmail(registryLock, userEmail, postInput.isLock);
});
String action = postInput.isLock ? "lock" : "unlock";
@@ -27,7 +27,6 @@ import google.registry.schema.domain.RegistryLock;
import google.registry.tools.DomainLockUtils;
import google.registry.ui.server.SoyTemplateUtils;
import google.registry.ui.soy.registrar.RegistryLockVerificationSoyInfo;
import google.registry.util.Clock;
import java.util.HashMap;
import javax.inject.Inject;
@@ -48,18 +47,15 @@ public final class RegistryLockVerifyAction extends HtmlAction {
google.registry.ui.soy.AnalyticsSoyInfo.getInstance(),
google.registry.ui.soy.registrar.RegistryLockVerificationSoyInfo.getInstance());
private final Clock clock;
private final DomainLockUtils domainLockUtils;
private final String lockVerificationCode;
private final Boolean isLock;
@Inject
public RegistryLockVerifyAction(
Clock clock,
DomainLockUtils domainLockUtils,
@Parameter("lockVerificationCode") String lockVerificationCode,
@Parameter("isLock") Boolean isLock) {
this.clock = clock;
this.domainLockUtils = domainLockUtils;
this.lockVerificationCode = lockVerificationCode;
this.isLock = isLock;
@@ -71,9 +67,9 @@ public final class RegistryLockVerifyAction extends HtmlAction {
boolean isAdmin = authResult.userAuthInfo().get().isUserAdmin();
final RegistryLock resultLock;
if (isLock) {
resultLock = domainLockUtils.verifyAndApplyLock(lockVerificationCode, isAdmin, clock);
resultLock = domainLockUtils.verifyAndApplyLock(lockVerificationCode, isAdmin);
} else {
resultLock = domainLockUtils.verifyAndApplyUnlock(lockVerificationCode, isAdmin, clock);
resultLock = domainLockUtils.verifyAndApplyUnlock(lockVerificationCode, isAdmin);
}
data.put("isLock", isLock);
data.put("success", true);
@@ -37,7 +37,9 @@ registry.json.locks = {};
* fullyQualifiedDomainName: string,
* lockedTime: string,
* lockedBy: string,
* userCanUnlock: boolean
* userCanUnlock: boolean,
* isLockPending: boolean,
* isUnlockPending: boolean
* }}
*/
registry.json.locks.ExistingLock;
@@ -45,6 +45,7 @@ registry.registrar.RegistryLock = function(console, resource) {
goog.inherits(registry.registrar.RegistryLock, registry.ResourceComponent);
registry.registrar.RegistryLock.prototype.runAfterRender = function(objArgs) {
this.isAdmin = objArgs.isAdmin;
this.clientId = objArgs.clientId;
this.xsrfToken = objArgs.xsrfToken;
@@ -55,8 +56,7 @@ registry.registrar.RegistryLock.prototype.runAfterRender = function(objArgs) {
} else {
goog.soy.renderElement(
goog.dom.getRequiredElement('locks-content'),
registry.soy.registrar.registrylock.lockNotAllowedOnRegistrar,
{supportEmail: objArgs.supportEmail});
registry.soy.registrar.registrylock.lockNotAllowedOnRegistrar);
}
};
@@ -92,7 +92,7 @@ registry.registrar.RegistryLock.prototype.fillLocksPage_ = function(e) {
lockEnabledForContact: locksDetails.lockEnabledForContact});
if (locksDetails.lockEnabledForContact) {
// Listen to the lock-domain 'submit' button click as well as the enter key
// Listen to the lock-domain 'submit' button click
var lockButton = goog.dom.getRequiredElement('button-lock-domain');
goog.events.listen(lockButton, goog.events.EventType.CLICK, this.onLockDomain_, false, this);
// For all unlock buttons, listen and perform the unlock action if they're clicked
@@ -115,9 +115,14 @@ registry.registrar.RegistryLock.prototype.showModal_ = function(targetElement, d
var parentElement = targetElement.parentElement;
// attach the modal to the parent element so focus remains correct if the user closes the modal
var modalElement = goog.soy.renderAsElement(
registry.soy.registrar.registrylock.confirmModal, {domain: domain, isLock: isLock});
registry.soy.registrar.registrylock.confirmModal,
{domain: domain, isLock: isLock, isAdmin: this.isAdmin});
parentElement.prepend(modalElement);
goog.dom.getRequiredElement('domain-lock-password').focus();
if (domain == null) {
goog.dom.getRequiredElement('domain-lock-input-value').focus();
} else {
goog.dom.getRequiredElement('domain-lock-password').focus();
}
// delete the modal when the user clicks the cancel button
goog.events.listen(
goog.dom.getRequiredElement('domain-lock-cancel'),
@@ -126,12 +131,29 @@ registry.registrar.RegistryLock.prototype.showModal_ = function(targetElement, d
false,
this);
// Listen to the "submit" click and also the user hitting enter
goog.events.listen(
goog.dom.getRequiredElement('domain-lock-submit'),
goog.events.EventType.CLICK,
e => this.lockOrUnlockDomain_(isLock, e),
false,
this);
[goog.dom.getElement('domain-lock-password'),
goog.dom.getElement('domain-lock-input-value')].forEach(elem => {
if (elem != null) {
goog.events.listen(
elem,
goog.events.EventType.KEYPRESS,
e => {
if (e.keyCode === goog.events.KeyCodes.ENTER) {
this.lockOrUnlockDomain_(isLock, e);
}
},
false,
this);
}
});
}
/**
@@ -256,10 +256,13 @@
{param placeholder: $placeholder /}
{/call}
{/if}
{if isNonnull($item['allowedToSetRegistryLockPassword'])}
<input type="hidden" name="allowedToSetRegistryLockPassword"
value="{$item['allowedToSetRegistryLockPassword']}">
{/if}
<input type="hidden" name="{$namePrefix}allowedToSetRegistryLockPassword"
{if isNonnull($item['allowedToSetRegistryLockPassword'])}
value="{$item['allowedToSetRegistryLockPassword']}"
{else}
value="false"
{/if}
>
<tr>
<td colspan="2">
<hr>
@@ -23,7 +23,8 @@
{template .locksContent}
{@param email: string}
{@param locks: list<[fullyQualifiedDomainName: string, lockedTime: string, lockedBy: string, userCanUnlock: bool]>}
{@param locks: list<[fullyQualifiedDomainName: string, lockedTime: string, lockedBy: string,
userCanUnlock: bool, isLockPending: bool, isUnlockPending: bool]>}
{@param lockEnabledForContact: bool}
{call .newLock}
@@ -63,7 +64,8 @@
/** Table that displays existing locks for this registrar. */
{template .existingLocksTable}
{@param locks: list<[fullyQualifiedDomainName: string, lockedTime: string, lockedBy: string, userCanUnlock: bool]>}
{@param locks: list<[fullyQualifiedDomainName: string, lockedTime: string, lockedBy: string,
userCanUnlock: bool, isLockPending: bool, isUnlockPending: bool]>}
{@param lockEnabledForContact: bool}
<h2>Existing locks</h2>
<br>
@@ -76,19 +78,24 @@
</tr>
{for $lock in $locks}
<tr class="{css('registry-locks-table-row')}">
<td>{$lock.fullyQualifiedDomainName}</td>
<td>{$lock.fullyQualifiedDomainName}
{if $lock.isLockPending}<i> (pending)</i>
{elseif $lock.isUnlockPending}<i> (unlock pending)</i>
{/if}</td>
<td>{$lock.lockedTime}</td>
<td>{$lock.lockedBy}</td>
<td>
<button id="button-unlock-{$lock.fullyQualifiedDomainName}"
{if $lockEnabledForContact and $lock.userCanUnlock}
class="domain-unlock-button {css('kd-button')} {css('kd-button-submit')}"
{else}
class="{css('kd-button')}"
disabled
{/if}
>Unlock
</button>
{if not $lock.isLockPending and not $lock.isUnlockPending}
<button id="button-unlock-{$lock.fullyQualifiedDomainName}"
{if $lockEnabledForContact and $lock.userCanUnlock}
class="domain-unlock-button {css('kd-button')} {css('kd-button-submit')}"
{else}
class="{css('kd-button')}"
disabled
{/if}
>Unlock
</button>
{/if}
</td>
</tr>
{/for}
@@ -99,6 +106,7 @@
/** Modal that confirms that the user wishes to lock/unlock a domain. */
{template .confirmModal}
{@param isLock: bool}
{@param isAdmin: bool}
{@param? domain: string|null}
<div id="lock-confirm-modal" class="{css('lock-confirm-modal')}">
<div class="modal-content">
@@ -110,9 +118,11 @@
value="{$domain}" disabled
{/if}>
<br>
<label for="domain-lock-password">Registry lock password: </label>
<input type="password" id="domain-lock-password">
<br>
{if not $isAdmin}
<label for="domain-lock-password">Registry lock password: </label>
<input type="password" id="domain-lock-password">
<br>
{/if}
<div id="modal-error-message" hidden class="{css('kd-errormessage')}"></div>
<div class="{css('buttons-div')}">
<button id="domain-lock-cancel" class="{css('kd-button')}">Cancel</button>
@@ -126,7 +136,5 @@
/** Content if the registrar is not allowed to use registry lock. */
{template .lockNotAllowedOnRegistrar}
{@param supportEmail: string}
<h2>Sorry, your registrar hasn't enrolled in registry lock yet. To do so, please
contact {$supportEmail}.</h2>
<h2>Registry Lock is coming soon; please stay tuned for updates.</h2>
{/template}
@@ -46,10 +46,8 @@ public class CommitLogCheckpointActionTest {
private static final String QUEUE_NAME = "export-commits";
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
CommitLogCheckpointStrategy strategy = mock(CommitLogCheckpointStrategy.class);
@@ -47,9 +47,7 @@ import org.junit.runners.JUnit4;
public class CommitLogCheckpointStrategyTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -50,9 +50,7 @@ import org.junit.runners.JUnit4;
public class ExportCommitLogDiffActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
/** Local GCS service available for testing. */
private final GcsService gcsService = GcsServiceFactory.createGcsService();
@@ -62,9 +62,7 @@ public class GcsDiffFileListerTest {
private final TestLogHandler logHandler = new TestLogHandler();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Before
public void before() throws Exception {
@@ -71,9 +71,7 @@ public class RestoreCommitLogsActionTest {
final GcsService gcsService = createGcsService();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Before
public void init() {
@@ -61,7 +61,7 @@ public class AsyncTaskEnqueuerTest extends ShardableTestCase {
@Rule
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastore().withTaskQueue().build();
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule public final InjectRule inject = new InjectRule();
@@ -0,0 +1,176 @@
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.batch;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.eppcommon.StatusValue.PENDING_DELETE;
import static google.registry.model.eppcommon.StatusValue.PENDING_TRANSFER;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.testing.DatastoreHelper.createTlds;
import static google.registry.testing.DatastoreHelper.newDomainBase;
import static google.registry.testing.DatastoreHelper.persistActiveHost;
import static google.registry.testing.DatastoreHelper.persistDomainAsDeleted;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.SqlHelper.getMostRecentVerifiedRegistryLockByRepoId;
import static google.registry.testing.SqlHelper.getRegistryLockByVerificationCode;
import static google.registry.testing.SqlHelper.saveRegistryLock;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import com.google.common.collect.ImmutableSet;
import google.registry.model.domain.DomainBase;
import google.registry.model.host.HostResource;
import google.registry.schema.domain.RegistryLock;
import google.registry.testing.AppEngineRule;
import google.registry.testing.DeterministicStringGenerator;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse;
import google.registry.testing.UserInfo;
import google.registry.tools.DomainLockUtils;
import google.registry.util.StringGenerator.Alphabets;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link RelockDomainAction}. */
@RunWith(JUnit4.class)
public class RelockDomainActionTest {
private static final String DOMAIN_NAME = "example.tld";
private static final String CLIENT_ID = "TheRegistrar";
private static final String POC_ID = "marla.singer@example.com";
private final FakeResponse response = new FakeResponse();
private final FakeClock clock = new FakeClock();
private final DomainLockUtils domainLockUtils =
new DomainLockUtils(new DeterministicStringGenerator(Alphabets.BASE_58));
@Rule
public final AppEngineRule appEngineRule =
AppEngineRule.builder()
.withDatastoreAndCloudSql()
.withUserService(UserInfo.create(POC_ID, "12345"))
.build();
private DomainBase domain;
private RegistryLock oldLock;
private RelockDomainAction action;
@Before
public void setup() {
createTlds("tld", "net");
HostResource host = persistActiveHost("ns1.example.net");
domain = persistResource(newDomainBase(DOMAIN_NAME, host));
oldLock = domainLockUtils.administrativelyApplyLock(DOMAIN_NAME, CLIENT_ID, POC_ID, false);
assertThat(reloadDomain(domain).getStatusValues())
.containsAtLeastElementsIn(REGISTRY_LOCK_STATUSES);
oldLock = domainLockUtils.administrativelyApplyUnlock(DOMAIN_NAME, CLIENT_ID, false);
assertThat(reloadDomain(domain).getStatusValues()).containsNoneIn(REGISTRY_LOCK_STATUSES);
action = createAction(oldLock.getRevisionId());
}
@Test
public void testLock() {
action.run();
assertThat(reloadDomain(domain).getStatusValues())
.containsAtLeastElementsIn(REGISTRY_LOCK_STATUSES);
// the old lock should have a reference to the relock
RegistryLock newLock = getMostRecentVerifiedRegistryLockByRepoId(domain.getRepoId()).get();
assertThat(getRegistryLockByVerificationCode(oldLock.getVerificationCode()).get().getRelock())
.isEqualTo(newLock);
}
@Test
public void testFailure_unknownCode() {
action = createAction(12128675309L);
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload()).isEqualTo("Relock failed: Unknown revision ID 12128675309");
}
@Test
public void testFailure_pendingDelete() {
persistResource(domain.asBuilder().setStatusValues(ImmutableSet.of(PENDING_DELETE)).build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo(String.format("Relock failed: Domain %s has a pending delete", DOMAIN_NAME));
}
@Test
public void testFailure_pendingTransfer() {
persistResource(domain.asBuilder().setStatusValues(ImmutableSet.of(PENDING_TRANSFER)).build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo(String.format("Relock failed: Domain %s has a pending transfer", DOMAIN_NAME));
}
@Test
public void testFailure_domainAlreadyLocked() {
domainLockUtils.administrativelyApplyLock(DOMAIN_NAME, CLIENT_ID, null, true);
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo("Domain example.tld is already manually relocked, skipping automated relock.");
}
@Test
public void testFailure_domainDeleted() {
persistDomainAsDeleted(domain, clock.nowUtc());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo(String.format("Relock failed: Domain %s has been deleted", DOMAIN_NAME));
}
@Test
public void testFailure_domainTransferred() {
persistResource(domain.asBuilder().setPersistedCurrentSponsorClientId("NewRegistrar").build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo(
String.format(
"Relock failed: Domain %s has been transferred from registrar %s to registrar "
+ "%s since the unlock",
DOMAIN_NAME, CLIENT_ID, "NewRegistrar"));
}
@Test
public void testFailure_relockAlreadySet() {
RegistryLock newLock =
domainLockUtils.administrativelyApplyLock(DOMAIN_NAME, CLIENT_ID, null, true);
saveRegistryLock(oldLock.asBuilder().setRelock(newLock).build());
// Save the domain without the lock statuses so that we pass that check in the action
persistResource(domain.asBuilder().setStatusValues(ImmutableSet.of()).build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo("Domain example.tld is already manually relocked, skipping automated relock.");
}
private DomainBase reloadDomain(DomainBase domain) {
return ofy().load().entity(domain).now();
}
private RelockDomainAction createAction(Long oldUnlockRevisionId) {
return new RelockDomainAction(oldUnlockRevisionId, domainLockUtils, response);
}
}
@@ -70,7 +70,7 @@ public class ResaveEntityActionTest extends ShardableTestCase {
@Rule
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastore().withTaskQueue().build();
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule public final InjectRule inject = new InjectRule();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@@ -39,17 +39,20 @@ public class CommitLogFanoutActionTest {
private static final String QUEUE = "the-queue";
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue(Joiner.on('\n').join(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<queue-entries>",
" <queue>",
" <name>the-queue</name>",
" <rate>1/s</rate>",
" </queue>",
"</queue-entries>"))
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder()
.withDatastoreAndCloudSql()
.withTaskQueue(
Joiner.on('\n')
.join(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<queue-entries>",
" <queue>",
" <name>the-queue</name>",
" <rate>1/s</rate>",
" </queue>",
"</queue-entries>"))
.build();
@Test
public void testSuccess() {
@@ -54,17 +54,20 @@ public class TldFanoutActionTest {
private final FakeResponse response = new FakeResponse();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue(Joiner.on('\n').join(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<queue-entries>",
" <queue>",
" <name>the-queue</name>",
" <rate>1/s</rate>",
" </queue>",
"</queue-entries>"))
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder()
.withDatastoreAndCloudSql()
.withTaskQueue(
Joiner.on('\n')
.join(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<queue-entries>",
" <queue>",
" <name>the-queue</name>",
" <rate>1/s</rate>",
" </queue>",
"</queue-entries>"))
.build();
private static ImmutableListMultimap<String, String> getParamsMap(String... keysAndValues) {
ImmutableListMultimap.Builder<String, String> params = new ImmutableListMultimap.Builder<>();
@@ -46,10 +46,8 @@ import org.junit.runners.JUnit4;
public final class DnsInjectionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -35,10 +35,9 @@ import org.junit.runners.JUnit4;
public class DnsQueueTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
private DnsQueue dnsQueue;
private final FakeClock clock = new FakeClock(DateTime.parse("2010-01-01T10:00:00Z"));
@@ -55,10 +55,8 @@ import org.junit.runners.JUnit4;
public class PublishDnsUpdatesActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -73,22 +73,25 @@ public class ReadDnsQueueActionTest {
private FakeClock clock = new FakeClock(DateTime.parse("3000-01-01TZ"));
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue(Joiner.on('\n').join(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<queue-entries>",
" <queue>",
" <name>dns-publish</name>",
" <rate>1/s</rate>",
" </queue>",
" <queue>",
" <name>dns-pull</name>",
" <mode>pull</mode>",
" </queue>",
"</queue-entries>"))
.withClock(clock)
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder()
.withDatastoreAndCloudSql()
.withTaskQueue(
Joiner.on('\n')
.join(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<queue-entries>",
" <queue>",
" <name>dns-publish</name>",
" <rate>1/s</rate>",
" </queue>",
" <queue>",
" <name>dns-pull</name>",
" <mode>pull</mode>",
" </queue>",
"</queue-entries>"))
.withClock(clock)
.build();
@Before
public void before() {
@@ -42,7 +42,7 @@ public class RefreshDnsActionTest {
@Rule
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastore().withTaskQueue().build();
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
private final DnsQueue dnsQueue = mock(DnsQueue.class);
private final FakeClock clock = new FakeClock();
@@ -69,7 +69,9 @@ import org.mockito.junit.MockitoRule;
@RunWith(JUnit4.class)
public class CloudDnsWriterTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
private static final Inet4Address IPv4 = (Inet4Address) InetAddresses.forString("127.0.0.1");
@@ -76,7 +76,7 @@ public class DnsUpdateWriterTest {
@Rule
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastore().withTaskQueue().build();
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@Rule public final InjectRule inject = new InjectRule();
@@ -62,10 +62,9 @@ import org.junit.runners.JUnit4;
public class BigqueryPollJobActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
private static final String PROJECT_ID = "project_id";
private static final String JOB_ID = "job_id";
private static final String CHAINED_QUEUE_NAME = UpdateSnapshotViewAction.QUEUE;
@@ -59,7 +59,8 @@ public class ExportPremiumTermsActionTest {
private static final String EXPECTED_FILE_CONTENT =
DISCLAIMER_WITH_NEWLINE + "0,USD 549.00\n" + "2048,USD 549.00\n";
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
private final DriveConnection driveConnection = mock(DriveConnection.class);
private final Response response = mock(Response.class);
@@ -48,7 +48,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class ExportReservedTermsActionTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
private final DriveConnection driveConnection = mock(DriveConnection.class);
private final Response response = mock(Response.class);
@@ -32,9 +32,7 @@ import org.junit.runners.JUnit4;
public class ExportUtilsTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void test_exportReservedTerms() {
@@ -60,9 +60,7 @@ import org.junit.runners.JUnit4;
public class SyncGroupMembersActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -40,10 +40,8 @@ import org.junit.runners.JUnit4;
public class SyncRegistrarsSheetActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
private final FakeResponse response = new FakeResponse();
private final SyncRegistrarsSheet syncRegistrarsSheet = mock(SyncRegistrarsSheet.class);
@@ -58,7 +58,9 @@ import org.mockito.junit.MockitoRule;
@RunWith(JUnit4.class)
public class SyncRegistrarsSheetTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@Rule public final InjectRule inject = new InjectRule();
@@ -56,7 +56,9 @@ public class CheckApiActionTest {
private static final DateTime START_TIME = DateTime.parse("2000-01-01T00:00:00.0Z");
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@Mock private CheckApiMetrics checkApiMetrics;
@@ -48,10 +48,8 @@ import org.junit.runners.JUnit4;
public class EppCommitLogsTest extends ShardableTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -66,7 +66,10 @@ import org.mockito.junit.MockitoRule;
@RunWith(JUnit4.class)
public class EppControllerTest extends ShardableTestCase {
@Rule public AppEngineRule appEngineRule = new AppEngineRule.Builder().withDatastore().build();
@Rule
public AppEngineRule appEngineRule =
new AppEngineRule.Builder().withDatastoreAndCloudSql().build();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@Mock SessionMetadata sessionMetadata;
@@ -32,10 +32,8 @@ import org.junit.runners.JUnit4;
public class EppLifecycleContactTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Test
public void testContactLifecycle() throws Exception {
@@ -64,7 +64,7 @@ public class EppLifecycleDomainTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastore().withTaskQueue().build();
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Before
public void initTld() {
@@ -39,10 +39,8 @@ import org.junit.runners.JUnit4;
public class EppLifecycleHostTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Test
public void testLifecycle() throws Exception {
@@ -30,7 +30,7 @@ public class EppLifecycleLoginTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastore().withTaskQueue().build();
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Test
public void testLoginAndLogout_recordsEppMetric() throws Exception {
@@ -30,9 +30,7 @@ import org.junit.runners.JUnit4;
public class EppLoggedOutTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testHello() throws Exception {
@@ -33,7 +33,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class EppLoginTlsTest extends EppTestCase {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
void setClientCertificateHash(String clientCertificateHash) {
setTransportCredentials(
@@ -26,9 +26,7 @@ import org.junit.runners.JUnit4;
public class EppXxeAttackTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testRemoteXmlExternalEntity() throws Exception {
@@ -48,9 +48,7 @@ import org.junit.runners.JUnit4;
public class ExtensionManagerTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testDuplicateExtensionsForbidden() {
@@ -83,10 +83,8 @@ public abstract class FlowTestCase<F extends Flow> extends ShardableTestCase {
public enum UserPrivileges { NORMAL, SUPERUSER }
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -38,7 +38,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public final class TlsCredentialsTest extends ShardableTestCase {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testProvideClientCertificateHash() {
@@ -186,7 +186,7 @@ public class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFl
.build());
doCheckTest(
create(false, "example1.tld", "In use"),
create(true, "example2.tld", null),
create(false, "example2.tld", "Alloc token invalid for domain"),
create(false, "reserved.tld", "Reserved"),
create(true, "specificuse.tld", null));
}
@@ -203,7 +203,7 @@ public class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFl
.build());
doCheckTest(
create(false, "example1.tld", "In use"),
create(true, "example2.tld", null),
create(false, "example2.tld", "Alloc token invalid for domain"),
create(false, "reserved.tld", "Reserved"),
create(false, "specificuse.tld", "Allocation token required"));
}
@@ -224,8 +224,8 @@ public class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFl
.build())
.build());
doCheckTest(
create(true, "example1.tld", null),
create(true, "example2.tld", null),
create(false, "example1.tld", "Alloc token invalid for domain"),
create(false, "example2.tld", "Alloc token invalid for domain"),
create(false, "reserved.tld", "Reserved"),
create(true, "specificuse.tld", null));
}
@@ -246,8 +246,8 @@ public class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFl
.build())
.build());
doCheckTest(
create(false, "example1.tld", "Alloc token not in promo period"),
create(false, "example2.tld", "Alloc token not in promo period"),
create(false, "example1.tld", "Alloc token invalid for domain"),
create(false, "example2.tld", "Alloc token invalid for domain"),
create(false, "reserved.tld", "Reserved"),
create(false, "specificuse.tld", "Alloc token not in promo period"));
}
@@ -131,6 +131,7 @@ import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeExcep
import google.registry.flows.domain.DomainFlowUtils.UnsupportedMarkTypeException;
import google.registry.flows.domain.DomainPricingLogic.AllocationTokenInvalidForPremiumNameException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForDomainException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException;
@@ -440,6 +441,44 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_reservedDomainCreate_allocationTokenIsForADifferentDomain() {
// Try to register a reserved domain name with an allocation token valid for a different domain
// name.
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "resdom.tld"));
persistContactsAndHosts();
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(SINGLE_USE)
.setDomainName("otherdomain.tld")
.build());
clock.advanceOneMilli();
EppException thrown =
assertThrows(AllocationTokenNotValidForDomainException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
assertAllocationTokenWasNotRedeemed("abc123");
}
@Test
public void testFailure_nonreservedDomainCreate_allocationTokenIsForADifferentDomain() {
// Try to register a non-reserved domain name with an allocation token valid for a different
// domain name.
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld"));
persistContactsAndHosts();
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(SINGLE_USE)
.setDomainName("otherdomain.tld")
.build());
clock.advanceOneMilli();
EppException thrown =
assertThrows(AllocationTokenNotValidForDomainException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
assertAllocationTokenWasNotRedeemed("abc123");
}
@Test
public void testFailure_alreadyRedemeedAllocationToken() {
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld"));
@@ -1212,6 +1251,12 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
.isEqualTo(Key.create(getHistoryEntries(reloadResourceByForeignKey()).get(0)));
}
private void assertAllocationTokenWasNotRedeemed(String token) {
AllocationToken reloadedToken =
ofy().load().key(Key.create(AllocationToken.class, token)).now();
assertThat(reloadedToken.isRedeemed()).isFalse();
}
@Test
public void testSuccess_allocationTokenPromotion() throws Exception {
// A discount of 0.5 means that the first-year cost (13) is cut in half, so a discount of 6.5
@@ -63,7 +63,8 @@ public class AllocationTokenFlowUtilsTest extends ShardableTestCase {
private final AllocationTokenFlowUtils flowUtils =
new AllocationTokenFlowUtils(new AllocationTokenCustomLogic());
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Before
public void initTest() {
@@ -35,7 +35,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class HostFlowUtilsTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void test_validExternalHostName_validates() throws Exception {
@@ -37,7 +37,8 @@ public class KmsKeyringTest {
@Rule public final BouncyCastleProviderRule bouncy = new BouncyCastleProviderRule();
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
private KmsKeyring keyring;

Some files were not shown because too many files have changed in this diff Show More