mirror of
https://github.com/google/nomulus
synced 2026-06-09 16:33:02 +00:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9479e1e8b9 | |||
| 110bd9c057 | |||
| 2ae5aba7ff | |||
| b878e5acc1 | |||
| 4d0409c924 | |||
| 0292887cb9 | |||
| 464f6ba90a | |||
| 0ab0a8c2e6 | |||
| 2cc4e5fa94 | |||
| 47a890253e | |||
| b452b0628d | |||
| 5dfd96d26d | |||
| e2a673d914 | |||
| bf29d159f9 | |||
| e17cb52bf7 | |||
| 7352f9b4a6 | |||
| 5da48184f9 | |||
| 5bd2ccd210 | |||
| 8fd5ab2bec | |||
| 30f6113b05 | |||
| bd48041961 | |||
| 39ceda628c | |||
| 0e9b75e5e9 | |||
| c1207464d8 | |||
| 62eab98921 | |||
| 633dd887f4 | |||
| 650f1fdd52 | |||
| b0f6a498fd | |||
| 77590dcd8e | |||
| 29e4d8de05 | |||
| 242a560f20 | |||
| 3903abd9de | |||
| 8371cb838c | |||
| 8dd6797614 | |||
| 730f108e13 | |||
| e5bafddd2f | |||
| 82f51accbd | |||
| 6536631857 | |||
| 1be92968bf | |||
| 0564b207f2 | |||
| 8afc4f4d3d | |||
| 888bc158fe | |||
| 25ee92b5d8 | |||
| cf507dad6d | |||
| 32d5940be3 | |||
| 82fa3d7349 | |||
| 07239710ef | |||
| 0e8724a48f | |||
| 8332664af9 | |||
| 39abee6279 | |||
| 6daf72a54e |
@@ -4,3 +4,6 @@ python/
|
||||
.*/
|
||||
repos/**
|
||||
**/.idea/
|
||||
*.jar
|
||||
!third_party/**/*.jar
|
||||
!/gradle/wrapper/**/*.jar
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Nomulus
|
||||
|
||||
| Internal Build | FOSS Build | License | Code Search |
|
||||
|----------------|------------|---------|-------------|
|
||||
|[](https://storage.googleapis.com/domain-registry-kokoro/index.html)|[](https://travis-ci.org/google/nomulus)|[](https://github.com/jianglai/nomulus/blob/master/LICENSE)|[](https://sourcegraph.com/github.com/google/nomulus)|
|
||||
| Internal Build | FOSS Build | LGTM | License | Code Search |
|
||||
|----------------|------------|------|---------|-------------|
|
||||
|[](https://storage.googleapis.com/domain-registry-kokoro/index.html)|[](https://travis-ci.org/google/nomulus)|[](https://lgtm.com/projects/g/google/nomulus/alerts/)|[](https://github.com/google/nomulus/blob/master/LICENSE)|[](https://sourcegraph.com/github.com/google/nomulus)|
|
||||
|
||||

|
||||
|
||||
|
||||
+22
-2
@@ -1,3 +1,17 @@
|
||||
// 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.
|
||||
|
||||
def environments = ['production', 'sandbox', 'alpha', 'crash']
|
||||
|
||||
def projects = ['production': 'domain-registry',
|
||||
@@ -61,7 +75,13 @@ if (project.path == ":services:default") {
|
||||
|
||||
appengine {
|
||||
deploy {
|
||||
project = gcpProject
|
||||
// appengineDeployAll task requires the version to be set. So,
|
||||
// this config lets gcloud select a version name when deploying
|
||||
// to alpha from our workstation.
|
||||
if (environment != 'production' && environment != 'sandbox') {
|
||||
version = 'GCLOUD_CONFIG'
|
||||
}
|
||||
projectId = gcpProject
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +89,6 @@ dependencies {
|
||||
compile project(':core')
|
||||
}
|
||||
|
||||
rootProject.deploy.dependsOn appengineDeploy
|
||||
rootProject.deploy.dependsOn appengineDeployAll
|
||||
rootProject.stage.dependsOn appengineStage
|
||||
appengineDeploy.dependsOn rootProject.verifyDeployment
|
||||
|
||||
+84
-6
@@ -1,5 +1,19 @@
|
||||
// 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.
|
||||
|
||||
buildscript {
|
||||
if (project.disableDependencyLocking.toBoolean() == false) {
|
||||
if (rootProject.enableDependencyLocking.toBoolean()) {
|
||||
// Lock buildscript dependencies.
|
||||
configurations.classpath {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
@@ -7,7 +21,7 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.google.cloud.tools:appengine-gradle-plugin:1.3.3'
|
||||
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.0.1'
|
||||
classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.6.1"
|
||||
classpath 'org.sonatype.aether:aether-api:1.13.1'
|
||||
classpath 'org.sonatype.aether:aether-impl:1.13.1'
|
||||
@@ -32,6 +46,10 @@ plugins {
|
||||
id 'com.diffplug.gradle.spotless' version '3.18.0'
|
||||
}
|
||||
|
||||
wrapper {
|
||||
distributionType = Wrapper.DistributionType.ALL
|
||||
}
|
||||
|
||||
apply plugin: google.registry.gradle.plugin.ReportUploaderPlugin
|
||||
|
||||
reportUploader {
|
||||
@@ -57,6 +75,19 @@ reportUploader {
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
apply from: 'dependency_lic.gradle'
|
||||
|
||||
// Custom task to run checkLicense in buildSrc, which is not triggered
|
||||
// by root project tasks. A shell task is used because buildSrc tasks
|
||||
// cannot be referenced in the same way as tasks from a regular included
|
||||
// build.
|
||||
task checkBuildSrcLicense(type:Exec) {
|
||||
workingDir "${rootDir}/buildSrc"
|
||||
commandLine '../gradlew', 'checkLicense'
|
||||
}
|
||||
tasks.checkLicense.dependsOn(tasks.checkBuildSrcLicense)
|
||||
tasks.build.dependsOn(tasks.checkLicense)
|
||||
|
||||
// Provide defaults for all of the project properties.
|
||||
|
||||
// showAllOutput: boolean. If true, dump all test output during the build.
|
||||
@@ -138,16 +169,17 @@ subprojects {
|
||||
}
|
||||
}
|
||||
|
||||
if (rootProject.disableDependencyLocking.toBoolean() == false) {
|
||||
if (rootProject.enableDependencyLocking.toBoolean()) {
|
||||
buildscript {
|
||||
// Lock buildscript dependencies.
|
||||
configurations.classpath {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
}
|
||||
// Lock application dependencies.
|
||||
dependencyLocking {
|
||||
lockAllConfigurations()
|
||||
// Lock application dependencies except for the gradle-license-report
|
||||
// plugin. See dependency_lic.gradle for more information.
|
||||
configurations.findAll { it.name != 'dependencyLicenseReport' }.each {
|
||||
it.resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,3 +255,49 @@ subprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task checkDependenciesDotGradle {
|
||||
def buildSrcDepsFile = File.createTempFile('buildSrc', 'deps')
|
||||
buildSrcDepsFile.deleteOnExit()
|
||||
dependsOn createGetBuildSrcDirectDepsTask(buildSrcDepsFile)
|
||||
|
||||
doLast {
|
||||
Set<String> depsInUse = []
|
||||
allprojects {
|
||||
configurations.all {
|
||||
it.dependencies.findAll { it.group != null }.each {
|
||||
// Note: .toString() is required since GString should
|
||||
// not be mixed with Java Strings.
|
||||
depsInUse.add("${it.group}:${it.name}".toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
if (buildSrcDepsFile.exists()) {
|
||||
depsInUse.addAll(buildSrcDepsFile.readLines())
|
||||
}
|
||||
def unusedDeps =
|
||||
rootProject.dependencyMap.keySet()
|
||||
.findAll { !depsInUse.contains(it) }
|
||||
.toSorted()
|
||||
|
||||
if (unusedDeps.isEmpty()) {
|
||||
return
|
||||
}
|
||||
logger.error(
|
||||
"Unused dependencies in dependencies.gradle:\n${unusedDeps.toListString()}")
|
||||
throw new IllegalStateException(
|
||||
"The dependencies.gradle file should only contain direct dependencies.")
|
||||
}
|
||||
}
|
||||
tasks.build.dependsOn(tasks.checkDependenciesDotGradle)
|
||||
|
||||
def createGetBuildSrcDirectDepsTask(outputFileName) {
|
||||
return tasks
|
||||
.create(
|
||||
"getBuildSrcDeps_${java.util.UUID.randomUUID()}".toString(),
|
||||
Exec) {
|
||||
workingDir "${rootDir}/buildSrc"
|
||||
commandLine '../gradlew', 'exportDenpendencies',
|
||||
"-PdependencyExportFile=${outputFileName}"
|
||||
}
|
||||
}
|
||||
|
||||
+35
-2
@@ -1,5 +1,19 @@
|
||||
// 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.
|
||||
|
||||
buildscript {
|
||||
if (rootProject.disableDependencyLocking.toBoolean() == false) {
|
||||
if (project.enableDependencyLocking.toBoolean()) {
|
||||
// Lock buildscript dependencies.
|
||||
configurations.classpath {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
@@ -18,7 +32,7 @@ plugins {
|
||||
id 'com.diffplug.gradle.spotless' version '3.18.0'
|
||||
}
|
||||
|
||||
if (rootProject.disableDependencyLocking.toBoolean() == false) {
|
||||
if (rootProject.enableDependencyLocking.toBoolean()) {
|
||||
// Lock application dependencies.
|
||||
dependencyLocking {
|
||||
lockAllConfigurations()
|
||||
@@ -38,6 +52,7 @@ repositories {
|
||||
}
|
||||
|
||||
apply from: '../dependencies.gradle'
|
||||
apply from: '../dependency_lic.gradle'
|
||||
apply from: '../java_common.gradle'
|
||||
|
||||
sourceSets {
|
||||
@@ -74,3 +89,21 @@ gradle.projectsEvaluated {
|
||||
options.compilerArgs << "-Xlint:unchecked"
|
||||
}
|
||||
}
|
||||
|
||||
task exportDenpendencies {
|
||||
def outputFileProperty = 'dependencyExportFile'
|
||||
def output = project.hasProperty(outputFileProperty)
|
||||
? new PrintStream(
|
||||
new File(project.getProperty(outputFileProperty)))
|
||||
: System.out
|
||||
|
||||
doLast {
|
||||
project.configurations.all {
|
||||
it.dependencies.findAll {
|
||||
it.group != null
|
||||
}.each {
|
||||
output.println("${it.group}:${it.name}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
disableDependencyLocking=false
|
||||
enableDependencyLocking=false
|
||||
|
||||
@@ -25,6 +25,53 @@ by Joshua Bloch in his book Effective Java -->
|
||||
<property name="message" value='TODO is preferred to FIXME. e.g. "TODO(johndoe): Refactor when v2 is released."' />
|
||||
</module>
|
||||
|
||||
<!-- Checks that String.toUpper/LowerCase() is never used without locale. -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="\.to(Upper|Lower)Case\(\)"/>
|
||||
<property name="message" value="String.toUpper/LowerCase() can have unexpected results depending on locale. Either set the locale explicitly - e.g., toUpperCase(Locale.ENGLISH) - or use Ascii.toUpper/LowerCase(...) instead." />
|
||||
</module>
|
||||
|
||||
<!-- Checks that DateTime.now(...) is always passed a DateTimeZone parameter. -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="DateTime\.now\(\)"/>
|
||||
<property name="message" value="DateTime.now() must be called with a DateTimeZone parameter, e.g. DateTime.now(UTC)" />
|
||||
</module>
|
||||
|
||||
<!-- Checks that Javadoc does not include a malformed @see tag. -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value='@see\s\"http(|s)://'/>
|
||||
<property name="message" value='Your Javadocs appear to use invalid <a> tag syntax in @see tags. Please use the correct syntax: @see <a href="http(s)://your_url">url_description</a>'/>
|
||||
</module>
|
||||
|
||||
<!-- Checks that our Ofy wrapper is used instead of the "real" ofy(). -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="com\.googlecode\.objectify\.ObjectifyService\.ofy"/>
|
||||
<property name="message" value="Use google.registry.model.ofy.ObjectifyService.ofy(). Do not use com.googlecode.objectify.v4.ObjectifyService.ofy()."/>
|
||||
</module>
|
||||
|
||||
<!-- Checks that java.util.Optional is used instead of Guava's Optional. -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="com\.google\.common\.base\.Optional"/>
|
||||
<property name="message" value="Use java.util.Optional instead of Guava's Optional."/>
|
||||
</module>
|
||||
|
||||
<!-- Checks that our backport JUnit exception assertion methods are used instead of the ones slated for release in JUnit 4.13. -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="org\.junit\.Assert\.(assert|expect)Throws"/>
|
||||
<property name="message" value="Use the exception assertion methods in google.registry.testing.JUnitBackports instead of those in JUnit."/>
|
||||
</module>
|
||||
|
||||
<!-- Checks that the deprecated ExpectedException is not used. -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="org\.junit\.rules\.ExpectedException"/>
|
||||
<property name="message" value="Use assertThrows and expectThrows from JUnitBackports instead of the deprecated methods on ExpectedException."/>
|
||||
</module>
|
||||
|
||||
<!-- Checks that the deprecated MockitoJUnitRunner is not used. -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="MockitoJUnitRunner"/>
|
||||
<property name="message" value="MockitoJUnitRunner is deprecated. Use @RunWith(JUnit4.class) and MockitoRule instead."/>
|
||||
</module>
|
||||
|
||||
<!-- All Java AST specific tests live under TreeWalker module. -->
|
||||
<module name="TreeWalker">
|
||||
|
||||
@@ -9,4 +9,6 @@
|
||||
<suppress files="[/\\].*[/\\]generated.*[/\\]" checks="."/>
|
||||
<!-- Ignore Javadoc checks in test files -->
|
||||
<suppress files="[/\\].*[/\\]src/test/java/.*[/\\]" checks="JavadocType"/>
|
||||
<!-- ofy() regex check doesn't apply to these files -->
|
||||
<suppress files="AugmentedDeleter.java|AugmentedSaver.java|Ofy.java" checks="RegexpSingleline"/>
|
||||
</suppressions>
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
{
|
||||
"allowedLicenses": [
|
||||
{
|
||||
"moduleLicense": "Apache Software License, Version 1.1"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache 2"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache-2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache License 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache License v2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache License, Version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache Software License - Version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The Apache License, Version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The Apache Software License, Version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The Apache Software License, version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Bouncy Castle Licence"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD 2-Clause License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD 2-Clause license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD 3-clause"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD 3-Clause"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD 3-Clause License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The 3-Clause BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD New License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD New license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD style"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "New BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Revised BSD"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "CC0 1.0 Universal License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "CDDL 1.1"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "CDDL + GPLv2 with classpath exception"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "https://glassfish.java.net/public/CDDL+GPL_1_1.html, https://glassfish.java.net/public/CDDL+GPL_1_1.html"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "CDDL+GPL License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "\\n Dual license consisting of the CDDL v1.1 and GPL v2\\n "
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License - Version 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License - v 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Google App Engine Terms of Service"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU General Public License, version 2, with the Classpath Exception"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU GENERAL PUBLIC LICENSE, Version 2 + Classpath Exception"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GPL2 w/ CPE"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU Lesser Public License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The Go license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GWT Terms"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "ICU License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The JSON License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "LGPL-2.1+"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "LGPL, version 2.1"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "MIT"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "MIT License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "MIT license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The MIT License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The MIT license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Mozilla Public License Version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Public Domain"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "PUBLIC DOMAIN"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The W3C Software License"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"bundles" : [
|
||||
{
|
||||
"bundleName" : "Apache 2.0",
|
||||
"licenseName" : "Apache 2.0",
|
||||
"licenseUrl" : "http://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"bundleName" : "MIT License",
|
||||
"licenseName" : "MIT License",
|
||||
"licenseUrl" : "http://www.opensource.org/licenses/mit-license.php"
|
||||
}
|
||||
],
|
||||
"transformationRules" : [
|
||||
{
|
||||
"bundleName" : "Apache 2.0",
|
||||
"licenseUrlPattern" : "http://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"bundleName" : "Apache 2.0",
|
||||
"licenseUrlPattern" : "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"bundleName" : "MIT License",
|
||||
"licenseUrlPattern" : "http://www.opensource.org/licenses/mit-license.php"
|
||||
},
|
||||
{
|
||||
"bundleName" : "MIT License",
|
||||
"licenseUrlPattern" : "http://www.opensource.org/licenses/MIT"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -76,12 +76,17 @@ PRESUBMITS = {
|
||||
# License check
|
||||
PresubmitCheck(
|
||||
r".*Copyright 20\d{2} The Nomulus Authors\. All Rights Reserved\.",
|
||||
("java", "js", "soy", "sql", "py", "sh"), {
|
||||
("java", "js", "soy", "sql", "py", "sh", "gradle"), {
|
||||
".git", "/build/", "/generated/", "node_modules/",
|
||||
"JUnitBackports.java"
|
||||
}, REQUIRED):
|
||||
"File did not include the license header.",
|
||||
|
||||
# Files must end in a newline
|
||||
PresubmitCheck(r".*\n$", ("java", "js", "soy", "sql", "py", "sh", "gradle"),
|
||||
{"node_modules/"}, REQUIRED):
|
||||
"Source files must end in a newline.",
|
||||
|
||||
# System.(out|err).println should only appear in tools/
|
||||
PresubmitCheck(
|
||||
r".*\bSystem\.(out|err)\.print", "java", {
|
||||
@@ -158,7 +163,6 @@ PRESUBMITS = {
|
||||
|
||||
|
||||
def get_files():
|
||||
result = []
|
||||
for root, dirnames, filenames in os.walk("."):
|
||||
for filename in filenames:
|
||||
yield os.path.join(root, filename)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
FROM gcr.io/distroless/java:debug
|
||||
ADD build/libs/nomulus.jar /nomulus.jar
|
||||
ENTRYPOINT ["/usr/bin/java", "-jar", "/nomulus.jar"]
|
||||
+29
-69
@@ -1,3 +1,17 @@
|
||||
// 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.
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
}
|
||||
@@ -11,6 +25,7 @@ def screenshotsForGoldensDir = "${project.buildDir}/screenshots_for_goldens"
|
||||
def newGoldensDir = "${project.buildDir}/new_golden_images"
|
||||
def goldensDir =
|
||||
"${javaTestDir}/google/registry/webdriver/goldens/chrome-linux"
|
||||
def jsDir = "${project.projectDir}/src/main/javascript"
|
||||
|
||||
// Tests that conflict with (mostly unidentified) members of the main test
|
||||
// suite. It is unclear if they are offenders (i.e., those that pollute global
|
||||
@@ -82,14 +97,14 @@ sourceSets {
|
||||
}
|
||||
}
|
||||
|
||||
processTestResources {
|
||||
exclude '**/webdriver/*'
|
||||
}
|
||||
|
||||
configurations {
|
||||
css
|
||||
jaxb
|
||||
soy
|
||||
// Label for all dependencies inherited from Bazel build but not used in
|
||||
// either compile or testRuntime. However, they may be needed at runtime.
|
||||
// TODO(weiminyu): identify runtime dependencies and remove the rest.
|
||||
maybeRuntime
|
||||
closureCompiler
|
||||
|
||||
// Exclude non-canonical servlet-api jars. Our AppEngine deployment uses
|
||||
@@ -125,53 +140,38 @@ dependencies {
|
||||
"${rootDir}/third_party/objectify/v4_1/objectify-4.1.3.jar")
|
||||
testImplementation project(':third_party')
|
||||
|
||||
testRuntime files(sourceSets.test.resources.srcDirs)
|
||||
|
||||
compile deps['com.beust:jcommander']
|
||||
compile deps['com.google.api-client:google-api-client']
|
||||
maybeRuntime deps['com.google.api-client:google-api-client-appengine']
|
||||
maybeRuntime deps['com.google.api-client:google-api-client-jackson2']
|
||||
compile deps['com.google.monitoring-client:metrics']
|
||||
compile deps['com.google.monitoring-client:stackdriver']
|
||||
compile deps['com.google.api-client:google-api-client-java6']
|
||||
maybeRuntime deps['com.google.api-client:google-api-client-servlet']
|
||||
compile deps['com.google.apis:google-api-services-admin-directory']
|
||||
compile deps['com.google.apis:google-api-services-appengine']
|
||||
compile deps['com.google.apis:google-api-services-bigquery']
|
||||
maybeRuntime deps['com.google.apis:google-api-services-clouddebugger']
|
||||
compile deps['com.google.apis:google-api-services-cloudkms']
|
||||
maybeRuntime deps['com.google.apis:google-api-services-cloudresourcemanager']
|
||||
compile deps['com.google.apis:google-api-services-dataflow']
|
||||
compile deps['com.google.apis:google-api-services-dns']
|
||||
compile deps['com.google.apis:google-api-services-drive']
|
||||
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']
|
||||
maybeRuntime deps['com.google.apis:google-api-services-storage']
|
||||
testCompileOnly deps['com.google.appengine:appengine-api-1.0-sdk']
|
||||
maybeRuntime deps['com.google.appengine:appengine-api-labs']
|
||||
maybeRuntime deps['com.google.appengine:appengine-api-stubs']
|
||||
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']
|
||||
compile deps['com.google.appengine.tools:appengine-pipeline']
|
||||
compile deps['com.google.appengine:appengine-remote-api']
|
||||
maybeRuntime deps['com.google.appengine:appengine-tools-sdk']
|
||||
compile deps['com.google.auth:google-auth-library-credentials']
|
||||
compile deps['com.google.auth:google-auth-library-oauth2-http']
|
||||
maybeRuntime deps['com.google.auto:auto-common']
|
||||
maybeRuntime deps['com.google.auto.factory:auto-factory']
|
||||
compile deps['com.google.code.gson:gson']
|
||||
compile deps['com.google.auto.value:auto-value-annotations']
|
||||
maybeRuntime deps['com.google.cloud.bigdataoss:gcsio']
|
||||
maybeRuntime deps['com.google.cloud.bigdataoss:util']
|
||||
compile deps['com.google.code.findbugs:jsr305']
|
||||
compile deps['com.google.dagger:dagger']
|
||||
maybeRuntime deps['com.google.dagger:dagger-producers']
|
||||
compile deps['com.google.errorprone:error_prone_annotations']
|
||||
maybeRuntime deps['com.google.errorprone:javac-shaded']
|
||||
compile deps['com.google.flogger:flogger']
|
||||
runtime deps['com.google.flogger:flogger-system-backend']
|
||||
maybeRuntime deps['com.google.gdata:core']
|
||||
maybeRuntime deps['com.google.googlejavaformat:google-java-format']
|
||||
compile deps['com.google.guava:guava']
|
||||
gradleLint.ignore('unused-dependency') {
|
||||
compile deps['com.google.gwt:gwt-user']
|
||||
@@ -180,89 +180,48 @@ dependencies {
|
||||
compile deps['com.google.http-client:google-http-client-appengine']
|
||||
compile deps['com.google.http-client:google-http-client-jackson2']
|
||||
compile deps['com.google.oauth-client:google-oauth-client']
|
||||
maybeRuntime deps['com.google.oauth-client:google-oauth-client-appengine']
|
||||
compile deps['com.google.oauth-client:google-oauth-client-java6']
|
||||
compile deps['com.google.oauth-client:google-oauth-client-jetty']
|
||||
maybeRuntime deps['com.google.oauth-client:google-oauth-client-servlet']
|
||||
maybeRuntime deps['com.google.protobuf:protobuf-java']
|
||||
compile deps['com.google.re2j:re2j']
|
||||
compile deps['com.google.template:soy']
|
||||
maybeRuntime deps['com.googlecode.charts4j:charts4j']
|
||||
compile deps['com.googlecode.json-simple:json-simple']
|
||||
compile deps['com.jcraft:jsch']
|
||||
maybeRuntime deps['com.jcraft:jzlib']
|
||||
maybeRuntime deps['com.squareup:javapoet']
|
||||
maybeRuntime deps['com.squareup:javawriter']
|
||||
maybeRuntime deps['com.sun.activation:javax.activation']
|
||||
maybeRuntime deps['com.thoughtworks.paranamer:paranamer']
|
||||
testCompile deps['com.thoughtworks.qdox:qdox']
|
||||
maybeRuntime deps['commons-codec:commons-codec']
|
||||
maybeRuntime deps['commons-logging:commons-logging']
|
||||
compile deps['dnsjava:dnsjava']
|
||||
maybeRuntime deps['io.netty:netty-buffer']
|
||||
maybeRuntime deps['io.netty:netty-codec']
|
||||
maybeRuntime deps['io.netty:netty-codec-http']
|
||||
maybeRuntime deps['io.netty:netty-common']
|
||||
maybeRuntime deps['io.netty:netty-handler']
|
||||
maybeRuntime deps['io.netty:netty-resolver']
|
||||
maybeRuntime deps['io.netty:netty-tcnative']
|
||||
maybeRuntime deps['io.netty:netty-tcnative-boringssl-static']
|
||||
maybeRuntime deps['io.netty:netty-transport']
|
||||
maybeRuntime deps['it.unimi.dsi:fastutil']
|
||||
maybeRuntime deps['javax.annotation:jsr250-api']
|
||||
runtime deps['org.glassfish.jaxb:jaxb-runtime']
|
||||
testCompile deps['javax.annotation:jsr250-api']
|
||||
compile deps['javax.inject:javax.inject']
|
||||
compile deps['javax.mail:mail']
|
||||
compile deps['javax.servlet:servlet-api']
|
||||
compile deps['javax.xml.bind:jaxb-api']
|
||||
maybeRuntime deps['javax.xml.soap:javax.xml.soap-api']
|
||||
compile deps['jline:jline']
|
||||
compile deps['joda-time:joda-time']
|
||||
compile deps['org.apache.avro:avro']
|
||||
maybeRuntime deps['org.apache.beam:beam-runners-direct-java']
|
||||
testCompile deps['org.apache.beam:beam-runners-direct-java']
|
||||
compile deps['org.apache.beam:beam-runners-google-cloud-dataflow-java']
|
||||
maybeRuntime deps['org.apache.beam:beam-sdks-common-runner-api']
|
||||
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']
|
||||
maybeRuntime deps['org.apache.commons:commons-compress']
|
||||
testCompile deps['org.apache.commons:commons-text']
|
||||
maybeRuntime deps['org.apache.ftpserver:ftplet-api']
|
||||
testCompile deps['org.apache.ftpserver:ftplet-api']
|
||||
maybeRuntime deps['org.apache.ftpserver:ftpserver-core']
|
||||
testCompile deps['org.apache.ftpserver:ftpserver-core']
|
||||
compile deps['org.apache.httpcomponents:httpclient']
|
||||
compile deps['org.apache.httpcomponents:httpcore']
|
||||
maybeRuntime deps['org.apache.mina:mina-core']
|
||||
maybeRuntime deps['org.apache.sshd:sshd-core']
|
||||
testCompile deps['org.apache.sshd:sshd-core']
|
||||
maybeRuntime deps['org.apache.sshd:sshd-scp']
|
||||
testCompile deps['org.apache.sshd:sshd-scp']
|
||||
maybeRuntime deps['org.apache.sshd:sshd-sftp']
|
||||
testCompile deps['org.apache.sshd:sshd-sftp']
|
||||
maybeRuntime deps['org.apache.tomcat:tomcat-annotations-api']
|
||||
testCompile deps['org.apache.tomcat:tomcat-annotations-api']
|
||||
compile deps['org.bouncycastle:bcpg-jdk15on']
|
||||
testCompile deps['org.bouncycastle:bcpkix-jdk15on']
|
||||
compile deps['org.bouncycastle:bcprov-jdk15on']
|
||||
maybeRuntime deps['org.codehaus.jackson:jackson-core-asl']
|
||||
maybeRuntime deps['org.codehaus.jackson:jackson-mapper-asl']
|
||||
compile deps['org.joda:joda-money']
|
||||
compile deps['org.json:json']
|
||||
maybeRuntime deps['org.khronos:opengl-api']
|
||||
maybeRuntime deps['org.mortbay.jetty:jetty']
|
||||
testCompile deps['org.mortbay.jetty:jetty']
|
||||
maybeRuntime deps['org.mortbay.jetty:jetty-util']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-api']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-chrome-driver']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-java']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-remote-driver']
|
||||
maybeRuntime deps['org.slf4j:slf4j-api']
|
||||
testCompile deps['org.testcontainers:selenium']
|
||||
maybeRuntime deps['org.tukaani:xz']
|
||||
maybeRuntime deps['org.xerial.snappy:snappy-java']
|
||||
compile deps['xerces:xmlParserAPIs']
|
||||
compile deps['xpp3:xpp3']
|
||||
|
||||
@@ -466,7 +425,7 @@ task soyToJS {
|
||||
}
|
||||
|
||||
task stylesheetsToJavascript {
|
||||
def cssSourceDir = "${javaDir}/google/registry/ui/css"
|
||||
def cssSourceDir = "${jsDir}/google/registry/ui/css"
|
||||
def outputDir = "${resourcesDir}/google/registry/ui/css"
|
||||
inputs.dir cssSourceDir
|
||||
outputs.dir outputDir
|
||||
@@ -519,8 +478,8 @@ task compileProdJS(type: JavaExec) {
|
||||
def outputDir = "${resourcesDir}/google/registry/ui"
|
||||
def nodeModulesDir = "${rootDir}/node_modules"
|
||||
def cssSourceDir = "${resourcesDir}/google/registry/ui/css"
|
||||
def jsSourceDir = "${javaDir}/google/registry/ui/js"
|
||||
def externsDir = "${javaDir}/google/registry/ui/externs"
|
||||
def jsSourceDir = "${jsDir}/google/registry/ui/js"
|
||||
def externsDir = "${jsDir}/google/registry/ui/externs"
|
||||
def soySourceDir = "${generatedDir}/google/registry/ui/soy"
|
||||
|
||||
[nodeModulesDir, cssSourceDir, jsSourceDir, externsDir, soySourceDir].each {
|
||||
@@ -686,10 +645,11 @@ test {
|
||||
}.dependsOn(fragileTest, outcastTest)
|
||||
|
||||
createUberJar('nomulus', 'nomulus', 'google.registry.tools.RegistryTool')
|
||||
createUberJar('gtechTool', 'gtech_tool', 'google.registry.tools.GtechTool')
|
||||
project.nomulus.dependsOn project(':third_party').jar
|
||||
project.gtechTool.dependsOn project(':third_party').jar
|
||||
|
||||
project.build.dependsOn nomulus
|
||||
project.build.dependsOn gtechTool
|
||||
task buildToolImage(dependsOn: nomulus, type: Exec) {
|
||||
commandLine 'docker', 'build', '-t', 'nomulus-tool', '.'
|
||||
}
|
||||
|
||||
project.build.dependsOn buildToolImage
|
||||
project.build.dependsOn ':stage'
|
||||
|
||||
@@ -17,10 +17,11 @@ package google.registry.beam.invoicing;
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import google.registry.beam.invoicing.BillingEvent.InvoiceGroupingKey;
|
||||
import google.registry.beam.invoicing.BillingEvent.InvoiceGroupingKey.InvoiceGroupingKeyCoder;
|
||||
import google.registry.config.CredentialModule.LocalCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.reporting.billing.BillingModule;
|
||||
import google.registry.reporting.billing.GenerateInvoicesAction;
|
||||
import google.registry.tools.AuthModule.LocalOAuth2Credentials;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import java.io.Serializable;
|
||||
import javax.inject.Inject;
|
||||
import org.apache.beam.runners.dataflow.DataflowRunner;
|
||||
@@ -57,35 +58,31 @@ import org.apache.beam.sdk.values.TypeDescriptors;
|
||||
*/
|
||||
public class InvoicingPipeline implements Serializable {
|
||||
|
||||
@Inject
|
||||
@Config("projectId")
|
||||
String projectId;
|
||||
private final String projectId;
|
||||
private final String beamBucketUrl;
|
||||
private final String invoiceTemplateUrl;
|
||||
private final String beamStagingUrl;
|
||||
private final String billingBucketUrl;
|
||||
private final String invoiceFilePrefix;
|
||||
private final GoogleCredentials googleCredentials;
|
||||
|
||||
@Inject
|
||||
@Config("apacheBeamBucketUrl")
|
||||
String beamBucketUrl;
|
||||
|
||||
@Inject
|
||||
@Config("invoiceTemplateUrl")
|
||||
String invoiceTemplateUrl;
|
||||
|
||||
@Inject
|
||||
@Config("beamStagingUrl")
|
||||
String beamStagingUrl;
|
||||
|
||||
@Inject
|
||||
@Config("billingBucketUrl")
|
||||
String billingBucketUrl;
|
||||
|
||||
@Inject
|
||||
@Config("invoiceFilePrefix")
|
||||
String invoiceFilePrefix;
|
||||
|
||||
@Inject @LocalOAuth2Credentials
|
||||
GoogleCredentials credentials;
|
||||
|
||||
@Inject
|
||||
InvoicingPipeline() {}
|
||||
public InvoicingPipeline(
|
||||
@Config("projectId") String projectId,
|
||||
@Config("apacheBeamBucketUrl") String beamBucketUrl,
|
||||
@Config("invoiceTemplateUrl") String invoiceTemplateUrl,
|
||||
@Config("beamStagingUrl") String beamStagingUrl,
|
||||
@Config("billingBucketUrl") String billingBucketUrl,
|
||||
@Config("invoiceFilePrefix") String invoiceFilePrefix,
|
||||
@LocalCredential GoogleCredentialsBundle googleCredentialsBundle) {
|
||||
this.projectId = projectId;
|
||||
this.beamBucketUrl = beamBucketUrl;
|
||||
this.invoiceTemplateUrl = invoiceTemplateUrl;
|
||||
this.beamStagingUrl = beamStagingUrl;
|
||||
this.billingBucketUrl = billingBucketUrl;
|
||||
this.invoiceFilePrefix = invoiceFilePrefix;
|
||||
this.googleCredentials = googleCredentialsBundle.getGoogleCredentials();
|
||||
}
|
||||
|
||||
/** Custom options for running the invoicing pipeline. */
|
||||
interface InvoicingPipelineOptions extends DataflowPipelineOptions {
|
||||
@@ -105,12 +102,15 @@ public class InvoicingPipeline implements Serializable {
|
||||
public void deploy() {
|
||||
// We can't store options as a member variable due to serialization concerns.
|
||||
InvoicingPipelineOptions options = PipelineOptionsFactory.as(InvoicingPipelineOptions.class);
|
||||
options.setGcpCredential(credentials);
|
||||
options.setProject(projectId);
|
||||
options.setRunner(DataflowRunner.class);
|
||||
// This causes p.run() to stage the pipeline as a template on GCS, as opposed to running it.
|
||||
options.setTemplateLocation(invoiceTemplateUrl);
|
||||
options.setStagingLocation(beamStagingUrl);
|
||||
// This credential is used when Dataflow deploys the template to GCS in target GCP project.
|
||||
// So, make sure the credential has write permission to GCS in that project.
|
||||
options.setGcpCredential(googleCredentials);
|
||||
|
||||
Pipeline p = Pipeline.create(options);
|
||||
|
||||
PCollection<BillingEvent> billingEvents =
|
||||
|
||||
@@ -17,9 +17,12 @@ package google.registry.beam.spec11;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.beam.BeamUtils.getQueryFromFile;
|
||||
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.auto.value.AutoValue;
|
||||
import google.registry.beam.spec11.SafeBrowsingTransforms.EvaluateSafeBrowsingFn;
|
||||
import google.registry.config.CredentialModule.LocalCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import google.registry.util.Retrier;
|
||||
import google.registry.util.SqlTemplate;
|
||||
import java.io.Serializable;
|
||||
@@ -77,26 +80,29 @@ public class Spec11Pipeline implements Serializable {
|
||||
/** The JSON object field we put the threat match array for Spec11 reports. */
|
||||
public static final String THREAT_MATCHES_FIELD = "threatMatches";
|
||||
|
||||
@Inject
|
||||
@Config("projectId")
|
||||
String projectId;
|
||||
private final String projectId;
|
||||
private final String beamStagingUrl;
|
||||
private final String spec11TemplateUrl;
|
||||
private final String reportingBucketUrl;
|
||||
private final GoogleCredentials googleCredentials;
|
||||
private final Retrier retrier;
|
||||
|
||||
@Inject
|
||||
@Config("beamStagingUrl")
|
||||
String beamStagingUrl;
|
||||
|
||||
@Inject
|
||||
@Config("spec11TemplateUrl")
|
||||
String spec11TemplateUrl;
|
||||
|
||||
@Inject
|
||||
@Config("reportingBucketUrl")
|
||||
String reportingBucketUrl;
|
||||
|
||||
@Inject Retrier retrier;
|
||||
|
||||
@Inject
|
||||
Spec11Pipeline() {}
|
||||
public Spec11Pipeline(
|
||||
@Config("projectId") String projectId,
|
||||
@Config("beamStagingUrl") String beamStagingUrl,
|
||||
@Config("spec11TemplateUrl") String spec11TemplateUrl,
|
||||
@Config("reportingBucketUrl") String reportingBucketUrl,
|
||||
@LocalCredential GoogleCredentialsBundle googleCredentialsBundle,
|
||||
Retrier retrier
|
||||
) {
|
||||
this.projectId = projectId;
|
||||
this.beamStagingUrl = beamStagingUrl;
|
||||
this.spec11TemplateUrl = spec11TemplateUrl;
|
||||
this.reportingBucketUrl = reportingBucketUrl;
|
||||
this.googleCredentials = googleCredentialsBundle.getGoogleCredentials();
|
||||
this.retrier = retrier;
|
||||
}
|
||||
|
||||
/** Custom options for running the spec11 pipeline. */
|
||||
interface Spec11PipelineOptions extends DataflowPipelineOptions {
|
||||
@@ -134,6 +140,9 @@ public class Spec11Pipeline implements Serializable {
|
||||
// This causes p.run() to stage the pipeline as a template on GCS, as opposed to running it.
|
||||
options.setTemplateLocation(spec11TemplateUrl);
|
||||
options.setStagingLocation(beamStagingUrl);
|
||||
// This credential is used when Dataflow deploys the template to GCS in target GCP project.
|
||||
// So, make sure the credential has write permission to GCS in that project.
|
||||
options.setGcpCredential(googleCredentials);
|
||||
|
||||
Pipeline p = Pipeline.create(options);
|
||||
PCollection<Subdomain> domains =
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.bigquery;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.services.bigquery.Bigquery;
|
||||
import com.google.api.services.bigquery.model.TableFieldSchema;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -23,24 +22,29 @@ import dagger.Provides;
|
||||
import dagger.multibindings.Multibinds;
|
||||
import google.registry.config.CredentialModule.DefaultCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import java.util.Map;
|
||||
|
||||
/** Dagger module for Google {@link Bigquery} connection objects. */
|
||||
@Module
|
||||
public abstract class BigqueryModule {
|
||||
|
||||
/** Provides a map of BigQuery table names to field names. */
|
||||
@Multibinds
|
||||
abstract Map<String, ImmutableList<TableFieldSchema>> bigquerySchemas();
|
||||
// No subclasses.
|
||||
private BigqueryModule() {}
|
||||
|
||||
@Provides
|
||||
static Bigquery provideBigquery(
|
||||
@DefaultCredential GoogleCredential credential, @Config("projectId") String projectId) {
|
||||
return new Bigquery.Builder(credential.getTransport(), credential.getJsonFactory(), credential)
|
||||
@DefaultCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("projectId") String projectId) {
|
||||
return new Bigquery.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
// No subclasses.
|
||||
private BigqueryModule() {}
|
||||
/** Provides a map of BigQuery table names to field names. */
|
||||
@Multibinds
|
||||
abstract Map<String, ImmutableList<TableFieldSchema>> bigquerySchemas();
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
# Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Common routines for Nomulus build rules."""
|
||||
|
||||
ZIPPER = "@bazel_tools//tools/zip:zipper"
|
||||
|
||||
def long_path(ctx, file_):
|
||||
"""Constructs canonical runfile path relative to TEST_SRCDIR.
|
||||
|
||||
Args:
|
||||
ctx: A Skylark rule context.
|
||||
file_: A File object that should appear in the runfiles for the test.
|
||||
|
||||
Returns:
|
||||
A string path relative to TEST_SRCDIR suitable for use in tests and
|
||||
testing infrastructure.
|
||||
"""
|
||||
if file_.short_path.startswith("../"):
|
||||
return file_.short_path[3:]
|
||||
if file_.owner and file_.owner.workspace_root:
|
||||
return file_.owner.workspace_root + "/" + file_.short_path
|
||||
return ctx.workspace_name + "/" + file_.short_path
|
||||
|
||||
def collect_runfiles(targets):
|
||||
"""Aggregates runfiles from targets.
|
||||
|
||||
Args:
|
||||
targets: A list of Bazel targets.
|
||||
|
||||
Returns:
|
||||
A list of Bazel files.
|
||||
"""
|
||||
data = depset()
|
||||
for target in targets:
|
||||
if hasattr(target, "runfiles"):
|
||||
data += target.runfiles.files
|
||||
continue
|
||||
if hasattr(target, "data_runfiles"):
|
||||
data += target.data_runfiles.files
|
||||
if hasattr(target, "default_runfiles"):
|
||||
data += target.default_runfiles.files
|
||||
return data
|
||||
|
||||
def _get_runfiles(target, attribute):
|
||||
runfiles = getattr(target, attribute, None)
|
||||
if runfiles:
|
||||
return runfiles.files
|
||||
return []
|
||||
@@ -1,53 +0,0 @@
|
||||
# Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Build macro for creating App Engine EAR archives for Nomulus."""
|
||||
|
||||
load("//java/google/registry/builddefs:defs.bzl", "ZIPPER")
|
||||
|
||||
def registry_ear_file(name, out, configs, wars, **kwargs):
|
||||
"""Creates an EAR archive by combining WAR archives."""
|
||||
cmd = [
|
||||
"set -e",
|
||||
"repo=$$(pwd)",
|
||||
"zipper=$$repo/$(location %s)" % ZIPPER,
|
||||
"tmp=$$(mktemp -d $${TMPDIR:-/tmp}/registry_ear_file.XXXXXXXXXX)",
|
||||
"cd $${tmp}",
|
||||
]
|
||||
for target, dest in configs.items():
|
||||
cmd += [
|
||||
"mkdir -p $${tmp}/$$(dirname %s)" % dest,
|
||||
"ln -s $${repo}/$(location %s) $${tmp}/%s" % (target, dest),
|
||||
]
|
||||
for target, dest in wars.items():
|
||||
cmd += [
|
||||
"mkdir " + dest,
|
||||
"cd " + dest,
|
||||
"$${zipper} x $${repo}/$(location %s)" % target,
|
||||
"cd ..",
|
||||
]
|
||||
cmd += [
|
||||
"$${zipper} cC $${repo}/$@ $$(find . | sed 1d | cut -c 3- | LC_ALL=C sort)",
|
||||
"cd $${repo}",
|
||||
"rm -rf $${tmp}",
|
||||
]
|
||||
native.genrule(
|
||||
name = name,
|
||||
srcs = configs.keys() + wars.keys(),
|
||||
outs = [out],
|
||||
cmd = "\n".join(cmd),
|
||||
tools = [ZIPPER],
|
||||
message = "Generating EAR archive",
|
||||
**kwargs
|
||||
)
|
||||
@@ -1,256 +0,0 @@
|
||||
# Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Zip file creator that allows arbitrary path renaming.
|
||||
|
||||
This rule takes two main inputs: a bunch of filesets and a dictionary of
|
||||
hard-coded source to dest mappings. It then applies those mappings to the input
|
||||
file paths, to create a zip file with the same name as the rule.
|
||||
|
||||
The following preconditions must be met:
|
||||
|
||||
- Sources and destinations can't begin or end with slash.
|
||||
- Every file must be matched by a mapping.
|
||||
- Every mapping must match something.
|
||||
|
||||
The source can either be an exact match or a prefix.
|
||||
|
||||
- If a match is exact, the destination replaces the entire path. If the
|
||||
destination path is empty, then the path remains the same.
|
||||
|
||||
- If the match is a prefix, then the destination replaces the source prefix in
|
||||
the path. If the destination is empty, then the source prefix is removed.
|
||||
|
||||
- If source is an empty string, it matches everything. In this case,
|
||||
destination becomes the path prefix.
|
||||
|
||||
Prefixes are matched with component granularity, not characters. Mappings with
|
||||
more components take precedence. Mappings with equal components are sorted
|
||||
asciibetically.
|
||||
|
||||
Mappings apply to the "long path" of a file, i.e. relative to TEST_SRCDIR,
|
||||
e.g. workspace_name/pkg/file. Long paths do not take into consideration
|
||||
bazel-foo/ output directories.
|
||||
|
||||
The deps attribute allows zip_file() rules to depend on other zip_file() rules.
|
||||
In such cases, the contents of directly dependent zip files are unzipped and
|
||||
then re-zipped. Mappings specified by the current rule do not apply to the
|
||||
files extracted from dependent zips. However those files can be overridden.
|
||||
|
||||
The simplest example of this rule, which simply zips up short paths, is as
|
||||
follows:
|
||||
|
||||
# //my/package/BUILD
|
||||
zip_file(
|
||||
name = "doodle",
|
||||
srcs = ["hello.txt"],
|
||||
mappings = {"": ""},
|
||||
)
|
||||
|
||||
The rule above would create a zip file name //my/package/doodle.zip which would
|
||||
contain a single file named "my/package/hello.txt".
|
||||
|
||||
If we wanted to strip the package path, we could do the following:
|
||||
|
||||
# //my/package/BUILD
|
||||
zip_file(
|
||||
name = "doodle",
|
||||
srcs = ["hello.txt"],
|
||||
mappings = {"my/package": ""},
|
||||
)
|
||||
|
||||
In this case, doodle.zip would contain a single file: "hello.txt".
|
||||
|
||||
If we wanted to rename hello.txt, we could do the following:
|
||||
|
||||
# //my/package/BUILD
|
||||
zip_file(
|
||||
name = "doodle",
|
||||
srcs = ["hello.txt"],
|
||||
mappings = {"my/package/hello.txt": "my/package/world.txt"},
|
||||
)
|
||||
|
||||
A zip file can be assembled across many rules. For example:
|
||||
|
||||
# //webapp/html/BUILD
|
||||
zip_file(
|
||||
name = "assets",
|
||||
srcs = glob(["*.html"]),
|
||||
mappings = {"webapp/html": ""},
|
||||
)
|
||||
|
||||
# //webapp/js/BUILD
|
||||
zip_file(
|
||||
name = "assets",
|
||||
srcs = glob(["*.js"]),
|
||||
mappings = {"webapp/js": "assets/js"},
|
||||
)
|
||||
|
||||
# //webapp/BUILD
|
||||
zip_file(
|
||||
name = "war",
|
||||
deps = [
|
||||
"//webapp/html:assets",
|
||||
"//webapp/js:assets",
|
||||
],
|
||||
mappings = {"webapp/html": ""},
|
||||
)
|
||||
|
||||
You can exclude files with the "exclude" attribute:
|
||||
|
||||
# //webapp/BUILD
|
||||
zip_file(
|
||||
name = "war_without_tears",
|
||||
deps = ["war"],
|
||||
exclude = ["assets/js/tears.js"],
|
||||
)
|
||||
|
||||
Note that "exclude" excludes based on the mapped path relative to the root of
|
||||
the zipfile. If the file doesn't exist, you'll get an error.
|
||||
|
||||
"""
|
||||
|
||||
load(
|
||||
"//java/google/registry/builddefs:defs.bzl",
|
||||
"ZIPPER",
|
||||
"collect_runfiles",
|
||||
"long_path",
|
||||
)
|
||||
|
||||
def _zip_file(ctx):
|
||||
"""Implementation of zip_file() rule."""
|
||||
for s, d in ctx.attr.mappings.items():
|
||||
if (s.startswith("/") or s.endswith("/") or
|
||||
d.startswith("/") or d.endswith("/")):
|
||||
fail("mappings should not begin or end with slash")
|
||||
srcs = depset()
|
||||
srcs += ctx.files.srcs
|
||||
srcs += ctx.files.data
|
||||
srcs += collect_runfiles(ctx.attr.data)
|
||||
mapped = _map_sources(ctx, srcs, ctx.attr.mappings)
|
||||
cmd = [
|
||||
"#!/bin/sh",
|
||||
"set -e",
|
||||
'repo="$(pwd)"',
|
||||
'zipper="${repo}/%s"' % ctx.file._zipper.path,
|
||||
'archive="${repo}/%s"' % ctx.outputs.out.path,
|
||||
'tmp="$(mktemp -d "${TMPDIR:-/tmp}/zip_file.XXXXXXXXXX")"',
|
||||
'cd "${tmp}"',
|
||||
]
|
||||
cmd += [
|
||||
'"${zipper}" x "${repo}/%s"' % dep.zip_file.path
|
||||
for dep in ctx.attr.deps
|
||||
]
|
||||
cmd += ["rm %s" % filename for filename in ctx.attr.exclude]
|
||||
cmd += [
|
||||
'mkdir -p "${tmp}/%s"' % zip_path
|
||||
for zip_path in depset(
|
||||
[
|
||||
zip_path[:zip_path.rindex("/")]
|
||||
for _, zip_path in mapped
|
||||
if "/" in zip_path
|
||||
],
|
||||
).to_list()
|
||||
]
|
||||
cmd += [
|
||||
'ln -sf "${repo}/%s" "${tmp}/%s"' % (path, zip_path)
|
||||
for path, zip_path in mapped
|
||||
]
|
||||
cmd += [
|
||||
("find . | sed 1d | cut -c 3- | LC_ALL=C sort" +
|
||||
' | xargs "${zipper}" cC "${archive}"'),
|
||||
'cd "${repo}"',
|
||||
'rm -rf "${tmp}"',
|
||||
]
|
||||
if hasattr(ctx, "bin_dir"):
|
||||
script = ctx.new_file(ctx.bin_dir, "%s.sh" % ctx.label.name)
|
||||
else:
|
||||
# TODO(kchodorow): remove this once Bazel 4.0+ is required.
|
||||
script = ctx.new_file(ctx.configuration.bin_dir, "%s.sh" % ctx.label.name)
|
||||
ctx.actions.write(output = script, content = "\n".join(cmd), is_executable = True)
|
||||
inputs = [ctx.file._zipper]
|
||||
inputs += [dep.zip_file for dep in ctx.attr.deps]
|
||||
inputs += srcs.to_list()
|
||||
ctx.actions.run(
|
||||
inputs = inputs,
|
||||
outputs = [ctx.outputs.out],
|
||||
executable = script,
|
||||
mnemonic = "zip",
|
||||
progress_message = "Creating zip with %d inputs %s" % (
|
||||
len(inputs),
|
||||
ctx.label,
|
||||
),
|
||||
)
|
||||
return struct(files = depset([ctx.outputs.out]), zip_file = ctx.outputs.out)
|
||||
|
||||
def _map_sources(ctx, srcs, mappings):
|
||||
"""Calculates paths in zip file for srcs."""
|
||||
|
||||
# order mappings with more path components first
|
||||
mappings = sorted([
|
||||
(-len(source.split("/")), source, dest)
|
||||
for source, dest in mappings.items()
|
||||
])
|
||||
|
||||
# get rid of the integer part of tuple used for sorting
|
||||
mappings = [(source, dest) for _, source, dest in mappings]
|
||||
mappings_indexes = range(len(mappings))
|
||||
used = {i: False for i in mappings_indexes}
|
||||
mapped = []
|
||||
for file_ in srcs:
|
||||
run_path = long_path(ctx, file_)
|
||||
zip_path = None
|
||||
for i in mappings_indexes:
|
||||
source = mappings[i][0]
|
||||
dest = mappings[i][1]
|
||||
if not source:
|
||||
if dest:
|
||||
zip_path = dest + "/" + run_path
|
||||
else:
|
||||
zip_path = run_path
|
||||
elif source == run_path:
|
||||
if dest:
|
||||
zip_path = dest
|
||||
else:
|
||||
zip_path = run_path
|
||||
elif run_path.startswith(source + "/"):
|
||||
if dest:
|
||||
zip_path = dest + run_path[len(source):]
|
||||
else:
|
||||
zip_path = run_path[len(source) + 1:]
|
||||
else:
|
||||
continue
|
||||
used[i] = True
|
||||
break
|
||||
if not zip_path:
|
||||
fail("no mapping matched: " + run_path)
|
||||
mapped += [(file_.path, zip_path)]
|
||||
for i in mappings_indexes:
|
||||
if not used[i]:
|
||||
fail('superfluous mapping: "%s" -> "%s"' % mappings[i])
|
||||
return mapped
|
||||
|
||||
zip_file = rule(
|
||||
implementation = _zip_file,
|
||||
output_to_genfiles = True,
|
||||
attrs = {
|
||||
"out": attr.output(mandatory = True),
|
||||
"srcs": attr.label_list(allow_files = True),
|
||||
"data": attr.label_list(allow_files = True),
|
||||
"deps": attr.label_list(providers = ["zip_file"]),
|
||||
"exclude": attr.string_list(),
|
||||
"mappings": attr.string_dict(),
|
||||
"_zipper": attr.label(default = Label(ZIPPER), allow_single_file = True),
|
||||
},
|
||||
)
|
||||
@@ -17,31 +17,28 @@ package google.registry.config;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
|
||||
import com.google.api.client.googleapis.util.Utils;
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.keyring.api.KeyModule.Key;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.security.GeneralSecurityException;
|
||||
import javax.inject.Qualifier;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Dagger module that provides all {@link GoogleCredential GoogleCredentials} used in the
|
||||
* application.
|
||||
*/
|
||||
/** Dagger module that provides all {@link GoogleCredentials} used in the application. */
|
||||
@Module
|
||||
public abstract class CredentialModule {
|
||||
|
||||
/**
|
||||
* Provides the default {@link GoogleCredential} from the Google Cloud runtime.
|
||||
* Provides the default {@link GoogleCredentialsBundle} from the Google Cloud runtime.
|
||||
*
|
||||
* <p>The credential returned depends on the runtime environment:
|
||||
*
|
||||
@@ -58,7 +55,30 @@ public abstract class CredentialModule {
|
||||
@DefaultCredential
|
||||
@Provides
|
||||
@Singleton
|
||||
public static GoogleCredential provideDefaultCredential(
|
||||
public static GoogleCredentialsBundle provideDefaultCredential(
|
||||
@Config("defaultCredentialOauthScopes") ImmutableList<String> requiredScopes) {
|
||||
GoogleCredentials credential;
|
||||
try {
|
||||
credential = GoogleCredentials.getApplicationDefault();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (credential.createScopedRequired()) {
|
||||
credential = credential.createScoped(requiredScopes);
|
||||
}
|
||||
return GoogleCredentialsBundle.create(credential);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the default {@link GoogleCredential} from the Google Cloud runtime for G Suite
|
||||
* Drive API.
|
||||
* TODO(b/138195359): Deprecate this credential once we figure out how to use
|
||||
* {@link GoogleCredentials} for G Suite Drive API.
|
||||
*/
|
||||
@GSuiteDriveCredential
|
||||
@Provides
|
||||
@Singleton
|
||||
public static GoogleCredential provideGSuiteDriveCredential(
|
||||
@Config("defaultCredentialOauthScopes") ImmutableList<String> requiredScopes) {
|
||||
GoogleCredential credential;
|
||||
try {
|
||||
@@ -66,35 +86,6 @@ public abstract class CredentialModule {
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (credential.createScopedRequired()) {
|
||||
return credential.createScoped(requiredScopes);
|
||||
}
|
||||
return credential;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a {@link GoogleCredential} from the service account's JSON key file.
|
||||
*
|
||||
* <p>On App Engine, a thread created using Java's built-in API needs this credential when it
|
||||
* calls App Engine API. The Google Sheets API also needs this credential.
|
||||
*/
|
||||
@JsonCredential
|
||||
@Provides
|
||||
@Singleton
|
||||
public static GoogleCredential provideJsonCredential(
|
||||
@Config("defaultCredentialOauthScopes") ImmutableList<String> requiredScopes,
|
||||
@Key("jsonCredential") String jsonCredential) {
|
||||
GoogleCredential credential;
|
||||
try {
|
||||
credential =
|
||||
GoogleCredential.fromStream(
|
||||
new ByteArrayInputStream(jsonCredential.getBytes(UTF_8)),
|
||||
// We cannot use UrlFetchTransport as that uses App Engine API.
|
||||
GoogleNetHttpTransport.newTrustedTransport(),
|
||||
Utils.getDefaultJsonFactory());
|
||||
} catch (IOException | GeneralSecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (credential.createScopedRequired()) {
|
||||
credential = credential.createScoped(requiredScopes);
|
||||
}
|
||||
@@ -102,7 +93,32 @@ public abstract class CredentialModule {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a {@link GoogleCredential} with delegated admin access for a G Suite domain.
|
||||
* Provides a {@link GoogleCredentialsBundle} from the service account's JSON key file.
|
||||
*
|
||||
* <p>On App Engine, a thread created using Java's built-in API needs this credential when it
|
||||
* calls App Engine API. The Google Sheets API also needs this credential.
|
||||
*/
|
||||
@JsonCredential
|
||||
@Provides
|
||||
@Singleton
|
||||
public static GoogleCredentialsBundle provideJsonCredential(
|
||||
@Config("defaultCredentialOauthScopes") ImmutableList<String> requiredScopes,
|
||||
@Key("jsonCredential") String jsonCredential) {
|
||||
GoogleCredentials credential;
|
||||
try {
|
||||
credential =
|
||||
GoogleCredentials.fromStream(new ByteArrayInputStream(jsonCredential.getBytes(UTF_8)));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
if (credential.createScopedRequired()) {
|
||||
credential = credential.createScoped(requiredScopes);
|
||||
}
|
||||
return GoogleCredentialsBundle.create(credential);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a {@link GoogleCredentialsBundle} with delegated admin access for a G Suite domain.
|
||||
*
|
||||
* <p>The G Suite domain must grant delegated admin access to the registry service account with
|
||||
* all scopes in {@code requiredScopes}, including ones not related to G Suite.
|
||||
@@ -110,18 +126,14 @@ public abstract class CredentialModule {
|
||||
@DelegatedCredential
|
||||
@Provides
|
||||
@Singleton
|
||||
public static GoogleCredential provideDelegatedCredential(
|
||||
public static GoogleCredentialsBundle provideDelegatedCredential(
|
||||
@Config("delegatedCredentialOauthScopes") ImmutableList<String> requiredScopes,
|
||||
@JsonCredential GoogleCredential googleCredential,
|
||||
@JsonCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("gSuiteAdminAccountEmailAddress") String gSuiteAdminAccountEmailAddress) {
|
||||
return new GoogleCredential.Builder()
|
||||
.setTransport(Utils.getDefaultTransport())
|
||||
.setJsonFactory(Utils.getDefaultJsonFactory())
|
||||
.setServiceAccountId(googleCredential.getServiceAccountId())
|
||||
.setServiceAccountPrivateKey(googleCredential.getServiceAccountPrivateKey())
|
||||
.setServiceAccountScopes(requiredScopes)
|
||||
.setServiceAccountUser(gSuiteAdminAccountEmailAddress)
|
||||
.build();
|
||||
return GoogleCredentialsBundle.create(credentialsBundle
|
||||
.getGoogleCredentials()
|
||||
.createDelegated(gSuiteAdminAccountEmailAddress)
|
||||
.createScoped(requiredScopes));
|
||||
}
|
||||
|
||||
/** Dagger qualifier for the Application Default Credential. */
|
||||
@@ -130,6 +142,13 @@ public abstract class CredentialModule {
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DefaultCredential {}
|
||||
|
||||
|
||||
/** Dagger qualifier for the credential for G Suite Drive API. */
|
||||
@Qualifier
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface GSuiteDriveCredential {}
|
||||
|
||||
/**
|
||||
* Dagger qualifier for a credential from a service account's JSON key, to be used in non-request
|
||||
* threads.
|
||||
|
||||
@@ -894,9 +894,9 @@ public final class RegistryConfig {
|
||||
* @see google.registry.reporting.spec11.Spec11EmailUtils
|
||||
*/
|
||||
@Provides
|
||||
@Config("spec11ReplyToEmailAddress")
|
||||
public static InternetAddress provideSpec11ReplyToEmailAddress(RegistryConfigSettings config) {
|
||||
return parseEmailAddress(config.misc.spec11ReplyToEmailAddress);
|
||||
@Config("spec11OutgoingEmailAddress")
|
||||
public static InternetAddress provideSpec11OutgoingEmailAddress(RegistryConfigSettings config) {
|
||||
return parseEmailAddress(config.misc.spec11OutgoingEmailAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -173,7 +173,7 @@ public class RegistryConfigSettings {
|
||||
public static class Misc {
|
||||
public String sheetExportId;
|
||||
public String alertRecipientEmailAddress;
|
||||
public String spec11ReplyToEmailAddress;
|
||||
public String spec11OutgoingEmailAddress;
|
||||
public int asyncDeleteDelaySeconds;
|
||||
public int transientFailureRetries;
|
||||
}
|
||||
|
||||
@@ -357,9 +357,9 @@ misc:
|
||||
# Address we send alert summary emails to.
|
||||
alertRecipientEmailAddress: email@example.com
|
||||
|
||||
# Address to which the Spec 11 emails to registrars should be replied. This needs
|
||||
# to be a deliverable email address in case the registrars want to contact us.
|
||||
spec11ReplyToEmailAddress: reply-to@example.com
|
||||
# Address from which Spec 11 emails to registrars are sent. This needs
|
||||
# to be a deliverable email address to handle replies from registrars as well.
|
||||
spec11OutgoingEmailAddress: abuse@example.com
|
||||
|
||||
# How long to delay processing of asynchronous deletions. This should always
|
||||
# be longer than eppResourceCachingSeconds, to prevent deleted contacts or
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.dns.writer.clouddns;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.services.dns.Dns;
|
||||
import com.google.common.util.concurrent.RateLimiter;
|
||||
import dagger.Binds;
|
||||
@@ -26,6 +25,7 @@ import dagger.multibindings.StringKey;
|
||||
import google.registry.config.CredentialModule.DefaultCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.dns.writer.DnsWriter;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Named;
|
||||
|
||||
@@ -35,12 +35,15 @@ public abstract class CloudDnsWriterModule {
|
||||
|
||||
@Provides
|
||||
static Dns provideDns(
|
||||
@DefaultCredential GoogleCredential credential,
|
||||
@DefaultCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("projectId") String projectId,
|
||||
@Config("cloudDnsRootUrl") Optional<String> rootUrl,
|
||||
@Config("cloudDnsServicePath") Optional<String> servicePath) {
|
||||
Dns.Builder builder =
|
||||
new Dns.Builder(credential.getTransport(), credential.getJsonFactory(), credential)
|
||||
new Dns.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(projectId);
|
||||
|
||||
rootUrl.ifPresent(builder::setRootUrl);
|
||||
|
||||
@@ -112,8 +112,6 @@
|
||||
<target>backend</target>
|
||||
</cron>
|
||||
|
||||
<!--
|
||||
TODO(b/134576418) enable this cron job once we're sure the Action works
|
||||
<cron>
|
||||
<url><![CDATA[/_dr/task/updateRegistrarRdapBaseUrls]]></url>
|
||||
<description>
|
||||
@@ -122,7 +120,6 @@
|
||||
<schedule>every day 02:34</schedule>
|
||||
<target>backend</target>
|
||||
</cron>
|
||||
-->
|
||||
|
||||
<cron>
|
||||
<url><![CDATA[/_dr/task/deleteOldCommitLogs]]></url>
|
||||
|
||||
@@ -20,7 +20,7 @@ import dagger.Component;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule;
|
||||
import google.registry.config.CredentialModule.DefaultCredential;
|
||||
import google.registry.config.CredentialModule.GSuiteDriveCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryConfig.ConfigModule;
|
||||
import google.registry.storage.drive.DriveConnection;
|
||||
@@ -32,8 +32,13 @@ public final class DriveModule {
|
||||
|
||||
@Provides
|
||||
static Drive provideDrive(
|
||||
@DefaultCredential GoogleCredential credential, @Config("projectId") String projectId) {
|
||||
return new Drive.Builder(credential.getTransport(), credential.getJsonFactory(), credential)
|
||||
@GSuiteDriveCredential GoogleCredential googleCredential,
|
||||
@Config("projectId") String projectId) {
|
||||
|
||||
return new Drive.Builder(
|
||||
googleCredential.getTransport(),
|
||||
googleCredential.getJsonFactory(),
|
||||
googleCredential)
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
|
||||
package google.registry.export.datastore;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/** Dagger module that configures provision of {@link DatastoreAdmin}. */
|
||||
@@ -28,10 +28,12 @@ public abstract class DatastoreAdminModule {
|
||||
@Singleton
|
||||
@Provides
|
||||
static DatastoreAdmin provideDatastoreAdmin(
|
||||
@CredentialModule.DefaultCredential GoogleCredential credential,
|
||||
@CredentialModule.DefaultCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@RegistryConfig.Config("projectId") String projectId) {
|
||||
return new DatastoreAdmin.Builder(
|
||||
credential.getTransport(), credential.getJsonFactory(), credential)
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(projectId)
|
||||
.setProjectId(projectId)
|
||||
.build();
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
|
||||
package google.registry.export.sheet;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.services.sheets.v4.Sheets;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.JsonCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
|
||||
/** Dagger module for {@link Sheets}. */
|
||||
@Module
|
||||
@@ -27,8 +27,12 @@ public final class SheetsServiceModule {
|
||||
|
||||
@Provides
|
||||
static Sheets provideSheets(
|
||||
@JsonCredential GoogleCredential credential, @Config("projectId") String projectId) {
|
||||
return new Sheets.Builder(credential.getTransport(), credential.getJsonFactory(), credential)
|
||||
@JsonCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("projectId") String projectId) {
|
||||
return new Sheets.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -209,6 +209,7 @@ public abstract class EppException extends Exception {
|
||||
/** Specified command is not implemented. */
|
||||
@EppResultCode(Code.UNIMPLEMENTED_COMMAND)
|
||||
public static class UnimplementedCommandException extends EppException {
|
||||
|
||||
public UnimplementedCommandException(InnerCommand command) {
|
||||
super(String.format(
|
||||
"No flow found for %s with extension %s",
|
||||
@@ -217,6 +218,10 @@ public abstract class EppException extends Exception {
|
||||
? ((ResourceCommandWrapper) command).getResourceCommand().getClass().getSimpleName()
|
||||
: null));
|
||||
}
|
||||
|
||||
public UnimplementedCommandException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
/** Abstract exception class. Do not throw this directly or catch in tests. */
|
||||
|
||||
@@ -39,6 +39,13 @@ public class EppMetrics {
|
||||
LabelDescriptor.create("tld", "The TLD acted on by the command (if applicable)."),
|
||||
LabelDescriptor.create("status", "The return status of the command."));
|
||||
|
||||
private static final ImmutableSet<LabelDescriptor> LABEL_DESCRIPTORS =
|
||||
ImmutableSet.of(
|
||||
LabelDescriptor.create("command", "The name of the command."),
|
||||
LabelDescriptor.create("traffic_type",
|
||||
"The traffic type of the command; one of CANARY, PROBER, or REAL."),
|
||||
LabelDescriptor.create("status", "The return status of the command."));
|
||||
|
||||
private static final IncrementableMetric eppRequestsByRegistrar =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newIncrementableMetric(
|
||||
@@ -73,6 +80,19 @@ public class EppMetrics {
|
||||
LABEL_DESCRIPTORS_BY_TLD,
|
||||
DEFAULT_FITTER);
|
||||
|
||||
private static final EventMetric requestTime =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newEventMetric(
|
||||
"/epp/request_time",
|
||||
"EPP Request Time",
|
||||
"milliseconds",
|
||||
LABEL_DESCRIPTORS,
|
||||
DEFAULT_FITTER);
|
||||
|
||||
private enum TrafficType {
|
||||
CANARY, PROBER, REAL
|
||||
}
|
||||
|
||||
@Inject
|
||||
public EppMetrics() {}
|
||||
|
||||
@@ -97,15 +117,21 @@ public class EppMetrics {
|
||||
metric.getStatus().isPresent() ? String.valueOf(metric.getStatus().get().code) : "";
|
||||
long processingTime =
|
||||
metric.getEndTimestamp().getMillis() - metric.getStartTimestamp().getMillis();
|
||||
processingTimeByRegistrar.record(
|
||||
processingTime,
|
||||
metric.getCommandName().orElse(""),
|
||||
metric.getClientId().orElse(""),
|
||||
eppStatusCode);
|
||||
processingTimeByTld.record(
|
||||
processingTime,
|
||||
metric.getCommandName().orElse(""),
|
||||
metric.getTld().orElse(""),
|
||||
eppStatusCode);
|
||||
String commandName = metric.getCommandName().orElse("");
|
||||
processingTimeByRegistrar
|
||||
.record(processingTime, commandName, metric.getClientId().orElse(""), eppStatusCode);
|
||||
String tld = metric.getTld().orElse("");
|
||||
processingTimeByTld.record(processingTime, commandName, tld, eppStatusCode);
|
||||
requestTime.record(processingTime, commandName, getTrafficType(tld).toString(), eppStatusCode);
|
||||
}
|
||||
|
||||
private static TrafficType getTrafficType(String tld) {
|
||||
if (tld.endsWith("canary.test")) {
|
||||
return TrafficType.CANARY;
|
||||
} else if (tld.endsWith(".test")) {
|
||||
return TrafficType.PROBER;
|
||||
} else {
|
||||
return TrafficType.REAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +82,9 @@ public class FlowPicker {
|
||||
/** Marker class for unimplemented flows. */
|
||||
private abstract static class UnimplementedFlow implements Flow {}
|
||||
|
||||
/** Marker class for unimplemented restore flows. */
|
||||
private abstract static class UnimplementedRestoreFlow implements Flow {}
|
||||
|
||||
/** A function type that takes an {@link EppInput} and returns a {@link Flow} class. */
|
||||
private abstract static class FlowProvider {
|
||||
/** Get the flow associated with this {@link EppInput} or return null to signal no match. */
|
||||
@@ -160,7 +163,7 @@ public class FlowPicker {
|
||||
// Restore command with an op of "report" is not currently supported.
|
||||
return (rgpUpdateExtension.get().getRestoreCommand().getRestoreOp() == RestoreOp.REQUEST)
|
||||
? DomainRestoreRequestFlow.class
|
||||
: UnimplementedFlow.class;
|
||||
: UnimplementedRestoreFlow.class;
|
||||
}};
|
||||
|
||||
/**
|
||||
@@ -265,8 +268,11 @@ public class FlowPicker {
|
||||
Class<? extends Flow> flowClass = flowProvider.get(eppInput);
|
||||
if (flowClass == UnimplementedFlow.class) {
|
||||
break; // We found it, but it's marked as not implemented.
|
||||
}
|
||||
if (flowClass != null) {
|
||||
} else if (flowClass == UnimplementedRestoreFlow.class) {
|
||||
throw new UnimplementedCommandException(
|
||||
"Domain restores are approved and enacted instantly, "
|
||||
+ "therefore domain restore reports are not supported");
|
||||
} else if (flowClass != null) {
|
||||
return flowClass; // We found it!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
|
||||
package google.registry.groups;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.services.admin.directory.Directory;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.DelegatedCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
|
||||
/** Dagger module for the Google {@link Directory} service. */
|
||||
@Module
|
||||
@@ -27,8 +27,12 @@ public final class DirectoryModule {
|
||||
|
||||
@Provides
|
||||
static Directory provideDirectory(
|
||||
@DelegatedCredential GoogleCredential credential, @Config("projectId") String projectId) {
|
||||
return new Directory.Builder(credential.getTransport(), credential.getJsonFactory(), credential)
|
||||
@DelegatedCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("projectId") String projectId) {
|
||||
return new Directory.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
|
||||
package google.registry.groups;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.services.groupssettings.Groupssettings;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.DelegatedCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
|
||||
/** Dagger module for the Google {@link Groupssettings} service. */
|
||||
@Module
|
||||
@@ -27,9 +27,12 @@ public final class GroupssettingsModule {
|
||||
|
||||
@Provides
|
||||
static Groupssettings provideDirectory(
|
||||
@DelegatedCredential GoogleCredential credential, @Config("projectId") String projectId) {
|
||||
@DelegatedCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("projectId") String projectId) {
|
||||
return new Groupssettings.Builder(
|
||||
credential.getTransport(), credential.getJsonFactory(), credential)
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.keyring.kms;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.services.cloudkms.v1.CloudKMS;
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
@@ -24,6 +23,7 @@ import dagger.multibindings.StringKey;
|
||||
import google.registry.config.CredentialModule.DefaultCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.keyring.api.Keyring;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
|
||||
/** Dagger module for Cloud KMS. */
|
||||
@Module
|
||||
@@ -31,20 +31,23 @@ public abstract class KmsModule {
|
||||
|
||||
public static final String NAME = "KMS";
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@StringKey(NAME)
|
||||
abstract Keyring provideKeyring(KmsKeyring keyring);
|
||||
|
||||
@Provides
|
||||
static CloudKMS provideKms(
|
||||
@DefaultCredential GoogleCredential credential,
|
||||
@DefaultCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("cloudKmsProjectId") String projectId) {
|
||||
return new CloudKMS.Builder(credential.getTransport(), credential.getJsonFactory(), credential)
|
||||
return new CloudKMS.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@StringKey(NAME)
|
||||
abstract Keyring provideKeyring(KmsKeyring keyring);
|
||||
|
||||
@Binds
|
||||
abstract KmsConnection provideKmsConnection(KmsConnectionImpl kmsConnectionImpl);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import static google.registry.util.CollectionUtils.forceEmptyToNull;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
import static google.registry.util.CollectionUtils.union;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.earliestOf;
|
||||
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
|
||||
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
||||
@@ -104,7 +105,7 @@ public class DomainBase extends EppResource
|
||||
* from (creationTime, deletionTime) there can only be one domain in Datastore with this name.
|
||||
* However, there can be many domains with the same name and non-overlapping lifetimes.
|
||||
*
|
||||
* @invariant fullyQualifiedDomainName == fullyQualifiedDomainName.toLowerCase()
|
||||
* @invariant fullyQualifiedDomainName == fullyQualifiedDomainName.toLowerCase(Locale.ENGLISH)
|
||||
*/
|
||||
@Index
|
||||
String fullyQualifiedDomainName;
|
||||
@@ -376,10 +377,10 @@ public class DomainBase extends EppResource
|
||||
|
||||
Optional<DateTime> newLastEppUpdateTime = Optional.empty();
|
||||
|
||||
// There is no transfer. Do any necessary autorenews.
|
||||
// There is no transfer. Do any necessary autorenews for active domains.
|
||||
|
||||
Builder builder = asBuilder();
|
||||
if (isBeforeOrAt(registrationExpirationTime, now)) {
|
||||
if (isBeforeOrAt(registrationExpirationTime, now) && END_OF_TIME.equals(getDeletionTime())) {
|
||||
// Autorenew by the number of years between the old expiration time and now.
|
||||
DateTime lastAutorenewTime = leapSafeAddYears(
|
||||
registrationExpirationTime,
|
||||
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
package google.registry.model.domain.fee;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName;
|
||||
import java.util.Locale;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlValue;
|
||||
|
||||
@@ -47,7 +47,7 @@ public class FeeExtensionCommandDescriptor extends ImmutableObject {
|
||||
|
||||
public CommandName getCommand() {
|
||||
// Require the xml string to be lowercase.
|
||||
if (command != null && CharMatcher.javaLowerCase().matchesAllOf(command)) {
|
||||
if (command != null && command.toLowerCase(Locale.ENGLISH).equals(command)) {
|
||||
try {
|
||||
return CommandName.valueOf(Ascii.toUpperCase(command));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
package google.registry.model.domain.fee12;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
@@ -83,7 +83,7 @@ public class FeeCheckCommandExtensionItemV12 extends FeeCheckCommandExtensionIte
|
||||
@Override
|
||||
public CommandName getCommandName() {
|
||||
// Require the xml string to be lowercase.
|
||||
if (commandName != null && CharMatcher.javaLowerCase().matchesAllOf(commandName)) {
|
||||
if (commandName != null && commandName.toLowerCase(Locale.ENGLISH).equals(commandName)) {
|
||||
try {
|
||||
return CommandName.valueOf(Ascii.toUpperCase(commandName));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
@@ -868,7 +868,9 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDriveFolderId(String driveFolderId) {
|
||||
public Builder setDriveFolderId(@Nullable String driveFolderId) {
|
||||
checkArgument(driveFolderId == null || !driveFolderId.contains("/"),
|
||||
"Drive folder ID must not be a full URL");
|
||||
getInstance().driveFolderId = driveFolderId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.monitoring.whitebox;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.services.monitoring.v3.Monitoring;
|
||||
import com.google.api.services.monitoring.v3.model.MonitoredResource;
|
||||
import com.google.appengine.api.modules.ModulesService;
|
||||
@@ -27,6 +26,7 @@ import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.JsonCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Dagger module for Google Stackdriver service connection objects. */
|
||||
@@ -39,9 +39,12 @@ public final class StackdriverModule {
|
||||
|
||||
@Provides
|
||||
static Monitoring provideMonitoring(
|
||||
@JsonCredential GoogleCredential credential, @Config("projectId") String projectId) {
|
||||
@JsonCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("projectId") String projectId) {
|
||||
return new Monitoring.Builder(
|
||||
credential.getTransport(), credential.getJsonFactory(), credential)
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.rdap;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
@@ -23,6 +24,7 @@ import com.google.api.client.http.HttpRequest;
|
||||
import com.google.api.client.http.HttpRequestFactory;
|
||||
import com.google.api.client.http.HttpResponse;
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
@@ -34,8 +36,9 @@ import com.google.gson.JsonObject;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.keyring.api.KeyModule;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registry.Registries;
|
||||
import google.registry.model.registry.Registry.TldType;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.auth.Auth;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -56,7 +59,18 @@ import javax.inject.Inject;
|
||||
* <p>It is a "login/query/logout" system where you login using the ICANN Reporting credentials, get
|
||||
* a cookie you then send to get the list and finally logout.
|
||||
*
|
||||
* <p>The username is [TLD]_ry. It could be any "real" TLD.
|
||||
* <p>For clarity, this is how one would contact this endpoint "manually", from a whitelisted IP
|
||||
* server:
|
||||
*
|
||||
* <p>$ curl [base]/login -I --user [tld]_ry:[password]
|
||||
*
|
||||
* <p>get the id=xxx value from the reply
|
||||
*
|
||||
* <p>$ curl [base]/registrarRdapBaseUrl/list -b 'id=xxx'
|
||||
*
|
||||
* <p>$ curl [base]/logout -b 'id=xxx'
|
||||
*
|
||||
* <p>where [base] is https://mosapi.icann.org/mosapi/v1/[tld]
|
||||
*/
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
@@ -75,41 +89,29 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
@Inject HttpTransport httpTransport;
|
||||
@Inject @KeyModule.Key("icannReportingPassword") String password;
|
||||
|
||||
/**
|
||||
* The TLD for which we make the request.
|
||||
*
|
||||
* <p>The actual value doesn't matter, as long as it's a TLD that has access to the ICANN
|
||||
* Reporter. It's just used to login.
|
||||
*/
|
||||
@Inject @Parameter("tld") String tld;
|
||||
|
||||
@Inject
|
||||
UpdateRegistrarRdapBaseUrlsAction() {}
|
||||
|
||||
private String loginAndGetId(HttpRequestFactory requestFactory) {
|
||||
try {
|
||||
logger.atInfo().log("Logging in to MoSAPI");
|
||||
HttpRequest request =
|
||||
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGIN_URL, tld)));
|
||||
request.getHeaders().setBasicAuthentication(String.format("%s_ry", tld), password);
|
||||
HttpResponse response = request.execute();
|
||||
private String loginAndGetId(HttpRequestFactory requestFactory, String tld) throws IOException {
|
||||
logger.atInfo().log("Logging in to MoSAPI");
|
||||
HttpRequest request =
|
||||
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGIN_URL, tld)));
|
||||
request.getHeaders().setBasicAuthentication(String.format("%s_ry", tld), password);
|
||||
HttpResponse response = request.execute();
|
||||
|
||||
Optional<HttpCookie> idCookie =
|
||||
HttpCookie.parse(response.getHeaders().getFirstHeaderStringValue("Set-Cookie")).stream()
|
||||
.filter(cookie -> cookie.getName().equals(COOKIE_ID))
|
||||
.findAny();
|
||||
checkState(
|
||||
idCookie.isPresent(),
|
||||
"Didn't get the ID cookie from the login response. Code: %s, headers: %s",
|
||||
response.getStatusCode(),
|
||||
response.getHeaders());
|
||||
return idCookie.get().getValue();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Error logging in to MoSAPI server: " + e.getMessage(), e);
|
||||
}
|
||||
Optional<HttpCookie> idCookie =
|
||||
HttpCookie.parse(response.getHeaders().getFirstHeaderStringValue("Set-Cookie")).stream()
|
||||
.filter(cookie -> cookie.getName().equals(COOKIE_ID))
|
||||
.findAny();
|
||||
checkState(
|
||||
idCookie.isPresent(),
|
||||
"Didn't get the ID cookie from the login response. Code: %s, headers: %s",
|
||||
response.getStatusCode(),
|
||||
response.getHeaders());
|
||||
return idCookie.get().getValue();
|
||||
}
|
||||
|
||||
private void logout(HttpRequestFactory requestFactory, String id) {
|
||||
private void logout(HttpRequestFactory requestFactory, String id, String tld) {
|
||||
try {
|
||||
HttpRequest request =
|
||||
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGOUT_URL, tld)));
|
||||
@@ -122,9 +124,8 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaId() {
|
||||
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
|
||||
String id = loginAndGetId(requestFactory);
|
||||
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaIdWithTld(
|
||||
String tld, String id, HttpRequestFactory requestFactory) {
|
||||
String content;
|
||||
try {
|
||||
HttpRequest request =
|
||||
@@ -139,7 +140,7 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
throw new UncheckedIOException(
|
||||
"Error reading RDAP list from MoSAPI server: " + e.getMessage(), e);
|
||||
} finally {
|
||||
logout(requestFactory, id);
|
||||
logout(requestFactory, id, tld);
|
||||
}
|
||||
|
||||
logger.atInfo().log("list reply: '%s'", content);
|
||||
@@ -160,6 +161,36 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaId() {
|
||||
// All TLDs have the same data, so just keep trying until one works
|
||||
// (the expectation is that all / any should work)
|
||||
ImmutableList<String> tlds = ImmutableList.sortedCopyOf(Registries.getTldsOfType(TldType.REAL));
|
||||
checkArgument(!tlds.isEmpty(), "There must exist at least one REAL TLD.");
|
||||
Throwable finalThrowable = null;
|
||||
for (String tld : tlds) {
|
||||
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
|
||||
String id;
|
||||
try {
|
||||
id = loginAndGetId(requestFactory, tld);
|
||||
} catch (Throwable e) {
|
||||
// Login failures are bad but not unexpected for certain TLDs. We shouldn't store those
|
||||
// but rather should only store useful Throwables.
|
||||
logger.atWarning().log("Error logging in to MoSAPI server: " + e.getMessage(), e);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
return getRdapBaseUrlsPerIanaIdWithTld(tld, id, requestFactory);
|
||||
} catch (Throwable throwable) {
|
||||
logger.atWarning().log(
|
||||
String.format(
|
||||
"Error retrieving RDAP urls with TLD %s: %s", tld, throwable.getMessage()));
|
||||
finalThrowable = throwable;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException(
|
||||
String.format("Error contacting MosAPI server. Tried TLDs %s", tlds), finalThrowable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ImmutableSetMultimap<String, String> ianaToBaseUrls = getRdapBaseUrlsPerIanaId();
|
||||
|
||||
@@ -17,7 +17,6 @@ package google.registry.reporting;
|
||||
import static google.registry.request.RequestParameters.extractOptionalParameter;
|
||||
import static google.registry.request.RequestParameters.extractRequiredParameter;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.services.dataflow.Dataflow;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
@@ -26,6 +25,7 @@ import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.request.HttpException.BadRequestException;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import java.util.Optional;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.joda.time.DateTimeZone;
|
||||
@@ -118,8 +118,12 @@ public class ReportingModule {
|
||||
/** Constructs a {@link Dataflow} API client with default settings. */
|
||||
@Provides
|
||||
static Dataflow provideDataflow(
|
||||
@DefaultCredential GoogleCredential credential, @Config("projectId") String projectId) {
|
||||
return new Dataflow.Builder(credential.getTransport(), credential.getJsonFactory(), credential)
|
||||
@DefaultCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("projectId") String projectId) {
|
||||
return new Dataflow.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(String.format("%s billing", projectId))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import com.google.appengine.tools.cloudstorage.GcsFilename;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.io.ByteStreams;
|
||||
@@ -38,6 +39,7 @@ import google.registry.util.Retrier;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Copy all registrar detail reports in a given bucket's subdirectory from GCS to Drive. */
|
||||
@@ -95,6 +97,8 @@ public final class CopyDetailReportsAction implements Runnable {
|
||||
response.setPayload(String.format("Failure, encountered %s", e.getMessage()));
|
||||
return;
|
||||
}
|
||||
ImmutableMap.Builder<String, Throwable> copyErrorsBuilder =
|
||||
new ImmutableMap.Builder<String, Throwable>();
|
||||
for (String detailReportName : detailReportObjectNames) {
|
||||
// The standard report format is "invoice_details_yyyy-MM_registrarId_tld.csv
|
||||
// TODO(larryruili): Determine a safer way of enforcing this.
|
||||
@@ -117,7 +121,7 @@ public final class CopyDetailReportsAction implements Runnable {
|
||||
try (InputStream input =
|
||||
gcsUtils.openInputStream(
|
||||
new GcsFilename(billingBucket, invoiceDirectoryPrefix + detailReportName))) {
|
||||
driveConnection.createFile(
|
||||
driveConnection.createOrUpdateFile(
|
||||
detailReportName,
|
||||
MediaType.CSV_UTF_8,
|
||||
driveFolderId,
|
||||
@@ -129,15 +133,31 @@ public final class CopyDetailReportsAction implements Runnable {
|
||||
},
|
||||
IOException.class);
|
||||
} catch (Throwable e) {
|
||||
emailUtils.sendAlertEmail(
|
||||
String alertMessage =
|
||||
String.format(
|
||||
"Warning: CopyDetailReportsAction failed.\nEncountered: %s on file: %s",
|
||||
getRootCause(e).getMessage(), detailReportName));
|
||||
throw e;
|
||||
"Warning: CopyDetailReportsAction failed for registrar %s.\n"
|
||||
+ "Encountered: %s on file: %s",
|
||||
registrarId, getRootCause(e).getMessage(), detailReportName);
|
||||
copyErrorsBuilder.put(registrarId, e);
|
||||
logger.atSevere().withCause(e).log(alertMessage);
|
||||
}
|
||||
}
|
||||
response.setStatus(SC_OK);
|
||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||
response.setPayload("Copied detail reports.");
|
||||
StringBuilder payload = new StringBuilder().append("Copied detail reports.\n");
|
||||
ImmutableMap<String, Throwable> copyErrors = copyErrorsBuilder.build();
|
||||
if (!copyErrors.isEmpty()) {
|
||||
payload.append("The following errors were encountered:\n");
|
||||
payload.append(
|
||||
copyErrors.entrySet().stream()
|
||||
.map(
|
||||
entrySet ->
|
||||
String.format(
|
||||
"Registrar: %s\nError: %s\n",
|
||||
entrySet.getKey(), entrySet.getValue().getMessage()))
|
||||
.collect(Collectors.joining()));
|
||||
}
|
||||
response.setPayload(payload.toString());
|
||||
emailUtils.sendAlertEmail(payload.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,22 +59,19 @@ public class Spec11EmailUtils {
|
||||
private final SendEmailService emailService;
|
||||
private final InternetAddress outgoingEmailAddress;
|
||||
private final InternetAddress alertRecipientAddress;
|
||||
private final InternetAddress spec11ReplyToAddress;
|
||||
private final ImmutableList<String> spec11WebResources;
|
||||
private final String registryName;
|
||||
|
||||
@Inject
|
||||
Spec11EmailUtils(
|
||||
SendEmailService emailService,
|
||||
@Config("gSuiteOutgoingEmailAddress") InternetAddress outgoingEmailAddress,
|
||||
@Config("alertRecipientEmailAddress") InternetAddress alertRecipientAddress,
|
||||
@Config("spec11ReplyToEmailAddress") InternetAddress spec11ReplyToAddress,
|
||||
@Config("spec11OutgoingEmailAddress") InternetAddress spec11OutgoingEmailAddress,
|
||||
@Config("spec11WebResources") ImmutableList<String> spec11WebResources,
|
||||
@Config("registryName") String registryName) {
|
||||
this.emailService = emailService;
|
||||
this.outgoingEmailAddress = outgoingEmailAddress;
|
||||
this.outgoingEmailAddress = spec11OutgoingEmailAddress;
|
||||
this.alertRecipientAddress = alertRecipientAddress;
|
||||
this.spec11ReplyToAddress = spec11ReplyToAddress;
|
||||
this.spec11WebResources = spec11WebResources;
|
||||
this.registryName = registryName;
|
||||
}
|
||||
@@ -149,7 +146,7 @@ public class Spec11EmailUtils {
|
||||
.setContentType(MediaType.HTML_UTF_8)
|
||||
.setFrom(outgoingEmailAddress)
|
||||
.addRecipient(getEmailAddressForRegistrar(registrarThreatMatches.clientId()))
|
||||
.setBcc(spec11ReplyToAddress)
|
||||
.setBcc(outgoingEmailAddress)
|
||||
.build());
|
||||
}
|
||||
|
||||
@@ -172,7 +169,7 @@ public class Spec11EmailUtils {
|
||||
ImmutableMap.of(
|
||||
"date", date.toString(),
|
||||
"registry", registryName,
|
||||
"replyToEmail", spec11ReplyToAddress.getAddress(),
|
||||
"replyToEmail", outgoingEmailAddress.getAddress(),
|
||||
"threats", threatMatchMap,
|
||||
"resources", spec11WebResources);
|
||||
renderer.setData(data);
|
||||
|
||||
@@ -54,6 +54,10 @@ public class DriveConnection {
|
||||
/**
|
||||
* Creates a file with the given parent.
|
||||
*
|
||||
* <p>If a file with the same path already exists, a duplicate is created. If overwriting the
|
||||
* existing file is the desired behavior, use {@link #createOrUpdateFile(String, MediaType,
|
||||
* String, byte[])} instead.
|
||||
*
|
||||
* @returns the file id.
|
||||
*/
|
||||
public String createFile(String title, MediaType mimeType, String parentFolderId, byte[] bytes)
|
||||
|
||||
@@ -14,13 +14,12 @@
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.client.googleapis.util.Utils;
|
||||
import com.google.api.services.appengine.v1.Appengine;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.LocalCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/** Module providing the instance of {@link Appengine} to access App Engine Admin Api. */
|
||||
@@ -30,9 +29,12 @@ public abstract class AppEngineAdminApiModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
public static Appengine provideAppengine(
|
||||
@LocalCredential GoogleCredential credential, @Config("projectId") String projectId) {
|
||||
@LocalCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@Config("projectId") String projectId) {
|
||||
return new Appengine.Builder(
|
||||
Utils.getDefaultTransport(), Utils.getDefaultJsonFactory(), credential)
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.google.api.client.auth.oauth2.Credential;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets.Details;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import com.google.api.client.json.JsonFactory;
|
||||
import com.google.api.client.util.store.AbstractDataStoreFactory;
|
||||
@@ -39,10 +38,10 @@ import google.registry.config.CredentialModule.DefaultCredential;
|
||||
import google.registry.config.CredentialModule.LocalCredential;
|
||||
import google.registry.config.CredentialModule.LocalCredentialJson;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -60,14 +59,6 @@ public class AuthModule {
|
||||
private static final File DATA_STORE_DIR =
|
||||
new File(System.getProperty("user.home"), ".config/nomulus/credentials");
|
||||
|
||||
@Module
|
||||
abstract static class LocalCredentialModule {
|
||||
@Binds
|
||||
@DefaultCredential
|
||||
abstract GoogleCredential provideLocalCredentialAsDefaultCredential(
|
||||
@LocalCredential GoogleCredential credential);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@StoredCredential
|
||||
static Credential provideCredential(
|
||||
@@ -86,38 +77,21 @@ public class AuthModule {
|
||||
|
||||
@Provides
|
||||
@LocalCredential
|
||||
public static GoogleCredential provideLocalCredential(
|
||||
public static GoogleCredentialsBundle provideLocalCredential(
|
||||
@LocalCredentialJson String credentialJson,
|
||||
@Config("localCredentialOauthScopes") ImmutableList<String> scopes) {
|
||||
try {
|
||||
GoogleCredential credential =
|
||||
GoogleCredential.fromStream(new ByteArrayInputStream(credentialJson.getBytes(UTF_8)));
|
||||
GoogleCredentials credential =
|
||||
GoogleCredentials.fromStream(new ByteArrayInputStream(credentialJson.getBytes(UTF_8)));
|
||||
if (credential.createScopedRequired()) {
|
||||
credential = credential.createScoped(scopes);
|
||||
}
|
||||
return credential;
|
||||
return GoogleCredentialsBundle.create(credential);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@LocalOAuth2Credentials
|
||||
public static GoogleCredentials provideLocalOAuth2Credentials(
|
||||
@LocalCredentialJson String credentialJson,
|
||||
@Config("localCredentialOauthScopes") ImmutableList<String> scopes) {
|
||||
try {
|
||||
GoogleCredentials credentials =
|
||||
GoogleCredentials.fromStream(new ByteArrayInputStream(credentialJson.getBytes(UTF_8)));
|
||||
if (credentials.createScopedRequired()) {
|
||||
credentials = credentials.createScoped(scopes);
|
||||
}
|
||||
return credentials;
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
public static GoogleAuthorizationCodeFlow provideAuthorizationCodeFlow(
|
||||
JsonFactory jsonFactory,
|
||||
@@ -126,7 +100,7 @@ public class AuthModule {
|
||||
AbstractDataStoreFactory dataStoreFactory) {
|
||||
try {
|
||||
return new GoogleAuthorizationCodeFlow.Builder(
|
||||
new NetHttpTransport(), jsonFactory, clientSecrets, requiredOauthScopes)
|
||||
new NetHttpTransport(), jsonFactory, clientSecrets, requiredOauthScopes)
|
||||
.setDataStoreFactory(dataStoreFactory)
|
||||
.build();
|
||||
} catch (IOException ex) {
|
||||
@@ -198,16 +172,11 @@ public class AuthModule {
|
||||
}
|
||||
}
|
||||
|
||||
/** Raised when we need a user login. */
|
||||
static class LoginRequiredException extends RuntimeException {
|
||||
LoginRequiredException() {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dagger qualifier for the {@link Credential} constructed from the data stored on disk.
|
||||
*
|
||||
* <p>This {@link Credential} should not be used in another module, hence the private qualifier.
|
||||
* It's only use is to build a {@link GoogleCredential}, which is used in injection sites
|
||||
* It's only use is to build a {@link GoogleCredentials}, which is used in injection sites
|
||||
* elsewhere.
|
||||
*/
|
||||
@Qualifier
|
||||
@@ -227,9 +196,16 @@ public class AuthModule {
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface OAuthClientId {}
|
||||
|
||||
/** Dagger qualifier for the local OAuth2 Credentials. */
|
||||
@Qualifier
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface LocalOAuth2Credentials {}
|
||||
@Module
|
||||
abstract static class LocalCredentialModule {
|
||||
@Binds
|
||||
@DefaultCredential
|
||||
abstract GoogleCredentialsBundle provideLocalCredentialAsDefaultCredential(
|
||||
@LocalCredential GoogleCredentialsBundle credential);
|
||||
}
|
||||
|
||||
/** Raised when we need a user login. */
|
||||
static class LoginRequiredException extends RuntimeException {
|
||||
LoginRequiredException() {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ final class CreateAnchorTenantCommand extends MutatingEppToolCommand {
|
||||
|
||||
@Parameter(
|
||||
names = {"--contact"},
|
||||
description = "Contact ID for the request. This will be used for registrant, admin contact,"
|
||||
description = "Contact ID for the request. This will be used for registrant, admin contact, "
|
||||
+ "and tech contact.",
|
||||
required = true)
|
||||
private String contact;
|
||||
|
||||
@@ -237,7 +237,7 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
|
||||
@Nullable
|
||||
@Parameter(
|
||||
names = "--drive_folder_id",
|
||||
description = "Id of this registrar's folder in Drive",
|
||||
description = "Id (not full URL) of this registrar's folder in Drive",
|
||||
converter = OptionalStringParameter.class,
|
||||
validateWith = OptionalStringParameter.class)
|
||||
Optional<String> driveFolderId;
|
||||
|
||||
@@ -19,7 +19,6 @@ import static google.registry.util.CollectionUtils.findDuplicates;
|
||||
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -255,7 +254,7 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
|
||||
tld,
|
||||
canonicalizeDomainName(tld));
|
||||
checkArgument(
|
||||
!CharMatcher.javaDigit().matches(tld.charAt(0)),
|
||||
!Character.isDigit(tld.charAt(0)),
|
||||
"TLDs cannot begin with a number");
|
||||
Registry oldRegistry = getOldRegistry(tld);
|
||||
// TODO(b/26901539): Add a flag to set the pricing engine once we have more than one option.
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.client.http.HttpRequestFactory;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.DefaultCredential;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
|
||||
/**
|
||||
* Module for providing the HttpRequestFactory.
|
||||
@@ -30,12 +30,12 @@ import google.registry.config.RegistryConfig;
|
||||
*/
|
||||
@Module
|
||||
class RequestFactoryModule {
|
||||
|
||||
|
||||
static final int REQUEST_TIMEOUT_MS = 10 * 60 * 1000;
|
||||
|
||||
@Provides
|
||||
static HttpRequestFactory provideHttpRequestFactory(
|
||||
@DefaultCredential GoogleCredential credential) {
|
||||
@DefaultCredential GoogleCredentialsBundle credentialsBundle) {
|
||||
if (RegistryConfig.areServersLocal()) {
|
||||
return new NetHttpTransport()
|
||||
.createRequestFactory(
|
||||
@@ -47,11 +47,12 @@ class RequestFactoryModule {
|
||||
return new NetHttpTransport()
|
||||
.createRequestFactory(
|
||||
request -> {
|
||||
credential.initialize(request);
|
||||
credentialsBundle.getHttpRequestInitializer().initialize(request);
|
||||
// GAE request times out after 10 min, so here we set the timeout to 10 min. This is
|
||||
// needed to support some nomulus commands like updating premium lists that take
|
||||
// a lot of time to complete.
|
||||
// See https://developers.google.com/api-client-library/java/google-api-java-client/errors
|
||||
// See
|
||||
// https://developers.google.com/api-client-library/java/google-api-java-client/errors
|
||||
request.setConnectTimeout(REQUEST_TIMEOUT_MS);
|
||||
request.setReadTimeout(REQUEST_TIMEOUT_MS);
|
||||
});
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
# -*-protobuf-*-
|
||||
|
||||
requirement: {
|
||||
type: BANNED_PROPERTY_WRITE
|
||||
error_message: 'Assignment to Element.prototype.innerHTML is not allowed. '
|
||||
'Use goog.dom.safe.setInnerHtml instead. '
|
||||
value: 'Element.prototype.innerHTML'
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<!doctype html>
|
||||
<meta http-equiv="refresh" content="0;URL=/registrar">
|
||||
<title>Nomulus</title>
|
||||
<body>
|
||||
<body lang="en-US">
|
||||
If this page doesn't change automatically, please go
|
||||
to <a href="/registrar">https://www.registry.google/registrar</a>
|
||||
|
||||
@@ -1,410 +0,0 @@
|
||||
# Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# .'``'. ...
|
||||
# :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
|
||||
#
|
||||
|
||||
pkginfo_generated_files = [
|
||||
"contact/package-info.java",
|
||||
"domain/package-info.java",
|
||||
"dsig/package-info.java",
|
||||
"epp/package-info.java",
|
||||
"eppcom/package-info.java",
|
||||
"fee06/package-info.java",
|
||||
"fee11/package-info.java",
|
||||
"fee12/package-info.java",
|
||||
"host/package-info.java",
|
||||
"iirdea/package-info.java",
|
||||
"launch/package-info.java",
|
||||
"mark/package-info.java",
|
||||
"rde/package-info.java",
|
||||
"rdecontact/package-info.java",
|
||||
"rdedomain/package-info.java",
|
||||
"rdeeppparams/package-info.java",
|
||||
"rdeheader/package-info.java",
|
||||
"rdehost/package-info.java",
|
||||
"rdeidn/package-info.java",
|
||||
"rdenndn/package-info.java",
|
||||
"rdenotification/package-info.java",
|
||||
"rdepolicy/package-info.java",
|
||||
"rderegistrar/package-info.java",
|
||||
"rdereport/package-info.java",
|
||||
"rgp/package-info.java",
|
||||
"secdns/package-info.java",
|
||||
"smd/package-info.java",
|
||||
]
|
||||
|
||||
xjc_generated_files = [
|
||||
"contact/ObjectFactory.java",
|
||||
"contact/XjcContactAddRemType.java",
|
||||
"contact/XjcContactAddrType.java",
|
||||
"contact/XjcContactAuthIDType.java",
|
||||
"contact/XjcContactAuthInfoType.java",
|
||||
"contact/XjcContactCheck.java",
|
||||
"contact/XjcContactCheckIDType.java",
|
||||
"contact/XjcContactCheckType.java",
|
||||
"contact/XjcContactChgPostalInfoType.java",
|
||||
"contact/XjcContactChgType.java",
|
||||
"contact/XjcContactChkData.java",
|
||||
"contact/XjcContactCreData.java",
|
||||
"contact/XjcContactCreate.java",
|
||||
"contact/XjcContactDelete.java",
|
||||
"contact/XjcContactDiscloseType.java",
|
||||
"contact/XjcContactE164Type.java",
|
||||
"contact/XjcContactInfData.java",
|
||||
"contact/XjcContactInfo.java",
|
||||
"contact/XjcContactIntLocType.java",
|
||||
"contact/XjcContactPaCLIDType.java",
|
||||
"contact/XjcContactPanData.java",
|
||||
"contact/XjcContactPostalInfoEnumType.java",
|
||||
"contact/XjcContactPostalInfoType.java",
|
||||
"contact/XjcContactStatusType.java",
|
||||
"contact/XjcContactStatusValueType.java",
|
||||
"contact/XjcContactTransfer.java",
|
||||
"contact/XjcContactTrnData.java",
|
||||
"contact/XjcContactUpdate.java",
|
||||
"domain/ObjectFactory.java",
|
||||
"domain/XjcDomainAddRemType.java",
|
||||
"domain/XjcDomainAuthInfoChgType.java",
|
||||
"domain/XjcDomainAuthInfoType.java",
|
||||
"domain/XjcDomainCheck.java",
|
||||
"domain/XjcDomainCheckNameType.java",
|
||||
"domain/XjcDomainCheckType.java",
|
||||
"domain/XjcDomainChgType.java",
|
||||
"domain/XjcDomainChkData.java",
|
||||
"domain/XjcDomainContactAttrType.java",
|
||||
"domain/XjcDomainContactType.java",
|
||||
"domain/XjcDomainCreData.java",
|
||||
"domain/XjcDomainCreate.java",
|
||||
"domain/XjcDomainDelete.java",
|
||||
"domain/XjcDomainHostAttrType.java",
|
||||
"domain/XjcDomainHostsType.java",
|
||||
"domain/XjcDomainInfData.java",
|
||||
"domain/XjcDomainInfo.java",
|
||||
"domain/XjcDomainInfoNameType.java",
|
||||
"domain/XjcDomainNsType.java",
|
||||
"domain/XjcDomainPUnitType.java",
|
||||
"domain/XjcDomainPaNameType.java",
|
||||
"domain/XjcDomainPanData.java",
|
||||
"domain/XjcDomainPeriodType.java",
|
||||
"domain/XjcDomainRenData.java",
|
||||
"domain/XjcDomainRenew.java",
|
||||
"domain/XjcDomainStatusType.java",
|
||||
"domain/XjcDomainStatusValueType.java",
|
||||
"domain/XjcDomainTransfer.java",
|
||||
"domain/XjcDomainTrnData.java",
|
||||
"domain/XjcDomainUpdate.java",
|
||||
"dsig/ObjectFactory.java",
|
||||
"dsig/XjcDsigCanonicalizationMethod.java",
|
||||
"dsig/XjcDsigDSAKeyValue.java",
|
||||
"dsig/XjcDsigDigestMethod.java",
|
||||
"dsig/XjcDsigDigestValue.java",
|
||||
"dsig/XjcDsigKeyInfo.java",
|
||||
"dsig/XjcDsigKeyName.java",
|
||||
"dsig/XjcDsigKeyValue.java",
|
||||
"dsig/XjcDsigManifest.java",
|
||||
"dsig/XjcDsigMgmtData.java",
|
||||
"dsig/XjcDsigObject.java",
|
||||
"dsig/XjcDsigPGPData.java",
|
||||
"dsig/XjcDsigRSAKeyValue.java",
|
||||
"dsig/XjcDsigReference.java",
|
||||
"dsig/XjcDsigRetrievalMethod.java",
|
||||
"dsig/XjcDsigSPKIData.java",
|
||||
"dsig/XjcDsigSignature.java",
|
||||
"dsig/XjcDsigSignatureMethod.java",
|
||||
"dsig/XjcDsigSignatureProperties.java",
|
||||
"dsig/XjcDsigSignatureProperty.java",
|
||||
"dsig/XjcDsigSignatureValue.java",
|
||||
"dsig/XjcDsigSignedInfo.java",
|
||||
"dsig/XjcDsigTransform.java",
|
||||
"dsig/XjcDsigTransforms.java",
|
||||
"dsig/XjcDsigX509Data.java",
|
||||
"dsig/XjcDsigX509IssuerSerialType.java",
|
||||
"epp/ObjectFactory.java",
|
||||
"epp/XjcEpp.java",
|
||||
"epp/XjcEppCommandType.java",
|
||||
"epp/XjcEppCredsOptionsType.java",
|
||||
"epp/XjcEppDcpAccessType.java",
|
||||
"epp/XjcEppDcpExpiryType.java",
|
||||
"epp/XjcEppDcpOursType.java",
|
||||
"epp/XjcEppDcpPurposeType.java",
|
||||
"epp/XjcEppDcpRecipientType.java",
|
||||
"epp/XjcEppDcpRetentionType.java",
|
||||
"epp/XjcEppDcpStatementType.java",
|
||||
"epp/XjcEppDcpType.java",
|
||||
"epp/XjcEppElement.java",
|
||||
"epp/XjcEppErrValueType.java",
|
||||
"epp/XjcEppExtAnyType.java",
|
||||
"epp/XjcEppExtErrValueType.java",
|
||||
"epp/XjcEppExtURIType.java",
|
||||
"epp/XjcEppGreetingType.java",
|
||||
"epp/XjcEppLoginSvcType.java",
|
||||
"epp/XjcEppLoginType.java",
|
||||
"epp/XjcEppMixedMsgType.java",
|
||||
"epp/XjcEppMsgQType.java",
|
||||
"epp/XjcEppMsgType.java",
|
||||
"epp/XjcEppPollOpType.java",
|
||||
"epp/XjcEppPollType.java",
|
||||
"epp/XjcEppReadWriteType.java",
|
||||
"epp/XjcEppResponse.java",
|
||||
"epp/XjcEppResultType.java",
|
||||
"epp/XjcEppSvcMenuType.java",
|
||||
"epp/XjcEppTrIDType.java",
|
||||
"epp/XjcEppTransferOpType.java",
|
||||
"epp/XjcEppTransferType.java",
|
||||
"eppcom/ObjectFactory.java",
|
||||
"eppcom/XjcEppcomExtAuthInfoType.java",
|
||||
"eppcom/XjcEppcomPwAuthInfoType.java",
|
||||
"eppcom/XjcEppcomReasonType.java",
|
||||
"eppcom/XjcEppcomTrStatusType.java",
|
||||
"fee06/ObjectFactory.java",
|
||||
"fee06/XjcFee06Check.java",
|
||||
"fee06/XjcFee06ChkData.java",
|
||||
"fee06/XjcFee06CommandType.java",
|
||||
"fee06/XjcFee06CreData.java",
|
||||
"fee06/XjcFee06Create.java",
|
||||
"fee06/XjcFee06CreditType.java",
|
||||
"fee06/XjcFee06DelData.java",
|
||||
"fee06/XjcFee06DomainCDType.java",
|
||||
"fee06/XjcFee06DomainCheckType.java",
|
||||
"fee06/XjcFee06FeeType.java",
|
||||
"fee06/XjcFee06InfData.java",
|
||||
"fee06/XjcFee06Info.java",
|
||||
"fee06/XjcFee06RenData.java",
|
||||
"fee06/XjcFee06Renew.java",
|
||||
"fee06/XjcFee06Transfer.java",
|
||||
"fee06/XjcFee06TransformCommandType.java",
|
||||
"fee06/XjcFee06TransformResultType.java",
|
||||
"fee06/XjcFee06TrnData.java",
|
||||
"fee06/XjcFee06UpdData.java",
|
||||
"fee06/XjcFee06Update.java",
|
||||
"fee11/ObjectFactory.java",
|
||||
"fee11/XjcFee11Check.java",
|
||||
"fee11/XjcFee11ChkData.java",
|
||||
"fee11/XjcFee11CommandType.java",
|
||||
"fee11/XjcFee11CreData.java",
|
||||
"fee11/XjcFee11Create.java",
|
||||
"fee11/XjcFee11CreditType.java",
|
||||
"fee11/XjcFee11DelData.java",
|
||||
"fee11/XjcFee11FeeType.java",
|
||||
"fee11/XjcFee11ObjectCDType.java",
|
||||
"fee11/XjcFee11RenData.java",
|
||||
"fee11/XjcFee11Renew.java",
|
||||
"fee11/XjcFee11Transfer.java",
|
||||
"fee11/XjcFee11TransformCommandType.java",
|
||||
"fee11/XjcFee11TransformResultType.java",
|
||||
"fee11/XjcFee11TrnData.java",
|
||||
"fee11/XjcFee11UpdData.java",
|
||||
"fee11/XjcFee11Update.java",
|
||||
"fee12/ObjectFactory.java",
|
||||
"fee12/XjcFee12Check.java",
|
||||
"fee12/XjcFee12ChkData.java",
|
||||
"fee12/XjcFee12CommandCDType.java",
|
||||
"fee12/XjcFee12CommandCheckType.java",
|
||||
"fee12/XjcFee12CreData.java",
|
||||
"fee12/XjcFee12Create.java",
|
||||
"fee12/XjcFee12CreditType.java",
|
||||
"fee12/XjcFee12DelData.java",
|
||||
"fee12/XjcFee12FeeType.java",
|
||||
"fee12/XjcFee12ObjectCDType.java",
|
||||
"fee12/XjcFee12RenData.java",
|
||||
"fee12/XjcFee12Renew.java",
|
||||
"fee12/XjcFee12Transfer.java",
|
||||
"fee12/XjcFee12TransformCommandType.java",
|
||||
"fee12/XjcFee12TransformResultType.java",
|
||||
"fee12/XjcFee12TrnData.java",
|
||||
"fee12/XjcFee12UpdData.java",
|
||||
"fee12/XjcFee12Update.java",
|
||||
"host/ObjectFactory.java",
|
||||
"host/XjcHostAddRemType.java",
|
||||
"host/XjcHostAddrType.java",
|
||||
"host/XjcHostCheck.java",
|
||||
"host/XjcHostCheckNameType.java",
|
||||
"host/XjcHostCheckType.java",
|
||||
"host/XjcHostChgType.java",
|
||||
"host/XjcHostChkData.java",
|
||||
"host/XjcHostCreData.java",
|
||||
"host/XjcHostCreate.java",
|
||||
"host/XjcHostDelete.java",
|
||||
"host/XjcHostInfData.java",
|
||||
"host/XjcHostInfo.java",
|
||||
"host/XjcHostIpType.java",
|
||||
"host/XjcHostPaNameType.java",
|
||||
"host/XjcHostPanData.java",
|
||||
"host/XjcHostSNameType.java",
|
||||
"host/XjcHostStatusType.java",
|
||||
"host/XjcHostStatusValueType.java",
|
||||
"host/XjcHostUpdate.java",
|
||||
"iirdea/ObjectFactory.java",
|
||||
"iirdea/XjcIirdeaCode.java",
|
||||
"iirdea/XjcIirdeaResponse.java",
|
||||
"iirdea/XjcIirdeaResponseElement.java",
|
||||
"iirdea/XjcIirdeaResult.java",
|
||||
"launch/ObjectFactory.java",
|
||||
"launch/XjcLaunchCdNameType.java",
|
||||
"launch/XjcLaunchCdType.java",
|
||||
"launch/XjcLaunchCheck.java",
|
||||
"launch/XjcLaunchCheckFormType.java",
|
||||
"launch/XjcLaunchChkData.java",
|
||||
"launch/XjcLaunchClaimKeyType.java",
|
||||
"launch/XjcLaunchCodeMarkType.java",
|
||||
"launch/XjcLaunchCodeType.java",
|
||||
"launch/XjcLaunchCreData.java",
|
||||
"launch/XjcLaunchCreate.java",
|
||||
"launch/XjcLaunchCreateNoticeType.java",
|
||||
"launch/XjcLaunchDelete.java",
|
||||
"launch/XjcLaunchIdContainerType.java",
|
||||
"launch/XjcLaunchInfData.java",
|
||||
"launch/XjcLaunchInfo.java",
|
||||
"launch/XjcLaunchNoticeIDType.java",
|
||||
"launch/XjcLaunchObjectType.java",
|
||||
"launch/XjcLaunchPhaseType.java",
|
||||
"launch/XjcLaunchPhaseTypeValue.java",
|
||||
"launch/XjcLaunchStatusType.java",
|
||||
"launch/XjcLaunchStatusValueType.java",
|
||||
"launch/XjcLaunchUpdate.java",
|
||||
"mark/ObjectFactory.java",
|
||||
"mark/XjcMarkAbstractMark.java",
|
||||
"mark/XjcMarkAbstractMarkType.java",
|
||||
"mark/XjcMarkAddrType.java",
|
||||
"mark/XjcMarkContactType.java",
|
||||
"mark/XjcMarkContactTypeType.java",
|
||||
"mark/XjcMarkCourtType.java",
|
||||
"mark/XjcMarkE164Type.java",
|
||||
"mark/XjcMarkEntitlementType.java",
|
||||
"mark/XjcMarkHolderType.java",
|
||||
"mark/XjcMarkMark.java",
|
||||
"mark/XjcMarkMarkType.java",
|
||||
"mark/XjcMarkProtectionType.java",
|
||||
"mark/XjcMarkTrademarkType.java",
|
||||
"mark/XjcMarkTreatyOrStatuteType.java",
|
||||
"rde/ObjectFactory.java",
|
||||
"rde/XjcRdeContent.java",
|
||||
"rde/XjcRdeContentType.java",
|
||||
"rde/XjcRdeContentsType.java",
|
||||
"rde/XjcRdeDelete.java",
|
||||
"rde/XjcRdeDeleteType.java",
|
||||
"rde/XjcRdeDeletesType.java",
|
||||
"rde/XjcRdeDeposit.java",
|
||||
"rde/XjcRdeDepositTypeType.java",
|
||||
"rde/XjcRdeMenuType.java",
|
||||
"rde/XjcRdeRrType.java",
|
||||
"rdecontact/ObjectFactory.java",
|
||||
"rdecontact/XjcRdeContact.java",
|
||||
"rdecontact/XjcRdeContactAbstract.java",
|
||||
"rdecontact/XjcRdeContactDelete.java",
|
||||
"rdecontact/XjcRdeContactDeleteType.java",
|
||||
"rdecontact/XjcRdeContactElement.java",
|
||||
"rdecontact/XjcRdeContactTransferDataType.java",
|
||||
"rdedomain/ObjectFactory.java",
|
||||
"rdedomain/XjcRdeDomain.java",
|
||||
"rdedomain/XjcRdeDomainAbstract.java",
|
||||
"rdedomain/XjcRdeDomainDelete.java",
|
||||
"rdedomain/XjcRdeDomainDeleteType.java",
|
||||
"rdedomain/XjcRdeDomainElement.java",
|
||||
"rdedomain/XjcRdeDomainTransferDataType.java",
|
||||
"rdeeppparams/ObjectFactory.java",
|
||||
"rdeeppparams/XjcRdeEppParams.java",
|
||||
"rdeeppparams/XjcRdeEppParamsAbstract.java",
|
||||
"rdeeppparams/XjcRdeEppParamsElement.java",
|
||||
"rdeheader/ObjectFactory.java",
|
||||
"rdeheader/XjcRdeHeader.java",
|
||||
"rdeheader/XjcRdeHeaderCount.java",
|
||||
"rdeheader/XjcRdeHeaderElement.java",
|
||||
"rdehost/ObjectFactory.java",
|
||||
"rdehost/XjcRdeHost.java",
|
||||
"rdehost/XjcRdeHostAbstractHost.java",
|
||||
"rdehost/XjcRdeHostDelete.java",
|
||||
"rdehost/XjcRdeHostDeleteType.java",
|
||||
"rdehost/XjcRdeHostElement.java",
|
||||
"rdeidn/ObjectFactory.java",
|
||||
"rdeidn/XjcRdeIdn.java",
|
||||
"rdeidn/XjcRdeIdnDelete.java",
|
||||
"rdeidn/XjcRdeIdnDeleteType.java",
|
||||
"rdeidn/XjcRdeIdnElement.java",
|
||||
"rdenndn/ObjectFactory.java",
|
||||
"rdenndn/XjcRdeNndn.java",
|
||||
"rdenndn/XjcRdeNndnAbstract.java",
|
||||
"rdenndn/XjcRdeNndnDelete.java",
|
||||
"rdenndn/XjcRdeNndnDeleteType.java",
|
||||
"rdenndn/XjcRdeNndnElement.java",
|
||||
"rdenndn/XjcRdeNndnNameState.java",
|
||||
"rdenndn/XjcRdeNndnNameStateValue.java",
|
||||
"rdenotification/ObjectFactory.java",
|
||||
"rdenotification/XjcRdeNotification.java",
|
||||
"rdenotification/XjcRdeNotificationElement.java",
|
||||
"rdenotification/XjcRdeNotificationName.java",
|
||||
"rdenotification/XjcRdeNotificationStatusType.java",
|
||||
"rdepolicy/ObjectFactory.java",
|
||||
"rdepolicy/XjcRdePolicy.java",
|
||||
"rdepolicy/XjcRdePolicyElement.java",
|
||||
"rderegistrar/ObjectFactory.java",
|
||||
"rderegistrar/XjcRdeRegistrar.java",
|
||||
"rderegistrar/XjcRdeRegistrarAbstract.java",
|
||||
"rderegistrar/XjcRdeRegistrarAddrType.java",
|
||||
"rderegistrar/XjcRdeRegistrarDelete.java",
|
||||
"rderegistrar/XjcRdeRegistrarDeleteType.java",
|
||||
"rderegistrar/XjcRdeRegistrarElement.java",
|
||||
"rderegistrar/XjcRdeRegistrarPostalInfoEnumType.java",
|
||||
"rderegistrar/XjcRdeRegistrarPostalInfoType.java",
|
||||
"rderegistrar/XjcRdeRegistrarStatusType.java",
|
||||
"rderegistrar/XjcRdeRegistrarWhoisInfoType.java",
|
||||
"rdereport/ObjectFactory.java",
|
||||
"rdereport/XjcRdeReport.java",
|
||||
"rdereport/XjcRdeReportReport.java",
|
||||
"rgp/ObjectFactory.java",
|
||||
"rgp/XjcRgpInfData.java",
|
||||
"rgp/XjcRgpMixedType.java",
|
||||
"rgp/XjcRgpOpType.java",
|
||||
"rgp/XjcRgpReportTextType.java",
|
||||
"rgp/XjcRgpReportType.java",
|
||||
"rgp/XjcRgpRespDataType.java",
|
||||
"rgp/XjcRgpRestoreType.java",
|
||||
"rgp/XjcRgpStatusType.java",
|
||||
"rgp/XjcRgpStatusValueType.java",
|
||||
"rgp/XjcRgpUpData.java",
|
||||
"rgp/XjcRgpUpdate.java",
|
||||
"secdns/ObjectFactory.java",
|
||||
"secdns/XjcSecdnsChgType.java",
|
||||
"secdns/XjcSecdnsCreate.java",
|
||||
"secdns/XjcSecdnsDsDataType.java",
|
||||
"secdns/XjcSecdnsDsOrKeyType.java",
|
||||
"secdns/XjcSecdnsInfData.java",
|
||||
"secdns/XjcSecdnsKeyDataType.java",
|
||||
"secdns/XjcSecdnsRemType.java",
|
||||
"secdns/XjcSecdnsUpdate.java",
|
||||
"smd/ObjectFactory.java",
|
||||
"smd/XjcSmdAbstractSignedMark.java",
|
||||
"smd/XjcSmdAbstractSignedMarkElement.java",
|
||||
"smd/XjcSmdEncodedSignedMark.java",
|
||||
"smd/XjcSmdIssuerInfo.java",
|
||||
"smd/XjcSmdSignedMark.java",
|
||||
"smd/XjcSmdSignedMarkElement.java",
|
||||
]
|
||||
+89
@@ -4402,3 +4402,92 @@ Component: Footers
|
||||
border:1px solid #a7a7a7;
|
||||
border-bottom:0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
Blue style override
|
||||
------------------------------------------------------------------*/
|
||||
|
||||
.componentName, #stickersheet h2.componentName a { color: #dd4b3a; }
|
||||
.kd-content-sidebar .kd-sidebarlistitem.selected > a { border-left-color:#dd4b3a; }
|
||||
.kd-appbar .kd-appname, .kd-appbar .kd-appname a { color:#dd4b3a; }
|
||||
|
||||
.kd-button-submit.disabled, .kd-button-submit.disabled:hover, .kd-button-submit.disabled:active {
|
||||
border-color:#3079ee;
|
||||
background-color: #4d90ff;
|
||||
}
|
||||
.kd-button-action.disabled, .kd-button-action.disabled:hover, .kd-button-action.disabled:active {
|
||||
border-color: #b0281b;
|
||||
background-color: #d14837;
|
||||
}
|
||||
|
||||
.kd-button-submit:focus, .kd-button-submit.focus{
|
||||
border-color:#4d90ff
|
||||
}
|
||||
.kd-button-action:focus, .kd-button-action.focus{
|
||||
border-color:#d14837;
|
||||
}
|
||||
|
||||
.kd-button-submit {
|
||||
border-color: #3079ee;
|
||||
background-color: #4d90ff;
|
||||
background-image: -webkit-gradient(linear,left top,left bottom,from(#4d90ff),to(#4787ed));
|
||||
/* @alternate */ background-image: -webkit-linear-gradient(top,#4d90ff,#4787ed);
|
||||
/* @alternate */ background-image: -moz-linear-gradient(top,#4d90ff,#4787ed);
|
||||
/* @alternate */ background-image: -ms-linear-gradient(top,#4d90ff,#4787ed);
|
||||
/* @alternate */ background-image: -o-linear-gradient(top,#4d90ff,#4787ed);
|
||||
/* @alternate */ background-image: linear-gradient(top,#4d90ff,#4787ed);
|
||||
/* filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#4d90ff',EndColorStr='#4787ed'); */
|
||||
}
|
||||
.kd-button-submit:hover {
|
||||
border-color: #2f5bb8;
|
||||
background-color: #357ae9;
|
||||
background-image: -webkit-gradient(linear,left top,left bottom,from(#4d90ff),to(#357ae9));
|
||||
/* @alternate */ background-image: -webkit-linear-gradient(top,#4d90ff,#357ae9);
|
||||
/* @alternate */ background-image: -moz-linear-gradient(top,#4d90ff,#357ae9);
|
||||
/* @alternate */ background-image: -ms-linear-gradient(top,#4d90ff,#357ae9);
|
||||
/* @alternate */ background-image: -o-linear-gradient(top,#4d90ff,#357ae9);
|
||||
/* @alternate */ background-image: linear-gradient(top,#4d90ff,#357ae9);
|
||||
/* filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#4d90ff',EndColorStr='#357ae9'); */
|
||||
}
|
||||
|
||||
.kd-button-action {
|
||||
margin-bottom: 16px;
|
||||
border: 1px solid transparent;
|
||||
color: #fff;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1;
|
||||
background-color: #d14837;
|
||||
background-image: -webkit-gradient(linear,left top,left bottom,from(#dd4b3a),to(#d14837));
|
||||
/* @alternate */ background-image: -webkit-linear-gradient(top,#dd4b3a,#d14837);
|
||||
/* @alternate */ background-image: -moz-linear-gradient(top,#dd4b3a,#d14837);
|
||||
/* @alternate */ background-image: -ms-linear-gradient(top,#dd4b3a,#d14837);
|
||||
/* @alternate */ background-image: -o-linear-gradient(top,#dd4b3a,#d14837);
|
||||
/* @alternate */ background-image: linear-gradient(top,#dd4b3a,#d14837);
|
||||
/* filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#dd4b3a',EndColorStr='#d14837'); */
|
||||
}
|
||||
.kd-button-action:hover {
|
||||
border-color: #b0281b;
|
||||
border-bottom-color: #af3020;
|
||||
background-color: #c53728;
|
||||
background-image: -webkit-gradient(linear,left top,left bottom,from(#dd4b3a),to(#c53728));
|
||||
/* @alternate */ background-image: -webkit-linear-gradient(top,#dd4b3a,#c53728);
|
||||
/* @alternate */ background-image: -moz-linear-gradient(top,#dd4b3a,#c53728);
|
||||
/* @alternate */ background-image: -ms-linear-gradient(top,#dd4b3a,#c53728);
|
||||
/* @alternate */ background-image: -o-linear-gradient(top,#dd4b3a,#c53728);
|
||||
/* @alternate */ background-image: linear-gradient(top,#dd4b3a,#c53728);
|
||||
/* filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#dd4b3a',EndColorStr='#c53728'); */
|
||||
}
|
||||
.kd-button-action:active,
|
||||
.kd-button-action:focus:active,
|
||||
.kd-button-action.focus:active {
|
||||
border-color: #992a1c;
|
||||
background-color: #b0281b;
|
||||
background-image: -webkit-gradient(linear,left top,left bottom,from(#dd4b3a),to(#b0281b));
|
||||
/* @alternate */ background-image: -webkit-linear-gradient(top,#dd4b3a,#b0281b);
|
||||
/* @alternate */ background-image: -moz-linear-gradient(top,#dd4b3a,#b0281b);
|
||||
/* @alternate */ background-image: -ms-linear-gradient(top,#dd4b3a,#b0281b);
|
||||
/* @alternate */ background-image: -o-linear-gradient(top,#dd4b3a,#b0281b);
|
||||
/* @alternate */ background-image: linear-gradient(top,#dd4b3a,#b0281b);
|
||||
}
|
||||
|
||||
.kd-accordion .expanded .row > a { color:#d14837; }
|
||||
@@ -69,7 +69,7 @@
|
||||
{@param logoutUrl: string}
|
||||
{@param logoFilename: string}
|
||||
{@param productName: string}
|
||||
<div id="kd-googlebar" role="banner">
|
||||
<div id="kd-googlebar" role="banner" lang="en-US">
|
||||
<a class="{css('logo')}" href="/registrar">
|
||||
<img src="/assets/images/{$logoFilename}" alt="{$productName}">
|
||||
</a>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
{param analyticsConfig: $analyticsConfig /}
|
||||
{/call}
|
||||
{call registry.soy.console.googlebar data="all" /}
|
||||
<div id="reg-app">
|
||||
<div id="reg-app" lang="en-US">
|
||||
<div id="reg-appbar" class="{css('kd-appbar')}">
|
||||
<div class="{css('kd-description')}">
|
||||
Accessing <span class="{css('kd-value')}">{$clientId}</span> as{sp}
|
||||
|
||||
@@ -240,12 +240,12 @@
|
||||
{param required: true /}
|
||||
{/call}
|
||||
{call registry.soy.forms.inputFieldRowWithValue}
|
||||
{param label: 'DRIVE ID' /}
|
||||
{param label: 'Drive ID' /}
|
||||
{param name: 'driveId' /}
|
||||
{param value: $driveId /}
|
||||
{param placeholder: 'required' /}
|
||||
{param description kind="text"}
|
||||
Id of this registrar's folder in Drive.
|
||||
ID (not full URL) of this registrar's folder in Google Drive.
|
||||
{/param}
|
||||
{param required: true /}
|
||||
{/call}
|
||||
|
||||
@@ -16,8 +16,10 @@ package google.registry.beam.invoicing;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import google.registry.util.ResourceUtils;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -58,15 +60,17 @@ public class InvoicingPipelineTest {
|
||||
|
||||
@Before
|
||||
public void initializePipeline() throws IOException {
|
||||
invoicingPipeline = new InvoicingPipeline();
|
||||
invoicingPipeline.projectId = "test-project";
|
||||
File beamTempFolder = tempFolder.newFolder();
|
||||
invoicingPipeline.beamBucketUrl = beamTempFolder.getAbsolutePath();
|
||||
invoicingPipeline.invoiceFilePrefix = "REG-INV";
|
||||
invoicingPipeline.beamStagingUrl = beamTempFolder.getAbsolutePath() + "/staging";
|
||||
invoicingPipeline.invoiceTemplateUrl =
|
||||
beamTempFolder.getAbsolutePath() + "/templates/invoicing";
|
||||
invoicingPipeline.billingBucketUrl = tempFolder.getRoot().getAbsolutePath();
|
||||
String beamTempFolderPath = beamTempFolder.getAbsolutePath();
|
||||
invoicingPipeline = new InvoicingPipeline(
|
||||
"test-project",
|
||||
beamTempFolderPath,
|
||||
beamTempFolderPath + "/templates/invoicing",
|
||||
beamTempFolderPath + "/staging",
|
||||
tempFolder.getRoot().getAbsolutePath(),
|
||||
"REG-INV",
|
||||
GoogleCredentialsBundle.create(GoogleCredentials.create(null))
|
||||
);
|
||||
}
|
||||
|
||||
private ImmutableList<BillingEvent> getInputEvents() {
|
||||
|
||||
@@ -21,11 +21,13 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.withSettings;
|
||||
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.io.CharStreams;
|
||||
import google.registry.beam.spec11.SafeBrowsingTransforms.EvaluateSafeBrowsingFn;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeSleeper;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import google.registry.util.ResourceUtils;
|
||||
import google.registry.util.Retrier;
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -50,6 +52,7 @@ import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.BasicHttpEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.joda.time.DateTime;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@@ -78,16 +81,21 @@ public class Spec11PipelineTest {
|
||||
@Rule public final transient TestPipeline p = TestPipeline.fromOptions(pipelineOptions);
|
||||
@Rule public final TemporaryFolder tempFolder = new TemporaryFolder();
|
||||
|
||||
private final Retrier retrier = new Retrier(
|
||||
new FakeSleeper(new FakeClock(DateTime.parse("2019-07-15TZ"))), 1);
|
||||
private Spec11Pipeline spec11Pipeline;
|
||||
|
||||
@Before
|
||||
public void initializePipeline() throws IOException {
|
||||
spec11Pipeline = new Spec11Pipeline();
|
||||
spec11Pipeline.projectId = "test-project";
|
||||
spec11Pipeline.reportingBucketUrl = tempFolder.getRoot().getAbsolutePath();
|
||||
File beamTempFolder = tempFolder.newFolder();
|
||||
spec11Pipeline.beamStagingUrl = beamTempFolder.getAbsolutePath() + "/staging";
|
||||
spec11Pipeline.spec11TemplateUrl = beamTempFolder.getAbsolutePath() + "/templates/invoicing";
|
||||
spec11Pipeline = new Spec11Pipeline(
|
||||
"test-project",
|
||||
beamTempFolder.getAbsolutePath() + "/staging",
|
||||
beamTempFolder.getAbsolutePath() + "/templates/invoicing",
|
||||
tempFolder.getRoot().getAbsolutePath(),
|
||||
GoogleCredentialsBundle.create(GoogleCredentials.create(null)),
|
||||
retrier
|
||||
);
|
||||
}
|
||||
|
||||
private static final ImmutableList<String> BAD_DOMAINS =
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
hello
|
||||
@@ -1 +0,0 @@
|
||||
OMG IM AN OVERRIDE
|
||||
@@ -1 +0,0 @@
|
||||
world
|
||||
@@ -1,66 +0,0 @@
|
||||
# Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Build rule for unit testing the zip_file() rule."""
|
||||
|
||||
load("//java/google/registry/builddefs:defs.bzl", "ZIPPER")
|
||||
|
||||
def _impl(ctx):
|
||||
"""Implementation of zip_contents_test() rule."""
|
||||
cmd = [
|
||||
"set -e",
|
||||
'repo="$(pwd)"',
|
||||
'zipper="${repo}/%s"' % ctx.file._zipper.short_path,
|
||||
'archive="${repo}/%s"' % ctx.file.src.short_path,
|
||||
('listing="$("${zipper}" v "${archive}"' +
|
||||
' | grep -v ^d | awk \'{print $3}\' | LC_ALL=C sort)"'),
|
||||
'if [[ "${listing}" != "%s" ]]; then' % (
|
||||
"\n".join(ctx.attr.contents.keys())
|
||||
),
|
||||
' echo "archive had different file listing:"',
|
||||
' "${zipper}" v "${archive}" | grep -v ^d',
|
||||
" exit 1",
|
||||
"fi",
|
||||
'tmp="$(mktemp -d "${TMPDIR:-/tmp}/zip_contents_test.XXXXXXXXXX")"',
|
||||
'cd "${tmp}"',
|
||||
'"${zipper}" x "${archive}"',
|
||||
]
|
||||
for path, data in ctx.attr.contents.items():
|
||||
cmd += [
|
||||
'if [[ "$(cat "%s")" != "%s" ]]; then' % (path, data),
|
||||
' echo "%s had different contents:"' % path,
|
||||
' cat "%s"' % path,
|
||||
" exit 1",
|
||||
"fi",
|
||||
]
|
||||
cmd += [
|
||||
'cd "${repo}"',
|
||||
'rm -rf "${tmp}"',
|
||||
]
|
||||
ctx.actions.write(
|
||||
output = ctx.outputs.executable,
|
||||
content = "\n".join(cmd),
|
||||
is_executable = True,
|
||||
)
|
||||
return struct(runfiles = ctx.runfiles([ctx.file.src, ctx.file._zipper]))
|
||||
|
||||
zip_contents_test = rule(
|
||||
implementation = _impl,
|
||||
test = True,
|
||||
attrs = {
|
||||
"src": attr.label(allow_single_file = True),
|
||||
"contents": attr.string_dict(),
|
||||
"_zipper": attr.label(default = Label(ZIPPER), allow_single_file = True),
|
||||
},
|
||||
)
|
||||
@@ -96,7 +96,7 @@ public class FlowContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to locate test files for this flow by looking in javatests/ for all files with the
|
||||
* Helper to locate test files for this flow by looking in src/test/java/ for all files with the
|
||||
* exact same relative filename as the flow file, but with a "*Test{,Case}.java" suffix.
|
||||
*/
|
||||
private static Set<String> getTestFilenames(String flowName) throws IOException {
|
||||
|
||||
@@ -35,10 +35,10 @@ import org.junit.runners.JUnit4;
|
||||
* condition. For example, there should always be a matching pair of lines such as the following:
|
||||
*
|
||||
* <pre>
|
||||
* java/.../flows/session/LoginFlow.java:
|
||||
* src/main/java/.../flows/session/LoginFlow.java:
|
||||
* @error {@link AlreadyLoggedInException}
|
||||
*
|
||||
* javatests/.../flows/session/LoginFlowTest.java:
|
||||
* src/test/java/.../flows/session/LoginFlowTest.java:
|
||||
* import .....flows.session.LoginFlow.AlreadyLoggedInException;
|
||||
* </pre>
|
||||
*
|
||||
|
||||
@@ -17,17 +17,17 @@ package google.registry.export.datastore;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.client.http.GenericUrl;
|
||||
import com.google.api.client.http.HttpRequest;
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import com.google.api.client.json.jackson2.JacksonFactory;
|
||||
import com.google.auth.oauth2.AccessToken;
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.testing.TestDataHelper;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -48,27 +48,44 @@ public class DatastoreAdminTest {
|
||||
|
||||
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
|
||||
|
||||
private HttpTransport httpTransport;
|
||||
private GoogleCredential googleCredential;
|
||||
private DatastoreAdmin datastoreAdmin;
|
||||
|
||||
private static HttpRequest simulateSendRequest(HttpRequest httpRequest) {
|
||||
try {
|
||||
httpRequest.setUrl(new GenericUrl("https://localhost:65537")).execute();
|
||||
} catch (Exception expected) {
|
||||
}
|
||||
return httpRequest;
|
||||
}
|
||||
|
||||
private static Optional<String> getAccessToken(HttpRequest httpRequest) {
|
||||
return httpRequest.getHeaders().getAuthorizationAsList().stream()
|
||||
.filter(header -> header.startsWith(AUTH_HEADER_PREFIX))
|
||||
.map(header -> header.substring(AUTH_HEADER_PREFIX.length()))
|
||||
.findAny();
|
||||
}
|
||||
|
||||
private static Optional<String> getRequestContent(HttpRequest httpRequest) throws IOException {
|
||||
if (httpRequest.getContent() == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
httpRequest.getContent().writeTo(outputStream);
|
||||
outputStream.close();
|
||||
return Optional.of(outputStream.toString(StandardCharsets.UTF_8.name()));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
httpTransport = new NetHttpTransport();
|
||||
googleCredential =
|
||||
new GoogleCredential.Builder()
|
||||
.setTransport(httpTransport)
|
||||
.setJsonFactory(JacksonFactory.getDefaultInstance())
|
||||
.setClock(() -> 0)
|
||||
.build();
|
||||
googleCredential.setAccessToken(ACCESS_TOKEN);
|
||||
googleCredential.setExpiresInSeconds(1_000L);
|
||||
|
||||
Date oneHourLater = new Date(System.currentTimeMillis() + 3_600_000);
|
||||
GoogleCredentials googleCredentials = GoogleCredentials
|
||||
.create(new AccessToken(ACCESS_TOKEN, oneHourLater));
|
||||
GoogleCredentialsBundle credentialsBundle = GoogleCredentialsBundle.create(googleCredentials);
|
||||
datastoreAdmin =
|
||||
new DatastoreAdmin.Builder(
|
||||
googleCredential.getTransport(),
|
||||
googleCredential.getJsonFactory(),
|
||||
googleCredential)
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
.setApplicationName("MyApplication")
|
||||
.setProjectId("MyCloudProject")
|
||||
.build();
|
||||
@@ -151,29 +168,4 @@ public class DatastoreAdminTest {
|
||||
simulateSendRequest(httpRequest);
|
||||
assertThat(getAccessToken(httpRequest)).hasValue(ACCESS_TOKEN);
|
||||
}
|
||||
|
||||
private static HttpRequest simulateSendRequest(HttpRequest httpRequest) {
|
||||
try {
|
||||
httpRequest.setUrl(new GenericUrl("https://localhost:65537")).execute();
|
||||
} catch (Exception expected) {
|
||||
}
|
||||
return httpRequest;
|
||||
}
|
||||
|
||||
private static Optional<String> getAccessToken(HttpRequest httpRequest) {
|
||||
return httpRequest.getHeaders().getAuthorizationAsList().stream()
|
||||
.filter(header -> header.startsWith(AUTH_HEADER_PREFIX))
|
||||
.map(header -> header.substring(AUTH_HEADER_PREFIX.length()))
|
||||
.findAny();
|
||||
}
|
||||
|
||||
private static Optional<String> getRequestContent(HttpRequest httpRequest) throws IOException {
|
||||
if (httpRequest.getContent() == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
httpRequest.getContent().writeTo(outputStream);
|
||||
outputStream.close();
|
||||
return Optional.of(outputStream.toString(StandardCharsets.UTF_8.name()));
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user