mirror of
https://github.com/google/nomulus
synced 2026-01-28 16:42:18 +00:00
Compare commits
52 Commits
nomulus-20
...
nomulus-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a06ef09c0 | ||
|
|
9e0368b77c | ||
|
|
05c45da07a | ||
|
|
365c5da942 | ||
|
|
2cc2571375 | ||
|
|
d55230933b | ||
|
|
09aef04117 | ||
|
|
a392100852 | ||
|
|
b005e3aeb0 | ||
|
|
bce09a3aa3 | ||
|
|
cb87658827 | ||
|
|
455daae25c | ||
|
|
dea7dfcf28 | ||
|
|
3a47fa2fe9 | ||
|
|
0b7a0ba99d | ||
|
|
ae89a8b76f | ||
|
|
f0345ddf89 | ||
|
|
e9f20b3401 | ||
|
|
64e7a593ef | ||
|
|
135ab66e55 | ||
|
|
69acb9f6de | ||
|
|
5359f4640a | ||
|
|
5c2856e3e2 | ||
|
|
86e1fb85b6 | ||
|
|
301ab54fb4 | ||
|
|
2c6d71f04c | ||
|
|
ee4e6ace2a | ||
|
|
c4721121eb | ||
|
|
37b9999cfc | ||
|
|
5f62f91cd5 | ||
|
|
6f87fc115f | ||
|
|
aaca6651c8 | ||
|
|
03bbb2c057 | ||
|
|
d00ade8ae0 | ||
|
|
5e61adb396 | ||
|
|
6fe9cced3e | ||
|
|
6a3bd9418f | ||
|
|
3106958f18 | ||
|
|
7da94c90dc | ||
|
|
dbb4092680 | ||
|
|
af3223d086 | ||
|
|
2d7f80baaf | ||
|
|
d4d5d6a570 | ||
|
|
53c0be6537 | ||
|
|
63bb2dd79b | ||
|
|
8278b5409e | ||
|
|
f98b0f8739 | ||
|
|
128fde16c3 | ||
|
|
45f7c89efd | ||
|
|
13dc758747 | ||
|
|
85c11ca889 | ||
|
|
340bf40642 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -98,7 +98,6 @@ nomulus.iws
|
||||
.gradle/
|
||||
**/build
|
||||
node_modules/**
|
||||
!node_modules/soyutils_usegoog.js
|
||||
/repos/
|
||||
|
||||
# Compiled JS/CSS code
|
||||
|
||||
18
build.gradle
18
build.gradle
@@ -34,7 +34,7 @@ buildscript {
|
||||
plugins {
|
||||
// Java static analysis plugins. Keep versions consistent with
|
||||
// ./buildSrc/build.gradle
|
||||
id 'nebula.lint' version '10.4.2'
|
||||
id 'nebula.lint' version '16.0.2'
|
||||
// TODO(weiminyu): consider remove net.ltgt.apt. Gradle 5.2+
|
||||
// has similar functionalities.
|
||||
id 'net.ltgt.apt' version '0.19' apply false
|
||||
@@ -46,7 +46,7 @@ plugins {
|
||||
id "com.moowork.node" version "1.2.0"
|
||||
|
||||
id 'idea'
|
||||
id 'com.diffplug.gradle.spotless' version '3.18.0'
|
||||
id 'com.diffplug.gradle.spotless' version '3.25.0'
|
||||
|
||||
id 'jacoco'
|
||||
}
|
||||
@@ -288,20 +288,6 @@ subprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (['util', 'proxy', 'core', 'prober', 'db'].contains(project.name)) return
|
||||
|
||||
// TODO(weiminyu): investigate if the block below is still needed
|
||||
ext.relativePath = "google/registry/${project.name}"
|
||||
|
||||
sourceSets.each {
|
||||
it.java {
|
||||
include "${project.relativePath}/"
|
||||
}
|
||||
it.resources {
|
||||
include "${project.relativePath}/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If "-P verboseTestOutput=true" is passed in, configure all subprojects to dump all of their
|
||||
|
||||
@@ -23,13 +23,13 @@ buildscript {
|
||||
|
||||
plugins {
|
||||
// Java static analysis plugins. Keep versions consistent with ../build.gradle
|
||||
id 'nebula.lint' version '10.4.2'
|
||||
id 'nebula.lint' version '16.0.2'
|
||||
// Config helper for annotation processors such as AutoValue and Dagger.
|
||||
// Ensures that source code is generated at an appropriate location.
|
||||
id 'net.ltgt.apt' version '0.19' apply false
|
||||
id 'net.ltgt.errorprone' version '0.6.1'
|
||||
id 'checkstyle'
|
||||
id 'com.diffplug.gradle.spotless' version '3.18.0'
|
||||
id 'com.diffplug.gradle.spotless' version '3.25.0'
|
||||
}
|
||||
|
||||
if (rootProject.enableDependencyLocking.toBoolean()) {
|
||||
|
||||
@@ -1,60 +1,44 @@
|
||||
# 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.
|
||||
cglib:cglib-nodep:3.2.2
|
||||
com.diffplug.durian:durian-collect:1.2.0
|
||||
com.diffplug.durian:durian-core:1.2.0
|
||||
com.diffplug.durian:durian-io:1.2.0
|
||||
com.diffplug.gradle.spotless:com.diffplug.gradle.spotless.gradle.plugin:3.18.0
|
||||
com.diffplug.spotless:spotless-lib-extra:1.18.0
|
||||
com.diffplug.spotless:spotless-lib:1.18.0
|
||||
com.diffplug.spotless:spotless-plugin-gradle:3.18.0
|
||||
com.diffplug.gradle.spotless:com.diffplug.gradle.spotless.gradle.plugin:3.25.0
|
||||
com.diffplug.spotless:spotless-lib-extra:1.25.0
|
||||
com.diffplug.spotless:spotless-lib:1.25.0
|
||||
com.diffplug.spotless:spotless-plugin-gradle:3.25.0
|
||||
com.google.guava:guava:19.0
|
||||
com.googlecode.concurrent-trees:concurrent-trees:2.6.1
|
||||
com.googlecode.javaewah:JavaEWAH:1.1.6
|
||||
com.jcraft:jsch:0.1.54
|
||||
com.jcraft:jsch:0.1.55
|
||||
com.jcraft:jzlib:1.1.1
|
||||
com.netflix.nebula:gradle-lint-plugin:10.4.2
|
||||
com.netflix.nebula:gradle-lint-plugin:16.0.2
|
||||
com.netflix.nebula:nebula-gradle-interop:1.0.11
|
||||
com.netflix.nebula:nebula-test:7.3.0
|
||||
commons-codec:commons-codec:1.9
|
||||
commons-io:commons-io:2.5
|
||||
commons-lang:commons-lang:2.6
|
||||
commons-logging:commons-logging:1.2
|
||||
javax.inject:javax.inject:1
|
||||
junit:junit:4.12
|
||||
log4j:log4j:1.2.14
|
||||
nebula.lint:nebula.lint.gradle.plugin:10.4.2
|
||||
nebula.lint:nebula.lint.gradle.plugin:16.0.2
|
||||
net.ltgt.apt:net.ltgt.apt.gradle.plugin:0.19
|
||||
net.ltgt.errorprone:net.ltgt.errorprone.gradle.plugin:0.6.1
|
||||
net.ltgt.gradle:gradle-apt-plugin:0.19
|
||||
net.ltgt.gradle:gradle-errorprone-plugin:0.6.1
|
||||
org.apache.ant:ant-antlr:1.8.4
|
||||
org.apache.ant:ant-junit:1.8.4
|
||||
org.apache.ant:ant-launcher:1.8.4
|
||||
org.apache.ant:ant:1.8.4
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.httpcomponents:httpclient:4.5.2
|
||||
org.apache.httpcomponents:httpcore:4.4.4
|
||||
org.apache.maven:maven-artifact:3.6.2
|
||||
org.apache.maven:maven-builder-support:3.6.2
|
||||
org.apache.maven:maven-model-builder:3.6.2
|
||||
org.apache.maven:maven-model:3.6.2
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.codehaus.gpars:gpars:1.2.1
|
||||
org.codehaus.groovy:groovy-all:2.4.9
|
||||
org.codehaus.groovy:groovy-ant:2.1.8
|
||||
org.codehaus.groovy:groovy-groovydoc:2.1.8
|
||||
org.codehaus.groovy:groovy-templates:2.1.8
|
||||
org.codehaus.groovy:groovy-xml:2.4.7
|
||||
org.codehaus.groovy:groovy:2.4.7
|
||||
org.codehaus.jsr166-mirror:jsr166y:1.7.0
|
||||
org.codehaus.plexus:plexus-interpolation:1.25
|
||||
org.codehaus.plexus:plexus-utils:3.2.1
|
||||
org.codenarc:CodeNarc:0.25.2
|
||||
org.eclipse.jdt:core:3.1.1
|
||||
org.eclipse.jgit:org.eclipse.jgit:5.0.1.201806211838-r
|
||||
org.eclipse.jgit:org.eclipse.jgit:5.5.0.201909110433-r
|
||||
org.eclipse.sisu:org.eclipse.sisu.inject:0.3.3
|
||||
org.gmetrics:GMetrics:0.7
|
||||
org.hamcrest:hamcrest-core:1.3
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50
|
||||
@@ -62,7 +46,8 @@ org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.50
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.3.50
|
||||
org.jetbrains:annotations:13.0
|
||||
org.multiverse:multiverse-core:0.7.0
|
||||
org.objenesis:objenesis:2.4
|
||||
org.ow2.asm:asm:7.0
|
||||
org.ow2.asm:asm-analysis:7.1
|
||||
org.ow2.asm:asm-commons:7.1
|
||||
org.ow2.asm:asm-tree:7.1
|
||||
org.ow2.asm:asm:7.1
|
||||
org.slf4j:slf4j-api:1.7.2
|
||||
org.spockframework:spock-core:1.1-groovy-2.4-rc-4
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
# This file is expected to be part of source control.
|
||||
antlr:antlr:2.7.7
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.2.0
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:guava:28.0-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.puppycrawl.tools:checkstyle:8.17
|
||||
commons-beanutils:commons-beanutils:1.9.3
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.puppycrawl.tools:checkstyle:8.24
|
||||
commons-beanutils:commons-beanutils:1.9.4
|
||||
commons-collections:commons-collections:3.2.2
|
||||
info.picocli:picocli:3.9.0
|
||||
net.sf.saxon:Saxon-HE:9.9.0-2
|
||||
info.picocli:picocli:4.0.3
|
||||
net.sf.saxon:Saxon-HE:9.9.1-4
|
||||
org.antlr:antlr4-runtime:4.7.2
|
||||
org.checkerframework:checker-qual:2.5.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# 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.
|
||||
org.jacoco:org.jacoco.agent:0.8.4
|
||||
org.jacoco:org.jacoco.agent:0.8.5
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# 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.
|
||||
org.jacoco:org.jacoco.agent:0.8.4
|
||||
org.jacoco:org.jacoco.ant:0.8.4
|
||||
org.jacoco:org.jacoco.core:0.8.4
|
||||
org.jacoco:org.jacoco.report:0.8.4
|
||||
org.ow2.asm:asm-analysis:7.1
|
||||
org.ow2.asm:asm-commons:7.1
|
||||
org.ow2.asm:asm-tree:7.1
|
||||
org.ow2.asm:asm:7.1
|
||||
org.jacoco:org.jacoco.agent:0.8.5
|
||||
org.jacoco:org.jacoco.ant:0.8.5
|
||||
org.jacoco:org.jacoco.core:0.8.5
|
||||
org.jacoco:org.jacoco.report:0.8.5
|
||||
org.ow2.asm:asm-analysis:7.2
|
||||
org.ow2.asm:asm-commons:7.2
|
||||
org.ow2.asm:asm-tree:7.2
|
||||
org.ow2.asm:asm:7.2
|
||||
|
||||
61
buildSrc/gradle/dependency-locks/runtime.lockfile
Normal file
61
buildSrc/gradle/dependency-locks/runtime.lockfile
Normal file
@@ -0,0 +1,61 @@
|
||||
# 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.
|
||||
aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.0.23
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.27.0
|
||||
com.google.api.grpc:proto-google-common-protos:1.12.0
|
||||
com.google.api.grpc:proto-google-iam-v1:0.12.0
|
||||
com.google.api:api-common:1.7.0
|
||||
com.google.api:gax-httpjson:0.52.1
|
||||
com.google.api:gax:1.35.1
|
||||
com.google.apis:google-api-services-storage:v1-rev20181013-1.27.0
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.cloud:google-cloud-core-http:1.59.0
|
||||
com.google.cloud:google-cloud-core:1.59.0
|
||||
com.google.cloud:google-cloud-storage:1.59.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.7
|
||||
com.google.common.html.types:types:1.0.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.8.0-beta1
|
||||
com.google.http-client:google-http-client-appengine:1.27.0
|
||||
com.google.http-client:google-http-client-jackson2:1.30.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.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.template:soy:2018-03-14
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.annotation:javax.annotation-api:1.2
|
||||
javax.annotation:jsr250-api:1.0
|
||||
javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.json:json:20160212
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
org.ow2.asm:asm-tree:6.0
|
||||
org.ow2.asm:asm-util:6.0
|
||||
org.ow2.asm:asm:6.0
|
||||
org.threeten:threetenbp:1.3.3
|
||||
71
buildSrc/gradle/dependency-locks/testRuntime.lockfile
Normal file
71
buildSrc/gradle/dependency-locks/testRuntime.lockfile
Normal file
@@ -0,0 +1,71 @@
|
||||
# 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.
|
||||
aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.0.23
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.27.0
|
||||
com.google.api.grpc:proto-google-common-protos:1.12.0
|
||||
com.google.api.grpc:proto-google-iam-v1:0.12.0
|
||||
com.google.api:api-common:1.7.0
|
||||
com.google.api:gax-httpjson:0.52.1
|
||||
com.google.api:gax:1.35.1
|
||||
com.google.apis:google-api-services-storage:v1-rev20181013-1.27.0
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.cloud:google-cloud-core-http:1.59.0
|
||||
com.google.cloud:google-cloud-core:1.59.0
|
||||
com.google.cloud:google-cloud-storage:1.59.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.7
|
||||
com.google.common.html.types:types:1.0.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.8.0-beta1
|
||||
com.google.http-client:google-http-client-appengine:1.27.0
|
||||
com.google.http-client:google-http-client-jackson2:1.30.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.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.template:soy:2018-03-14
|
||||
com.google.truth.extensions:truth-java8-extension:1.0
|
||||
com.google.truth:truth:1.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.annotation:javax.annotation-api:1.2
|
||||
javax.annotation:jsr250-api:1.0
|
||||
javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.9.7
|
||||
net.bytebuddy:byte-buddy:1.9.7
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.hamcrest:hamcrest-core:1.3
|
||||
org.json:json:20160212
|
||||
org.mockito:mockito-core:2.25.0
|
||||
org.objenesis:objenesis:2.6
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
org.ow2.asm:asm-tree:6.0
|
||||
org.ow2.asm:asm-util:6.0
|
||||
org.ow2.asm:asm:6.0
|
||||
org.threeten:threetenbp:1.3.3
|
||||
@@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.template.soy.SoyFileSet;
|
||||
import com.google.template.soy.tofu.SoyTofu;
|
||||
import google.registry.gradle.plugin.ProjectData.TaskData;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.function.Supplier;
|
||||
@@ -148,10 +149,14 @@ final class CoverPageGenerator {
|
||||
|
||||
/** returns a soy-friendly version of the given task data. */
|
||||
static ImmutableMap<String, Object> taskDataToSoy(TaskData task) {
|
||||
// Note that all instances of File.separator are replaced with forward slashes so that we can
|
||||
// generate a valid href on Windows.
|
||||
return new ImmutableMap.Builder<String, Object>()
|
||||
.put("uniqueName", task.uniqueName())
|
||||
.put("description", task.description())
|
||||
.put("log", task.log().isPresent() ? getLogPath(task).toString() : "")
|
||||
.put(
|
||||
"log",
|
||||
task.log().isPresent() ? getLogPath(task).toString().replace(File.separator, "/") : "")
|
||||
.put(
|
||||
"reports",
|
||||
task.reports().entrySet().stream()
|
||||
@@ -161,7 +166,11 @@ final class CoverPageGenerator {
|
||||
entry ->
|
||||
entry.getValue().files().isEmpty()
|
||||
? ""
|
||||
: entry.getValue().entryPoint().toString())))
|
||||
: entry
|
||||
.getValue()
|
||||
.entryPoint()
|
||||
.toString()
|
||||
.replace(File.separator, "/"))))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -188,8 +197,10 @@ final class CoverPageGenerator {
|
||||
}
|
||||
|
||||
private static Path getLogPath(TaskData task) {
|
||||
// TODO(guyben):escape uniqueName to guarantee legal file name.
|
||||
return Paths.get("logs", task.uniqueName() + ".log");
|
||||
// We replace colons with dashes so that the resulting filename is always valid, even in
|
||||
// Windows. As a dash is not a valid character in Java identifies, a task name cannot include
|
||||
// it, so the uniqueness of the name is perserved.
|
||||
return Paths.get("logs", task.uniqueName().replace(":", "-") + ".log");
|
||||
}
|
||||
|
||||
private static Supplier<byte[]> resourceLoader(Path path) {
|
||||
|
||||
@@ -64,7 +64,8 @@ final class GcsPluginUtils {
|
||||
|
||||
static void uploadFileToGcs(
|
||||
Storage storage, String bucket, Path path, Supplier<byte[]> dataSupplier) {
|
||||
String filename = path.toString();
|
||||
// Replace Windows file separators with forward slashes.
|
||||
String filename = path.toString().replace(File.separator, "/");
|
||||
storage.create(
|
||||
BlobInfo.newBuilder(bucket, filename).setContentType(getContentType(filename)).build(),
|
||||
dataSupplier.get());
|
||||
|
||||
@@ -20,9 +20,11 @@ import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.toByteArraySupplier;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.gradle.plugin.ProjectData.TaskData;
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -63,6 +65,8 @@ public final class CoverPageGeneratorTest {
|
||||
.setState(TaskData.State.UP_TO_DATE)
|
||||
.build();
|
||||
|
||||
private static final Joiner filenameJoiner = Joiner.on(File.separator);
|
||||
|
||||
private ImmutableMap<String, String> getGeneratedFiles(ProjectData project) {
|
||||
CoverPageGenerator coverPageGenerator = new CoverPageGenerator(project);
|
||||
FilesWithEntryPoint files = coverPageGenerator.getFilesToUpload();
|
||||
@@ -172,8 +176,8 @@ public final class CoverPageGeneratorTest {
|
||||
@Test
|
||||
public void testGetFilesToUpload_containsCssFile() {
|
||||
ImmutableMap<String, String> files = getGeneratedFiles(EMPTY_PROJECT);
|
||||
assertThat(files).containsKey("css/style.css");
|
||||
assertThat(files.get("css/style.css")).contains("body {");
|
||||
assertThat(files).containsKey(filenameJoiner.join("css", "style.css"));
|
||||
assertThat(files.get(filenameJoiner.join("css", "style.css"))).contains("body {");
|
||||
assertThat(files.get("index.html"))
|
||||
.contains("<link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\">");
|
||||
}
|
||||
@@ -191,8 +195,8 @@ public final class CoverPageGeneratorTest {
|
||||
.setLog(toByteArraySupplier("my log data"))
|
||||
.build())
|
||||
.build());
|
||||
assertThat(files).containsEntry("logs/my:name.log", "my log data");
|
||||
assertThat(files.get("index.html")).contains("<a href=\"logs/my:name.log\">[log]</a>");
|
||||
assertThat(files).containsEntry(filenameJoiner.join("logs", "my-name.log"), "my log data");
|
||||
assertThat(files.get("index.html")).contains("<a href=\"logs/my-name.log\">[log]</a>");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -203,7 +207,7 @@ public final class CoverPageGeneratorTest {
|
||||
.toBuilder()
|
||||
.addTask(EMPTY_TASK_SUCCESS.toBuilder().setUniqueName("my:name").build())
|
||||
.build());
|
||||
assertThat(files).doesNotContainKey("logs/my:name.log");
|
||||
assertThat(files).doesNotContainKey("logs/my-name.log");
|
||||
assertThat(files.get("index.html")).contains("<span class=\"report_link_broken\">[log]</span>");
|
||||
}
|
||||
|
||||
@@ -225,7 +229,7 @@ public final class CoverPageGeneratorTest {
|
||||
Paths.get("path", "report.txt")))
|
||||
.build())
|
||||
.build());
|
||||
assertThat(files).containsEntry("path/report.txt", "report content");
|
||||
assertThat(files).containsEntry(filenameJoiner.join("path", "report.txt"), "report content");
|
||||
assertThat(files.get("index.html")).contains("<a href=\"path/report.txt\">[someReport]</a>");
|
||||
}
|
||||
|
||||
@@ -244,7 +248,7 @@ public final class CoverPageGeneratorTest {
|
||||
ImmutableMap.of(), Paths.get("path", "report.txt")))
|
||||
.build())
|
||||
.build());
|
||||
assertThat(files).doesNotContainKey("path/report.txt");
|
||||
assertThat(files).doesNotContainKey(filenameJoiner.join("path", "report.txt"));
|
||||
assertThat(files.get("index.html"))
|
||||
.contains("<span class=\"report_link_broken\">[someReport]</span>");
|
||||
}
|
||||
@@ -275,12 +279,15 @@ public final class CoverPageGeneratorTest {
|
||||
ImmutableMap.of(), Paths.get("path-empty", "report.txt")))
|
||||
.build())
|
||||
.build());
|
||||
assertThat(files).containsEntry("path-filled/report.txt", "report content");
|
||||
assertThat(files).containsEntry("path-filled/other/file.txt", "some other content");
|
||||
assertThat(files).containsEntry("logs/my:name.log", "log data");
|
||||
assertThat(files)
|
||||
.containsEntry(filenameJoiner.join("path-filled", "report.txt"), "report content");
|
||||
assertThat(files)
|
||||
.containsEntry(
|
||||
filenameJoiner.join("path-filled", "other", "file.txt"), "some other content");
|
||||
assertThat(files).containsEntry(filenameJoiner.join("logs", "my-name.log"), "log data");
|
||||
assertThat(files.get("index.html"))
|
||||
.contains("<a href=\"path-filled/report.txt\">[filledReport]</a>");
|
||||
assertThat(files.get("index.html")).contains("<a href=\"logs/my:name.log\">[log]</a>");
|
||||
assertThat(files.get("index.html")).contains("<a href=\"logs/my-name.log\">[log]</a>");
|
||||
assertThat(files.get("index.html"))
|
||||
.contains("<span class=\"report_link_broken\">[emptyReport]</span>");
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import com.google.cloud.storage.BlobInfo;
|
||||
import com.google.cloud.storage.Storage;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
@@ -45,6 +46,8 @@ import org.junit.runners.JUnit4;
|
||||
@RunWith(JUnit4.class)
|
||||
public final class GcsPluginUtilsTest {
|
||||
|
||||
private static final Joiner filenameJoiner = Joiner.on(File.separator);
|
||||
|
||||
@Rule public final TemporaryFolder folder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
@@ -155,8 +158,10 @@ public final class GcsPluginUtilsTest {
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination, Optional.of(ignoredHint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("some/path/file.txt");
|
||||
assertThat(readAllFiles(files)).containsExactly("some/path/file.txt", "some data");
|
||||
assertThat(files.entryPoint().toString())
|
||||
.isEqualTo(filenameJoiner.join("some", "path", "file.txt"));
|
||||
assertThat(readAllFiles(files))
|
||||
.containsExactly(filenameJoiner.join("some", "path", "file.txt"), "some data");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -171,7 +176,7 @@ public final class GcsPluginUtilsTest {
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination, Optional.of(ignoredHint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("non/existing.txt");
|
||||
assertThat(files.entryPoint().toString()).isEqualTo(filenameJoiner.join("non", "existing.txt"));
|
||||
assertThat(files.files()).isEmpty();
|
||||
}
|
||||
|
||||
@@ -187,7 +192,7 @@ public final class GcsPluginUtilsTest {
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination, Optional.of(ignoredHint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("some/path");
|
||||
assertThat(files.entryPoint().toString()).isEqualTo(filenameJoiner.join("some", "path"));
|
||||
assertThat(files.files()).isEmpty();
|
||||
}
|
||||
|
||||
@@ -205,8 +210,10 @@ public final class GcsPluginUtilsTest {
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination, Optional.of(ignoredHint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("some/path/a/file.txt");
|
||||
assertThat(readAllFiles(files)).containsExactly("some/path/a/file.txt", "some data");
|
||||
assertThat(files.entryPoint().toString())
|
||||
.isEqualTo(filenameJoiner.join("some", "path", "a", "file.txt"));
|
||||
assertThat(readAllFiles(files))
|
||||
.containsExactly(filenameJoiner.join("some", "path", "a", "file.txt"), "some data");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,8 +239,10 @@ public final class GcsPluginUtilsTest {
|
||||
|
||||
FilesWithEntryPoint files = readFilesWithEntryPoint(destination, Optional.empty(), root);
|
||||
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("some/path/path.zip");
|
||||
assertThat(readAllFiles(files).keySet()).containsExactly("some/path/path.zip");
|
||||
assertThat(files.entryPoint().toString())
|
||||
.isEqualTo(filenameJoiner.join("some", "path", "path.zip"));
|
||||
assertThat(readAllFiles(files).keySet())
|
||||
.containsExactly(filenameJoiner.join("some", "path", "path.zip"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,8 +270,10 @@ public final class GcsPluginUtilsTest {
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination, Optional.of(badEntryPoint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("some/path/path.zip");
|
||||
assertThat(readAllFiles(files).keySet()).containsExactly("some/path/path.zip");
|
||||
assertThat(files.entryPoint().toString())
|
||||
.isEqualTo(filenameJoiner.join("some", "path", "path.zip"));
|
||||
assertThat(readAllFiles(files).keySet())
|
||||
.containsExactly(filenameJoiner.join("some", "path", "path.zip"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -285,12 +296,13 @@ public final class GcsPluginUtilsTest {
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination, Optional.of(goodEntryPoint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("some/path/index.html");
|
||||
assertThat(files.entryPoint().toString())
|
||||
.isEqualTo(filenameJoiner.join("some", "path", "index.html"));
|
||||
assertThat(readAllFiles(files))
|
||||
.containsExactly(
|
||||
"some/path/index.html", "some data",
|
||||
"some/path/a/index.html", "wrong index",
|
||||
"some/path/c/style.css", "css file",
|
||||
"some/path/my_image.png", "images");
|
||||
filenameJoiner.join("some", "path", "index.html"), "some data",
|
||||
filenameJoiner.join("some", "path", "a", "index.html"), "wrong index",
|
||||
filenameJoiner.join("some", "path", "c", "style.css"), "css file",
|
||||
filenameJoiner.join("some", "path", "my_image.png"), "images");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,19 @@ by Joshua Bloch in his book Effective Java -->
|
||||
<property name="message" value="MockitoJUnitRunner is deprecated. Use @RunWith(JUnit4.class) and MockitoRule instead."/>
|
||||
</module>
|
||||
|
||||
<module name="LineLength">
|
||||
<!-- Checks if a line is too long. -->
|
||||
<property name="max" value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.max}" default="100"/>
|
||||
<property name="severity" value="error"/>
|
||||
|
||||
<!-- Ignore lines that have any series of 80 or more non-whitespace characters.
|
||||
These lines likely cannot be broken.
|
||||
-->
|
||||
<property name="ignorePattern"
|
||||
value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.ignorePattern}"
|
||||
default=".*[^ ]{80,}.*"/>
|
||||
</module>
|
||||
|
||||
<!-- All Java AST specific tests live under TreeWalker module. -->
|
||||
<module name="TreeWalker">
|
||||
|
||||
@@ -184,19 +197,6 @@ by Joshua Bloch in his book Effective Java -->
|
||||
LENGTH and CODING CHECKS
|
||||
-->
|
||||
|
||||
<module name="LineLength">
|
||||
<!-- Checks if a line is too long. -->
|
||||
<property name="max" value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.max}" default="100"/>
|
||||
<property name="severity" value="error"/>
|
||||
|
||||
<!-- Ignore lines that have any series of 80 or more non-whitespace characters.
|
||||
These lines likely cannot be broken.
|
||||
-->
|
||||
<property name="ignorePattern"
|
||||
value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.ignorePattern}"
|
||||
default=".*[^ ]{80,}.*"/>
|
||||
</module>
|
||||
|
||||
<module name="OperatorWrap">
|
||||
<property name="option" value="nl"/>
|
||||
<property name="tokens" value="QUESTION, EQUAL, NOT_EQUAL, DIV, PLUS, MINUS, STAR, MOD, SR, BSR, GE, GT, SL, LE, LT, BXOR, BOR, LOR, BAND, LAND, TYPE_EXTENSION_AND, LITERAL_INSTANCEOF"/>
|
||||
|
||||
16
config/dependency-license/README.md
Normal file
16
config/dependency-license/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
## Summary
|
||||
|
||||
This folder contains configuration files for the gradle-license-report plugin:
|
||||
|
||||
* allowed_licenses.json declares the acceptable licenses. A license may have
|
||||
multiple entries in this file, since the 'moduleLicense' property value must
|
||||
match exactly the phrases found in pom or manifest files.
|
||||
* license_normalizer_bundle.json configures normalization rules for license
|
||||
reporting.
|
||||
|
||||
## Notes About Adding New Licenses
|
||||
|
||||
* The WTFPL license is not allowed.
|
||||
|
||||
* Each 'Public Domain' license entry must include a specific 'moduleName'. Do
|
||||
not omit moduleName or use wildcards.
|
||||
@@ -3,6 +3,9 @@
|
||||
{
|
||||
"moduleLicense": "Apache Software License, Version 1.1"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache Software License, version 1.1"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache 2"
|
||||
},
|
||||
@@ -90,6 +93,9 @@
|
||||
{
|
||||
"moduleLicense": "The BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The New BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The PostgreSQL License"
|
||||
},
|
||||
@@ -135,6 +141,9 @@
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License - v 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "https://www.eclipse.org/legal/epl-2.0/, http://www.gnu.org/copyleft/gpl.html, http://www.gnu.org/licenses/lgpl.html"
|
||||
},
|
||||
@@ -198,6 +207,9 @@
|
||||
{
|
||||
"moduleLicense": "The MIT license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The MIT License (MIT)"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The PostgreSQL License"
|
||||
},
|
||||
@@ -205,10 +217,12 @@
|
||||
"moduleLicense": "Mozilla Public License Version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Public Domain"
|
||||
"moduleLicense": "Public Domain",
|
||||
"moduleName": "aopalliance:aopalliance"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "PUBLIC DOMAIN"
|
||||
"moduleLicense": "Public Domain",
|
||||
"moduleName": "org.tukaani:xz"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The W3C Software License"
|
||||
|
||||
@@ -80,7 +80,7 @@ PRESUBMITS = {
|
||||
".git", "/build/", "/generated/", "node_modules/",
|
||||
"JUnitBackports.java", "registrar_bin.", "registrar_dbg.",
|
||||
"google-java-format-diff.py",
|
||||
"nomulus.golden.sql"
|
||||
"nomulus.golden.sql", "soyutils_usegoog.js"
|
||||
}, REQUIRED):
|
||||
"File did not include the license header.",
|
||||
|
||||
@@ -99,6 +99,12 @@ PRESUBMITS = {
|
||||
"System.(out|err).println is only allowed in tools/ packages. Please "
|
||||
"use a logger instead.",
|
||||
|
||||
# PostgreSQLContainer instantiation must specify docker tag
|
||||
PresubmitCheck(
|
||||
r"[\s\S]*new\s+PostgreSQLContainer(<[\s\S]*>)?\(\s*\)[\s\S]*",
|
||||
"java", {}):
|
||||
"PostgreSQLContainer instantiation must specify docker tag.",
|
||||
|
||||
# Various Soy linting checks
|
||||
PresubmitCheck(
|
||||
r".* (/\*)?\* {?@param ",
|
||||
|
||||
@@ -76,9 +76,9 @@ sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDirs += generatedDir
|
||||
// Javadoc API is deprecated and removed in Java 12.
|
||||
// Javadoc API is deprecated in Java 11 and removed in Java 12.
|
||||
// TODO(jianglai): re-enable after migrating to the new Javadoc API
|
||||
if ((JavaVersion.current().majorVersion as Integer) > 11) {
|
||||
if ((JavaVersion.current().majorVersion as Integer) >= 11) {
|
||||
exclude 'google/registry/documentation/**'
|
||||
}
|
||||
}
|
||||
@@ -88,9 +88,9 @@ sourceSets {
|
||||
}
|
||||
test {
|
||||
java {
|
||||
// Javadoc API is deprecated and removed in Java 12.
|
||||
// Javadoc API is deprecated in Java 11 and removed in Java 12.
|
||||
// TODO(jianglai): re-enable after migrating to the new Javadoc API
|
||||
if ((JavaVersion.current().majorVersion as Integer) > 11) {
|
||||
if ((JavaVersion.current().majorVersion as Integer) >= 11) {
|
||||
exclude 'google/registry/documentation/**'
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,6 @@ dependencies {
|
||||
compile deps['com.google.apis:google-api-services-groupssettings']
|
||||
compile deps['com.google.apis:google-api-services-monitoring']
|
||||
compile deps['com.google.apis:google-api-services-sheets']
|
||||
testCompileOnly deps['com.google.appengine:appengine-api-1.0-sdk']
|
||||
testCompile deps['com.google.appengine:appengine-api-stubs']
|
||||
compile deps['com.google.appengine.tools:appengine-gcs-client']
|
||||
compile deps['com.google.appengine.tools:appengine-mapreduce']
|
||||
@@ -192,10 +191,12 @@ dependencies {
|
||||
compile deps['com.jcraft:jsch']
|
||||
testCompile deps['com.thoughtworks.qdox:qdox']
|
||||
compile deps['dnsjava:dnsjava']
|
||||
runtime deps['org.glassfish.jaxb:jaxb-runtime']
|
||||
testCompile deps['io.github.classgraph:classgraph']
|
||||
testCompile deps['javax.annotation:javax.annotation-api']
|
||||
testCompile deps['javax.annotation:jsr250-api']
|
||||
compile deps['javax.inject:javax.inject']
|
||||
compile deps['javax.mail:mail']
|
||||
compile deps['javax.persistence:javax.persistence-api']
|
||||
compile deps['javax.servlet:servlet-api']
|
||||
compile deps['javax.xml.bind:jaxb-api']
|
||||
compile deps['jline:jline']
|
||||
@@ -206,6 +207,7 @@ dependencies {
|
||||
compile deps['org.apache.beam:beam-sdks-java-core']
|
||||
compile deps['org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core']
|
||||
compile deps['org.apache.beam:beam-sdks-java-io-google-cloud-platform']
|
||||
testCompile deps['org.apache.commons:commons-lang3']
|
||||
testCompile deps['org.apache.commons:commons-text']
|
||||
testCompile deps['org.apache.ftpserver:ftplet-api']
|
||||
testCompile deps['org.apache.ftpserver:ftpserver-core']
|
||||
@@ -218,6 +220,8 @@ dependencies {
|
||||
compile deps['org.bouncycastle:bcpg-jdk15on']
|
||||
testCompile deps['org.bouncycastle:bcpkix-jdk15on']
|
||||
compile deps['org.bouncycastle:bcprov-jdk15on']
|
||||
runtime deps['org.glassfish.jaxb:jaxb-runtime']
|
||||
compile deps['org.hibernate:hibernate-core']
|
||||
compile deps['org.joda:joda-money']
|
||||
compile deps['org.json:json']
|
||||
testCompile deps['org.mortbay.jetty:jetty']
|
||||
@@ -226,14 +230,21 @@ dependencies {
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-chrome-driver']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-java']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-remote-driver']
|
||||
testCompile deps['org.testcontainers:jdbc']
|
||||
compile deps['org.testcontainers:postgresql']
|
||||
testCompile deps['org.testcontainers:selenium']
|
||||
testCompile deps['org.testcontainers:testcontainers']
|
||||
compile deps['xerces:xmlParserAPIs']
|
||||
compile deps['xpp3:xpp3']
|
||||
// This dependency must come after javax.mail:mail as it would otherwise
|
||||
// shadow classes in package javax.mail with its own implementation.
|
||||
compile deps['com.google.appengine:appengine-api-1.0-sdk']
|
||||
|
||||
// Known issue: nebula-lint misses inherited dependency.
|
||||
compile project(':third_party')
|
||||
compile project(':util')
|
||||
// Import NomulusPostreSql from ':db' for compile but exclude dependencies.
|
||||
compile project(path: ':db', configuration: 'compileApi')
|
||||
testRuntime project(':db')
|
||||
|
||||
// Include auto-value in compile until nebula-lint understands
|
||||
@@ -289,12 +300,12 @@ dependencies {
|
||||
task jaxbToJava {
|
||||
def xsdFilesDir = "${javaDir}/google/registry/xml/xsd"
|
||||
def bindingsFile = "${javaDir}/google/registry/xjc/bindings.xjb"
|
||||
def pkgInfoGenerator = "${javaDir}/google/registry/xjc/make_pkginfo.sh"
|
||||
def pkgInfoTemplate = "${javaDir}/google/registry/xjc/package-info.java.in"
|
||||
def pkgInfoMap = "${javaDir}/google/registry/xjc/package-info.map"
|
||||
def outputDir = "${generatedDir}/google/registry/xjc"
|
||||
|
||||
inputs.dir xsdFilesDir
|
||||
inputs.files bindingsFile, pkgInfoTemplate, pkgInfoGenerator
|
||||
inputs.files bindingsFile, pkgInfoTemplate, pkgInfoMap
|
||||
outputs.dir outputDir
|
||||
|
||||
doLast {
|
||||
@@ -332,11 +343,17 @@ task jaxbToJava {
|
||||
// below.
|
||||
arg(line: '-npa -quiet -extension')
|
||||
}
|
||||
exec {
|
||||
workingDir "${generatedDir}"
|
||||
|
||||
executable pkgInfoGenerator
|
||||
args pkgInfoTemplate, outputDir
|
||||
new File(pkgInfoMap).eachLine { line ->
|
||||
def (packageName, namespace) = line.split()
|
||||
ant.copy(
|
||||
tofile: "${outputDir}/${packageName}/package-info.java",
|
||||
overwrite: true,
|
||||
file: "${pkgInfoTemplate}") {
|
||||
filterSet() {
|
||||
filter(token: 'PACKAGE', value: packageName)
|
||||
filter(token: 'NAMESPACE', value: namespace)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -412,8 +429,10 @@ task soyToJS {
|
||||
"--allowExternalCalls", "false",
|
||||
"--srcs", "${soyFiles.join(',')}",
|
||||
"--shouldProvideRequireSoyNamespaces", "true",
|
||||
"--compileTimeGlobalsFile", "${resourcesSourceDir}/google/registry/ui/globals.txt",
|
||||
"--deps", "${deps.join(',')}"
|
||||
"--compileTimeGlobalsFile", "${resourcesSourceDir}/google/registry/ui/globals.txt"
|
||||
if (deps != "") {
|
||||
args "--deps", "${deps.join(',')}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,7 +533,7 @@ task compileProdJS(type: JavaExec) {
|
||||
|
||||
// manually include all the required js files
|
||||
closureArgs << "--js=${nodeModulesDir}/google-closure-library/**.js"
|
||||
closureArgs << "--js=${nodeModulesDir}/soyutils_usegoog.js"
|
||||
closureArgs << "--js=${jsDir}/soyutils_usegoog.js"
|
||||
closureArgs << "--js=${cssSourceDir}/registrar_bin.css.js"
|
||||
closureArgs << "--js=${jsSourceDir}/**.js"
|
||||
// TODO(shicong) Verify the compiled JS file works in Alpha
|
||||
@@ -525,7 +544,12 @@ task compileProdJS(type: JavaExec) {
|
||||
|
||||
compileJava.dependsOn jaxbToJava
|
||||
compileJava.dependsOn soyToJava
|
||||
compileJava.dependsOn compileProdJS
|
||||
// The Closure JS compiler does not support Windows. It is fine to disable it if
|
||||
// all we want to do is to complile the Java code on Windows.
|
||||
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||
compileJava.dependsOn compileProdJS
|
||||
assemble.dependsOn compileProdJS
|
||||
}
|
||||
|
||||
// stylesheetsToJavascript must happen after processResources, which wipes the
|
||||
// resources folder before copying data into it.
|
||||
@@ -536,13 +560,12 @@ compileProdJS.dependsOn rootProject.npmInstall
|
||||
compileProdJS.dependsOn processResources
|
||||
compileProdJS.dependsOn processTestResources
|
||||
compileProdJS.dependsOn soyToJS
|
||||
assemble.dependsOn compileProdJS
|
||||
|
||||
task karmaTest(type: Exec) {
|
||||
dependsOn ':npmInstall'
|
||||
workingDir rootProject.projectDir
|
||||
executable 'node_modules/karma/bin/karma'
|
||||
args('start')
|
||||
args('start', "${project.projectDir}/karma.conf.js")
|
||||
}
|
||||
|
||||
test.dependsOn karmaTest
|
||||
@@ -577,14 +600,43 @@ artifacts {
|
||||
*/
|
||||
class FilteringTest extends Test {
|
||||
|
||||
void setTests(List<String> tests) {
|
||||
// Common exclude pattern. See README in parent directory for explanation.
|
||||
exclude "**/*TestCase.*", "**/*TestSuite.*"
|
||||
include tests
|
||||
private void applyTestFilter() {
|
||||
if (project.testFilter) {
|
||||
testNameIncludePatterns = project.testFilter.split(',')
|
||||
|
||||
// By default, gradle test tasks will produce a failure if no tests
|
||||
// match the include/exclude/filter rules. Since test filtering allows us
|
||||
// to select a set of tests from a particular task, we don't want this
|
||||
// behavior.
|
||||
filter.failOnNoMatchingTests = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to false if you also want to include TestCase and TestSuite classes.
|
||||
*
|
||||
* <p>Must be defined before "test", if at all.
|
||||
*/
|
||||
boolean excludeTestCases = true
|
||||
|
||||
void setTests(List<String> tests) {
|
||||
// Common exclude pattern. See README in parent directory for explanation.
|
||||
if (excludeTestCases) {
|
||||
exclude "**/*TestCase.*", "**/*TestSuite.*"
|
||||
}
|
||||
include tests
|
||||
applyTestFilter()
|
||||
}
|
||||
|
||||
/**
|
||||
* Include all of the tests (except Test{Case,TestSuite}). This actually
|
||||
* doesn't explicitly "include" anything, in which cast the Test class tries
|
||||
* to include everything that is not explicitly excluded.
|
||||
*/
|
||||
void includeAllTests() {
|
||||
exclude "**/*TestCase.*", "**/*TestSuite.*"
|
||||
applyTestFilter()
|
||||
}
|
||||
}
|
||||
|
||||
task fragileTest(type: FilteringTest) {
|
||||
@@ -606,6 +658,12 @@ task outcastTest(type: FilteringTest) {
|
||||
maxParallelForks 5
|
||||
}
|
||||
|
||||
// Dedicated test suite for schema-dependent tests.
|
||||
task sqlIntegrationTest(type: FilteringTest) {
|
||||
excludeTestCases = false
|
||||
tests = ['google/registry/schema/integration/SqlIntegrationTestSuite.*']
|
||||
}
|
||||
|
||||
task findGoldenImages(type: JavaExec) {
|
||||
classpath = sourceSets.test.runtimeClasspath
|
||||
main = 'google.registry.webdriver.GoldenImageFinder'
|
||||
@@ -688,9 +746,8 @@ task flowDocsTool(type: JavaExec) {
|
||||
args arguments
|
||||
}
|
||||
|
||||
test {
|
||||
// Common exclude pattern. See README in parent directory for explanation.
|
||||
exclude "**/*TestCase.*", "**/*TestSuite.*"
|
||||
task standardTest(type: FilteringTest) {
|
||||
includeAllTests()
|
||||
exclude fragileTestPatterns
|
||||
exclude outcastTestPatterns
|
||||
|
||||
@@ -712,7 +769,13 @@ test {
|
||||
doFirst {
|
||||
new File(screenshotsDir).deleteDir()
|
||||
}
|
||||
}.dependsOn(fragileTest, outcastTest)
|
||||
}
|
||||
|
||||
test {
|
||||
// Don't run any tests from this task, all testing gets done in the
|
||||
// FilteringTest tasks.
|
||||
exclude "**"
|
||||
}.dependsOn(fragileTest, outcastTest, standardTest)
|
||||
|
||||
createUberJar('nomulus', 'nomulus', 'google.registry.tools.RegistryTool')
|
||||
project.nomulus.dependsOn project(':third_party').jar
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
# This file is expected to be part of source control.
|
||||
antlr:antlr:2.7.7
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.2.0
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:guava:28.0-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.puppycrawl.tools:checkstyle:8.17
|
||||
commons-beanutils:commons-beanutils:1.9.3
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.puppycrawl.tools:checkstyle:8.24
|
||||
commons-beanutils:commons-beanutils:1.9.4
|
||||
commons-collections:commons-collections:3.2.2
|
||||
info.picocli:picocli:3.9.0
|
||||
net.sf.saxon:Saxon-HE:9.9.0-2
|
||||
info.picocli:picocli:4.0.3
|
||||
net.sf.saxon:Saxon-HE:9.9.1-4
|
||||
org.antlr:antlr4-runtime:4.7.2
|
||||
org.checkerframework:checker-qual:2.5.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
|
||||
@@ -6,11 +6,10 @@ 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.8
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.fasterxml.jackson.core:jackson-databind:2.9.8
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.9.10
|
||||
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.luben:zstd-jni:1.3.8-3
|
||||
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
|
||||
@@ -18,7 +17,7 @@ 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.44.0
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.43.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:1.6.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:1.6.0
|
||||
@@ -44,7 +43,7 @@ com.google.apis:google-api-services-bigquery:v2-rev20181104-1.27.0
|
||||
com.google.apis:google-api-services-clouddebugger:v2-rev20180801-1.27.0
|
||||
com.google.apis:google-api-services-cloudkms:v1-rev12-1.22.0
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20181015-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190126-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190607-1.27.0
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev6-1.22.0
|
||||
com.google.apis:google-api-services-drive:v2-rev160-1.19.1
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
|
||||
@@ -165,22 +164,23 @@ javax.transaction:transaction-api:1.1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.9.2
|
||||
joda-time:joda-time:2.10.3
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy:1.9.11
|
||||
net.java.dev.jna:jna-platform:5.3.1
|
||||
net.java.dev.jna:jna:5.3.1
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-job-management:2.11.0
|
||||
org.apache.beam:beam-model-pipeline:2.11.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.11.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.11.0
|
||||
org.apache.beam:beam-sdks-java-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.11.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.11.0
|
||||
org.apache.beam:beam-vendor-grpc-1_13_1:0.2
|
||||
org.apache.beam:beam-vendor-guava-20_0:0.1
|
||||
org.apache.beam:beam-model-job-management:2.16.0
|
||||
org.apache.beam:beam-model-pipeline:2.16.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.16.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.16.0
|
||||
org.apache.beam:beam-sdks-java-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.16.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.16.0
|
||||
org.apache.beam:beam-vendor-bytebuddy-1_9_3:0.1
|
||||
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.8
|
||||
@@ -204,7 +204,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -6,11 +6,10 @@ 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.8
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.fasterxml.jackson.core:jackson-databind:2.9.8
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.9.10
|
||||
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.luben:zstd-jni:1.3.8-3
|
||||
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
|
||||
@@ -18,7 +17,7 @@ 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.44.0
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.43.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:1.6.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:1.6.0
|
||||
@@ -44,7 +43,7 @@ com.google.apis:google-api-services-bigquery:v2-rev20181104-1.27.0
|
||||
com.google.apis:google-api-services-clouddebugger:v2-rev20180801-1.27.0
|
||||
com.google.apis:google-api-services-cloudkms:v1-rev12-1.22.0
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20181015-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190126-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190607-1.27.0
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev6-1.22.0
|
||||
com.google.apis:google-api-services-drive:v2-rev160-1.19.1
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
|
||||
@@ -163,22 +162,23 @@ javax.transaction:transaction-api:1.1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.9.2
|
||||
joda-time:joda-time:2.10.3
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy:1.9.11
|
||||
net.java.dev.jna:jna-platform:5.3.1
|
||||
net.java.dev.jna:jna:5.3.1
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-job-management:2.11.0
|
||||
org.apache.beam:beam-model-pipeline:2.11.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.11.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.11.0
|
||||
org.apache.beam:beam-sdks-java-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.11.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.11.0
|
||||
org.apache.beam:beam-vendor-grpc-1_13_1:0.2
|
||||
org.apache.beam:beam-vendor-guava-20_0:0.1
|
||||
org.apache.beam:beam-model-job-management:2.16.0
|
||||
org.apache.beam:beam-model-pipeline:2.16.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.16.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.16.0
|
||||
org.apache.beam:beam-sdks-java-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.16.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.16.0
|
||||
org.apache.beam:beam-vendor-bytebuddy-1_9_3:0.1
|
||||
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.8
|
||||
@@ -202,7 +202,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -6,9 +6,9 @@ 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.8
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.fasterxml.jackson.core:jackson-databind:2.9.8
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.9.10
|
||||
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
|
||||
com.github.jnr:jnr-a64asm:1.0.0
|
||||
@@ -18,7 +18,6 @@ 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.github.luben:zstd-jni:1.3.8-3
|
||||
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
|
||||
@@ -26,7 +25,7 @@ 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.44.0
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.43.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:1.6.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:1.6.0
|
||||
@@ -52,7 +51,7 @@ com.google.apis:google-api-services-bigquery:v2-rev20181104-1.27.0
|
||||
com.google.apis:google-api-services-clouddebugger:v2-rev20180801-1.27.0
|
||||
com.google.apis:google-api-services-cloudkms:v1-rev12-1.22.0
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20181015-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190126-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190607-1.27.0
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev6-1.22.0
|
||||
com.google.apis:google-api-services-drive:v2-rev160-1.19.1
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
|
||||
@@ -176,22 +175,23 @@ javax.transaction:transaction-api:1.1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.9.2
|
||||
joda-time:joda-time:2.10.3
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy:1.9.11
|
||||
net.java.dev.jna:jna-platform:5.3.1
|
||||
net.java.dev.jna:jna:5.3.1
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-job-management:2.11.0
|
||||
org.apache.beam:beam-model-pipeline:2.11.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.11.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.11.0
|
||||
org.apache.beam:beam-sdks-java-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.11.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.11.0
|
||||
org.apache.beam:beam-vendor-grpc-1_13_1:0.2
|
||||
org.apache.beam:beam-vendor-guava-20_0:0.1
|
||||
org.apache.beam:beam-model-job-management:2.16.0
|
||||
org.apache.beam:beam-model-pipeline:2.16.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.16.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.16.0
|
||||
org.apache.beam:beam-sdks-java-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.16.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.16.0
|
||||
org.apache.beam:beam-vendor-bytebuddy-1_9_3:0.1
|
||||
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.8
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# 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.
|
||||
org.jacoco:org.jacoco.agent:0.8.4
|
||||
org.jacoco:org.jacoco.agent:0.8.5
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# 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.
|
||||
org.jacoco:org.jacoco.agent:0.8.4
|
||||
org.jacoco:org.jacoco.ant:0.8.4
|
||||
org.jacoco:org.jacoco.core:0.8.4
|
||||
org.jacoco:org.jacoco.report:0.8.4
|
||||
org.ow2.asm:asm-analysis:7.1
|
||||
org.ow2.asm:asm-commons:7.1
|
||||
org.ow2.asm:asm-tree:7.1
|
||||
org.ow2.asm:asm:7.1
|
||||
org.jacoco:org.jacoco.agent:0.8.5
|
||||
org.jacoco:org.jacoco.ant:0.8.5
|
||||
org.jacoco:org.jacoco.core:0.8.5
|
||||
org.jacoco:org.jacoco.report:0.8.5
|
||||
org.ow2.asm:asm-analysis:7.2
|
||||
org.ow2.asm:asm-commons:7.2
|
||||
org.ow2.asm:asm-tree:7.2
|
||||
org.ow2.asm:asm:7.2
|
||||
|
||||
@@ -6,11 +6,10 @@ 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.8
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.fasterxml.jackson.core:jackson-databind:2.9.8
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.9.10
|
||||
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.luben:zstd-jni:1.3.8-3
|
||||
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
|
||||
@@ -18,7 +17,7 @@ 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.44.0
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.43.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:1.6.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:1.6.0
|
||||
@@ -44,7 +43,7 @@ com.google.apis:google-api-services-bigquery:v2-rev20181104-1.27.0
|
||||
com.google.apis:google-api-services-clouddebugger:v2-rev20180801-1.27.0
|
||||
com.google.apis:google-api-services-cloudkms:v1-rev12-1.22.0
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20181015-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190126-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190607-1.27.0
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev6-1.22.0
|
||||
com.google.apis:google-api-services-drive:v2-rev160-1.19.1
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
|
||||
@@ -165,22 +164,23 @@ javax.transaction:transaction-api:1.1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.9.2
|
||||
joda-time:joda-time:2.10.3
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy:1.9.11
|
||||
net.java.dev.jna:jna-platform:5.3.1
|
||||
net.java.dev.jna:jna:5.3.1
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-job-management:2.11.0
|
||||
org.apache.beam:beam-model-pipeline:2.11.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.11.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.11.0
|
||||
org.apache.beam:beam-sdks-java-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.11.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.11.0
|
||||
org.apache.beam:beam-vendor-grpc-1_13_1:0.2
|
||||
org.apache.beam:beam-vendor-guava-20_0:0.1
|
||||
org.apache.beam:beam-model-job-management:2.16.0
|
||||
org.apache.beam:beam-model-pipeline:2.16.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.16.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.16.0
|
||||
org.apache.beam:beam-sdks-java-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.16.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.16.0
|
||||
org.apache.beam:beam-vendor-bytebuddy-1_9_3:0.1
|
||||
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.8
|
||||
@@ -204,7 +204,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -6,9 +6,9 @@ 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.8
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.fasterxml.jackson.core:jackson-databind:2.9.8
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.9.10
|
||||
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
|
||||
com.github.jnr:jnr-a64asm:1.0.0
|
||||
@@ -18,7 +18,6 @@ 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.github.luben:zstd-jni:1.3.8-3
|
||||
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
|
||||
@@ -26,7 +25,7 @@ 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.44.0
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.43.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:1.6.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:1.6.0
|
||||
@@ -52,7 +51,7 @@ com.google.apis:google-api-services-bigquery:v2-rev20181104-1.27.0
|
||||
com.google.apis:google-api-services-clouddebugger:v2-rev20180801-1.27.0
|
||||
com.google.apis:google-api-services-cloudkms:v1-rev12-1.22.0
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20181015-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190126-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190607-1.27.0
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev6-1.22.0
|
||||
com.google.apis:google-api-services-drive:v2-rev160-1.19.1
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
|
||||
@@ -176,22 +175,23 @@ javax.transaction:transaction-api:1.1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.9.2
|
||||
joda-time:joda-time:2.10.3
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy:1.9.11
|
||||
net.java.dev.jna:jna-platform:5.3.1
|
||||
net.java.dev.jna:jna:5.3.1
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-job-management:2.11.0
|
||||
org.apache.beam:beam-model-pipeline:2.11.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.11.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.11.0
|
||||
org.apache.beam:beam-sdks-java-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.11.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.11.0
|
||||
org.apache.beam:beam-vendor-grpc-1_13_1:0.2
|
||||
org.apache.beam:beam-vendor-guava-20_0:0.1
|
||||
org.apache.beam:beam-model-job-management:2.16.0
|
||||
org.apache.beam:beam-model-pipeline:2.16.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.16.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.16.0
|
||||
org.apache.beam:beam-sdks-java-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.16.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.16.0
|
||||
org.apache.beam:beam-vendor-bytebuddy-1_9_3:0.1
|
||||
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.8
|
||||
@@ -215,7 +215,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:1.9.5
|
||||
|
||||
@@ -6,11 +6,10 @@ 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.8
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.fasterxml.jackson.core:jackson-databind:2.9.8
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.9.10
|
||||
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.luben:zstd-jni:1.3.8-3
|
||||
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
|
||||
@@ -18,7 +17,7 @@ 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.44.0
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.43.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:1.6.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:1.6.0
|
||||
@@ -44,7 +43,7 @@ com.google.apis:google-api-services-bigquery:v2-rev20181104-1.27.0
|
||||
com.google.apis:google-api-services-clouddebugger:v2-rev20180801-1.27.0
|
||||
com.google.apis:google-api-services-cloudkms:v1-rev12-1.22.0
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20181015-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190126-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190607-1.27.0
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev6-1.22.0
|
||||
com.google.apis:google-api-services-drive:v2-rev160-1.19.1
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
|
||||
@@ -130,6 +129,7 @@ commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:2.1.7
|
||||
io.dropwizard.metrics:metrics-core:3.1.2
|
||||
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
|
||||
@@ -173,24 +173,25 @@ javax.transaction:transaction-api:1.1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.9.2
|
||||
joda-time:joda-time:2.10.3
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.9.7
|
||||
net.bytebuddy:byte-buddy:1.9.11
|
||||
net.java.dev.jna:jna-platform:5.3.1
|
||||
net.java.dev.jna:jna:5.3.1
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-job-management:2.11.0
|
||||
org.apache.beam:beam-model-pipeline:2.11.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.11.0
|
||||
org.apache.beam:beam-runners-direct-java:2.11.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.11.0
|
||||
org.apache.beam:beam-sdks-java-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.11.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.11.0
|
||||
org.apache.beam:beam-vendor-grpc-1_13_1:0.2
|
||||
org.apache.beam:beam-vendor-guava-20_0:0.1
|
||||
org.apache.beam:beam-model-job-management:2.16.0
|
||||
org.apache.beam:beam-model-pipeline:2.16.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.16.0
|
||||
org.apache.beam:beam-runners-direct-java:2.16.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.16.0
|
||||
org.apache.beam:beam-sdks-java-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.16.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.16.0
|
||||
org.apache.beam:beam-vendor-bytebuddy-1_9_3:0.1
|
||||
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-exec:1.3
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
@@ -227,7 +228,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -6,11 +6,10 @@ 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.8
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.fasterxml.jackson.core:jackson-databind:2.9.8
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.9.10
|
||||
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.luben:zstd-jni:1.3.8-3
|
||||
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
|
||||
@@ -18,7 +17,7 @@ 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.44.0
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.43.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:1.6.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:1.6.0
|
||||
@@ -44,7 +43,7 @@ com.google.apis:google-api-services-bigquery:v2-rev20181104-1.27.0
|
||||
com.google.apis:google-api-services-clouddebugger:v2-rev20180801-1.27.0
|
||||
com.google.apis:google-api-services-cloudkms:v1-rev12-1.22.0
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20181015-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190126-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190607-1.27.0
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev6-1.22.0
|
||||
com.google.apis:google-api-services-drive:v2-rev160-1.19.1
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
|
||||
@@ -129,6 +128,7 @@ commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:2.1.7
|
||||
io.dropwizard.metrics:metrics-core:3.1.2
|
||||
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
|
||||
@@ -171,24 +171,25 @@ javax.transaction:transaction-api:1.1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.9.2
|
||||
joda-time:joda-time:2.10.3
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.9.7
|
||||
net.bytebuddy:byte-buddy:1.9.11
|
||||
net.java.dev.jna:jna-platform:5.3.1
|
||||
net.java.dev.jna:jna:5.3.1
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-job-management:2.11.0
|
||||
org.apache.beam:beam-model-pipeline:2.11.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.11.0
|
||||
org.apache.beam:beam-runners-direct-java:2.11.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.11.0
|
||||
org.apache.beam:beam-sdks-java-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.11.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.11.0
|
||||
org.apache.beam:beam-vendor-grpc-1_13_1:0.2
|
||||
org.apache.beam:beam-vendor-guava-20_0:0.1
|
||||
org.apache.beam:beam-model-job-management:2.16.0
|
||||
org.apache.beam:beam-model-pipeline:2.16.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.16.0
|
||||
org.apache.beam:beam-runners-direct-java:2.16.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.16.0
|
||||
org.apache.beam:beam-sdks-java-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.16.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.16.0
|
||||
org.apache.beam:beam-vendor-bytebuddy-1_9_3:0.1
|
||||
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-exec:1.3
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
@@ -225,7 +226,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# 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.
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.48
|
||||
|
||||
@@ -6,9 +6,9 @@ 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.8
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.fasterxml.jackson.core:jackson-databind:2.9.8
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.9.10
|
||||
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
|
||||
com.github.jnr:jnr-a64asm:1.0.0
|
||||
@@ -18,7 +18,6 @@ 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.github.luben:zstd-jni:1.3.8-3
|
||||
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
|
||||
@@ -26,7 +25,7 @@ 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.44.0
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.43.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:1.6.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:1.6.0
|
||||
@@ -52,7 +51,7 @@ com.google.apis:google-api-services-bigquery:v2-rev20181104-1.27.0
|
||||
com.google.apis:google-api-services-clouddebugger:v2-rev20180801-1.27.0
|
||||
com.google.apis:google-api-services-cloudkms:v1-rev12-1.22.0
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20181015-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190126-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190607-1.27.0
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev6-1.22.0
|
||||
com.google.apis:google-api-services-drive:v2-rev160-1.19.1
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
|
||||
@@ -141,6 +140,7 @@ commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:2.1.7
|
||||
io.dropwizard.metrics:metrics-core:3.1.2
|
||||
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
|
||||
@@ -184,24 +184,25 @@ javax.transaction:transaction-api:1.1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.9.2
|
||||
joda-time:joda-time:2.10.3
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.9.7
|
||||
net.bytebuddy:byte-buddy:1.9.11
|
||||
net.java.dev.jna:jna-platform:5.3.1
|
||||
net.java.dev.jna:jna:5.3.1
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-job-management:2.11.0
|
||||
org.apache.beam:beam-model-pipeline:2.11.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.11.0
|
||||
org.apache.beam:beam-runners-direct-java:2.11.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.11.0
|
||||
org.apache.beam:beam-sdks-java-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.11.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.11.0
|
||||
org.apache.beam:beam-vendor-grpc-1_13_1:0.2
|
||||
org.apache.beam:beam-vendor-guava-20_0:0.1
|
||||
org.apache.beam:beam-model-job-management:2.16.0
|
||||
org.apache.beam:beam-model-pipeline:2.16.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.16.0
|
||||
org.apache.beam:beam-runners-direct-java:2.16.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.16.0
|
||||
org.apache.beam:beam-sdks-java-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.16.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.16.0
|
||||
org.apache.beam:beam-vendor-bytebuddy-1_9_3:0.1
|
||||
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-exec:1.3
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
@@ -239,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -6,9 +6,9 @@ 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.8
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.fasterxml.jackson.core:jackson-databind:2.9.8
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.9.10
|
||||
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
|
||||
com.github.jnr:jnr-a64asm:1.0.0
|
||||
@@ -18,7 +18,6 @@ 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.github.luben:zstd-jni:1.3.8-3
|
||||
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
|
||||
@@ -26,7 +25,7 @@ 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.44.0
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:0.38.0
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.43.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:1.6.0
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:1.6.0
|
||||
@@ -52,7 +51,7 @@ com.google.apis:google-api-services-bigquery:v2-rev20181104-1.27.0
|
||||
com.google.apis:google-api-services-clouddebugger:v2-rev20180801-1.27.0
|
||||
com.google.apis:google-api-services-cloudkms:v1-rev12-1.22.0
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20181015-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190126-1.27.0
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20190607-1.27.0
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev6-1.22.0
|
||||
com.google.apis:google-api-services-drive:v2-rev160-1.19.1
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev60-1.22.0
|
||||
@@ -141,6 +140,7 @@ commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:2.1.7
|
||||
io.dropwizard.metrics:metrics-core:3.1.2
|
||||
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
|
||||
@@ -184,24 +184,25 @@ javax.transaction:transaction-api:1.1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.9.2
|
||||
joda-time:joda-time:2.10.3
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.9.7
|
||||
net.bytebuddy:byte-buddy:1.9.11
|
||||
net.java.dev.jna:jna-platform:5.3.1
|
||||
net.java.dev.jna:jna:5.3.1
|
||||
org.apache.avro:avro:1.8.2
|
||||
org.apache.beam:beam-model-job-management:2.11.0
|
||||
org.apache.beam:beam-model-pipeline:2.11.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.11.0
|
||||
org.apache.beam:beam-runners-direct-java:2.11.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.11.0
|
||||
org.apache.beam:beam-sdks-java-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.11.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.11.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.11.0
|
||||
org.apache.beam:beam-vendor-grpc-1_13_1:0.2
|
||||
org.apache.beam:beam-vendor-guava-20_0:0.1
|
||||
org.apache.beam:beam-model-job-management:2.16.0
|
||||
org.apache.beam:beam-model-pipeline:2.16.0
|
||||
org.apache.beam:beam-runners-core-construction-java:2.16.0
|
||||
org.apache.beam:beam-runners-direct-java:2.16.0
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.16.0
|
||||
org.apache.beam:beam-sdks-java-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.16.0
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.16.0
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.16.0
|
||||
org.apache.beam:beam-vendor-bytebuddy-1_9_3:0.1
|
||||
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-exec:1.3
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
@@ -239,7 +240,7 @@ org.jboss.logging:jboss-logging:3.3.2.Final
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
|
||||
org.jboss:jandex:2.0.5.Final
|
||||
org.jetbrains:annotations:17.0.0
|
||||
org.joda:joda-money:0.10.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mockito:mockito-core:2.25.0
|
||||
|
||||
@@ -16,6 +16,7 @@ process.env.CHROME_BIN = require('puppeteer').executablePath()
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
basePath: '..',
|
||||
browsers: ['ChromeHeadlessNoSandbox'],
|
||||
customLaunchers: {
|
||||
ChromeHeadlessNoSandbox: {
|
||||
@@ -41,10 +42,6 @@ module.exports = function(config) {
|
||||
pattern: 'core/build/generated/source/custom/main/**/*.soy.js',
|
||||
included: false
|
||||
},
|
||||
{
|
||||
pattern: 'node_modules/soyutils_usegoog.js',
|
||||
included: false
|
||||
},
|
||||
{
|
||||
pattern: 'node_modules/google-closure-library/closure/goog/deps.js',
|
||||
included: false,
|
||||
@@ -69,7 +66,6 @@ module.exports = function(config) {
|
||||
'node_modules/google-closure-library/closure/**/*.js': ['closure'],
|
||||
'core/src/*/javascript/**/*.js': ['closure'],
|
||||
'core/build/generated/source/custom/main/**/*.soy.js': ['closure'],
|
||||
'node_modules/soyutils_usegoog.js': ['closure']
|
||||
},
|
||||
proxies: {
|
||||
"/assets/": "/base/core/build/resources/main/google/registry/ui/assets/"
|
||||
@@ -85,7 +85,7 @@ public class InvoicingPipeline implements Serializable {
|
||||
}
|
||||
|
||||
/** Custom options for running the invoicing pipeline. */
|
||||
interface InvoicingPipelineOptions extends DataflowPipelineOptions {
|
||||
public interface InvoicingPipelineOptions extends DataflowPipelineOptions {
|
||||
/** Returns the yearMonth we're generating invoices for, in yyyy-MM format. */
|
||||
@Description("The yearMonth we generate invoices for, in yyyy-MM format.")
|
||||
ValueProvider<String> getYearMonth();
|
||||
|
||||
@@ -105,7 +105,7 @@ public class Spec11Pipeline implements Serializable {
|
||||
}
|
||||
|
||||
/** Custom options for running the spec11 pipeline. */
|
||||
interface Spec11PipelineOptions extends DataflowPipelineOptions {
|
||||
public interface Spec11PipelineOptions extends DataflowPipelineOptions {
|
||||
/** Returns the local date we're generating the report for, in yyyy-MM-dd format. */
|
||||
@Description("The local date we generate the report for, in yyyy-MM-dd format.")
|
||||
ValueProvider<String> getDate();
|
||||
|
||||
@@ -1296,12 +1296,6 @@ public final class RegistryConfig {
|
||||
return config.registryTool.clientSecret;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("toolsCloudSqlJdbcUrl")
|
||||
public static String providesToolsCloudSqlJdbcUrl(RegistryConfigSettings config) {
|
||||
return config.registryTool.jdbcUrl;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("toolsCloudSqlUsername")
|
||||
public static String providesToolsCloudSqlUsername(RegistryConfigSettings config) {
|
||||
|
||||
@@ -213,7 +213,6 @@ public class RegistryConfigSettings {
|
||||
public static class RegistryTool {
|
||||
public String clientId;
|
||||
public String clientSecret;
|
||||
public String jdbcUrl;
|
||||
public String username;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,6 +422,4 @@ registryTool:
|
||||
clientId: YOUR_CLIENT_ID
|
||||
# OAuth client secret used by the tool.
|
||||
clientSecret: YOUR_CLIENT_SECRET
|
||||
# Nomulus tool uses a different jdbc url and user to connect to Cloud SQL
|
||||
jdbcUrl: jdbc:postgresql://localhost/tool
|
||||
username: toolusername
|
||||
|
||||
@@ -55,6 +55,12 @@
|
||||
<url-pattern>/registrar-settings</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Registry lock get/post/verify. -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>frontend-servlet</servlet-name>
|
||||
<url-pattern>/registry-lock-get</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Security config -->
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
|
||||
@@ -187,6 +187,7 @@ import org.joda.time.Duration;
|
||||
* @error {@link DomainFlowUtils.UnexpectedClaimsNoticeException}
|
||||
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
|
||||
* @error {@link DomainFlowUtils.UnsupportedMarkTypeException}
|
||||
* @error {@link DomainPricingLogic.AllocationTokenInvalidForPremiumNameException}
|
||||
*/
|
||||
@ReportingSpec(ActivityReportField.DOMAIN_CREATE)
|
||||
public class DomainCreateFlow implements TransactionalFlow {
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.pricing.PricingEngineProxy.getDomainFeeClass;
|
||||
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
||||
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.CommandUseErrorException;
|
||||
import google.registry.flows.FlowScope;
|
||||
import google.registry.flows.custom.DomainPricingCustomLogic;
|
||||
import google.registry.flows.custom.DomainPricingCustomLogic.CreatePriceParameters;
|
||||
@@ -182,13 +182,14 @@ public final class DomainPricingLogic {
|
||||
}
|
||||
|
||||
private Money getDomainCreateCostWithDiscount(
|
||||
String domainName, DateTime date, int years, Optional<AllocationToken> allocationToken) {
|
||||
String domainName, DateTime date, int years, Optional<AllocationToken> allocationToken)
|
||||
throws EppException {
|
||||
DomainPrices domainPrices = PricingEngineProxy.getPricesForDomainName(domainName, date);
|
||||
checkArgument(
|
||||
!allocationToken.isPresent()
|
||||
|| allocationToken.get().getDiscountFraction() == 0.0
|
||||
|| !domainPrices.isPremium(),
|
||||
"A nonzero discount code cannot be applied to premium domains");
|
||||
if (allocationToken.isPresent()
|
||||
&& allocationToken.get().getDiscountFraction() != 0.0
|
||||
&& domainPrices.isPremium()) {
|
||||
throw new AllocationTokenInvalidForPremiumNameException();
|
||||
}
|
||||
Money oneYearCreateCost = domainPrices.getCreateCost();
|
||||
Money totalDomainCreateCost = oneYearCreateCost.multipliedBy(years);
|
||||
// If a discount is applicable, apply it only to the first year
|
||||
@@ -200,4 +201,12 @@ public final class DomainPricingLogic {
|
||||
}
|
||||
return totalDomainCreateCost;
|
||||
}
|
||||
|
||||
/** An allocation token was provided that is invalid for premium domains. */
|
||||
public static class AllocationTokenInvalidForPremiumNameException
|
||||
extends CommandUseErrorException {
|
||||
public AllocationTokenInvalidForPremiumNameException() {
|
||||
super("A nonzero discount code cannot be applied to premium domains");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,16 @@ public class Cursor extends ImmutableObject {
|
||||
* stored is the last time that registrar changes were successfully synced to the sheet. If
|
||||
* there were no changes since the last time the action run, the cursor is not updated.
|
||||
*/
|
||||
SYNC_REGISTRAR_SHEET(EntityGroupRoot.class);
|
||||
SYNC_REGISTRAR_SHEET(EntityGroupRoot.class),
|
||||
|
||||
/** Cursor for tracking monthly uploads of ICANN transaction reports. */
|
||||
ICANN_UPLOAD_TX(Registry.class),
|
||||
|
||||
/** Cursor for tracking monthly uploads of ICANN activity reports. */
|
||||
ICANN_UPLOAD_ACTIVITY(Registry.class),
|
||||
|
||||
/** Cursor for tracking monthly upload of MANIFEST.txt to ICANN. */
|
||||
ICANN_UPLOAD_MANIFEST(EntityGroupRoot.class);
|
||||
|
||||
/** See the definition of scope on {@link #getScopeClass}. */
|
||||
private final Class<? extends ImmutableObject> scope;
|
||||
|
||||
@@ -35,6 +35,8 @@ import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import com.googlecode.objectify.annotation.Mapify;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.domain.DomainFlowUtils;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
@@ -201,6 +203,13 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
getInstance().redemptionHistoryEntry == null
|
||||
|| TokenType.SINGLE_USE.equals(getInstance().tokenType),
|
||||
"Redemption history entry can only be specified for SINGLE_USE tokens");
|
||||
if (getInstance().domainName != null) {
|
||||
try {
|
||||
DomainFlowUtils.validateDomainName(getInstance().domainName);
|
||||
} catch (EppException e) {
|
||||
throw new IllegalArgumentException("Invalid domain name: " + getInstance().domainName, e);
|
||||
}
|
||||
}
|
||||
return super.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.registry.Registry.TldType;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -80,6 +81,15 @@ public final class Registries {
|
||||
return ImmutableSet.copyOf(filterValues(cache.get(), equalTo(type)).keySet());
|
||||
}
|
||||
|
||||
/** Returns the Registry entities themselves of the given type loaded fresh from Datastore. */
|
||||
public static ImmutableSet<Registry> getTldEntitiesOfType(TldType type) {
|
||||
ImmutableSet<Key<Registry>> keys =
|
||||
filterValues(cache.get(), equalTo(type)).keySet().stream()
|
||||
.map(tld -> Key.create(getCrossTldKey(), Registry.class, tld))
|
||||
.collect(toImmutableSet());
|
||||
return ImmutableSet.copyOf(tm().doTransactionless(() -> ofy().load().keys(keys).values()));
|
||||
}
|
||||
|
||||
/** Pass-through check that the specified TLD exists, otherwise throw an IAE. */
|
||||
public static String assertTldExists(String tld) {
|
||||
checkArgument(
|
||||
|
||||
@@ -17,7 +17,9 @@ package google.registry.model.registry;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.schema.domain.RegistryLock;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
/** Data access object for {@link google.registry.schema.domain.RegistryLock}. */
|
||||
@@ -40,13 +42,50 @@ public final class RegistryLockDao {
|
||||
Long.class)
|
||||
.setParameter("verificationCode", verificationCode)
|
||||
.getSingleResult();
|
||||
// TODO(gbrodman): Don't throw NPE here. Maybe NoResultException fits better?
|
||||
checkNotNull(revisionId, "No registry lock with this code");
|
||||
return em.find(RegistryLock.class, revisionId);
|
||||
});
|
||||
}
|
||||
|
||||
public static void save(RegistryLock registryLock) {
|
||||
/** Returns all lock objects that this registrar has created. */
|
||||
public static ImmutableList<RegistryLock> getByRegistrarId(String registrarId) {
|
||||
return jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
ImmutableList.copyOf(
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createQuery(
|
||||
"SELECT lock FROM RegistryLock lock WHERE"
|
||||
+ " lock.registrarId = :registrarId",
|
||||
RegistryLock.class)
|
||||
.setParameter("registrarId", registrarId)
|
||||
.getResultList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the most recent lock object for a given repo ID (i.e. a domain) or empty if this domain
|
||||
* hasn't been locked before.
|
||||
*/
|
||||
public static Optional<RegistryLock> getMostRecentByRepoId(String repoId) {
|
||||
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());
|
||||
}
|
||||
|
||||
public static RegistryLock save(RegistryLock registryLock) {
|
||||
checkNotNull(registryLock, "Null registry lock cannot be saved");
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(registryLock));
|
||||
return jpaTm().transact(() -> jpaTm().getEntityManager().merge(registryLock));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,17 +79,14 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
||||
T result = work.run();
|
||||
txn.commit();
|
||||
return result;
|
||||
} catch (Throwable transactionException) {
|
||||
String rollbackMessage;
|
||||
} catch (RuntimeException e) {
|
||||
try {
|
||||
txn.rollback();
|
||||
rollbackMessage = "transaction rolled back";
|
||||
logger.atWarning().log("Error during transaction; transaction rolled back");
|
||||
} catch (Throwable rollbackException) {
|
||||
logger.atSevere().withCause(rollbackException).log("Rollback failed, suppressing error");
|
||||
rollbackMessage = "transaction rollback failed";
|
||||
logger.atSevere().withCause(rollbackException).log("Rollback failed; suppressing error");
|
||||
}
|
||||
throw new PersistenceException(
|
||||
"Error during transaction, " + rollbackMessage, transactionException);
|
||||
throw e;
|
||||
} finally {
|
||||
txnInfo.clear();
|
||||
}
|
||||
|
||||
@@ -14,8 +14,13 @@
|
||||
|
||||
package google.registry.model.transaction;
|
||||
|
||||
|
||||
import com.google.appengine.api.utils.SystemProperty;
|
||||
import com.google.appengine.api.utils.SystemProperty.Environment.Value;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import google.registry.model.ofy.DatastoreTransactionManager;
|
||||
import google.registry.persistence.DaggerPersistenceComponent;
|
||||
import google.registry.tools.RegistryToolEnvironment;
|
||||
|
||||
/** Factory class to create {@link TransactionManager} instance. */
|
||||
// TODO: Rename this to PersistenceFactory and move to persistence package.
|
||||
@@ -27,19 +32,14 @@ public class TransactionManagerFactory {
|
||||
private TransactionManagerFactory() {}
|
||||
|
||||
private static JpaTransactionManager createJpaTransactionManager() {
|
||||
// TODO(shicong): There is currently no environment where we want to create a real JPA
|
||||
// transaction manager here. The unit tests that require one are all set up using
|
||||
// JpaTransactionManagerRule which launches its own PostgreSQL instance. When we actually have
|
||||
// PostgreSQL tables in production, ensure that all of the test environments are set up
|
||||
// correctly and restore the code that creates a JpaTransactionManager when
|
||||
// RegistryEnvironment.get() != UNITTEST.
|
||||
//
|
||||
// We removed the original code because it didn't work in sandbox (due to the absence of the
|
||||
// persistence.xml file, which has since been added), and then (after adding this) didn't work
|
||||
// in crash because the postgresql password hadn't been set up. Prior to restoring, we'll need
|
||||
// to do setup in all environments, and we probably only want to do this once we're actually
|
||||
// using Cloud SQL for one of the new tables.
|
||||
return DummyJpaTransactionManager.create();
|
||||
if (isInAppEngine()) {
|
||||
return DaggerPersistenceComponent.create().appEngineJpaTransactionManager();
|
||||
} else if (RegistryToolEnvironment.isInRegistryTool()
|
||||
&& RegistryToolEnvironment.isJpaTmEnabled()) {
|
||||
return DaggerPersistenceComponent.create().nomulusToolJpaTransactionManager();
|
||||
} else {
|
||||
return DummyJpaTransactionManager.create();
|
||||
}
|
||||
}
|
||||
|
||||
private static TransactionManager createTransactionManager() {
|
||||
@@ -50,12 +50,16 @@ public class TransactionManagerFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets jpaTm to the implementation for Nomulus tool. Note that this method should be only used by
|
||||
* {@link google.registry.tools.RegistryCli} to initialize jpaTm.
|
||||
* This function uses App Engine API to determine if the current runtime environment is App
|
||||
* Engine.
|
||||
*
|
||||
* @see <a
|
||||
* href="https://cloud.google.com/appengine/docs/standard/java/javadoc/com/google/appengine/api/utils/SystemProperty">App
|
||||
* Engine API public doc</a>
|
||||
*/
|
||||
public static void initForTool() {
|
||||
// TODO(shicong): Uncomment the line below when we set up Cloud SQL instance in all environments
|
||||
// jpaTm = DaggerPersistenceComponent.create().nomulusToolJpaTransactionManager();
|
||||
private static boolean isInAppEngine() {
|
||||
// SystemProperty.environment.value() returns null if the current runtime is local JVM
|
||||
return SystemProperty.environment.value() == Value.Production;
|
||||
}
|
||||
|
||||
/** Returns {@link TransactionManager} instance. */
|
||||
|
||||
@@ -30,6 +30,7 @@ import google.registry.ui.server.registrar.ConsoleUiAction;
|
||||
import google.registry.ui.server.registrar.OteStatusAction;
|
||||
import google.registry.ui.server.registrar.RegistrarConsoleModule;
|
||||
import google.registry.ui.server.registrar.RegistrarSettingsAction;
|
||||
import google.registry.ui.server.registrar.RegistryLockGetAction;
|
||||
|
||||
/** Dagger component with per-request lifetime for "default" App Engine module. */
|
||||
@RequestScope
|
||||
@@ -50,6 +51,8 @@ interface FrontendRequestComponent {
|
||||
OteStatusAction oteStatusAction();
|
||||
RegistrarSettingsAction registrarSettingsAction();
|
||||
|
||||
RegistryLockGetAction registryLockGetAction();
|
||||
|
||||
@Subcomponent.Builder
|
||||
abstract class Builder implements RequestComponentBuilder<FrontendRequestComponent> {
|
||||
@Override public abstract Builder requestModule(RequestModule requestModule);
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package google.registry.persistence;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Converter;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
|
||||
/** JPA converter for {@link CurrencyUnit}s. */
|
||||
@Converter(autoApply = true)
|
||||
public class CurrencyUnitConverter extends ToStringConverterBase<CurrencyUnit> {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public CurrencyUnit convertToEntityAttribute(@Nullable String columnValue) {
|
||||
return (columnValue == null) ? null : CurrencyUnit.of(columnValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.persistence;
|
||||
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Converter;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** JPA converter to for storing/retrieving {@link org.joda.time.DateTime} objects. */
|
||||
@Converter(autoApply = true)
|
||||
public class DateTimeConverter implements AttributeConverter<DateTime, Timestamp> {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Timestamp convertToDatabaseColumn(@Nullable DateTime attribute) {
|
||||
return attribute == null ? null : new Timestamp(attribute.getMillis());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public DateTime convertToEntityAttribute(@Nullable Timestamp dbData) {
|
||||
DateTime result = dbData == null ? null : new DateTime(dbData.getTime(), UTC);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.persistence;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Maps;
|
||||
import java.io.File;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
import org.hibernate.tool.schema.TargetType;
|
||||
|
||||
/** Utility class to export DDL script for given {@link javax.persistence.Entity} classes. */
|
||||
public class HibernateSchemaExporter {
|
||||
private final String jdbcUrl;
|
||||
private final String username;
|
||||
private final String password;
|
||||
|
||||
private HibernateSchemaExporter(String jdbcUrl, String username, String password) {
|
||||
this.jdbcUrl = jdbcUrl;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/** Constructs a {@link HibernateSchemaExporter} instance. */
|
||||
public static HibernateSchemaExporter create(String jdbcUrl, String username, String password) {
|
||||
return new HibernateSchemaExporter(jdbcUrl, username, password);
|
||||
}
|
||||
|
||||
/** Exports DDL script to the {@code outputFile} for the given {@code entityClasses}. */
|
||||
public void export(ImmutableList<Class> entityClasses, File outputFile) {
|
||||
// Configure Hibernate settings.
|
||||
Map<String, String> settings = Maps.newHashMap();
|
||||
settings.put(Environment.DIALECT, NomulusPostgreSQLDialect.class.getName());
|
||||
settings.put(Environment.URL, jdbcUrl);
|
||||
settings.put(Environment.USER, username);
|
||||
settings.put(Environment.PASS, password);
|
||||
settings.put(Environment.HBM2DDL_AUTO, "none");
|
||||
settings.put(Environment.SHOW_SQL, "true");
|
||||
settings.put(
|
||||
Environment.PHYSICAL_NAMING_STRATEGY, NomulusNamingStrategy.class.getCanonicalName());
|
||||
|
||||
try (StandardServiceRegistry registry =
|
||||
new StandardServiceRegistryBuilder().applySettings(settings).build()) {
|
||||
MetadataSources metadata = new MetadataSources(registry);
|
||||
|
||||
// Note that we need to also add all converters to the Hibernate context because
|
||||
// the entity class may use the customized type.
|
||||
Stream.concat(entityClasses.stream(), findAllConverters().stream())
|
||||
.forEach(metadata::addAnnotatedClass);
|
||||
|
||||
SchemaExport export = new SchemaExport();
|
||||
export.setHaltOnError(true);
|
||||
export.setFormat(true);
|
||||
export.setDelimiter(";");
|
||||
export.setOutputFile(outputFile.getAbsolutePath());
|
||||
export.createOnly(EnumSet.of(TargetType.SCRIPT), metadata.buildMetadata());
|
||||
}
|
||||
}
|
||||
|
||||
private ImmutableList<Class> findAllConverters() {
|
||||
return PersistenceXmlUtility.getManagedClasses().stream()
|
||||
.filter(AttributeConverter.class::isAssignableFrom)
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,10 @@ public class PersistenceModule {
|
||||
public static final String HIKARI_MAXIMUM_POOL_SIZE = "hibernate.hikari.maximumPoolSize";
|
||||
public static final String HIKARI_IDLE_TIMEOUT = "hibernate.hikari.idleTimeout";
|
||||
|
||||
public static final String HIKARI_DS_SOCKET_FACTORY = "hibernate.hikari.dataSource.socketFactory";
|
||||
public static final String HIKARI_DS_CLOUD_SQL_INSTANCE =
|
||||
"hibernate.hikari.dataSource.cloudSqlInstance";
|
||||
|
||||
@Provides
|
||||
@DefaultHibernateConfigs
|
||||
public static ImmutableMap<String, String> providesDefaultDatabaseConfigs() {
|
||||
@@ -79,27 +83,31 @@ public class PersistenceModule {
|
||||
return properties.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@PartialCloudSqlConfigs
|
||||
public static ImmutableMap<String, String> providesPartialCloudSqlConfigs(
|
||||
@Config("cloudSqlJdbcUrl") String jdbcUrl,
|
||||
@Config("cloudSqlInstanceConnectionName") String instanceConnectionName,
|
||||
@DefaultHibernateConfigs ImmutableMap<String, String> defaultConfigs) {
|
||||
HashMap<String, String> overrides = Maps.newHashMap(defaultConfigs);
|
||||
overrides.put(Environment.URL, jdbcUrl);
|
||||
overrides.put(HIKARI_DS_SOCKET_FACTORY, "com.google.cloud.sql.postgres.SocketFactory");
|
||||
overrides.put(HIKARI_DS_CLOUD_SQL_INSTANCE, instanceConnectionName);
|
||||
return ImmutableMap.copyOf(overrides);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@AppEngineJpaTm
|
||||
public static JpaTransactionManager providesAppEngineJpaTm(
|
||||
@Config("cloudSqlJdbcUrl") String jdbcUrl,
|
||||
@Config("cloudSqlUsername") String username,
|
||||
@Config("cloudSqlInstanceConnectionName") String instanceConnectionName,
|
||||
KmsKeyring kmsKeyring,
|
||||
@DefaultHibernateConfigs ImmutableMap<String, String> defaultConfigs,
|
||||
@PartialCloudSqlConfigs ImmutableMap<String, String> cloudSqlConfigs,
|
||||
Clock clock) {
|
||||
HashMap<String, String> overrides = Maps.newHashMap(defaultConfigs);
|
||||
|
||||
// For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections.
|
||||
// See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
|
||||
overrides.put("socketFactory", "com.google.cloud.sql.postgres.SocketFactory");
|
||||
overrides.put("cloudSqlInstance", instanceConnectionName);
|
||||
|
||||
overrides.put(Environment.URL, jdbcUrl);
|
||||
HashMap<String, String> overrides = Maps.newHashMap(cloudSqlConfigs);
|
||||
overrides.put(Environment.USER, username);
|
||||
overrides.put(Environment.PASS, kmsKeyring.getCloudSqlPassword());
|
||||
|
||||
return new JpaTransactionManagerImpl(create(overrides), clock);
|
||||
}
|
||||
|
||||
@@ -107,27 +115,13 @@ public class PersistenceModule {
|
||||
@Singleton
|
||||
@NomulusToolJpaTm
|
||||
public static JpaTransactionManager providesNomulusToolJpaTm(
|
||||
@Config("toolsCloudSqlJdbcUrl") String jdbcUrl,
|
||||
@Config("toolsCloudSqlUsername") String username,
|
||||
@Config("cloudSqlInstanceConnectionName") String instanceConnectionName,
|
||||
KmsKeyring kmsKeyring,
|
||||
@DefaultHibernateConfigs ImmutableMap<String, String> defaultConfigs,
|
||||
@PartialCloudSqlConfigs ImmutableMap<String, String> cloudSqlConfigs,
|
||||
Clock clock) {
|
||||
|
||||
// Cloud SQL JDBC Socket Factory library requires the jdbc url to include all connection
|
||||
// information, otherwise the connection initialization will fail. See here for more details:
|
||||
// https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory
|
||||
String fullJdbcUrl =
|
||||
new StringBuilder(jdbcUrl)
|
||||
.append("?cloudSqlInstance=" + instanceConnectionName)
|
||||
.append("&socketFactory=com.google.cloud.sql.postgres.SocketFactory")
|
||||
.append("&user=" + username)
|
||||
.append("&password=" + kmsKeyring.getCloudSqlPassword())
|
||||
.toString();
|
||||
|
||||
HashMap<String, String> overrides = Maps.newHashMap(defaultConfigs);
|
||||
overrides.put(Environment.URL, fullJdbcUrl);
|
||||
|
||||
HashMap<String, String> overrides = Maps.newHashMap(cloudSqlConfigs);
|
||||
overrides.put(Environment.USER, username);
|
||||
overrides.put(Environment.PASS, kmsKeyring.getToolsCloudSqlPassword());
|
||||
return new JpaTransactionManagerImpl(create(overrides), clock);
|
||||
}
|
||||
|
||||
@@ -166,6 +160,11 @@ public class PersistenceModule {
|
||||
@Documented
|
||||
@interface NomulusToolJpaTm {}
|
||||
|
||||
/** Dagger qualifier for the partial Cloud SQL configs. */
|
||||
@Qualifier
|
||||
@Documented
|
||||
@interface PartialCloudSqlConfigs {}
|
||||
|
||||
/** Dagger qualifier for the default Hibernate configurations. */
|
||||
// TODO(shicong): Change annotations in this class to none public or put them in a top level
|
||||
// package
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.persistence;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.Properties;
|
||||
import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
|
||||
import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
|
||||
|
||||
/** Utility class that provides methods to manipulate persistence.xml file. */
|
||||
public class PersistenceXmlUtility {
|
||||
private PersistenceXmlUtility() {}
|
||||
|
||||
/**
|
||||
* Returns the {@link ParsedPersistenceXmlDescriptor} instance constructed from persistence.xml.
|
||||
*/
|
||||
public static ParsedPersistenceXmlDescriptor getParsedPersistenceXmlDescriptor() {
|
||||
return PersistenceXmlParser.locatePersistenceUnits(new Properties()).stream()
|
||||
.filter(unit -> PersistenceModule.PERSISTENCE_UNIT_NAME.equals(unit.getName()))
|
||||
.findFirst()
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new IllegalArgumentException(
|
||||
String.format(
|
||||
"Could not find persistence unit with name %s",
|
||||
PersistenceModule.PERSISTENCE_UNIT_NAME)));
|
||||
}
|
||||
|
||||
/** Returns all managed classes defined in persistence.xml. */
|
||||
public static ImmutableList<Class> getManagedClasses() {
|
||||
return getParsedPersistenceXmlDescriptor().getManagedClassNames().stream()
|
||||
.map(
|
||||
className -> {
|
||||
try {
|
||||
return Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Could not load class with name %s present in persistence.xml", className),
|
||||
e);
|
||||
}
|
||||
})
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package google.registry.persistence;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
/** Abstract JPA converter for objects that are stored by their toString() value. */
|
||||
abstract class ToStringConverterBase<T> implements AttributeConverter<T, String> {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String convertToDatabaseColumn(@Nullable T entity) {
|
||||
return (entity == null) ? null : entity.toString();
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ import google.registry.util.Retrier;
|
||||
import google.registry.util.SendEmailService;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
@@ -102,7 +103,7 @@ public final class IcannReportingUploadAction implements Runnable {
|
||||
final byte[] payload = readBytesFromGcs(gcsFilename);
|
||||
return icannReporter.send(payload, reportFilename);
|
||||
},
|
||||
IOException.class);
|
||||
IcannReportingUploadAction::isUploadFailureRetryable);
|
||||
} catch (RuntimeException e) {
|
||||
logger.atWarning().withCause(e).log("Upload to %s failed.", gcsFilename);
|
||||
}
|
||||
@@ -115,6 +116,21 @@ public final class IcannReportingUploadAction implements Runnable {
|
||||
String.format("OK, attempted uploading %d reports", manifestedFiles.size()));
|
||||
}
|
||||
|
||||
/** Don't retry when reports are already uploaded or can't be uploaded. */
|
||||
private static final String ICANN_UPLOAD_PERMANENT_ERROR_MESSAGE =
|
||||
"A report for that month already exists, the cut-off date already passed.";
|
||||
|
||||
/** Don't retry when the IP address isn't whitelisted, as retries go through the same IP. */
|
||||
private static final Pattern ICANN_UPLOAD_WHITELIST_ERROR =
|
||||
Pattern.compile("Your IP address .+ is not allowed to connect");
|
||||
|
||||
/** Predicate to retry uploads on IOException, so long as they aren't non-retryable errors. */
|
||||
private static boolean isUploadFailureRetryable(Throwable e) {
|
||||
return (e instanceof IOException)
|
||||
&& !e.getMessage().contains(ICANN_UPLOAD_PERMANENT_ERROR_MESSAGE)
|
||||
&& !ICANN_UPLOAD_WHITELIST_ERROR.matcher(e.getMessage()).matches();
|
||||
}
|
||||
|
||||
private void emailUploadResults(ImmutableMap<String, Boolean> reportSummary) {
|
||||
String subject = String.format(
|
||||
"ICANN Monthly report upload summary: %d/%d succeeded",
|
||||
|
||||
@@ -347,7 +347,7 @@ public class AuthenticatedRegistrarAccessor {
|
||||
|
||||
/** Exception thrown when the current user doesn't have access to the requested Registrar. */
|
||||
public static class RegistrarAccessDeniedException extends Exception {
|
||||
RegistrarAccessDeniedException(String message) {
|
||||
public RegistrarAccessDeniedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,8 @@ import org.joda.time.DateTime;
|
||||
name = "idx_registry_lock_repo_id_revision_id",
|
||||
columnList = "repoId, revisionId",
|
||||
unique = true),
|
||||
@Index(name = "idx_registry_lock_verification_code", columnList = "verificationCode")
|
||||
@Index(name = "idx_registry_lock_verification_code", columnList = "verificationCode"),
|
||||
@Index(name = "idx_registry_lock_registrar_id", columnList = "registrarId")
|
||||
})
|
||||
public final class RegistryLock extends ImmutableObject implements Buildable {
|
||||
|
||||
@@ -175,12 +176,13 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
|
||||
this.completionTimestamp = toZonedDateTime(dateTime);
|
||||
}
|
||||
|
||||
public boolean isVerified() {
|
||||
return completionTimestamp != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
RegistryLock clone = clone(this);
|
||||
// Revision ID should be different for every object
|
||||
clone.revisionId = null;
|
||||
return new Builder(clone);
|
||||
return new Builder(clone(this));
|
||||
}
|
||||
|
||||
/** Builder for {@link google.registry.schema.domain.RegistryLock}. */
|
||||
|
||||
@@ -72,7 +72,7 @@ final class CreateDomainCommand extends CreateOrUpdateDomainCommand
|
||||
!force || forcePremiums,
|
||||
"Forced creates on premium domain(s) require --force_premiums");
|
||||
Money createCost = prices.getCreateCost();
|
||||
currency = createCost.getCurrencyUnit().getCurrencyCode();
|
||||
currency = createCost.getCurrencyUnit().getCode();
|
||||
cost = createCost.multipliedBy(period).getAmount().toString();
|
||||
System.out.printf(
|
||||
"NOTE: %s is premium at %s per year; sending total cost for %d year(s) of %s %s.\n",
|
||||
|
||||
@@ -19,23 +19,12 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import google.registry.persistence.NomulusNamingStrategy;
|
||||
import google.registry.persistence.NomulusPostgreSQLDialect;
|
||||
import google.registry.persistence.PersistenceModule;
|
||||
import google.registry.persistence.HibernateSchemaExporter;
|
||||
import google.registry.persistence.NomulusPostgreSql;
|
||||
import google.registry.persistence.PersistenceXmlUtility;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
|
||||
import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
import org.hibernate.tool.schema.TargetType;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
|
||||
/**
|
||||
@@ -47,6 +36,9 @@ import org.testcontainers.containers.PostgreSQLContainer;
|
||||
*/
|
||||
@Parameters(separators = " =", commandDescription = "Generate PostgreSQL schema.")
|
||||
public class GenerateSqlSchemaCommand implements Command {
|
||||
private static final String DB_NAME = "postgres";
|
||||
private static final String DB_USERNAME = "postgres";
|
||||
private static final String DB_PASSWORD = "domain-registry";
|
||||
|
||||
@VisibleForTesting
|
||||
public static final String DB_OPTIONS_CLASH =
|
||||
@@ -91,10 +83,11 @@ public class GenerateSqlSchemaCommand implements Command {
|
||||
}
|
||||
|
||||
// Start the container and store the address information.
|
||||
postgresContainer = new PostgreSQLContainer()
|
||||
.withDatabaseName("postgres")
|
||||
.withUsername("postgres")
|
||||
.withPassword("domain-registry");
|
||||
postgresContainer =
|
||||
new PostgreSQLContainer(NomulusPostgreSql.getDockerTag())
|
||||
.withDatabaseName(DB_NAME)
|
||||
.withUsername(DB_USERNAME)
|
||||
.withPassword(DB_PASSWORD);
|
||||
postgresContainer.start();
|
||||
databaseHost = postgresContainer.getContainerIpAddress();
|
||||
databasePort = postgresContainer.getMappedPort(POSTGRESQL_PORT);
|
||||
@@ -119,29 +112,7 @@ public class GenerateSqlSchemaCommand implements Command {
|
||||
}
|
||||
|
||||
try {
|
||||
// Configure Hibernate settings.
|
||||
Map<String, String> settings = new HashMap<>();
|
||||
settings.put("hibernate.dialect", NomulusPostgreSQLDialect.class.getName());
|
||||
settings.put(
|
||||
"hibernate.connection.url",
|
||||
"jdbc:postgresql://" + databaseHost + ":" + databasePort + "/postgres?useSSL=false");
|
||||
settings.put("hibernate.connection.username", "postgres");
|
||||
settings.put("hibernate.connection.password", "domain-registry");
|
||||
settings.put("hibernate.hbm2ddl.auto", "none");
|
||||
settings.put("show_sql", "true");
|
||||
settings.put(
|
||||
Environment.PHYSICAL_NAMING_STRATEGY, NomulusNamingStrategy.class.getCanonicalName());
|
||||
|
||||
MetadataSources metadata =
|
||||
new MetadataSources(new StandardServiceRegistryBuilder().applySettings(settings).build());
|
||||
|
||||
addAnnotatedClasses(metadata, settings);
|
||||
|
||||
SchemaExport schemaExport = new SchemaExport();
|
||||
schemaExport.setHaltOnError(true);
|
||||
schemaExport.setFormat(true);
|
||||
schemaExport.setDelimiter(";");
|
||||
schemaExport.setOutputFile(outFile);
|
||||
File outputFile = new File(outFile);
|
||||
|
||||
// Generate the copyright header (this file gets checked for copyright). The schema exporter
|
||||
// appends to the existing file, so this has the additional desired effect of clearing any
|
||||
@@ -161,44 +132,30 @@ public class GenerateSqlSchemaCommand implements Command {
|
||||
+ "-- See the License for the specific language governing permissions and\n"
|
||||
+ "-- limitations under the License.\n";
|
||||
try {
|
||||
Files.write(Paths.get(outFile), copyright.getBytes(UTF_8));
|
||||
Files.write(outputFile.toPath(), copyright.getBytes(UTF_8));
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error writing sql file: " + e);
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
schemaExport.createOnly(EnumSet.of(TargetType.SCRIPT), metadata.buildMetadata());
|
||||
HibernateSchemaExporter exporter =
|
||||
HibernateSchemaExporter.create(
|
||||
"jdbc:postgresql://"
|
||||
+ databaseHost
|
||||
+ ":"
|
||||
+ databasePort
|
||||
+ "/"
|
||||
+ DB_NAME
|
||||
+ "?useSSL=false",
|
||||
DB_USERNAME,
|
||||
DB_PASSWORD);
|
||||
exporter.export(PersistenceXmlUtility.getManagedClasses(), outputFile);
|
||||
|
||||
} finally {
|
||||
if (postgresContainer != null) {
|
||||
postgresContainer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addAnnotatedClasses(MetadataSources metadata, Map<String, String> settings) {
|
||||
ParsedPersistenceXmlDescriptor descriptor =
|
||||
PersistenceXmlParser.locatePersistenceUnits(settings).stream()
|
||||
.filter(unit -> PersistenceModule.PERSISTENCE_UNIT_NAME.equals(unit.getName()))
|
||||
.findFirst()
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new IllegalArgumentException(
|
||||
String.format(
|
||||
"Could not find persistence unit with name %s",
|
||||
PersistenceModule.PERSISTENCE_UNIT_NAME)));
|
||||
|
||||
List<String> classNames = descriptor.getManagedClassNames();
|
||||
for (String className : classNames) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(className);
|
||||
metadata.addAnnotatedClass(clazz);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Could not load class with name %s present in persistence.xml", className),
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.model.ofy.ObjectifyService;
|
||||
import google.registry.model.transaction.TransactionManagerFactory;
|
||||
import google.registry.tools.AuthModule.LoginRequiredException;
|
||||
import google.registry.tools.params.ParameterFactory;
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -237,7 +236,7 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
||||
}
|
||||
|
||||
if (command instanceof CommandWithCloudSql) {
|
||||
TransactionManagerFactory.initForTool();
|
||||
RegistryToolEnvironment.get().enableJpaTm();
|
||||
}
|
||||
|
||||
command.run();
|
||||
|
||||
@@ -25,7 +25,7 @@ import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.config.SystemPropertySetter;
|
||||
|
||||
/** Enum of production environments, used for the {@code --environment} flag. */
|
||||
enum RegistryToolEnvironment {
|
||||
public enum RegistryToolEnvironment {
|
||||
PRODUCTION(RegistryEnvironment.PRODUCTION),
|
||||
ALPHA(RegistryEnvironment.ALPHA),
|
||||
CRASH(RegistryEnvironment.CRASH),
|
||||
@@ -39,6 +39,7 @@ enum RegistryToolEnvironment {
|
||||
|
||||
private static final ImmutableList<String> FLAGS = ImmutableList.of("-e", "--environment");
|
||||
private static RegistryToolEnvironment instance;
|
||||
private static boolean isJpaTmEnabled = false;
|
||||
private final RegistryEnvironment actualEnvironment;
|
||||
private final ImmutableMap<String, String> extraProperties;
|
||||
|
||||
@@ -72,7 +73,7 @@ enum RegistryToolEnvironment {
|
||||
*
|
||||
* <p>This should be called after {@link #parseFromArgs(String[])}.
|
||||
*/
|
||||
static RegistryToolEnvironment get() {
|
||||
public static RegistryToolEnvironment get() {
|
||||
checkState(instance != null, "No RegistryToolEnvironment has been set up");
|
||||
return instance;
|
||||
}
|
||||
@@ -98,6 +99,26 @@ enum RegistryToolEnvironment {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true if the RegistryToolEnvironment is set up. */
|
||||
public static boolean isInRegistryTool() {
|
||||
return instance != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the flag to indicate that the running command needs JpaTransactionManager to be enabled.
|
||||
*/
|
||||
public static void enableJpaTm() {
|
||||
isJpaTmEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the JpaTransactionManager is enabled. Note that JpaTm is actually enabled in
|
||||
* {@link google.registry.model.transaction.TransactionManagerFactory} by reading this flag.
|
||||
*/
|
||||
public static boolean isJpaTmEnabled() {
|
||||
return isJpaTmEnabled;
|
||||
}
|
||||
|
||||
/** Extracts value from command-line arguments associated with any {@code flags}. */
|
||||
private static String getFlagValue(String[] args, Iterable<String> flags) {
|
||||
for (String flag : flags) {
|
||||
|
||||
@@ -32,7 +32,7 @@ import java.util.List;
|
||||
|
||||
/** A command to upload a {@link ClaimsListShard}. */
|
||||
@Parameters(separators = " =", commandDescription = "Manually upload a new claims list file")
|
||||
final class UploadClaimsListCommand extends ConfirmingCommand implements CommandWithRemoteApi {
|
||||
final class UploadClaimsListCommand extends ConfirmingCommand implements CommandWithCloudSql {
|
||||
|
||||
@Parameter(description = "Claims list filename")
|
||||
private List<String> mainParameters = new ArrayList<>();
|
||||
|
||||
@@ -21,7 +21,9 @@ import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import com.google.re2j.Pattern;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
@@ -194,12 +196,10 @@ public final class RegistrarFormFields {
|
||||
FormField.named("visibleInDomainWhoisAsAbuse", Boolean.class).build();
|
||||
|
||||
public static final FormField<String, String> CONTACT_PHONE_NUMBER_FIELD =
|
||||
FormFields.PHONE_NUMBER.asBuilder()
|
||||
.build();
|
||||
FormFields.PHONE_NUMBER.asBuilder().build();
|
||||
|
||||
public static final FormField<String, String> CONTACT_FAX_NUMBER_FIELD =
|
||||
FormFields.PHONE_NUMBER.asBuilderNamed("faxNumber")
|
||||
.build();
|
||||
FormFields.PHONE_NUMBER.asBuilderNamed("faxNumber").build();
|
||||
|
||||
public static final FormField<String, String> CONTACT_GAE_USER_ID_FIELD =
|
||||
FormFields.NAME.asBuilderNamed("gaeUserId").build();
|
||||
@@ -217,11 +217,8 @@ public final class RegistrarFormFields {
|
||||
.asSet(Splitter.on(',').omitEmptyStrings().trimResults())
|
||||
.build();
|
||||
|
||||
public static final FormField<List<Map<String, ?>>, List<RegistrarContact.Builder>>
|
||||
CONTACTS_FIELD = FormField.mapNamed("contacts")
|
||||
.transform(RegistrarContact.Builder.class, RegistrarFormFields::toRegistrarContactBuilder)
|
||||
.asList()
|
||||
.build();
|
||||
public static final FormField<List<Map<String, ?>>, List<Map<String, ?>>> CONTACTS_AS_MAPS =
|
||||
FormField.mapNamed("contacts").asList().build();
|
||||
|
||||
public static final FormField<List<String>, List<String>> I18N_STREET_FIELD =
|
||||
FormFields.XS_NORMALIZED_STRING.asBuilderNamed("street")
|
||||
@@ -344,33 +341,60 @@ public final class RegistrarFormFields {
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable RegistrarContact.Builder toRegistrarContactBuilder(
|
||||
@Nullable Map<String, ?> args) {
|
||||
public static ImmutableList<RegistrarContact.Builder> getRegistrarContactBuilders(
|
||||
ImmutableSet<RegistrarContact> existingContacts, @Nullable Map<String, ?> args) {
|
||||
if (args == null) {
|
||||
return null;
|
||||
return ImmutableList.of();
|
||||
}
|
||||
RegistrarContact.Builder builder = new RegistrarContact.Builder();
|
||||
CONTACT_NAME_FIELD.extractUntyped(args).ifPresent(builder::setName);
|
||||
CONTACT_EMAIL_ADDRESS_FIELD.extractUntyped(args).ifPresent(builder::setEmailAddress);
|
||||
CONTACT_VISIBLE_IN_WHOIS_AS_ADMIN_FIELD
|
||||
.extractUntyped(args)
|
||||
.ifPresent(builder::setVisibleInWhoisAsAdmin);
|
||||
CONTACT_VISIBLE_IN_WHOIS_AS_TECH_FIELD
|
||||
.extractUntyped(args)
|
||||
.ifPresent(builder::setVisibleInWhoisAsTech);
|
||||
PHONE_AND_EMAIL_VISIBLE_IN_DOMAIN_WHOIS_AS_ABUSE_FIELD
|
||||
.extractUntyped(args)
|
||||
.ifPresent(builder::setVisibleInDomainWhoisAsAbuse);
|
||||
CONTACT_PHONE_NUMBER_FIELD.extractUntyped(args).ifPresent(builder::setPhoneNumber);
|
||||
CONTACT_FAX_NUMBER_FIELD.extractUntyped(args).ifPresent(builder::setFaxNumber);
|
||||
CONTACT_TYPES.extractUntyped(args).ifPresent(builder::setTypes);
|
||||
CONTACT_GAE_USER_ID_FIELD.extractUntyped(args).ifPresent(builder::setGaeUserId);
|
||||
CONTACT_ALLOWED_TO_SET_REGISTRY_LOCK_PASSWORD
|
||||
.extractUntyped(args)
|
||||
.ifPresent(builder::setAllowedToSetRegistryLockPassword);
|
||||
Optional<List<Map<String, ?>>> contactsAsMaps = CONTACTS_AS_MAPS.extractUntyped(args);
|
||||
if (!contactsAsMaps.isPresent()) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
ImmutableList.Builder<RegistrarContact.Builder> result = new ImmutableList.Builder<>();
|
||||
for (Map<String, ?> contactAsMap : contactsAsMaps.get()) {
|
||||
String emailAddress =
|
||||
CONTACT_EMAIL_ADDRESS_FIELD
|
||||
.extractUntyped(contactAsMap)
|
||||
.orElseThrow(
|
||||
() -> new IllegalArgumentException("Contacts from UI must have email addresses"));
|
||||
// Start with a new builder if the contact didn't previously exist
|
||||
RegistrarContact.Builder contactBuilder =
|
||||
existingContacts.stream()
|
||||
.filter(rc -> rc.getEmailAddress().equals(emailAddress))
|
||||
.findFirst()
|
||||
.map(RegistrarContact::asBuilder)
|
||||
.orElse(new RegistrarContact.Builder());
|
||||
applyRegistrarContactArgs(contactBuilder, contactAsMap);
|
||||
result.add(contactBuilder);
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
|
||||
private static void applyRegistrarContactArgs(
|
||||
RegistrarContact.Builder builder, Map<String, ?> args) {
|
||||
builder.setName(CONTACT_NAME_FIELD.extractUntyped(args).orElse(null));
|
||||
builder.setEmailAddress(CONTACT_EMAIL_ADDRESS_FIELD.extractUntyped(args).orElse(null));
|
||||
builder.setVisibleInWhoisAsAdmin(
|
||||
CONTACT_VISIBLE_IN_WHOIS_AS_ADMIN_FIELD.extractUntyped(args).orElse(false));
|
||||
builder.setVisibleInWhoisAsTech(
|
||||
CONTACT_VISIBLE_IN_WHOIS_AS_TECH_FIELD.extractUntyped(args).orElse(false));
|
||||
builder.setVisibleInDomainWhoisAsAbuse(
|
||||
PHONE_AND_EMAIL_VISIBLE_IN_DOMAIN_WHOIS_AS_ABUSE_FIELD.extractUntyped(args).orElse(false));
|
||||
builder.setPhoneNumber(CONTACT_PHONE_NUMBER_FIELD.extractUntyped(args).orElse(null));
|
||||
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));
|
||||
builder.setAllowedToSetRegistryLockPassword(
|
||||
CONTACT_ALLOWED_TO_SET_REGISTRY_LOCK_PASSWORD.extractUntyped(args).orElse(false));
|
||||
|
||||
// Registry lock password does not need to be set every time
|
||||
CONTACT_REGISTRY_LOCK_PASSWORD_FIELD
|
||||
.extractUntyped(args)
|
||||
.ifPresent(builder::setRegistryLockPassword);
|
||||
return builder;
|
||||
.ifPresent(
|
||||
password -> {
|
||||
if (!Strings.isNullOrEmpty(password)) {
|
||||
builder.setRegistryLockPassword(password);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import static com.google.common.io.Resources.asCharSource;
|
||||
import static com.google.common.io.Resources.getResource;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Supplier;
|
||||
@@ -42,6 +43,12 @@ import java.util.Map;
|
||||
/** Helper methods for rendering Soy templates from Java code. */
|
||||
public final class SoyTemplateUtils {
|
||||
|
||||
@VisibleForTesting
|
||||
public static final Supplier<SoyCssRenamingMap> CSS_RENAMING_MAP_SUPPLIER =
|
||||
SoyTemplateUtils.createCssRenamingMapSupplier(
|
||||
Resources.getResource("google/registry/ui/css/registrar_bin.css.js"),
|
||||
Resources.getResource("google/registry/ui/css/registrar_dbg.css.js"));
|
||||
|
||||
/** Returns a memoized supplier containing compiled tofu. */
|
||||
public static Supplier<SoyTofu> createTofuSupplier(final SoyFileInfo... soyInfos) {
|
||||
return memoize(
|
||||
|
||||
@@ -15,45 +15,30 @@
|
||||
package google.registry.ui.server.registrar;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.net.HttpHeaders.LOCATION;
|
||||
import static com.google.common.net.HttpHeaders.X_FRAME_OPTIONS;
|
||||
import static google.registry.config.RegistryEnvironment.PRODUCTION;
|
||||
import static google.registry.ui.server.SoyTemplateUtils.CSS_RENAMING_MAP_SUPPLIER;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY;
|
||||
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.io.Resources;
|
||||
import com.google.common.net.MediaType;
|
||||
import com.google.template.soy.shared.SoyCssRenamingMap;
|
||||
import com.google.template.soy.tofu.SoyTofu;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.OteAccountBuilder;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Method;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.RequestMethod;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
import google.registry.ui.server.SendEmailUtils;
|
||||
import google.registry.ui.server.SoyTemplateUtils;
|
||||
import google.registry.ui.soy.registrar.OteSetupConsoleSoyInfo;
|
||||
import google.registry.util.StringGenerator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Action that serves OT&E setup web page.
|
||||
@@ -69,14 +54,9 @@ import javax.servlet.http.HttpServletRequest;
|
||||
path = ConsoleOteSetupAction.PATH,
|
||||
method = {Method.POST, Method.GET},
|
||||
auth = Auth.AUTH_PUBLIC)
|
||||
public final class ConsoleOteSetupAction implements Runnable {
|
||||
public final class ConsoleOteSetupAction extends HtmlAction {
|
||||
|
||||
public static final String PATH = "/registrar-ote-setup";
|
||||
@VisibleForTesting // webdriver and screenshot tests need this
|
||||
public static final Supplier<SoyCssRenamingMap> CSS_RENAMING_MAP_SUPPLIER =
|
||||
SoyTemplateUtils.createCssRenamingMapSupplier(
|
||||
Resources.getResource("google/registry/ui/css/registrar_bin.css.js"),
|
||||
Resources.getResource("google/registry/ui/css/registrar_dbg.css.js"));
|
||||
private static final int PASSWORD_LENGTH = 16;
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private static final Supplier<SoyTofu> TOFU_SUPPLIER =
|
||||
@@ -85,27 +65,10 @@ public final class ConsoleOteSetupAction implements Runnable {
|
||||
google.registry.ui.soy.FormsSoyInfo.getInstance(),
|
||||
google.registry.ui.soy.AnalyticsSoyInfo.getInstance(),
|
||||
google.registry.ui.soy.registrar.OteSetupConsoleSoyInfo.getInstance());
|
||||
@Inject HttpServletRequest req;
|
||||
@Inject @RequestMethod Method method;
|
||||
@Inject Response response;
|
||||
|
||||
@Inject AuthenticatedRegistrarAccessor registrarAccessor;
|
||||
@Inject UserService userService;
|
||||
@Inject XsrfTokenManager xsrfTokenManager;
|
||||
@Inject AuthResult authResult;
|
||||
@Inject SendEmailUtils sendEmailUtils;
|
||||
|
||||
@Inject
|
||||
@Config("logoFilename")
|
||||
String logoFilename;
|
||||
|
||||
@Inject
|
||||
@Config("productName")
|
||||
String productName;
|
||||
|
||||
@Inject
|
||||
@Config("analyticsConfig")
|
||||
Map<String, Object> analyticsConfig;
|
||||
|
||||
@Inject
|
||||
@Named("base58StringGenerator")
|
||||
StringGenerator passwordGenerator;
|
||||
@@ -126,43 +89,9 @@ public final class ConsoleOteSetupAction implements Runnable {
|
||||
ConsoleOteSetupAction() {}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
response.setHeader(X_FRAME_OPTIONS, "SAMEORIGIN"); // Disallow iframing.
|
||||
response.setHeader("X-Ui-Compatible", "IE=edge"); // Ask IE not to be silly.
|
||||
|
||||
logger.atInfo().log(
|
||||
"User %s is accessing the OT&E setup page. Method= %s",
|
||||
registrarAccessor.userIdForLogging(), method);
|
||||
public void runAfterLogin(HashMap<String, Object> data) {
|
||||
checkState(
|
||||
!RegistryEnvironment.get().equals(PRODUCTION), "Can't create OT&E in prod");
|
||||
if (!authResult.userAuthInfo().isPresent()) {
|
||||
response.setStatus(SC_MOVED_TEMPORARILY);
|
||||
String location;
|
||||
try {
|
||||
location = userService.createLoginURL(req.getRequestURI());
|
||||
} catch (IllegalArgumentException e) {
|
||||
// UserServiceImpl.createLoginURL() throws IllegalArgumentException if underlying API call
|
||||
// returns an error code of NOT_ALLOWED. createLoginURL() assumes that the error is caused
|
||||
// by an invalid URL. But in fact, the error can also occur if UserService doesn't have any
|
||||
// user information, which happens when the request has been authenticated as internal. In
|
||||
// this case, we want to avoid dying before we can send the redirect, so just redirect to
|
||||
// the root path.
|
||||
location = "/";
|
||||
}
|
||||
response.setHeader(LOCATION, location);
|
||||
return;
|
||||
}
|
||||
User user = authResult.userAuthInfo().get().user();
|
||||
|
||||
// Using HashMap to allow null values
|
||||
HashMap<String, Object> data = new HashMap<>();
|
||||
data.put("logoFilename", logoFilename);
|
||||
data.put("productName", productName);
|
||||
data.put("username", user.getNickname());
|
||||
data.put("logoutUrl", userService.createLogoutURL(PATH));
|
||||
data.put("xsrfToken", xsrfTokenManager.generateToken(user.getEmail()));
|
||||
data.put("analyticsConfig", analyticsConfig);
|
||||
response.setContentType(MediaType.HTML_UTF_8);
|
||||
|
||||
if (!registrarAccessor.isAdmin()) {
|
||||
response.setStatus(SC_FORBIDDEN);
|
||||
@@ -187,6 +116,11 @@ public final class ConsoleOteSetupAction implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return PATH;
|
||||
}
|
||||
|
||||
private void runPost(HashMap<String, Object> data) {
|
||||
try {
|
||||
checkState(clientId.isPresent() && email.isPresent(), "Must supply clientId and email");
|
||||
|
||||
@@ -18,27 +18,18 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.net.HttpHeaders.LOCATION;
|
||||
import static com.google.common.net.HttpHeaders.X_FRAME_OPTIONS;
|
||||
import static google.registry.model.common.GaeUserIdConverter.convertEmailAddressToGaeUserId;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.ui.server.SoyTemplateUtils.CSS_RENAMING_MAP_SUPPLIER;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY;
|
||||
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.io.Resources;
|
||||
import com.google.common.net.MediaType;
|
||||
import com.google.template.soy.shared.SoyCssRenamingMap;
|
||||
import com.google.template.soy.tofu.SoyTofu;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarAddress;
|
||||
@@ -46,23 +37,17 @@ import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Method;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.RequestMethod;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
import google.registry.ui.server.SendEmailUtils;
|
||||
import google.registry.ui.server.SoyTemplateUtils;
|
||||
import google.registry.ui.soy.registrar.RegistrarCreateConsoleSoyInfo;
|
||||
import google.registry.util.StringGenerator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
|
||||
/**
|
||||
@@ -79,7 +64,7 @@ import org.joda.money.CurrencyUnit;
|
||||
path = ConsoleRegistrarCreatorAction.PATH,
|
||||
method = {Method.POST, Method.GET},
|
||||
auth = Auth.AUTH_PUBLIC)
|
||||
public final class ConsoleRegistrarCreatorAction implements Runnable {
|
||||
public final class ConsoleRegistrarCreatorAction extends HtmlAction {
|
||||
|
||||
private static final int PASSWORD_LENGTH = 16;
|
||||
private static final int PASSCODE_LENGTH = 5;
|
||||
@@ -95,23 +80,8 @@ public final class ConsoleRegistrarCreatorAction implements Runnable {
|
||||
google.registry.ui.soy.AnalyticsSoyInfo.getInstance(),
|
||||
google.registry.ui.soy.registrar.RegistrarCreateConsoleSoyInfo.getInstance());
|
||||
|
||||
@VisibleForTesting // webdriver and screenshot tests need this
|
||||
public static final Supplier<SoyCssRenamingMap> CSS_RENAMING_MAP_SUPPLIER =
|
||||
SoyTemplateUtils.createCssRenamingMapSupplier(
|
||||
Resources.getResource("google/registry/ui/css/registrar_bin.css.js"),
|
||||
Resources.getResource("google/registry/ui/css/registrar_dbg.css.js"));
|
||||
|
||||
@Inject HttpServletRequest req;
|
||||
@Inject @RequestMethod Method method;
|
||||
@Inject Response response;
|
||||
@Inject AuthenticatedRegistrarAccessor registrarAccessor;
|
||||
@Inject UserService userService;
|
||||
@Inject XsrfTokenManager xsrfTokenManager;
|
||||
@Inject AuthResult authResult;
|
||||
@Inject SendEmailUtils sendEmailUtils;
|
||||
@Inject @Config("logoFilename") String logoFilename;
|
||||
@Inject @Config("productName") String productName;
|
||||
@Inject @Config("analyticsConfig") Map<String, Object> analyticsConfig;
|
||||
@Inject @Named("base58StringGenerator") StringGenerator passwordGenerator;
|
||||
@Inject @Named("digitOnlyStringGenerator") StringGenerator passcodeGenerator;
|
||||
@Inject @Parameter("clientId") Optional<String> clientId;
|
||||
@@ -137,42 +107,7 @@ public final class ConsoleRegistrarCreatorAction implements Runnable {
|
||||
@Inject ConsoleRegistrarCreatorAction() {}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
response.setHeader(X_FRAME_OPTIONS, "SAMEORIGIN"); // Disallow iframing.
|
||||
response.setHeader("X-Ui-Compatible", "IE=edge"); // Ask IE not to be silly.
|
||||
|
||||
logger.atInfo().log(
|
||||
"User %s is accessing the Registrar creation page. Method= %s",
|
||||
registrarAccessor.userIdForLogging(), method);
|
||||
if (!authResult.userAuthInfo().isPresent()) {
|
||||
response.setStatus(SC_MOVED_TEMPORARILY);
|
||||
String location;
|
||||
try {
|
||||
location = userService.createLoginURL(req.getRequestURI());
|
||||
} catch (IllegalArgumentException e) {
|
||||
// UserServiceImpl.createLoginURL() throws IllegalArgumentException if underlying API call
|
||||
// returns an error code of NOT_ALLOWED. createLoginURL() assumes that the error is caused
|
||||
// by an invalid URL. But in fact, the error can also occur if UserService doesn't have any
|
||||
// user information, which happens when the request has been authenticated as internal. In
|
||||
// this case, we want to avoid dying before we can send the redirect, so just redirect to
|
||||
// the root path.
|
||||
location = "/";
|
||||
}
|
||||
response.setHeader(LOCATION, location);
|
||||
return;
|
||||
}
|
||||
User user = authResult.userAuthInfo().get().user();
|
||||
|
||||
// Using HashMap to allow null values
|
||||
HashMap<String, Object> data = new HashMap<>();
|
||||
data.put("logoFilename", logoFilename);
|
||||
data.put("productName", productName);
|
||||
data.put("username", user.getNickname());
|
||||
data.put("logoutUrl", userService.createLogoutURL(PATH));
|
||||
data.put("xsrfToken", xsrfTokenManager.generateToken(user.getEmail()));
|
||||
data.put("analyticsConfig", analyticsConfig);
|
||||
response.setContentType(MediaType.HTML_UTF_8);
|
||||
|
||||
public void runAfterLogin(HashMap<String, Object> data) {
|
||||
if (!registrarAccessor.isAdmin()) {
|
||||
response.setStatus(SC_FORBIDDEN);
|
||||
response.setPayload(
|
||||
@@ -196,6 +131,11 @@ public final class ConsoleRegistrarCreatorAction implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return PATH;
|
||||
}
|
||||
|
||||
private void checkPresent(Optional<?> value, String name) {
|
||||
checkState(value.isPresent(), "Missing value for %s", name);
|
||||
}
|
||||
@@ -226,7 +166,6 @@ public final class ConsoleRegistrarCreatorAction implements Runnable {
|
||||
|
||||
private void runPost(HashMap<String, Object> data) {
|
||||
try {
|
||||
|
||||
checkPresent(clientId, "clientId");
|
||||
checkPresent(name, "name");
|
||||
checkPresent(billingAccount, "billingAccount");
|
||||
@@ -321,11 +260,11 @@ public final class ConsoleRegistrarCreatorAction implements Runnable {
|
||||
data.put("errorMessage", e.getMessage());
|
||||
response.setPayload(
|
||||
TOFU_SUPPLIER
|
||||
.get()
|
||||
.newRenderer(RegistrarCreateConsoleSoyInfo.FORM_PAGE)
|
||||
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
|
||||
.setData(data)
|
||||
.render());
|
||||
.get()
|
||||
.newRenderer(RegistrarCreateConsoleSoyInfo.FORM_PAGE)
|
||||
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
|
||||
.setData(data)
|
||||
.render());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,8 +296,8 @@ public final class ConsoleRegistrarCreatorAction implements Runnable {
|
||||
String environment = Ascii.toLowerCase(String.valueOf(RegistryEnvironment.get()));
|
||||
String body =
|
||||
String.format(
|
||||
"The following registrar was created in %s by %s:\n",
|
||||
environment, registrarAccessor.userIdForLogging())
|
||||
"The following registrar was created in %s by %s:\n",
|
||||
environment, registrarAccessor.userIdForLogging())
|
||||
+ toEmailLine(clientId, "clientId")
|
||||
+ toEmailLine(name, "name")
|
||||
+ toEmailLine(billingAccount, "billingAccount")
|
||||
|
||||
@@ -14,47 +14,35 @@
|
||||
|
||||
package google.registry.ui.server.registrar;
|
||||
|
||||
import static com.google.common.net.HttpHeaders.LOCATION;
|
||||
import static com.google.common.net.HttpHeaders.X_FRAME_OPTIONS;
|
||||
import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.ADMIN;
|
||||
import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.OWNER;
|
||||
import static google.registry.ui.server.SoyTemplateUtils.CSS_RENAMING_MAP_SUPPLIER;
|
||||
import static google.registry.ui.server.registrar.RegistrarConsoleModule.PARAM_CLIENT_ID;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;
|
||||
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.io.Resources;
|
||||
import com.google.common.net.MediaType;
|
||||
import com.google.template.soy.data.SoyMapData;
|
||||
import com.google.template.soy.shared.SoyCssRenamingMap;
|
||||
import com.google.template.soy.tofu.SoyTofu;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor.Role;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
import google.registry.ui.server.SoyTemplateUtils;
|
||||
import google.registry.ui.soy.registrar.ConsoleSoyInfo;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/** Action that serves Registrar Console single HTML page (SPA). */
|
||||
@Action(service = Action.Service.DEFAULT, path = ConsoleUiAction.PATH, auth = Auth.AUTH_PUBLIC)
|
||||
public final class ConsoleUiAction implements Runnable {
|
||||
public final class ConsoleUiAction extends HtmlAction {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -66,27 +54,8 @@ public final class ConsoleUiAction implements Runnable {
|
||||
google.registry.ui.soy.registrar.ConsoleSoyInfo.getInstance(),
|
||||
google.registry.ui.soy.AnalyticsSoyInfo.getInstance());
|
||||
|
||||
@VisibleForTesting // webdriver and screenshot tests need this
|
||||
public static final Supplier<SoyCssRenamingMap> CSS_RENAMING_MAP_SUPPLIER =
|
||||
SoyTemplateUtils.createCssRenamingMapSupplier(
|
||||
Resources.getResource("google/registry/ui/css/registrar_bin.css.js"),
|
||||
Resources.getResource("google/registry/ui/css/registrar_dbg.css.js"));
|
||||
|
||||
@Inject HttpServletRequest req;
|
||||
@Inject Response response;
|
||||
@Inject RegistrarConsoleMetrics registrarConsoleMetrics;
|
||||
@Inject AuthenticatedRegistrarAccessor registrarAccessor;
|
||||
@Inject UserService userService;
|
||||
@Inject XsrfTokenManager xsrfTokenManager;
|
||||
@Inject AuthResult authResult;
|
||||
|
||||
@Inject
|
||||
@Config("logoFilename")
|
||||
String logoFilename;
|
||||
|
||||
@Inject
|
||||
@Config("productName")
|
||||
String productName;
|
||||
|
||||
@Inject
|
||||
@Config("integrationEmail")
|
||||
@@ -112,10 +81,6 @@ public final class ConsoleUiAction implements Runnable {
|
||||
@Config("registrarConsoleEnabled")
|
||||
boolean enabled;
|
||||
|
||||
@Inject
|
||||
@Config("analyticsConfig")
|
||||
Map<String, Object> analyticsConfig;
|
||||
|
||||
@Inject
|
||||
@Parameter(PARAM_CLIENT_ID)
|
||||
Optional<String> paramClientId;
|
||||
@@ -124,37 +89,15 @@ public final class ConsoleUiAction implements Runnable {
|
||||
ConsoleUiAction() {}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!authResult.userAuthInfo().isPresent()) {
|
||||
response.setStatus(SC_MOVED_TEMPORARILY);
|
||||
String location;
|
||||
try {
|
||||
location = userService.createLoginURL(req.getRequestURI());
|
||||
} catch (IllegalArgumentException e) {
|
||||
// UserServiceImpl.createLoginURL() throws IllegalArgumentException if underlying API call
|
||||
// returns an error code of NOT_ALLOWED. createLoginURL() assumes that the error is caused
|
||||
// by an invalid URL. But in fact, the error can also occur if UserService doesn't have any
|
||||
// user information, which happens when the request has been authenticated as internal. In
|
||||
// this case, we want to avoid dying before we can send the redirect, so just redirect to
|
||||
// the root path.
|
||||
location = "/";
|
||||
}
|
||||
response.setHeader(LOCATION, location);
|
||||
return;
|
||||
}
|
||||
User user = authResult.userAuthInfo().get().user();
|
||||
response.setContentType(MediaType.HTML_UTF_8);
|
||||
response.setHeader(X_FRAME_OPTIONS, "SAMEORIGIN"); // Disallow iframing.
|
||||
response.setHeader("X-Ui-Compatible", "IE=edge"); // Ask IE not to be silly.
|
||||
SoyMapData data = new SoyMapData();
|
||||
data.put("logoFilename", logoFilename);
|
||||
data.put("productName", productName);
|
||||
data.put("integrationEmail", integrationEmail);
|
||||
data.put("supportEmail", supportEmail);
|
||||
data.put("announcementsEmail", announcementsEmail);
|
||||
data.put("supportPhoneNumber", supportPhoneNumber);
|
||||
data.put("technicalDocsUrl", technicalDocsUrl);
|
||||
data.put("analyticsConfig", analyticsConfig);
|
||||
public void runAfterLogin(HashMap<String, Object> data) {
|
||||
SoyMapData soyMapData = new SoyMapData();
|
||||
data.forEach((key, value) -> soyMapData.put(key, value));
|
||||
|
||||
soyMapData.put("integrationEmail", integrationEmail);
|
||||
soyMapData.put("supportEmail", supportEmail);
|
||||
soyMapData.put("announcementsEmail", announcementsEmail);
|
||||
soyMapData.put("supportPhoneNumber", supportPhoneNumber);
|
||||
soyMapData.put("technicalDocsUrl", technicalDocsUrl);
|
||||
if (!enabled) {
|
||||
response.setStatus(SC_SERVICE_UNAVAILABLE);
|
||||
response.setPayload(
|
||||
@@ -162,23 +105,20 @@ public final class ConsoleUiAction implements Runnable {
|
||||
.get()
|
||||
.newRenderer(ConsoleSoyInfo.DISABLED)
|
||||
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
|
||||
.setData(data)
|
||||
.setData(soyMapData)
|
||||
.render());
|
||||
return;
|
||||
}
|
||||
data.put("username", user.getNickname());
|
||||
data.put("logoutUrl", userService.createLogoutURL(PATH));
|
||||
data.put("xsrfToken", xsrfTokenManager.generateToken(user.getEmail()));
|
||||
ImmutableSetMultimap<String, Role> roleMap = registrarAccessor.getAllClientIdWithRoles();
|
||||
data.put("allClientIds", roleMap.keySet());
|
||||
data.put("environment", RegistryEnvironment.get().toString());
|
||||
soyMapData.put("allClientIds", roleMap.keySet());
|
||||
soyMapData.put("environment", RegistryEnvironment.get().toString());
|
||||
// We set the initial value to the value that will show if guessClientId throws.
|
||||
String clientId = "<null>";
|
||||
try {
|
||||
clientId = paramClientId.orElse(registrarAccessor.guessClientId());
|
||||
data.put("clientId", clientId);
|
||||
data.put("isOwner", roleMap.containsEntry(clientId, OWNER));
|
||||
data.put("isAdmin", roleMap.containsEntry(clientId, ADMIN));
|
||||
soyMapData.put("clientId", clientId);
|
||||
soyMapData.put("isOwner", roleMap.containsEntry(clientId, OWNER));
|
||||
soyMapData.put("isAdmin", roleMap.containsEntry(clientId, ADMIN));
|
||||
|
||||
// We want to load the registrar even if we won't use it later (even if we remove the
|
||||
// requireFeeExtension) - to make sure the user indeed has access to the guessed registrar.
|
||||
@@ -197,7 +137,7 @@ public final class ConsoleUiAction implements Runnable {
|
||||
.get()
|
||||
.newRenderer(ConsoleSoyInfo.WHOAREYOU)
|
||||
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
|
||||
.setData(data)
|
||||
.setData(soyMapData)
|
||||
.render());
|
||||
registrarConsoleMetrics.registerConsoleRequest(
|
||||
clientId, paramClientId.isPresent(), roleMap.get(clientId), "FORBIDDEN");
|
||||
@@ -213,10 +153,15 @@ public final class ConsoleUiAction implements Runnable {
|
||||
.get()
|
||||
.newRenderer(ConsoleSoyInfo.MAIN)
|
||||
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
|
||||
.setData(data)
|
||||
.setData(soyMapData)
|
||||
.render();
|
||||
response.setPayload(payload);
|
||||
registrarConsoleMetrics.registerConsoleRequest(
|
||||
clientId, paramClientId.isPresent(), roleMap.get(clientId), "SUCCESS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return PATH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.ui.server.registrar;
|
||||
|
||||
import static com.google.common.net.HttpHeaders.LOCATION;
|
||||
import static com.google.common.net.HttpHeaders.X_FRAME_OPTIONS;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY;
|
||||
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.RequestMethod;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Handles some of the nitty-gritty of responding to requests that should return HTML, including
|
||||
* login, redirects, analytics, and some headers.
|
||||
*
|
||||
* If the user is not logged in, this will redirect to the login URL.
|
||||
*/
|
||||
public abstract class HtmlAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@Inject HttpServletRequest req;
|
||||
@Inject Response response;
|
||||
@Inject UserService userService;
|
||||
@Inject XsrfTokenManager xsrfTokenManager;
|
||||
@Inject AuthResult authResult;
|
||||
@Inject @RequestMethod Action.Method method;
|
||||
|
||||
@Inject
|
||||
@Config("logoFilename")
|
||||
String logoFilename;
|
||||
|
||||
@Inject
|
||||
@Config("productName")
|
||||
String productName;
|
||||
|
||||
@Inject
|
||||
@Config("analyticsConfig")
|
||||
Map<String, Object> analyticsConfig;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
response.setHeader(X_FRAME_OPTIONS, "SAMEORIGIN"); // Disallow iframing.
|
||||
response.setHeader("X-Ui-Compatible", "IE=edge"); // Ask IE not to be silly.
|
||||
|
||||
if (!authResult.userAuthInfo().isPresent()) {
|
||||
response.setStatus(SC_MOVED_TEMPORARILY);
|
||||
String location;
|
||||
try {
|
||||
location = userService.createLoginURL(req.getRequestURI());
|
||||
} catch (IllegalArgumentException e) {
|
||||
// UserServiceImpl.createLoginURL() throws IllegalArgumentException if underlying API call
|
||||
// returns an error code of NOT_ALLOWED. createLoginURL() assumes that the error is caused
|
||||
// by an invalid URL. But in fact, the error can also occur if UserService doesn't have any
|
||||
// user information, which happens when the request has been authenticated as internal. In
|
||||
// this case, we want to avoid dying before we can send the redirect, so just redirect to
|
||||
// the root path.
|
||||
location = "/";
|
||||
}
|
||||
response.setHeader(LOCATION, location);
|
||||
return;
|
||||
}
|
||||
response.setContentType(MediaType.HTML_UTF_8);
|
||||
|
||||
User user = authResult.userAuthInfo().get().user();
|
||||
|
||||
// Using HashMap to allow null values
|
||||
HashMap<String, Object> data = new HashMap<>();
|
||||
data.put("logoFilename", logoFilename);
|
||||
data.put("productName", productName);
|
||||
data.put("username", user.getNickname());
|
||||
data.put("logoutUrl", userService.createLogoutURL(getPath()));
|
||||
data.put("analyticsConfig", analyticsConfig);
|
||||
data.put("xsrfToken", xsrfTokenManager.generateToken(user.getEmail()));
|
||||
|
||||
logger.atInfo().log(
|
||||
"User %s is accessing %s. Method= %s",
|
||||
authResult.userIdForLogging(), getClass().getName(), method);
|
||||
runAfterLogin(data);
|
||||
}
|
||||
|
||||
public abstract void runAfterLogin(HashMap<String, Object> data);
|
||||
|
||||
public abstract String getPath();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.ui.server.registrar;
|
||||
|
||||
/**
|
||||
* Marker interface for {@link google.registry.request.Action}s that serve GET requests and return
|
||||
* JSON, rather than HTML.
|
||||
*/
|
||||
public interface JsonGetAction extends Runnable {}
|
||||
@@ -60,7 +60,6 @@ import google.registry.util.CollectionUtils;
|
||||
import google.registry.util.DiffUtils;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
@@ -175,8 +174,7 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
||||
}
|
||||
|
||||
private RegistrarResult update(final Map<String, ?> args, String clientId) {
|
||||
return tm()
|
||||
.transact(
|
||||
return tm().transact(
|
||||
() -> {
|
||||
// We load the registrar here rather than outside of the transaction - to make
|
||||
// sure we have the latest version. This one is loaded inside the transaction, so it's
|
||||
@@ -215,7 +213,8 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
||||
updatedRegistrar = checkAndUpdateAdminControlledFields(updatedRegistrar, args);
|
||||
|
||||
// read the contacts from the request.
|
||||
ImmutableSet<RegistrarContact> updatedContacts = readContacts(registrar, args);
|
||||
ImmutableSet<RegistrarContact> updatedContacts =
|
||||
readContacts(registrar, contacts, args);
|
||||
|
||||
// Save the updated contacts
|
||||
if (!updatedContacts.equals(contacts)) {
|
||||
@@ -240,11 +239,18 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
||||
});
|
||||
}
|
||||
|
||||
private Map<String, Object> expandRegistrarWithContacts(Iterable<RegistrarContact> contacts,
|
||||
Registrar registrar) {
|
||||
private Map<String, Object> expandRegistrarWithContacts(
|
||||
Iterable<RegistrarContact> contacts, Registrar registrar) {
|
||||
ImmutableSet<Map<String, Object>> expandedContacts =
|
||||
Streams.stream(contacts)
|
||||
.map(RegistrarContact::toDiffableFieldMap)
|
||||
// Note: per the javadoc, toDiffableFieldMap includes sensitive data but we don't want
|
||||
// to display it here
|
||||
.peek(
|
||||
map -> {
|
||||
map.remove("registryLockPasswordHash");
|
||||
map.remove("registryLockPasswordSalt");
|
||||
})
|
||||
.collect(toImmutableSet());
|
||||
// Use LinkedHashMap here to preserve ordering; null values mean we can't use ImmutableMap.
|
||||
LinkedHashMap<String, Object> result = new LinkedHashMap<>(registrar.toDiffableFieldMap());
|
||||
@@ -377,16 +383,10 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
||||
|
||||
/** Reads the contacts from the supplied args. */
|
||||
public static ImmutableSet<RegistrarContact> readContacts(
|
||||
Registrar registrar, Map<String, ?> args) {
|
||||
|
||||
ImmutableSet.Builder<RegistrarContact> contacts = new ImmutableSet.Builder<>();
|
||||
Optional<List<RegistrarContact.Builder>> builders =
|
||||
RegistrarFormFields.CONTACTS_FIELD.extractUntyped(args);
|
||||
if (builders.isPresent()) {
|
||||
builders.get().forEach(c -> contacts.add(c.setParent(registrar).build()));
|
||||
}
|
||||
|
||||
return contacts.build();
|
||||
Registrar registrar, ImmutableSet<RegistrarContact> existingContacts, Map<String, ?> args) {
|
||||
return RegistrarFormFields.getRegistrarContactBuilders(existingContacts, args).stream()
|
||||
.map(builder -> builder.setParent(registrar).build())
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -452,8 +452,17 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
||||
() ->
|
||||
new FormException(
|
||||
"Not allowed to set registry lock password directly on new contact"));
|
||||
if (!existingContact.isAllowedToSetRegistryLockPassword()) {
|
||||
throw new FormException("Registrar contact not allowed to set registry lock password");
|
||||
if (updatedContact.isRegistryLockAllowed()) {
|
||||
// the password must have been set before or the user was allowed to set it now
|
||||
if (!existingContact.isAllowedToSetRegistryLockPassword()
|
||||
&& !existingContact.isRegistryLockAllowed()) {
|
||||
throw new FormException("Registrar contact not allowed to set registry lock password");
|
||||
}
|
||||
}
|
||||
if (updatedContact.isAllowedToSetRegistryLockPassword()) {
|
||||
if (!existingContact.isAllowedToSetRegistryLockPassword()) {
|
||||
throw new FormException("Cannot set isAllowedToSetRegistryLockPassword through UI");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.ui.server.registrar;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
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;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.model.registry.RegistryLockDao;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Method;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.RequestMethod;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.schema.domain.RegistryLock;
|
||||
import google.registry.security.JsonResponseHelper;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* Servlet that allows for getting locks for a particular registrar.
|
||||
*
|
||||
* <p>Note: at the moment we have no mechanism for JSON GET/POSTs in the same class or at the same
|
||||
* URL, which is why this is distinct from the {@link RegistryLockPostAction}.
|
||||
*/
|
||||
@Action(
|
||||
service = Action.Service.DEFAULT,
|
||||
path = RegistryLockGetAction.PATH,
|
||||
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
||||
public final class RegistryLockGetAction implements JsonGetAction {
|
||||
|
||||
public static final String PATH = "/registry-lock-get";
|
||||
|
||||
private static final String LOCK_ENABLED_FOR_CONTACT_PARAM = "lockEnabledForContact";
|
||||
private static final String EMAIL_PARAM = "email";
|
||||
private static final String LOCKS_PARAM = "locks";
|
||||
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 FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
@VisibleForTesting Method method;
|
||||
private final Response response;
|
||||
private final AuthenticatedRegistrarAccessor registrarAccessor;
|
||||
@VisibleForTesting AuthResult authResult;
|
||||
@VisibleForTesting Optional<String> paramClientId;
|
||||
|
||||
@Inject
|
||||
RegistryLockGetAction(
|
||||
@RequestMethod Method method,
|
||||
Response response,
|
||||
AuthenticatedRegistrarAccessor registrarAccessor,
|
||||
AuthResult authResult,
|
||||
@Parameter(PARAM_CLIENT_ID) Optional<String> paramClientId) {
|
||||
this.method = method;
|
||||
this.response = response;
|
||||
this.registrarAccessor = registrarAccessor;
|
||||
this.authResult = authResult;
|
||||
this.paramClientId = paramClientId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
checkArgument(Method.GET.equals(method), "Only GET requests allowed");
|
||||
checkArgument(authResult.userAuthInfo().isPresent(), "User auth info must be present");
|
||||
checkArgument(paramClientId.isPresent(), "clientId must be present");
|
||||
response.setContentType(MediaType.JSON_UTF_8);
|
||||
|
||||
try {
|
||||
ImmutableMap<String, ?> resultMap = getLockedDomainsMap(paramClientId.get());
|
||||
ImmutableMap<String, ?> payload =
|
||||
JsonResponseHelper.create(SUCCESS, "Successful locks retrieval", resultMap);
|
||||
response.setPayload(GSON.toJson(payload));
|
||||
} catch (RegistrarAccessDeniedException e) {
|
||||
logger.atWarning().withCause(e).log(
|
||||
"User %s doesn't have access to this registrar", authResult.userIdForLogging());
|
||||
response.setStatus(SC_FORBIDDEN);
|
||||
} catch (Exception e) {
|
||||
logger.atWarning().withCause(e).log("Unexpected error when retrieving locks for a registrar");
|
||||
response.setStatus(SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private ImmutableMap<String, ?> getLockedDomainsMap(String clientId)
|
||||
throws RegistrarAccessDeniedException {
|
||||
// Note: admins always have access to the locks page
|
||||
checkArgument(authResult.userAuthInfo().isPresent(), "User auth info must be present");
|
||||
UserAuthInfo userAuthInfo = authResult.userAuthInfo().get();
|
||||
boolean isAdmin = userAuthInfo.isUserAdmin();
|
||||
Registrar registrar = getRegistrarAndVerifyLockAccess(clientId, isAdmin);
|
||||
User user = userAuthInfo.user();
|
||||
boolean isRegistryLockAllowed =
|
||||
isAdmin
|
||||
|| registrar.getContacts().stream()
|
||||
.filter(contact -> contact.getEmailAddress().equals(user.getEmail()))
|
||||
.findFirst()
|
||||
.map(RegistrarContact::isRegistryLockAllowed)
|
||||
.orElse(false);
|
||||
return ImmutableMap.of(
|
||||
LOCK_ENABLED_FOR_CONTACT_PARAM,
|
||||
isRegistryLockAllowed,
|
||||
EMAIL_PARAM,
|
||||
user.getEmail(),
|
||||
PARAM_CLIENT_ID,
|
||||
registrar.getClientId(),
|
||||
LOCKS_PARAM,
|
||||
getLockedDomains(clientId));
|
||||
}
|
||||
|
||||
private Registrar getRegistrarAndVerifyLockAccess(String clientId, boolean isAdmin)
|
||||
throws RegistrarAccessDeniedException {
|
||||
Registrar registrar = registrarAccessor.getRegistrar(clientId);
|
||||
checkArgument(
|
||||
isAdmin || registrar.isRegistryLockAllowed(),
|
||||
"Registry lock not allowed for this registrar");
|
||||
return registrar;
|
||||
}
|
||||
|
||||
private ImmutableList<ImmutableMap<String, ?>> getLockedDomains(String clientId) {
|
||||
ImmutableList<RegistryLock> locks =
|
||||
RegistryLockDao.getByRegistrarId(clientId).stream()
|
||||
.filter(RegistryLock::isVerified)
|
||||
.collect(toImmutableList());
|
||||
return locks.stream().map(this::lockToMap).collect(toImmutableList());
|
||||
}
|
||||
|
||||
private ImmutableMap<String, ?> lockToMap(RegistryLock lock) {
|
||||
return ImmutableMap.of(
|
||||
FULLY_QUALIFIED_DOMAIN_NAME_PARAM,
|
||||
lock.getDomainName(),
|
||||
LOCKED_TIME_PARAM,
|
||||
lock.getCompletionTimestamp().map(DateTime::toString).orElse(""),
|
||||
LOCKED_BY_PARAM,
|
||||
lock.isSuperuser() ? "admin" : lock.getRegistrarPocId());
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
tmp="$(mktemp -d "${TMPDIR:-/tmp}/list_generated_files.XXXXXXXX")"
|
||||
[[ "${tmp}" != "" ]] || exit 1
|
||||
trap "rm -rf ${tmp}" EXIT
|
||||
|
||||
base="${PWD}"
|
||||
export LC_ALL=C
|
||||
|
||||
cd "${tmp}"
|
||||
cp "${base}/java/google/registry/xjc/bindings.xjb" .
|
||||
cp "${base}"/java/google/registry/xml/xsd/*.xsd .
|
||||
"${base}/third_party/java/jaxb/jaxb-xjc" -extension -d "${tmp}" -b *.xjb *.xsd \
|
||||
| sed -ne s@google/registry/xjc/@@p \
|
||||
| grep -v package-info.java \
|
||||
| sort \
|
||||
> xjc_generated_files
|
||||
|
||||
cat <<EOF
|
||||
#
|
||||
# .'\`\`'. ...
|
||||
# :o o \`....'\` ;
|
||||
# \`. O :'
|
||||
# \`': \`.
|
||||
# \`:. \`.
|
||||
# : \`. \`.
|
||||
# \`..'\`... \`.
|
||||
# \`... \`.
|
||||
# DO NOT EDIT \`\`... \`.
|
||||
# THIS FILE \`\`\`\`\`.
|
||||
#
|
||||
# When you make changes to the XML schemas (*.xsd) or the JAXB bindings file
|
||||
# (bindings.xjb), you must regenerate this file with the following commands:
|
||||
#
|
||||
# bazel run java/google/registry/xjc:list_generated_files | tee /tmp/lol
|
||||
# mv /tmp/lol java/google/registry/xjc/generated_files.bzl
|
||||
#
|
||||
EOF
|
||||
|
||||
echo
|
||||
echo "pkginfo_generated_files = ["
|
||||
while read package; do
|
||||
printf ' "%s/package-info.java",\n' "${package}"
|
||||
done < <(awk -F/ '{print $1}' xjc_generated_files | sort -u)
|
||||
echo "]"
|
||||
|
||||
echo
|
||||
echo "xjc_generated_files = ["
|
||||
while read path; do
|
||||
printf ' "%s",\n' "${path}"
|
||||
done <xjc_generated_files
|
||||
echo "]"
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
[[ $# != 2 ]] && { echo "usage: $0 TEMPLATE OUTDIR" >&2; exit 1; }
|
||||
|
||||
template="$1"
|
||||
outdir="$2"
|
||||
|
||||
create() {
|
||||
package=$1
|
||||
namespace=$2
|
||||
sed -e "s,@PACKAGE@,${package},g" \
|
||||
-e "s,@NAMESPACE@,${namespace},g" \
|
||||
< "${template}" \
|
||||
> "${outdir}/${package}/package-info.java"
|
||||
}
|
||||
|
||||
create contact urn:ietf:params:xml:ns:contact-1.0
|
||||
create domain urn:ietf:params:xml:ns:domain-1.0
|
||||
create dsig http://www.w3.org/2000/09/xmldsig#
|
||||
create epp urn:ietf:params:xml:ns:epp-1.0
|
||||
create eppcom urn:ietf:params:xml:ns:eppcom-1.0
|
||||
create fee06 urn:ietf:params:xml:ns:fee-0.6
|
||||
create fee11 urn:ietf:params:xml:ns:fee-0.11
|
||||
create fee12 urn:ietf:params:xml:ns:fee-0.12
|
||||
create host urn:ietf:params:xml:ns:host-1.0
|
||||
create iirdea urn:ietf:params:xml:ns:iirdea-1.0
|
||||
create launch urn:ietf:params:xml:ns:launch-1.0
|
||||
create mark urn:ietf:params:xml:ns:mark-1.0
|
||||
create rde urn:ietf:params:xml:ns:rde-1.0
|
||||
create rdecontact urn:ietf:params:xml:ns:rdeContact-1.0
|
||||
create rdedomain urn:ietf:params:xml:ns:rdeDomain-1.0
|
||||
create rdeeppparams urn:ietf:params:xml:ns:rdeEppParams-1.0
|
||||
create rdeheader urn:ietf:params:xml:ns:rdeHeader-1.0
|
||||
create rdehost urn:ietf:params:xml:ns:rdeHost-1.0
|
||||
create rdeidn urn:ietf:params:xml:ns:rdeIDN-1.0
|
||||
create rdenndn urn:ietf:params:xml:ns:rdeNNDN-1.0
|
||||
create rdenotification urn:ietf:params:xml:ns:rdeNotification-1.0
|
||||
create rdepolicy urn:ietf:params:xml:ns:rdePolicy-1.0
|
||||
create rderegistrar urn:ietf:params:xml:ns:rdeRegistrar-1.0
|
||||
create rdereport urn:ietf:params:xml:ns:rdeReport-1.0
|
||||
create rgp urn:ietf:params:xml:ns:rgp-1.0
|
||||
create secdns urn:ietf:params:xml:ns:secDNS-1.1
|
||||
create smd urn:ietf:params:xml:ns:signedMark-1.0
|
||||
@@ -1,4 +1,3 @@
|
||||
// See build.xml and make_pkginfo.sh which preprocess this into actual files.
|
||||
@XmlSchema(
|
||||
elementFormDefault = XmlNsForm.QUALIFIED,
|
||||
namespace = "@NAMESPACE@",
|
||||
|
||||
27
core/src/main/java/google/registry/xjc/package-info.map
Normal file
27
core/src/main/java/google/registry/xjc/package-info.map
Normal file
@@ -0,0 +1,27 @@
|
||||
contact urn:ietf:params:xml:ns:contact-1.0
|
||||
domain urn:ietf:params:xml:ns:domain-1.0
|
||||
dsig http://www.w3.org/2000/09/xmldsig#
|
||||
epp urn:ietf:params:xml:ns:epp-1.0
|
||||
eppcom urn:ietf:params:xml:ns:eppcom-1.0
|
||||
fee06 urn:ietf:params:xml:ns:fee-0.6
|
||||
fee11 urn:ietf:params:xml:ns:fee-0.11
|
||||
fee12 urn:ietf:params:xml:ns:fee-0.12
|
||||
host urn:ietf:params:xml:ns:host-1.0
|
||||
iirdea urn:ietf:params:xml:ns:iirdea-1.0
|
||||
launch urn:ietf:params:xml:ns:launch-1.0
|
||||
mark urn:ietf:params:xml:ns:mark-1.0
|
||||
rde urn:ietf:params:xml:ns:rde-1.0
|
||||
rdecontact urn:ietf:params:xml:ns:rdeContact-1.0
|
||||
rdedomain urn:ietf:params:xml:ns:rdeDomain-1.0
|
||||
rdeeppparams urn:ietf:params:xml:ns:rdeEppParams-1.0
|
||||
rdeheader urn:ietf:params:xml:ns:rdeHeader-1.0
|
||||
rdehost urn:ietf:params:xml:ns:rdeHost-1.0
|
||||
rdeidn urn:ietf:params:xml:ns:rdeIDN-1.0
|
||||
rdenndn urn:ietf:params:xml:ns:rdeNNDN-1.0
|
||||
rdenotification urn:ietf:params:xml:ns:rdeNotification-1.0
|
||||
rdepolicy urn:ietf:params:xml:ns:rdePolicy-1.0
|
||||
rderegistrar urn:ietf:params:xml:ns:rdeRegistrar-1.0
|
||||
rdereport urn:ietf:params:xml:ns:rdeReport-1.0
|
||||
rgp urn:ietf:params:xml:ns:rgp-1.0
|
||||
secdns urn:ietf:params:xml:ns:secDNS-1.1
|
||||
smd urn:ietf:params:xml:ns:signedMark-1.0
|
||||
18
core/src/main/resources/META-INF/orm.xml
Normal file
18
core/src/main/resources/META-INF/orm.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
|
||||
http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd"
|
||||
version="2.2">
|
||||
<embeddable class="org.joda.money.Money" access="FIELD">
|
||||
<attributes>
|
||||
<embedded name="money" access="FIELD"/>
|
||||
</attributes>
|
||||
</embeddable>
|
||||
<embeddable class="org.joda.money.BigMoney" access="FIELD">
|
||||
<attributes>
|
||||
<basic name="amount" access="FIELD"/>
|
||||
<basic name="currency" access="FIELD"/>
|
||||
</attributes>
|
||||
</embeddable>
|
||||
</entity-mappings>
|
||||
@@ -35,6 +35,8 @@
|
||||
<!-- Customized type converters -->
|
||||
<class>google.registry.persistence.BloomFilterConverter</class>
|
||||
<class>google.registry.persistence.CreateAutoTimestampConverter</class>
|
||||
<class>google.registry.persistence.CurrencyUnitConverter</class>
|
||||
<class>google.registry.persistence.DateTimeConverter</class>
|
||||
<class>google.registry.persistence.UpdateAutoTimestampConverter</class>
|
||||
<class>google.registry.persistence.ZonedDateTimeConverter</class>
|
||||
|
||||
|
||||
@@ -37,17 +37,18 @@
|
||||
{/call}
|
||||
|
||||
<p>Please work with the registrant to mitigate any security issues and have the
|
||||
domains delisted.</p>
|
||||
domains delisted. If you believe that any of the domains were reported in error, or are still
|
||||
receiving reports for issues that have been remediated,
|
||||
please <a href="https://safebrowsing.google.com/safebrowsing/report_error/?hl=en">submit a
|
||||
request</a> to have the site reviewed.</p>
|
||||
|
||||
{call .resourceList}
|
||||
{param resources: $resources /}
|
||||
{/call}
|
||||
|
||||
<p>You will continue to receive a monthly summary of all domains managed by your registrar
|
||||
that remain on our lists of potential security threats. You will additionally receive a daily
|
||||
notice when any new domains that are added to these lists. Once the registrant has resolved
|
||||
the security issues and followed the steps to have his or her domain reviewed and delisted
|
||||
it will automatically be removed from our monthly reporting.</p>
|
||||
that remain on our lists of potential security threats. You will also receive a daily
|
||||
notice when any new domains are added to these lists.</p>
|
||||
|
||||
<p>If you have any questions regarding this notice, please contact {$replyToEmail}.</p>
|
||||
{/template}
|
||||
@@ -79,11 +80,14 @@
|
||||
{param resources: $resources /}
|
||||
{/call}
|
||||
|
||||
<p>If you believe that any of the domains were reported in error, or are still receiving
|
||||
reports for issues that have been remediated,
|
||||
please <a href="https://safebrowsing.google.com/safebrowsing/report_error/?hl=en">submit
|
||||
a request</a> to have the site reviewed.</p>
|
||||
|
||||
<p>You will continue to receive daily notices when new domains managed by your registrar
|
||||
are flagged for abuse, as well as a monthly summary of all of your domains under management
|
||||
that remain flagged for abuse. Once the registrant has resolved the security issues and
|
||||
followed the steps to have his or her domain reviewed and delisted it will automatically
|
||||
be removed from our reporting.</p>
|
||||
that remain flagged for abuse.</p>
|
||||
|
||||
<p>If you would like to change the email to which these notices are sent please update your
|
||||
abuse contact using your registrar portal account.</p>
|
||||
|
||||
@@ -129,6 +129,7 @@ import google.registry.flows.domain.DomainFlowUtils.TrailingDashException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.UnexpectedClaimsNoticeException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException;
|
||||
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.AllocationTokenNotValidForRegistrarException;
|
||||
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException;
|
||||
@@ -1227,9 +1228,9 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
||||
.build());
|
||||
clock.advanceOneMilli();
|
||||
setEppInput("domain_create_premium_allocationtoken.xml");
|
||||
assertThat(assertThrows(IllegalArgumentException.class, this::runFlow))
|
||||
.hasMessageThat()
|
||||
.isEqualTo("A nonzero discount code cannot be applied to premium domains");
|
||||
assertAboutEppExceptions()
|
||||
.that(assertThrows(AllocationTokenInvalidForPremiumNameException.class, this::runFlow))
|
||||
.marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.DatastoreHelper.createTld;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.ResourceFlowTestCase;
|
||||
import google.registry.flows.domain.DomainFlowUtils.BadDomainNameCharacterException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.BadDomainNamePartsCountException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.DashesInThirdAndFourthException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.DomainLabelTooLongException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.EmptyDomainNamePartException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.InvalidPunycodeException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.LeadingDashException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.TldDoesNotExistException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.TrailingDashException;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.testing.AppEngineRule;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DomainFlowUtilsTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase> {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
setEppInput("domain_info.xml");
|
||||
createTld("tld");
|
||||
persistResource(AppEngineRule.makeRegistrar1().asBuilder().build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDomainNameAcceptsValidName() throws EppException {
|
||||
assertThat(DomainFlowUtils.validateDomainName("example.tld")).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDomainName_IllegalCharacters() {
|
||||
BadDomainNameCharacterException thrown =
|
||||
assertThrows(
|
||||
BadDomainNameCharacterException.class,
|
||||
() -> DomainFlowUtils.validateDomainName("$.foo"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Domain names can only contain a-z, 0-9, '.' and '-'");
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDomainName_DomainNameWithEmptyParts() {
|
||||
EmptyDomainNamePartException thrown =
|
||||
assertThrows(
|
||||
EmptyDomainNamePartException.class,
|
||||
() -> DomainFlowUtils.validateDomainName("example."));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("No part of a domain name can be empty");
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDomainName_DomainNameWithLessThanTwoParts() {
|
||||
BadDomainNamePartsCountException thrown =
|
||||
assertThrows(
|
||||
BadDomainNamePartsCountException.class,
|
||||
() -> DomainFlowUtils.validateDomainName("example"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Domain name must have exactly one part above the TLD");
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDomainName_invalidTLD() {
|
||||
TldDoesNotExistException thrown =
|
||||
assertThrows(
|
||||
TldDoesNotExistException.class,
|
||||
() -> DomainFlowUtils.validateDomainName("example.nosuchtld"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Domain name is under tld nosuchtld which doesn't exist");
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDomainName_DomainNameIsTooLong() {
|
||||
DomainLabelTooLongException thrown =
|
||||
assertThrows(
|
||||
DomainLabelTooLongException.class,
|
||||
() ->
|
||||
DomainFlowUtils.validateDomainName(
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.foo"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Domain labels cannot be longer than 63 characters");
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDomainName_leadingDash() {
|
||||
LeadingDashException thrown =
|
||||
assertThrows(
|
||||
LeadingDashException.class, () -> DomainFlowUtils.validateDomainName("-example.foo"));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Domain labels cannot begin with a dash");
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDomainName_trailingDash() {
|
||||
TrailingDashException thrown =
|
||||
assertThrows(
|
||||
TrailingDashException.class, () -> DomainFlowUtils.validateDomainName("example-.foo"));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Domain labels cannot end with a dash");
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDomainName_invalidIDN() {
|
||||
InvalidPunycodeException thrown =
|
||||
assertThrows(
|
||||
InvalidPunycodeException.class,
|
||||
() -> DomainFlowUtils.validateDomainName("xn--abcd.foo"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Domain name starts with xn-- but is not a valid IDN");
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDomainName_containsInvalidDashes() {
|
||||
DashesInThirdAndFourthException thrown =
|
||||
assertThrows(
|
||||
DashesInThirdAndFourthException.class,
|
||||
() -> DomainFlowUtils.validateDomainName("ab--cd.foo"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Non-IDN domain names cannot contain dashes in the third or fourth position");
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import static google.registry.model.domain.token.AllocationToken.TokenStatus.VAL
|
||||
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
|
||||
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.testing.DatastoreHelper.createTld;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
@@ -36,11 +37,17 @@ import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||
import google.registry.model.domain.token.AllocationToken.TokenType;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/** Unit tests for {@link AllocationToken}. */
|
||||
public class AllocationTokenTest extends EntityTestCase {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
createTld("foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistence() {
|
||||
AllocationToken unlimitedUseToken =
|
||||
@@ -66,7 +73,7 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setRedemptionHistoryEntry(Key.create(HistoryEntry.class, 1L))
|
||||
.setDomainName("foo.example")
|
||||
.setDomainName("example.foo")
|
||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.setTokenType(SINGLE_USE)
|
||||
.build());
|
||||
@@ -81,7 +88,7 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setRedemptionHistoryEntry(Key.create(HistoryEntry.class, 1L))
|
||||
.setDomainName("blahdomain.fake")
|
||||
.setDomainName("blahdomain.foo")
|
||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.build()),
|
||||
"token",
|
||||
@@ -129,13 +136,49 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Token type can only be set once");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuild_DomainNameWithLessThanTwoParts() {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
new AllocationToken.Builder()
|
||||
.setDomainName("example")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setToken("barfoo")
|
||||
.build());
|
||||
assertThat(thrown)
|
||||
.hasCauseThat()
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Domain name must have exactly one part above the TLD");
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Invalid domain name: example");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuild_invalidTLD() {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
new AllocationToken.Builder()
|
||||
.setDomainName("example.nosuchtld")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setToken("barfoo")
|
||||
.build());
|
||||
assertThat(thrown)
|
||||
.hasCauseThat()
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Domain name is under tld nosuchtld which doesn't exist");
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Invalid domain name: example.nosuchtld");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuild_domainNameOnlyOnSingleUse() {
|
||||
AllocationToken.Builder builder =
|
||||
new AllocationToken.Builder()
|
||||
.setToken("foobar")
|
||||
.setTokenType(TokenType.UNLIMITED_USE)
|
||||
.setDomainName("foo.example");
|
||||
.setDomainName("example.foo");
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, builder::build);
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
|
||||
@@ -17,9 +17,12 @@ package google.registry.model.registry;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.testing.DatastoreHelper.createTlds;
|
||||
import static google.registry.testing.DatastoreHelper.newRegistry;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import google.registry.model.registry.Registry.TldType;
|
||||
import google.registry.testing.AppEngineRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -32,6 +35,7 @@ public class RegistriesTest {
|
||||
|
||||
@Rule
|
||||
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
|
||||
|
||||
private void initTestTlds() {
|
||||
createTlds("foo", "a.b.c"); // Test a multipart tld.
|
||||
}
|
||||
@@ -42,6 +46,16 @@ public class RegistriesTest {
|
||||
assertThat(Registries.getTlds()).containsExactly("foo", "a.b.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_getTldEntities() {
|
||||
initTestTlds();
|
||||
persistResource(newRegistry("testtld", "TESTTLD").asBuilder().setTldType(TldType.TEST).build());
|
||||
assertThat(Registries.getTldEntitiesOfType(TldType.REAL))
|
||||
.containsExactly(Registry.get("foo"), Registry.get("a.b.c"));
|
||||
assertThat(Registries.getTldEntitiesOfType(TldType.TEST))
|
||||
.containsExactly(Registry.get("testtld"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTlds_withNoRegistriesPersisted_returnsEmptySet() {
|
||||
assertThat(Registries.getTlds()).isEmpty();
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.model.registry;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
@@ -22,8 +23,8 @@ import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import google.registry.schema.domain.RegistryLock;
|
||||
import google.registry.schema.domain.RegistryLock.Action;
|
||||
import google.registry.testing.AppEngineRule;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.PersistenceException;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -52,15 +53,11 @@ public final class RegistryLockDaoTest {
|
||||
public void testSaveAndLoad_failure_differentCode() {
|
||||
RegistryLock lock = createLock();
|
||||
RegistryLockDao.save(lock);
|
||||
PersistenceException exception =
|
||||
NullPointerException thrown =
|
||||
assertThrows(
|
||||
PersistenceException.class,
|
||||
NullPointerException.class,
|
||||
() -> RegistryLockDao.getByVerificationCode(UUID.randomUUID().toString()));
|
||||
assertThat(exception)
|
||||
.hasCauseThat()
|
||||
.hasMessageThat()
|
||||
.isEqualTo("No registry lock with this code");
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(NullPointerException.class);
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("No registry lock with this code");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,10 +68,10 @@ public final class RegistryLockDaoTest {
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
RegistryLock secondLock =
|
||||
RegistryLock updatedLock =
|
||||
RegistryLockDao.getByVerificationCode(lock.getVerificationCode());
|
||||
secondLock.setCompletionTimestamp(jpaTmRule.getTxnClock().nowUtc());
|
||||
RegistryLockDao.save(secondLock);
|
||||
updatedLock.setCompletionTimestamp(jpaTmRule.getTxnClock().nowUtc());
|
||||
RegistryLockDao.save(updatedLock);
|
||||
});
|
||||
jpaTm()
|
||||
.transact(
|
||||
@@ -86,11 +83,63 @@ public final class RegistryLockDaoTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateLock_usingSamePrimaryKey() {
|
||||
RegistryLock lock = RegistryLockDao.save(createLock());
|
||||
jpaTmRule.getTxnClock().advanceOneMilli();
|
||||
RegistryLock updatedLock =
|
||||
lock.asBuilder().setCompletionTimestamp(jpaTmRule.getTxnClock().nowUtc()).build();
|
||||
jpaTm().transact(() -> RegistryLockDao.save(updatedLock));
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
RegistryLock fromDatabase =
|
||||
RegistryLockDao.getByVerificationCode(lock.getVerificationCode());
|
||||
assertThat(fromDatabase.getCompletionTimestamp())
|
||||
.isEqualTo(Optional.of(jpaTmRule.getTxnClock().nowUtc()));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_saveNull() {
|
||||
assertThrows(NullPointerException.class, () -> RegistryLockDao.save(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoad_byRegistrarId() {
|
||||
RegistryLock lock = createLock();
|
||||
RegistryLock secondLock = createLock().asBuilder().setDomainName("otherexample.test").build();
|
||||
RegistryLockDao.save(lock);
|
||||
RegistryLockDao.save(secondLock);
|
||||
|
||||
assertThat(
|
||||
RegistryLockDao.getByRegistrarId("TheRegistrar").stream()
|
||||
.map(RegistryLock::getDomainName)
|
||||
.collect(toImmutableSet()))
|
||||
.containsExactly("example.test", "otherexample.test");
|
||||
assertThat(RegistryLockDao.getByRegistrarId("nonexistent")).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoad_byRepoId() {
|
||||
RegistryLock completedLock =
|
||||
createLock().asBuilder().setCompletionTimestamp(jpaTmRule.getTxnClock().nowUtc()).build();
|
||||
RegistryLockDao.save(completedLock);
|
||||
|
||||
jpaTmRule.getTxnClock().advanceOneMilli();
|
||||
RegistryLock inProgressLock = createLock();
|
||||
RegistryLockDao.save(inProgressLock);
|
||||
|
||||
Optional<RegistryLock> mostRecent = RegistryLockDao.getMostRecentByRepoId("repoId");
|
||||
assertThat(mostRecent.isPresent()).isTrue();
|
||||
assertThat(mostRecent.get().isVerified()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoad_byRepoId_empty() {
|
||||
assertThat(RegistryLockDao.getMostRecentByRepoId("nonexistent").isPresent()).isFalse();
|
||||
}
|
||||
|
||||
private RegistryLock createLock() {
|
||||
return new RegistryLock.Builder()
|
||||
.setRepoId("repoId")
|
||||
|
||||
@@ -22,7 +22,6 @@ import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import google.registry.schema.tmch.ClaimsList;
|
||||
import google.registry.testing.FakeClock;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -71,9 +70,7 @@ public class ClaimsListDaoTest {
|
||||
|
||||
@Test
|
||||
public void getCurrent_throwsNoResultExceptionIfTableIsEmpty() {
|
||||
PersistenceException thrown =
|
||||
assertThrows(PersistenceException.class, () -> ClaimsListDao.getCurrent());
|
||||
assertThat(thrown).hasCauseThat().isInstanceOf(NoResultException.class);
|
||||
assertThrows(NoResultException.class, ClaimsListDao::getCurrent);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -14,28 +14,42 @@
|
||||
|
||||
package google.registry.model.transaction;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.testcontainers.containers.PostgreSQLContainer.POSTGRESQL_PORT;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.io.Resources;
|
||||
import google.registry.persistence.HibernateSchemaExporter;
|
||||
import google.registry.persistence.NomulusPostgreSql;
|
||||
import google.registry.persistence.PersistenceModule;
|
||||
import google.registry.persistence.PersistenceXmlUtility;
|
||||
import google.registry.testing.FakeClock;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
|
||||
import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
|
||||
import org.hibernate.jpa.boot.spi.Bootstrap;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.rules.ExternalResource;
|
||||
import org.junit.rules.RuleChain;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
|
||||
@@ -48,38 +62,59 @@ import org.testcontainers.containers.PostgreSQLContainer;
|
||||
* PostgreSQLContainer} to achieve test purpose.
|
||||
*/
|
||||
public class JpaTransactionManagerRule extends ExternalResource {
|
||||
private static final String SCHEMA_GOLDEN_SQL = "sql/schema/nomulus.golden.sql";
|
||||
private static final String GOLDEN_SCHEMA_SQL_PATH = "sql/schema/nomulus.golden.sql";
|
||||
private static final String DB_CLEANUP_SQL_PATH =
|
||||
"google/registry/model/transaction/cleanup_database.sql";
|
||||
private static final String MANAGEMENT_DB_NAME = "management";
|
||||
private static final String POSTGRES_DB_NAME = "postgres";
|
||||
|
||||
private final DateTime now = DateTime.now(UTC);
|
||||
private final FakeClock clock = new FakeClock(now);
|
||||
private final String initScript;
|
||||
private final String initScriptPath;
|
||||
private final ImmutableList<Class> extraEntityClasses;
|
||||
private final ImmutableMap userProperties;
|
||||
|
||||
private JdbcDatabaseContainer database;
|
||||
private static final JdbcDatabaseContainer database = create();
|
||||
private static final long ACTIVE_CONNECTIONS_BASELINE =
|
||||
getActiveConnectionCountByUser(database.getUsername());
|
||||
;
|
||||
private static final HibernateSchemaExporter exporter =
|
||||
HibernateSchemaExporter.create(
|
||||
database.getJdbcUrl(), database.getUsername(), database.getPassword());
|
||||
private EntityManagerFactory emf;
|
||||
private JpaTransactionManager cachedTm;
|
||||
|
||||
private JpaTransactionManagerRule(
|
||||
String initScript,
|
||||
String initScriptPath,
|
||||
ImmutableList<Class> extraEntityClasses,
|
||||
ImmutableMap<String, String> userProperties) {
|
||||
this.initScript = initScript;
|
||||
this.initScriptPath = initScriptPath;
|
||||
this.extraEntityClasses = extraEntityClasses;
|
||||
this.userProperties = userProperties;
|
||||
}
|
||||
|
||||
/** Wraps {@link JpaTransactionManagerRule} in a {@link PostgreSQLContainer}. */
|
||||
@Override
|
||||
public Statement apply(Statement base, Description description) {
|
||||
database = new PostgreSQLContainer().withInitScript(initScript);
|
||||
return RuleChain.outerRule(database)
|
||||
.around(JpaTransactionManagerRule.super::apply)
|
||||
.apply(base, description);
|
||||
private static JdbcDatabaseContainer create() {
|
||||
PostgreSQLContainer container =
|
||||
new PostgreSQLContainer(NomulusPostgreSql.getDockerTag())
|
||||
.withDatabaseName(MANAGEMENT_DB_NAME);
|
||||
container.start();
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> container.close()));
|
||||
return container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void before() {
|
||||
public void before() throws Exception {
|
||||
executeSql(MANAGEMENT_DB_NAME, readSqlInClassPath(DB_CLEANUP_SQL_PATH));
|
||||
executeSql(POSTGRES_DB_NAME, readSqlInClassPath(initScriptPath));
|
||||
if (!extraEntityClasses.isEmpty()) {
|
||||
File tempSqlFile = File.createTempFile("tempSqlFile", ".sql");
|
||||
tempSqlFile.deleteOnExit();
|
||||
exporter.export(extraEntityClasses, tempSqlFile);
|
||||
executeSql(
|
||||
POSTGRES_DB_NAME,
|
||||
new String(Files.readAllBytes(tempSqlFile.toPath()), StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
ImmutableMap properties = PersistenceModule.providesDefaultDatabaseConfigs();
|
||||
if (!userProperties.isEmpty()) {
|
||||
// If there are user properties, create a new properties object with these added.
|
||||
@@ -87,10 +122,10 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
builder.putAll(userProperties);
|
||||
properties = builder.build();
|
||||
}
|
||||
|
||||
assertNormalActiveConnection();
|
||||
emf =
|
||||
createEntityManagerFactory(
|
||||
database.getJdbcUrl(),
|
||||
getJdbcUrlFor(POSTGRES_DB_NAME),
|
||||
database.getUsername(),
|
||||
database.getPassword(),
|
||||
properties,
|
||||
@@ -105,8 +140,72 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
TransactionManagerFactory.jpaTm = cachedTm;
|
||||
if (emf != null) {
|
||||
emf.close();
|
||||
emf = null;
|
||||
}
|
||||
cachedTm = null;
|
||||
assertNormalActiveConnection();
|
||||
}
|
||||
|
||||
private static long getActiveConnectionCountByUser(String userName) {
|
||||
try (Connection conn = createConnection(POSTGRES_DB_NAME);
|
||||
Statement statement = conn.createStatement()) {
|
||||
ResultSet rs =
|
||||
statement.executeQuery(
|
||||
"SELECT COUNT(1) FROM pg_stat_activity WHERE usename = '" + userName + "'");
|
||||
rs.next();
|
||||
return rs.getLong(1);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function throws exception if it detects connection leak by checking the metadata table
|
||||
* pg_stat_activity.
|
||||
*/
|
||||
private void assertNormalActiveConnection() {
|
||||
assertThat(getActiveConnectionCountByUser(database.getUsername()))
|
||||
.isEqualTo(ACTIVE_CONNECTIONS_BASELINE);
|
||||
}
|
||||
|
||||
private static String readSqlInClassPath(String sqlScriptPath) {
|
||||
try {
|
||||
return Resources.toString(Resources.getResource(sqlScriptPath), Charsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeSql(String dbName, String sqlScript) {
|
||||
try (Connection conn = createConnection(dbName);
|
||||
Statement statement = conn.createStatement()) {
|
||||
statement.execute(sqlScript);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getJdbcUrlFor(String dbName) {
|
||||
// Disable Postgres driver use of java.util.logging to reduce noise at startup time
|
||||
return "jdbc:postgresql://"
|
||||
+ database.getContainerIpAddress()
|
||||
+ ":"
|
||||
+ database.getMappedPort(POSTGRESQL_PORT)
|
||||
+ "/"
|
||||
+ dbName
|
||||
+ "?loggerLevel=OFF";
|
||||
}
|
||||
|
||||
private static Connection createConnection(String dbName) {
|
||||
final Properties info = new Properties();
|
||||
info.put("user", database.getUsername());
|
||||
info.put("password", database.getPassword());
|
||||
final Driver jdbcDriverInstance = database.getJdbcDriverInstance();
|
||||
try {
|
||||
return jdbcDriverInstance.connect(getJdbcUrlFor(dbName), info);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Constructs the {@link EntityManagerFactory} instance. */
|
||||
@@ -122,15 +221,7 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
properties.put(Environment.PASS, password);
|
||||
|
||||
ParsedPersistenceXmlDescriptor descriptor =
|
||||
PersistenceXmlParser.locatePersistenceUnits(properties).stream()
|
||||
.filter(unit -> PersistenceModule.PERSISTENCE_UNIT_NAME.equals(unit.getName()))
|
||||
.findFirst()
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new IllegalArgumentException(
|
||||
String.format(
|
||||
"Could not find persistence unit with name %s",
|
||||
PersistenceModule.PERSISTENCE_UNIT_NAME)));
|
||||
PersistenceXmlUtility.getParsedPersistenceXmlDescriptor();
|
||||
|
||||
extraEntityClasses.stream().map(Class::getName).forEach(descriptor::addClasses);
|
||||
return Bootstrap.getEntityManagerFactoryBuilder(descriptor, properties).build();
|
||||
@@ -171,7 +262,7 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
/** Builds a {@link JpaTransactionManagerRule} instance. */
|
||||
public JpaTransactionManagerRule build() {
|
||||
if (initScript == null) {
|
||||
initScript = SCHEMA_GOLDEN_SQL;
|
||||
initScript = GOLDEN_SCHEMA_SQL_PATH;
|
||||
}
|
||||
return new JpaTransactionManagerRule(
|
||||
initScript,
|
||||
|
||||
@@ -23,7 +23,6 @@ import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.PersistenceException;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -37,7 +36,6 @@ public class JpaTransactionManagerRuleTest {
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
|
||||
@@ -24,12 +24,12 @@ import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/** Unit tests for {@link BloomFilterConverter}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class BloomFilterConverterTest {
|
||||
|
||||
@@ -37,7 +37,6 @@ public class BloomFilterConverterTest {
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
@@ -60,7 +59,7 @@ public class BloomFilterConverterTest {
|
||||
|
||||
public TestEntity() {}
|
||||
|
||||
public TestEntity(BloomFilter<String> bloomFilter) {
|
||||
TestEntity(BloomFilter<String> bloomFilter) {
|
||||
this.bloomFilter = bloomFilter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/** Unit tests for {@link CreateAutoTimestampConverter}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class CreateAutoTimestampConverterTest {
|
||||
|
||||
@@ -35,7 +35,6 @@ public class CreateAutoTimestampConverterTest {
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
@@ -70,7 +69,7 @@ public class CreateAutoTimestampConverterTest {
|
||||
|
||||
public TestEntity() {}
|
||||
|
||||
public TestEntity(String name, CreateAutoTimestamp cat) {
|
||||
TestEntity(String name, CreateAutoTimestamp cat) {
|
||||
this.name = name;
|
||||
this.cat = cat;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package google.registry.persistence;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.PersistenceException;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/** Unit tests for {@link CurrencyUnitConverter}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class CurrencyUnitConverterTest {
|
||||
|
||||
@Rule
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class)
|
||||
.build();
|
||||
|
||||
@Test
|
||||
public void roundTripConversion() {
|
||||
TestEntity entity = new TestEntity(CurrencyUnit.EUR);
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(entity));
|
||||
assertThat(
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(
|
||||
"SELECT currency FROM \"TestEntity\" WHERE name = 'id'")
|
||||
.getResultList()))
|
||||
.containsExactly("EUR");
|
||||
TestEntity persisted =
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "id"));
|
||||
assertThat(persisted.currency).isEqualTo(CurrencyUnit.EUR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidCurrency() {
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(
|
||||
"INSERT INTO \"TestEntity\" (name, currency) VALUES('id', 'XXXX')")
|
||||
.executeUpdate());
|
||||
PersistenceException thrown =
|
||||
assertThrows(
|
||||
PersistenceException.class,
|
||||
() ->
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> jpaTm().getEntityManager().find(TestEntity.class, "id").currency));
|
||||
assertThat(thrown).hasCauseThat().hasMessageThat().isEqualTo("Unknown currency 'XXXX'");
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
|
||||
public static class TestEntity extends ImmutableObject {
|
||||
|
||||
@Id String name = "id";
|
||||
|
||||
CurrencyUnit currency;
|
||||
|
||||
public TestEntity() {}
|
||||
|
||||
TestEntity(CurrencyUnit currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.persistence;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import java.sql.Timestamp;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.format.ISODateTimeFormat;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/** Unit tests for {@link DateTimeConverter}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class DateTimeConverterTest {
|
||||
|
||||
@Rule
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder().withEntityClass(TestEntity.class).build();
|
||||
|
||||
private final DateTimeConverter converter = new DateTimeConverter();
|
||||
|
||||
@Test
|
||||
public void convertToDatabaseColumn_returnsNullIfInputIsNull() {
|
||||
assertThat(converter.convertToDatabaseColumn(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertToDatabaseColumn_convertsCorrectly() {
|
||||
DateTime dateTime = DateTime.parse("2019-09-01T01:01:01");
|
||||
assertThat(converter.convertToDatabaseColumn(dateTime).getTime())
|
||||
.isEqualTo(dateTime.getMillis());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertToEntityAttribute_returnsNullIfInputIsNull() {
|
||||
assertThat(converter.convertToEntityAttribute(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertToEntityAttribute_convertsCorrectly() {
|
||||
DateTime dateTime = DateTime.parse("2019-09-01T01:01:01Z");
|
||||
long millis = dateTime.getMillis();
|
||||
assertThat(converter.convertToEntityAttribute(new Timestamp(millis))).isEqualTo(dateTime);
|
||||
}
|
||||
|
||||
static DateTime parseDateTime(String value) {
|
||||
return ISODateTimeFormat.dateTimeNoMillis().withOffsetParsed().parseDateTime(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void converter_generatesTimestampWithNormalizedZone() {
|
||||
DateTime dt = parseDateTime("2019-09-01T01:01:01Z");
|
||||
TestEntity entity = new TestEntity("normalized_utc_time", dt);
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(entity));
|
||||
TestEntity retrievedEntity =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> jpaTm().getEntityManager().find(TestEntity.class, "normalized_utc_time"));
|
||||
assertThat(retrievedEntity.dt.toString()).isEqualTo("2019-09-01T01:01:01.000Z");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void converter_convertsNonUtcZoneCorrectly() {
|
||||
DateTime dt = parseDateTime("2019-09-01T01:01:01-05:00");
|
||||
TestEntity entity = new TestEntity("new_york_time", dt);
|
||||
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(entity));
|
||||
TestEntity retrievedEntity =
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "new_york_time"));
|
||||
assertThat(retrievedEntity.dt.toString()).isEqualTo("2019-09-01T06:01:01.000Z");
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
|
||||
private static class TestEntity extends ImmutableObject {
|
||||
|
||||
@Id String name;
|
||||
|
||||
DateTime dt;
|
||||
|
||||
public TestEntity() {}
|
||||
|
||||
TestEntity(String name, DateTime dt) {
|
||||
this.name = name;
|
||||
this.dt = dt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.persistence;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
|
||||
/** Unit tests for {@link HibernateSchemaExporter}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class HibernateSchemaExporterTest {
|
||||
@ClassRule
|
||||
public static final PostgreSQLContainer database =
|
||||
new PostgreSQLContainer(NomulusPostgreSql.getDockerTag());
|
||||
|
||||
private static HibernateSchemaExporter exporter;
|
||||
|
||||
@Rule public final TemporaryFolder tempFolder = new TemporaryFolder();
|
||||
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
exporter =
|
||||
HibernateSchemaExporter.create(
|
||||
database.getJdbcUrl(), database.getUsername(), database.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void export_succeeds() throws IOException {
|
||||
File sqlFile = tempFolder.newFile();
|
||||
exporter.export(ImmutableList.of(TestEntity.class), sqlFile);
|
||||
assertThat(Files.readAllBytes(sqlFile.toPath()))
|
||||
.isEqualTo(
|
||||
("\n"
|
||||
+ " create table \"TestEntity\" (\n"
|
||||
+ " name text not null,\n"
|
||||
+ " cu text,\n"
|
||||
+ " primary key (name)\n"
|
||||
+ " );\n")
|
||||
.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
|
||||
private static class TestEntity {
|
||||
@Id String name;
|
||||
|
||||
CurrencyUnit cu;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package google.registry.persistence;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.PostLoad;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/**
|
||||
* Unit tests for embeddable {@link Money}.
|
||||
*
|
||||
* <p>{@link Money} is a wrapper around {@link org.joda.money.BigMoney} which itself contains two
|
||||
* fields: a {@link BigDecimal} {@code amount} and a {@link CurrencyUnit} {@code currency}. When we
|
||||
* store an entity with a {@link Money} field, we would like to store it in two columns, for the
|
||||
* amount and the currency separately, so that it is easily queryable. This requires that we make
|
||||
* {@link Money} a nested embeddable object.
|
||||
*
|
||||
* <p>However becaues {@link Money} is not a class that we control, we cannot use annotation-based
|
||||
* mapping. Therefore there is no {@code JodaMoneyConverter} class. Instead, we define the mapping
|
||||
* in {@code META-INF/orm.xml}.
|
||||
*
|
||||
* <p>Also note that any entity that contains a {@link Money} should should implement a
|
||||
* {@link @PostLoad} callback that converts the amount in the {@link Money} to a scale that is
|
||||
* appropriate for the currency. This is espcially necessary for currencies like JPY where the scale
|
||||
* is 0, which is different from the default scale that {@link BigDecimal} is persisted in database.
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class JodaMoneyConverterTest {
|
||||
@Rule
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class, ComplexTestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
public void roundTripConversion() {
|
||||
Money money = Money.of(CurrencyUnit.USD, 100);
|
||||
TestEntity entity = new TestEntity(money);
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(entity));
|
||||
List<?> result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(
|
||||
"SELECT amount, currency FROM TestEntity WHERE name = 'id'")
|
||||
.getResultList());
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertThat(Arrays.asList((Object[]) result.get(0)))
|
||||
.containsExactly(
|
||||
BigDecimal.valueOf(100).setScale(CurrencyUnit.USD.getDecimalPlaces()), "USD")
|
||||
.inOrder();
|
||||
TestEntity persisted =
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "id"));
|
||||
assertThat(persisted.money).isEqualTo(money);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundTripConversionWithComplexEntity() {
|
||||
Money myMoney = Money.of(CurrencyUnit.USD, 100);
|
||||
Money yourMoney = Money.of(CurrencyUnit.GBP, 80);
|
||||
ImmutableMap<String, Money> moneyMap =
|
||||
ImmutableMap.of(
|
||||
"uno", Money.of(CurrencyUnit.EUR, 500),
|
||||
"dos", Money.ofMajor(CurrencyUnit.JPY, 2000),
|
||||
"tres", Money.of(CurrencyUnit.GBP, 20));
|
||||
ComplexTestEntity entity = new ComplexTestEntity(moneyMap, myMoney, yourMoney);
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(entity));
|
||||
List<?> result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(
|
||||
"SELECT my_amount, my_currency, your_amount, your_currency FROM"
|
||||
+ " ComplexTestEntity WHERE name = 'id'")
|
||||
.getResultList());
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertThat(Arrays.asList((Object[]) result.get(0)))
|
||||
.containsExactly(
|
||||
BigDecimal.valueOf(100).setScale(2), "USD", BigDecimal.valueOf(80).setScale(2), "GBP")
|
||||
.inOrder();
|
||||
result =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(
|
||||
"SELECT map_amount, map_currency FROM MoneyMap"
|
||||
+ " WHERE entity_name = 'id' AND map_key = 'dos'")
|
||||
.getResultList());
|
||||
ComplexTestEntity persisted =
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().find(ComplexTestEntity.class, "id"));
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
|
||||
// Note that the amount has two decimal places even though JPY is supposed to have scale 0.
|
||||
// This is due to the unfournate fact that we need to accommodate differet currencies stored
|
||||
// in the same table so that the scale has to be set to the largest (2). When a Money field is
|
||||
// persisted in an entity, the entity should always have a @PostLoad callback to convert the
|
||||
// Money to the correct scale.
|
||||
assertThat(Arrays.asList((Object[]) result.get(0)))
|
||||
.containsExactly(BigDecimal.valueOf(2000).setScale(2), "JPY")
|
||||
.inOrder();
|
||||
// Make sure that the loaded entity contains the fields exactly as they are persisted.
|
||||
assertThat(persisted.myMoney).isEqualTo(myMoney);
|
||||
assertThat(persisted.yourMoney).isEqualTo(yourMoney);
|
||||
assertThat(persisted.moneyMap).containsExactlyEntriesIn(moneyMap);
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
|
||||
public static class TestEntity extends ImmutableObject {
|
||||
|
||||
@Id String name = "id";
|
||||
|
||||
Money money;
|
||||
|
||||
public TestEntity() {}
|
||||
|
||||
TestEntity(Money money) {
|
||||
this.money = money;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "ComplexTestEntity") // Override entity name to avoid the nested class reference.
|
||||
// This entity is used to test column override for embedded fields and collections.
|
||||
public static class ComplexTestEntity extends ImmutableObject {
|
||||
|
||||
// After the entity is loaded from the database, go through the money map and make sure that
|
||||
// the scale is consistent with the currency. This is necessary for currency like JPY where
|
||||
// the scale is 0 but the amount is persisteted as BigDecimal with scale 2.
|
||||
@PostLoad
|
||||
void setCurrencyScale() {
|
||||
moneyMap
|
||||
.entrySet()
|
||||
.forEach(
|
||||
entry -> {
|
||||
Money money = entry.getValue();
|
||||
if (!money.toBigMoney().isCurrencyScale()) {
|
||||
CurrencyUnit currency = money.getCurrencyUnit();
|
||||
BigDecimal amount = money.getAmount().setScale(currency.getDecimalPlaces());
|
||||
entry.setValue(Money.of(currency, amount));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Id String name = "id";
|
||||
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(name = "MoneyMap", joinColumns = @JoinColumn(name = "entity_name"))
|
||||
@MapKeyColumn(name = "map_key")
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "value.money.amount", column = @Column(name = "map_amount")),
|
||||
@AttributeOverride(name = "value.money.currency", column = @Column(name = "map_currency"))
|
||||
})
|
||||
Map<String, Money> moneyMap;
|
||||
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "money.amount", column = @Column(name = "my_amount")),
|
||||
@AttributeOverride(name = "money.currency", column = @Column(name = "my_currency"))
|
||||
})
|
||||
Money myMoney;
|
||||
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "money.amount", column = @Column(name = "your_amount")),
|
||||
@AttributeOverride(name = "money.currency", column = @Column(name = "your_currency"))
|
||||
})
|
||||
Money yourMoney;
|
||||
|
||||
public ComplexTestEntity() {}
|
||||
|
||||
ComplexTestEntity(ImmutableMap<String, Money> moneyMap, Money myMoney, Money yourMoney) {
|
||||
this.moneyMap = moneyMap;
|
||||
this.myMoney = myMoney;
|
||||
this.yourMoney = yourMoney;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,8 @@ import org.testcontainers.containers.PostgreSQLContainer;
|
||||
/** Unit tests for {@link PersistenceModule}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class PersistenceModuleTest {
|
||||
@Rule public PostgreSQLContainer database = new PostgreSQLContainer();
|
||||
@Rule
|
||||
public PostgreSQLContainer database = new PostgreSQLContainer(NomulusPostgreSql.getDockerTag());
|
||||
|
||||
private EntityManagerFactory emf;
|
||||
|
||||
|
||||
@@ -21,12 +21,12 @@ import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/** Unit tests for {@link UpdateAutoTimestampConverter}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class UpdateAutoTimestampConverterTest {
|
||||
|
||||
@@ -34,7 +34,6 @@ public class UpdateAutoTimestampConverterTest {
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
@@ -81,7 +80,7 @@ public class UpdateAutoTimestampConverterTest {
|
||||
|
||||
public TestEntity() {}
|
||||
|
||||
public TestEntity(String name, UpdateAutoTimestamp uat) {
|
||||
TestEntity(String name, UpdateAutoTimestamp uat) {
|
||||
this.name = name;
|
||||
this.uat = uat;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.time.Instant;
|
||||
import java.time.ZonedDateTime;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -38,7 +37,6 @@ public class ZonedDateTimeConverterTest {
|
||||
public final JpaTransactionManagerRule jpaTmRule =
|
||||
new JpaTransactionManagerRule.Builder()
|
||||
.withEntityClass(TestEntity.class)
|
||||
.withProperty(Environment.HBM2DDL_AUTO, "update")
|
||||
.build();
|
||||
|
||||
private final ZonedDateTimeConverter converter = new ZonedDateTimeConverter();
|
||||
@@ -113,7 +111,7 @@ public class ZonedDateTimeConverterTest {
|
||||
|
||||
public TestEntity() {}
|
||||
|
||||
public TestEntity(String name, ZonedDateTime zdt) {
|
||||
TestEntity(String name, ZonedDateTime zdt) {
|
||||
this.name = name;
|
||||
this.zdt = zdt;
|
||||
}
|
||||
|
||||
@@ -154,6 +154,45 @@ public class IcannReportingUploadActionTest {
|
||||
new InternetAddress("recipient@example.com"),
|
||||
new InternetAddress("sender@example.com")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_quicklySkipsOverNonRetryableUploadException() throws Exception {
|
||||
runTest_nonRetryableException(
|
||||
new IOException(
|
||||
"<msg>A report for that month already exists, the cut-off date already"
|
||||
+ " passed.</msg>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_quicklySkipsOverIpWhitelistException() throws Exception {
|
||||
runTest_nonRetryableException(
|
||||
new IOException("Your IP address 25.147.130.158 is not allowed to connect"));
|
||||
}
|
||||
|
||||
private void runTest_nonRetryableException(Exception nonRetryableException) throws Exception {
|
||||
IcannReportingUploadAction action = createAction();
|
||||
when(mockReporter.send(PAYLOAD_FAIL, "a-activity-201706.csv"))
|
||||
.thenThrow(nonRetryableException)
|
||||
.thenThrow(
|
||||
new AssertionError(
|
||||
"This should never be thrown because the previous exception isn't retryable"));
|
||||
action.run();
|
||||
verify(mockReporter, times(1)).send(PAYLOAD_FAIL, "a-activity-201706.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "test-transactions-201706.csv");
|
||||
verifyNoMoreInteractions(mockReporter);
|
||||
assertThat(((FakeResponse) action.response).getPayload())
|
||||
.isEqualTo("OK, attempted uploading 2 reports");
|
||||
verify(emailService)
|
||||
.sendEmail(
|
||||
EmailMessage.create(
|
||||
"ICANN Monthly report upload summary: 1/2 succeeded",
|
||||
"Report Filename - Upload status:\n"
|
||||
+ "test-transactions-201706.csv - SUCCESS\n"
|
||||
+ "a-activity-201706.csv - FAILURE",
|
||||
new InternetAddress("recipient@example.com"),
|
||||
new InternetAddress("sender@example.com")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFail_FileNotFound() throws Exception {
|
||||
IcannReportingUploadAction action = createAction();
|
||||
|
||||
@@ -61,63 +61,40 @@ public class Spec11EmailUtilsTest {
|
||||
|
||||
private static final ImmutableList<String> FAKE_RESOURCES = ImmutableList.of("foo");
|
||||
private static final String DAILY_EMAIL_FORMAT =
|
||||
"Dear registrar partner,"
|
||||
+ ""
|
||||
+ "<p>Super Cool Registry conducts a daily analysis of all domains registered in its "
|
||||
+ "TLDs to identify potential security concerns. On 2018-07-15, the following domains "
|
||||
+ "that your registrar manages were flagged for potential security concerns:</p>"
|
||||
+ ""
|
||||
+ "<table>"
|
||||
+ "<tr><th>Domain Name</th><th>Threat Type</th></tr>"
|
||||
+ "%s"
|
||||
+ "</table>"
|
||||
+ "<p><b>Please communicate these findings to the registrant and work with the "
|
||||
+ "registrant to mitigate any security issues and have the domains delisted.</b></p>"
|
||||
+ ""
|
||||
"Dear registrar partner,<p>Super Cool Registry conducts a daily analysis of all domains"
|
||||
+ " registered in its TLDs to identify potential security concerns. On 2018-07-15, the"
|
||||
+ " following domains that your registrar manages were flagged for potential security"
|
||||
+ " concerns:</p><table><tr><th>Domain Name</th><th>Threat Type</th></tr>%s"
|
||||
+ "</table><p><b>Please communicate these findings to the registrant and work with the"
|
||||
+ " registrant to mitigate any security issues and have the domains delisted.</b></p>"
|
||||
+ "Some helpful resources for getting off a blocked list include:"
|
||||
+ "<ul><li>foo</li></ul><p>"
|
||||
+ ""
|
||||
+ "You will continue to receive daily notices when new domains managed by your registrar "
|
||||
+ "are flagged for abuse, as well as a monthly summary of all of your domains under "
|
||||
+ "management that remain flagged for abuse. Once the registrant has resolved the "
|
||||
+ "security issues and followed the steps to have his or her domain reviewed and "
|
||||
+ "delisted it will automatically be removed from our reporting.</p>"
|
||||
+ ""
|
||||
+ "<p>If you would like to change the email to which these notices are sent please "
|
||||
+ "update your abuse contact using your registrar portal account.</p>"
|
||||
+ ""
|
||||
+ "<p>If you have any questions regarding this notice, please contact "
|
||||
+ "abuse@test.com.</p>";
|
||||
+ "<ul><li>foo</li></ul><p>If you believe that any of the domains were reported in"
|
||||
+ " error, or are still receiving reports for issues that have been remediated, please"
|
||||
+ " <a href=\"https://safebrowsing.google.com/safebrowsing/report_error/?hl=en\">submit"
|
||||
+ " a request</a> to have the site reviewed.</p><p>You will continue to receive daily"
|
||||
+ " notices when new domains managed by your registrar are flagged for abuse, as well as"
|
||||
+ " a monthly summary of all of your domains under management that remain flagged for"
|
||||
+ " abuse.</p><p>If you would like to change the email to which these notices are sent"
|
||||
+ " please update your abuse contact using your registrar portal account.</p><p>If you"
|
||||
+ " have any questions regarding this notice, please contact abuse@test.com.</p>";
|
||||
private static final String MONTHLY_EMAIL_FORMAT =
|
||||
"Dear registrar partner,"
|
||||
+ ""
|
||||
+ "<p>Super Cool Registry previously notified you when the following "
|
||||
+ "domains managed by your registrar were flagged for potential security concerns.</p>"
|
||||
+ "<p>The following domains that you manage continue to be flagged by our analysis "
|
||||
+ "for potential security concerns. This may be because the registrants have not "
|
||||
+ "completed the requisite steps to mitigate the potential security abuse and/or have "
|
||||
+ "it reviewed and delisted.</p>"
|
||||
+ ""
|
||||
+ "<table>"
|
||||
+ "<tr><th>Domain Name</th><th>Threat Type</th></tr>"
|
||||
+ "%s"
|
||||
+ "</table>"
|
||||
+ ""
|
||||
+ "<p>Please work with the registrant to mitigate any security issues "
|
||||
+ "and have the domains delisted.</p>"
|
||||
+ ""
|
||||
+ "Some helpful resources for getting off a blocked list include:"
|
||||
+ "<ul><li>foo</li></ul><p>"
|
||||
+ ""
|
||||
+ "You will continue to receive a monthly summary of all domains managed by your "
|
||||
+ "registrar that remain on our lists of potential security threats. You will "
|
||||
+ "additionally receive a daily notice when any new domains that are added to these "
|
||||
+ "lists. Once the registrant has resolved the security issues and followed the steps to "
|
||||
+ "have his or her domain reviewed and delisted it will automatically be removed from "
|
||||
+ "our monthly reporting.</p>"
|
||||
+ ""
|
||||
+ "<p>If you have any questions regarding this notice, please contact "
|
||||
+ "abuse@test.com.</p>";
|
||||
"Dear registrar partner,<p>Super Cool Registry previously notified you when the following"
|
||||
+ " domains managed by your registrar were flagged for potential security"
|
||||
+ " concerns.</p><p>The following domains that you manage continue to be flagged by our"
|
||||
+ " analysis for potential security concerns. This may be because the registrants have"
|
||||
+ " not completed the requisite steps to mitigate the potential security abuse and/or"
|
||||
+ " have it reviewed and delisted.</p><table><tr><th>Domain Name</th><th>Threat"
|
||||
+ " Type</th></tr>%s</table><p>Please work with the registrant to mitigate any security"
|
||||
+ " issues and have the domains delisted. If you believe that any of the domains were"
|
||||
+ " reported in error, or are still receiving reports for issues that have been"
|
||||
+ " remediated, please <a"
|
||||
+ " href=\"https://safebrowsing.google.com/safebrowsing/report_error/?hl=en\">submit a"
|
||||
+ " request</a> to have the site reviewed.</p>Some helpful resources for getting off a"
|
||||
+ " blocked list include:<ul><li>foo</li></ul><p>You will continue to receive a monthly"
|
||||
+ " summary of all domains managed by your registrar that remain on our lists of"
|
||||
+ " potential security threats. You will also receive a daily notice when any new"
|
||||
+ " domains are added to these lists.</p><p>If you have any questions regarding this"
|
||||
+ " notice, please contact abuse@test.com.</p>";
|
||||
|
||||
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright 2018 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.schema.integration;
|
||||
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Sets.SetView;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import io.github.classgraph.ClassGraph;
|
||||
import io.github.classgraph.ScanResult;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
/**
|
||||
* Verifies that all tests that depends on the Cloud SQL schema are included in the project's
|
||||
* sqlIntegrationTest suite. Names of the test classes is set to the 'test.sqlIntergrationTests'
|
||||
* system property as a comma-separated string.
|
||||
*
|
||||
* <p>A test is deemed dependent on the SQL schema iff it has a field with type {@link
|
||||
* JpaTransactionManagerRule}.
|
||||
*/
|
||||
// TODO(weiminyu): consider generating a TestSuite class instead.
|
||||
@RunWith(JUnit4.class)
|
||||
public class SqlIntegrationMembershipTest {
|
||||
|
||||
@Test
|
||||
public void sqlIntegrationMembershipComplete() {
|
||||
ImmutableSet<String> sqlDependentTests;
|
||||
try (ScanResult scanResult =
|
||||
new ClassGraph().enableAnnotationInfo().whitelistPackages("google.registry").scan()) {
|
||||
sqlDependentTests =
|
||||
scanResult.getClassesWithAnnotation(RunWith.class.getName()).stream()
|
||||
.filter(clazz -> clazz.getSimpleName().endsWith("Test"))
|
||||
.map(clazz -> clazz.loadClass())
|
||||
.filter(SqlIntegrationMembershipTest::isSqlDependent)
|
||||
.map(Class::getName)
|
||||
.collect(ImmutableSet.toImmutableSet());
|
||||
}
|
||||
ImmutableSet<String> declaredTests =
|
||||
Stream.of(SqlIntegrationTestSuite.class.getAnnotation(SuiteClasses.class).value())
|
||||
.map(Class::getName)
|
||||
.collect(ImmutableSet.toImmutableSet());
|
||||
SetView<String> undeclaredTests = Sets.difference(sqlDependentTests, declaredTests);
|
||||
assertWithMessage(
|
||||
"Undeclared sql-dependent tests found. "
|
||||
+ "Please add them to SqlIntegrationTestSuite.java.")
|
||||
.that(undeclaredTests)
|
||||
.isEmpty();
|
||||
SetView<String> unnecessaryDeclarations = Sets.difference(declaredTests, sqlDependentTests);
|
||||
assertWithMessage("Found tests that should not be included in SqlIntegrationTestSuite.java.")
|
||||
.that(unnecessaryDeclarations)
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
private static boolean isSqlDependent(Class<?> testClass) {
|
||||
return Stream.of(testClass.getDeclaredFields())
|
||||
.map(Field::getType)
|
||||
.anyMatch(JpaTransactionManagerRule.class::equals);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright 2018 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.schema.integration;
|
||||
|
||||
import google.registry.model.registry.RegistryLockDaoTest;
|
||||
import google.registry.model.tmch.ClaimsListDaoTest;
|
||||
import google.registry.model.transaction.JpaTransactionManagerImplTest;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRuleTest;
|
||||
import google.registry.persistence.BloomFilterConverterTest;
|
||||
import google.registry.persistence.CreateAutoTimestampConverterTest;
|
||||
import google.registry.persistence.CurrencyUnitConverterTest;
|
||||
import google.registry.persistence.DateTimeConverterTest;
|
||||
import google.registry.persistence.JodaMoneyConverterTest;
|
||||
import google.registry.persistence.UpdateAutoTimestampConverterTest;
|
||||
import google.registry.persistence.ZonedDateTimeConverterTest;
|
||||
import google.registry.schema.tld.PremiumListDaoTest;
|
||||
import google.registry.ui.server.registrar.RegistryLockGetActionTest;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
/**
|
||||
* Groups all tests that may depends on Cloud SQL schema. They will be run for server-schema
|
||||
* compatibility check.
|
||||
*
|
||||
* <p>Schema dependency is approximated by the use of {@link
|
||||
* google.registry.model.transaction.JpaTransactionManagerRule}.
|
||||
*
|
||||
* @see SqlIntegrationMembershipTest
|
||||
*/
|
||||
// TODO(weiminyu): refactor JpaTransactionManagerRule to eliminate false positives.
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({
|
||||
BloomFilterConverterTest.class,
|
||||
ClaimsListDaoTest.class,
|
||||
CreateAutoTimestampConverterTest.class,
|
||||
CurrencyUnitConverterTest.class,
|
||||
DateTimeConverterTest.class,
|
||||
JodaMoneyConverterTest.class,
|
||||
JpaTransactionManagerImplTest.class,
|
||||
JpaTransactionManagerRuleTest.class,
|
||||
PremiumListDaoTest.class,
|
||||
RegistryLockDaoTest.class,
|
||||
RegistryLockGetActionTest.class,
|
||||
UpdateAutoTimestampConverterTest.class,
|
||||
ZonedDateTimeConverterTest.class
|
||||
})
|
||||
public class SqlIntegrationTestSuite {}
|
||||
@@ -21,7 +21,6 @@ import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||
import java.math.BigDecimal;
|
||||
import javax.persistence.PersistenceException;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -68,16 +67,13 @@ public class PremiumListDaoTest {
|
||||
@Test
|
||||
public void saveNew_throwsWhenPremiumListAlreadyExists() {
|
||||
PremiumListDao.saveNew(PremiumList.create("testlist", CurrencyUnit.USD, TEST_PRICES));
|
||||
PersistenceException thrown =
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
PersistenceException.class,
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
PremiumListDao.saveNew(
|
||||
PremiumList.create("testlist", CurrencyUnit.USD, TEST_PRICES)));
|
||||
assertThat(thrown)
|
||||
.hasCauseThat()
|
||||
.hasMessageThat()
|
||||
.contains("A premium list of this name already exists");
|
||||
assertThat(thrown).hasMessageThat().contains("A premium list of this name already exists");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user