mirror of
https://github.com/google/nomulus
synced 2026-08-05 23:06:20 +00:00
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c123e1676 | ||
|
|
81b239c6b3 | ||
|
|
ea8c34bf8b | ||
|
|
b3e67e58b5 | ||
|
|
589041b3ed | ||
|
|
455364ff29 | ||
|
|
d90bc1a3e4 | ||
|
|
0e3875c1ff | ||
|
|
3b565b96b7 | ||
|
|
ec6c77927f | ||
|
|
e88ff77ecb |
@@ -54,11 +54,11 @@ org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
|
||||
org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
|
||||
org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
|
||||
org.javassist:javassist:3.28.0-GA=checkstyle
|
||||
org.junit.jupiter:junit-jupiter-api:5.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit:junit-bom:5.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit:junit-bom:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-commons:9.6=jacocoAnt
|
||||
org.ow2.asm:asm-tree:9.6=jacocoAnt
|
||||
|
||||
+20
-15
@@ -173,23 +173,11 @@ PRESUBMITS = {
|
||||
):
|
||||
"JavaScript files should not include console logging.",
|
||||
PresubmitCheck(
|
||||
r".*org\.testcontainers\.shaded.*",
|
||||
r".*\nimport (static )?.*\.shaded\..*",
|
||||
"java",
|
||||
{"/node_modules/"},
|
||||
):
|
||||
"Do not use shaded dependencies from testcontainers.",
|
||||
PresubmitCheck(
|
||||
r".*autovalue\.shaded.*",
|
||||
"java",
|
||||
{"/node_modules/"},
|
||||
):
|
||||
"Do not use shaded dependencies from autovalue.",
|
||||
PresubmitCheck(
|
||||
r".*avro\.shaded.*",
|
||||
"java",
|
||||
{"/node_modules/"},
|
||||
):
|
||||
"Do not use shaded dependencies from avro.",
|
||||
"Do not use shaded dependencies",
|
||||
PresubmitCheck(
|
||||
r".*com\.google\.common\.truth\.Truth8.*",
|
||||
"java",
|
||||
@@ -202,7 +190,24 @@ PRESUBMITS = {
|
||||
{"/node_modules/", "JpaTransactionManagerImpl.java"},
|
||||
):
|
||||
"Do not use java.util.Date. Use classes in java.time package instead.",
|
||||
|
||||
PresubmitCheck(
|
||||
r".*com\.google\.api\.client\.http\.HttpStatusCodes.*",
|
||||
"java",
|
||||
{"/node_modules/"},
|
||||
):
|
||||
"Use status code from jakarta.servlet.http.HttpServletResponse.",
|
||||
PresubmitCheck(
|
||||
r".*mock\(Response\.class\).*",
|
||||
"java",
|
||||
{"/node_modules/"},
|
||||
):
|
||||
"Do not mock Response, use FakeResponse.",
|
||||
PresubmitCheck(
|
||||
r".*javax\.servlet\..*",
|
||||
"java",
|
||||
{"/node_modules/"},
|
||||
):
|
||||
"Do not use javax.servlet.* Use jakarta.servlet.* instead.",
|
||||
}
|
||||
|
||||
# Note that this regex only works for one kind of Flyway file. If we want to
|
||||
|
||||
@@ -59,6 +59,8 @@ export class DomainListComponent {
|
||||
) {
|
||||
effect(() => {
|
||||
if (this.registrarService.registrarId()) {
|
||||
this.pageNumber = 0;
|
||||
this.totalResults = 0;
|
||||
this.reloadData();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -153,7 +153,6 @@ dependencies {
|
||||
implementation deps['com.google.apis:google-api-services-monitoring']
|
||||
implementation deps['com.google.apis:google-api-services-sheets']
|
||||
implementation deps['com.google.apis:google-api-services-storage']
|
||||
testImplementation deps['com.google.appengine:appengine-api-stubs']
|
||||
implementation deps['com.google.auth:google-auth-library-credentials']
|
||||
implementation deps['com.google.auth:google-auth-library-oauth2-http']
|
||||
implementation deps['com.google.cloud.bigdataoss:util']
|
||||
@@ -250,10 +249,6 @@ dependencies {
|
||||
implementation deps['us.fatehi:schemacrawler-tools']
|
||||
implementation deps['xerces:xmlParserAPIs']
|
||||
implementation deps['org.ogce:xpp3']
|
||||
// This dependency must come after javax.mail:mail as it would otherwise
|
||||
// shadow classes in package javax.mail with its own implementation.
|
||||
implementation deps['com.google.appengine:appengine-api-1.0-sdk']
|
||||
|
||||
// Known issue: nebula-lint misses inherited dependency.
|
||||
implementation project(':common')
|
||||
testImplementation project(path: ':common', configuration: 'testing')
|
||||
@@ -271,7 +266,6 @@ dependencies {
|
||||
testAnnotationProcessor project(':processor')
|
||||
|
||||
testImplementation deps['com.google.cloud:google-cloud-nio']
|
||||
testImplementation deps['com.google.appengine:appengine-testing']
|
||||
testImplementation deps['com.google.guava:guava-testlib']
|
||||
testImplementation deps['com.google.monitoring-client:contrib']
|
||||
testImplementation deps['com.google.protobuf:protobuf-java-util']
|
||||
|
||||
+55
-60
@@ -9,21 +9,21 @@ args4j:args4j:2.33=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRu
|
||||
cglib:cglib-nodep:2.2=css
|
||||
com.charleskorn.kaml:kaml:0.20.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.17.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.17.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.17.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.17.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.17.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.17.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml:classmate:1.5.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.github.ben-manes.caffeine:caffeine:3.1.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -40,13 +40,13 @@ com.github.jnr:jnr-unixsocket:0.38.22=compileClasspath,deploy_jar,nonprodCompile
|
||||
com.github.jnr:jnr-x86asm:1.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.android:annotations:4.1.1.4=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-appengine:2.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-appengine:2.6.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-jackson2:2.0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-java6:2.1.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-servlet:2.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-servlet:2.6.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client:1.35.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.32.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.38.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.39.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.176.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.176.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -57,8 +57,8 @@ com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.62.0=compileCl
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.32.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.38.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.39.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.39.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.39.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.176.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.176.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -70,23 +70,23 @@ com.google.api.grpc:proto-google-cloud-monitoring-v3:1.64.0=compileClasspath,non
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.39.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.109.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.13.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-executor-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.32.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.38.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.133.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.133.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.39.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.34.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:api-common:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-grpc:2.48.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:2.48.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.48.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.39.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.134.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.134.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.39.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.34.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:api-common:2.31.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-grpc:2.48.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:2.48.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.48.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev20240509-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-appengine:v1-rev20240415-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20240229-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -94,22 +94,17 @@ com.google.apis:google-api-services-cloudresourcemanager:v1-rev20240310-2.0.0=co
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20240218-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-drive:v2-rev393-1.25.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-gmail:v1-rev20240422-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-gmail:v1-rev20240520-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev20210624-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-healthcare:v1-rev20240130-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-iam:v2-rev20240314-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-iamcredentials:v1-rev20211203-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-monitoring:v3-rev20240427-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-monitoring:v3-rev20240519-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-pubsub:v1-rev20220904-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sheets:v4-rev20240423-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sheets:v4-rev20240514-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sqladmin:v1beta4-rev20240324-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240311-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240319-2.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-1.0-sdk:2.0.27=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-stubs:2.0.27=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-remote-api:2.0.27=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-testing:2.0.27=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-tools-sdk:2.0.27=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.service:auto-service-annotations:1.0.1=errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
@@ -124,28 +119,28 @@ com.google.cloud.bigdataoss:gcsio:2.2.16=compileClasspath,deploy_jar,nonprodComp
|
||||
com.google.cloud.bigdataoss:util:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigtable:bigtable-client-core-config:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.datastore:datastore-v1-proto-client:2.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:jdbc-socket-factory-core:1.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:postgres-socket-factory:1.18.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:jdbc-socket-factory-core:1.18.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:postgres-socket-factory:1.18.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigquerystorage:3.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable-stats:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.36.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.38.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.38.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.38.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.38.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.36.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.38.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.38.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-firestore:3.20.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-monitoring:1.82.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
com.google.cloud:google-cloud-monitoring:3.39.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-nio:0.127.17=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-nio:0.127.18=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsub:1.127.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsublite:1.13.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-spanner:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.32.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.38.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.39.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:grpc-gcp:1.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.20.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.findbugs:jsr305:3.0.1=css
|
||||
@@ -159,7 +154,7 @@ com.google.dagger:dagger:2.51.1=annotationProcessor,compileClasspath,deploy_jar,
|
||||
com.google.devtools.ksp:symbol-processing-api:1.9.20-1.0.14=annotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.26.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.27.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle,soy
|
||||
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
@@ -180,17 +175,17 @@ com.google.guava:guava:20.0=css
|
||||
com.google.guava:guava:31.0.1-jre=checkstyle,soy
|
||||
com.google.guava:guava:32.1.1-jre=errorprone,nonprodAnnotationProcessor
|
||||
com.google.guava:guava:33.0.0-jre=annotationProcessor,testAnnotationProcessor
|
||||
com.google.guava:guava:33.1.0-jre=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.guava:guava:33.2.0-android=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.guava:guava:33.2.0-jre=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.gwt:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.44.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.44.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-gson:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-protobuf:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client:1.44.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.inject:guice:4.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
@@ -253,7 +248,7 @@ com.sun.xml.bind:jaxb-xjc:2.3.9=jaxb
|
||||
com.sun.xml.fastinfoset:FastInfoset:1.2.15=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.zaxxer:HikariCP:5.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-beanutils:commons-beanutils:1.9.4=checkstyle
|
||||
commons-codec:commons-codec:1.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-codec:commons-codec:1.17.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-collections:commons-collections:3.2.2=checkstyle
|
||||
commons-io:commons-io:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-logging:commons-logging:1.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -333,7 +328,6 @@ javax.inject:javax.inject:1=annotationProcessor,compileClasspath,deploy_jar,erro
|
||||
javax.jdo:jdo2-api:2.3-20090302111651=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.mail:mail:1.5.0-b01=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.persistence:javax.persistence-api:2.2=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
javax.servlet:servlet-api:2.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.validation:validation-api:1.0.0.GA=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.xml.bind:jaxb-api:2.3.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.xml.bind:jaxb-api:2.4.0-b180830.0359=jaxb
|
||||
@@ -462,17 +456,17 @@ org.json:json:20160212=soy
|
||||
org.json:json:20240303=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jsoup:jsoup:1.17.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.junit-pioneer:junit-pioneer:2.2.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-migrationsupport:5.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-params:5.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-launcher:1.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-runner:1.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-api:1.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-commons:1.11.0-M1=testRuntimeClasspath
|
||||
org.junit:junit-bom:5.11.0-M1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-migrationsupport:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-params:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-launcher:1.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-runner:1.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-api:1.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-commons:1.11.0-M2=testRuntimeClasspath
|
||||
org.junit:junit-bom:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.jvnet.staxex:stax-ex:1.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.mockito:mockito-core:1.10.19=css
|
||||
org.mockito:mockito-core:5.12.0=testCompileClasspath,testRuntimeClasspath
|
||||
@@ -489,7 +483,8 @@ org.ow2.asm:asm-commons:9.6=jacocoAnt
|
||||
org.ow2.asm:asm-tree:7.0=soy
|
||||
org.ow2.asm:asm-tree:9.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-tree:9.6=jacocoAnt
|
||||
org.ow2.asm:asm-util:7.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-util:7.0=soy
|
||||
org.ow2.asm:asm-util:9.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm:7.0=soy
|
||||
org.ow2.asm:asm:9.2=compileClasspath,nonprodCompileClasspath
|
||||
org.ow2.asm:asm:9.6=deploy_jar,jacocoAnt,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
|
||||
@@ -46,7 +46,7 @@ import javax.net.ssl.HttpsURLConnection;
|
||||
path = "/_dr/task/executeCannedScript",
|
||||
method = {POST, GET},
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class CannedScriptExecutionAction implements Runnable {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
|
||||
@@ -38,10 +38,7 @@ import org.joda.time.Days;
|
||||
* An action that checks all {@link BulkPricingPackage} objects for compliance with their max create
|
||||
* limit.
|
||||
*/
|
||||
@Action(
|
||||
service = Service.BACKEND,
|
||||
path = CheckBulkComplianceAction.PATH,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
@Action(service = Service.BACKEND, path = CheckBulkComplianceAction.PATH, auth = Auth.AUTH_ADMIN)
|
||||
public class CheckBulkComplianceAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/checkBulkCompliance";
|
||||
|
||||
@@ -69,7 +69,7 @@ import org.joda.time.Duration;
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
path = DeleteExpiredDomainsAction.PATH,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class DeleteExpiredDomainsAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/deleteExpiredDomains";
|
||||
|
||||
@@ -56,7 +56,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.BACKEND,
|
||||
path = "/_dr/task/deleteLoadTestData",
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class DeleteLoadTestDataAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -61,7 +61,7 @@ import org.joda.time.Duration;
|
||||
service = Action.Service.BACKEND,
|
||||
path = "/_dr/task/deleteProberData",
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class DeleteProberDataAction implements Runnable {
|
||||
|
||||
// TODO(b/323026070): Add email alert on failure of this action
|
||||
|
||||
@@ -52,7 +52,7 @@ import org.joda.time.DateTime;
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
path = "/_dr/task/expandBillingRecurrences",
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class ExpandBillingRecurrencesAction implements Runnable {
|
||||
|
||||
public static final String PARAM_START_TIME = "startTime";
|
||||
|
||||
@@ -53,7 +53,7 @@ import org.joda.time.Duration;
|
||||
path = RelockDomainAction.PATH,
|
||||
method = POST,
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class RelockDomainAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/relockDomain";
|
||||
|
||||
@@ -55,7 +55,7 @@ import javax.inject.Inject;
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
path = ResaveAllEppResourcesPipelineAction.PATH,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class ResaveAllEppResourcesPipelineAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -40,7 +40,7 @@ import org.joda.time.DateTime;
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
path = ResaveEntityAction.PATH,
|
||||
auth = Auth.AUTH_API_ADMIN,
|
||||
auth = Auth.AUTH_ADMIN,
|
||||
method = Method.POST)
|
||||
public class ResaveEntityAction implements Runnable {
|
||||
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ import org.joda.time.format.DateTimeFormatter;
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
path = SendExpiringCertificateNotificationEmailAction.PATH,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class SendExpiringCertificateNotificationEmailAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/sendExpiringCertificateNotificationEmail";
|
||||
|
||||
@@ -51,7 +51,7 @@ import org.joda.time.DateTime;
|
||||
@Action(
|
||||
service = Service.BACKEND,
|
||||
path = WipeOutContactHistoryPiiAction.PATH,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class WipeOutContactHistoryPiiAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/wipeOutContactHistoryPii";
|
||||
|
||||
@@ -53,7 +53,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.BSA,
|
||||
path = BsaDownloadAction.PATH,
|
||||
method = {GET, POST},
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class BsaDownloadAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -44,7 +44,7 @@ import org.joda.time.Duration;
|
||||
service = Action.Service.BSA,
|
||||
path = BsaRefreshAction.PATH,
|
||||
method = {GET, POST},
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class BsaRefreshAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -32,7 +32,7 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.util.BatchedStreams.toBatches;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -70,7 +70,7 @@ import org.joda.time.Duration;
|
||||
service = Action.Service.BSA,
|
||||
path = BsaValidateAction.PATH,
|
||||
method = {GET, POST},
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class BsaValidateAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -23,9 +23,9 @@ import static google.registry.model.tld.label.ReservedList.loadReservedLists;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
|
||||
import com.google.api.client.http.HttpStatusCodes;
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -75,7 +75,7 @@ import org.joda.time.DateTime;
|
||||
service = Service.BSA,
|
||||
path = "/_dr/task/uploadBsaUnavailableNames",
|
||||
method = {GET, POST},
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class UploadBsaUnavailableDomainsAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
@@ -190,7 +190,7 @@ public class UploadBsaUnavailableDomainsAction implements Runnable {
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
logger.atSevere().withCause(e).log("Error while attempting to upload to BSA, aborting.");
|
||||
response.setStatus(HttpStatusCodes.STATUS_CODE_SERVER_ERROR);
|
||||
response.setStatus(SC_INTERNAL_SERVER_ERROR);
|
||||
response.setPayload("Error while attempting to upload to BSA: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -491,6 +491,18 @@ public final class RegistryConfig {
|
||||
return Optional.ofNullable(Strings.emptyToNull(config.gSuite.supportGroupEmailAddress));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the email address of the group containing emails of console users.
|
||||
*
|
||||
* <p>This group should be granted the {@code roles/iap.httpsResourceAccessor} role.
|
||||
*/
|
||||
@Provides
|
||||
@Config("gSuiteConsoleUserGroupEmailAddress")
|
||||
public static Optional<String> provideGSuiteConsoleUserGroupEmailAddress(
|
||||
RegistryConfigSettings config) {
|
||||
return Optional.ofNullable(Strings.emptyToNull(config.gSuite.consoleUserGroupEmailAddress));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the email address(es) that notifications of registrar and/or registrar contact
|
||||
* updates should be sent to, or the empty list if updates should not be sent.
|
||||
|
||||
@@ -83,6 +83,7 @@ public class RegistryConfigSettings {
|
||||
public String outgoingEmailDisplayName;
|
||||
public String adminAccountEmailAddress;
|
||||
public String supportGroupEmailAddress;
|
||||
public String consoleUserGroupEmailAddress;
|
||||
}
|
||||
|
||||
/** Configuration options for registry policy. */
|
||||
|
||||
@@ -47,6 +47,11 @@ gSuite:
|
||||
# given "ADMIN" role on the registrar console.
|
||||
supportGroupEmailAddress: support@example.com
|
||||
|
||||
# Group containing the emails of console users. This group should be granted
|
||||
# roles/iap.httpsResourceAccessor out-of-band. If this field is empty, each
|
||||
# console user will be granted to the role individually when they are created.
|
||||
consoleUserGroupEmailAddress:
|
||||
|
||||
registryPolicy:
|
||||
# Repository identifier (ROID) suffix for contacts and hosts.
|
||||
contactAndHostRoidSuffix: ROID
|
||||
|
||||
@@ -81,7 +81,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.BACKEND,
|
||||
path = "/_dr/cron/fanout",
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class TldFanoutAction implements Runnable {
|
||||
|
||||
/** A set of control params to TldFanoutAction that aren't passed down to the executing action. */
|
||||
|
||||
@@ -77,7 +77,7 @@ import org.joda.time.Duration;
|
||||
path = PublishDnsUpdatesAction.PATH,
|
||||
method = POST,
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
|
||||
public static final String PATH = "/_dr/task/publishDnsUpdates";
|
||||
|
||||
@@ -64,7 +64,7 @@ import org.joda.time.Duration;
|
||||
path = "/_dr/task/readDnsRefreshRequests",
|
||||
automaticallyPrintOk = true,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class ReadDnsRefreshRequestsAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -38,7 +38,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.BACKEND,
|
||||
path = "/_dr/dnsRefresh",
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class RefreshDnsAction implements Runnable {
|
||||
|
||||
private final Clock clock;
|
||||
|
||||
@@ -33,11 +33,7 @@ import google.registry.request.auth.Auth;
|
||||
import javax.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@Action(
|
||||
service = Service.BACKEND,
|
||||
path = PATH,
|
||||
method = Action.Method.POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
@Action(service = Service.BACKEND, path = PATH, method = Action.Method.POST, auth = Auth.AUTH_ADMIN)
|
||||
public class RefreshDnsOnHostRenameAction implements Runnable {
|
||||
|
||||
public static final String QUEUE_HOST_RENAME = "async-host-rename";
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>tools-servlet</servlet-name>
|
||||
<url-pattern>/_dr/admin/updateUserGroup</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>tools-servlet</servlet-name>
|
||||
<url-pattern>/_dr/admin/verifyOte</url-pattern>
|
||||
|
||||
@@ -49,7 +49,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.BACKEND,
|
||||
path = "/_dr/task/exportDomainLists",
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class ExportDomainListsAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -48,7 +48,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.BACKEND,
|
||||
path = "/_dr/task/exportPremiumTerms",
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class ExportPremiumTermsAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -37,7 +37,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.BACKEND,
|
||||
path = "/_dr/task/exportReservedTerms",
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class ExportReservedTermsAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -56,7 +56,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.BACKEND,
|
||||
path = "/_dr/task/syncGroupMembers",
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class SyncGroupMembersAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -57,7 +57,7 @@ import org.joda.time.Duration;
|
||||
service = Action.Service.BACKEND,
|
||||
path = SyncRegistrarsSheetAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class SyncRegistrarsSheetAction implements Runnable {
|
||||
|
||||
private enum Result {
|
||||
|
||||
@@ -29,7 +29,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.DEFAULT,
|
||||
path = "/_dr/epp",
|
||||
method = Method.POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class EppTlsAction implements Runnable {
|
||||
|
||||
@Inject @Payload byte[] inputXmlBytes;
|
||||
|
||||
@@ -33,7 +33,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.TOOLS,
|
||||
path = EppToolAction.PATH,
|
||||
method = Method.POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class EppToolAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/epptool";
|
||||
|
||||
@@ -159,7 +159,11 @@ public final class DomainPricingLogic {
|
||||
case NONPREMIUM -> {
|
||||
renewCost =
|
||||
getDomainCostWithDiscount(
|
||||
false, years, allocationToken, tld.getStandardRenewCost(dateTime));
|
||||
false,
|
||||
years,
|
||||
allocationToken,
|
||||
tld.getStandardRenewCost(dateTime),
|
||||
Optional.empty());
|
||||
isRenewCostPremiumPrice = false;
|
||||
}
|
||||
default ->
|
||||
@@ -252,7 +256,11 @@ public final class DomainPricingLogic {
|
||||
DomainPrices domainPrices, int years, Optional<AllocationToken> allocationToken)
|
||||
throws EppException {
|
||||
return getDomainCostWithDiscount(
|
||||
domainPrices.isPremium(), years, allocationToken, domainPrices.getCreateCost());
|
||||
domainPrices.isPremium(),
|
||||
years,
|
||||
allocationToken,
|
||||
domainPrices.getCreateCost(),
|
||||
Optional.of(domainPrices.getRenewCost()));
|
||||
}
|
||||
|
||||
/** Returns the domain renew cost with allocation-token-related discounts applied. */
|
||||
@@ -272,24 +280,45 @@ public final class DomainPricingLogic {
|
||||
}
|
||||
}
|
||||
return getDomainCostWithDiscount(
|
||||
domainPrices.isPremium(), years, allocationToken, domainPrices.getRenewCost());
|
||||
domainPrices.isPremium(),
|
||||
years,
|
||||
allocationToken,
|
||||
domainPrices.getRenewCost(),
|
||||
Optional.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the domain creation or renewal cost for the given number of {@code years}.
|
||||
*
|
||||
* <p>For domain creation, {@code firstYearCost} is the creation cost while {@code
|
||||
* subsequentYearCost} is the single-year renewal cost (which is guaranteed to be present).
|
||||
*
|
||||
* <p>For domain renewal, {@code firstYearCost} is the single-year renewal cost and {@code
|
||||
* subsequentYearCost} should be empty.
|
||||
*/
|
||||
private Money getDomainCostWithDiscount(
|
||||
boolean isPremium, int years, Optional<AllocationToken> allocationToken, Money oneYearCost)
|
||||
boolean isPremium,
|
||||
int years,
|
||||
Optional<AllocationToken> allocationToken,
|
||||
Money firstYearCost,
|
||||
Optional<Money> subsequentYearCost)
|
||||
throws AllocationTokenInvalidForPremiumNameException {
|
||||
checkArgument(years > 0, "Registration years to get cost for must be positive.");
|
||||
validateTokenForPossiblePremiumName(allocationToken, isPremium);
|
||||
Money totalDomainFlowCost = oneYearCost.multipliedBy(years);
|
||||
Money totalDomainFlowCost =
|
||||
firstYearCost.plus(subsequentYearCost.orElse(firstYearCost).multipliedBy(years - 1));
|
||||
|
||||
// Apply the allocation token discount, if applicable.
|
||||
if (allocationToken.isPresent()
|
||||
&& allocationToken.get().getTokenBehavior().equals(TokenBehavior.DEFAULT)) {
|
||||
int discountedYears = Math.min(years, allocationToken.get().getDiscountYears());
|
||||
Money discount =
|
||||
oneYearCost.multipliedBy(
|
||||
discountedYears * allocationToken.get().getDiscountFraction(),
|
||||
RoundingMode.HALF_EVEN);
|
||||
totalDomainFlowCost = totalDomainFlowCost.minus(discount);
|
||||
if (discountedYears > 0) {
|
||||
var discount =
|
||||
firstYearCost
|
||||
.plus(subsequentYearCost.orElse(firstYearCost).multipliedBy(discountedYears - 1))
|
||||
.multipliedBy(allocationToken.get().getDiscountFraction(), RoundingMode.HALF_EVEN);
|
||||
totalDomainFlowCost = totalDomainFlowCost.minus(discount);
|
||||
}
|
||||
}
|
||||
return totalDomainFlowCost;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ import org.joda.time.DateTime;
|
||||
path = LoadTestAction.PATH,
|
||||
method = Action.Method.POST,
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class LoadTestAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
@@ -350,9 +350,8 @@ public class LoadTestAction implements Runnable {
|
||||
.toBuilder()
|
||||
.getAppEngineHttpRequest()
|
||||
.toBuilder()
|
||||
// instead of adding the X_CSRF_TOKEN to params, this remains as part of
|
||||
// headers because of the existing setup for authentication in {@link
|
||||
// google.registry.request.auth.LegacyAuthenticationMechanism}
|
||||
// TODO: investigate if the following is necessary now that
|
||||
// LegacyAuthenticationMechanism is gone.
|
||||
.putHeaders(X_CSRF_TOKEN, xsrfToken)
|
||||
.build())
|
||||
.setScheduleTime(
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright 2021 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.annotations;
|
||||
|
||||
/**
|
||||
* Annotation to indicate a class that should be deleted after the database migration is complete.
|
||||
*/
|
||||
public @interface DeleteAfterMigration {}
|
||||
@@ -47,7 +47,6 @@ import google.registry.rde.JSchModule;
|
||||
import google.registry.request.Modules.GsonModule;
|
||||
import google.registry.request.Modules.NetHttpTransportModule;
|
||||
import google.registry.request.Modules.UrlConnectionServiceModule;
|
||||
import google.registry.request.Modules.UserServiceModule;
|
||||
import google.registry.request.RequestHandler;
|
||||
import google.registry.request.auth.AuthModule;
|
||||
import google.registry.request.auth.RequestAuthenticator;
|
||||
@@ -88,7 +87,6 @@ import javax.inject.Singleton;
|
||||
SheetsServiceModule.class,
|
||||
StackdriverModule.class,
|
||||
UrlConnectionServiceModule.class,
|
||||
UserServiceModule.class,
|
||||
UtilsModule.class,
|
||||
VoidDnsWriterModule.class,
|
||||
})
|
||||
|
||||
@@ -107,6 +107,7 @@ import google.registry.tools.server.ListReservedListsAction;
|
||||
import google.registry.tools.server.ListTldsAction;
|
||||
import google.registry.tools.server.RefreshDnsForAllDomainsAction;
|
||||
import google.registry.tools.server.ToolsServerModule;
|
||||
import google.registry.tools.server.UpdateUserGroupAction;
|
||||
import google.registry.tools.server.VerifyOteAction;
|
||||
import google.registry.ui.server.console.ConsoleDomainGetAction;
|
||||
import google.registry.ui.server.console.ConsoleDomainListAction;
|
||||
@@ -323,6 +324,8 @@ interface RequestComponent {
|
||||
|
||||
UpdateRegistrarRdapBaseUrlsAction updateRegistrarRdapBaseUrlsAction();
|
||||
|
||||
UpdateUserGroupAction updateUserGroupAction();
|
||||
|
||||
UploadBsaUnavailableDomainsAction uploadBsaUnavailableDomains();
|
||||
|
||||
VerifyOteAction verifyOteAction();
|
||||
|
||||
@@ -43,7 +43,6 @@ import google.registry.rde.JSchModule;
|
||||
import google.registry.request.Modules.GsonModule;
|
||||
import google.registry.request.Modules.NetHttpTransportModule;
|
||||
import google.registry.request.Modules.UrlConnectionServiceModule;
|
||||
import google.registry.request.Modules.UserServiceModule;
|
||||
import google.registry.request.auth.AuthModule;
|
||||
import google.registry.util.UtilsModule;
|
||||
import javax.inject.Singleton;
|
||||
@@ -78,7 +77,6 @@ import javax.inject.Singleton;
|
||||
SheetsServiceModule.class,
|
||||
StackdriverModule.class,
|
||||
UrlConnectionServiceModule.class,
|
||||
UserServiceModule.class,
|
||||
VoidDnsWriterModule.class,
|
||||
UtilsModule.class
|
||||
})
|
||||
|
||||
@@ -28,7 +28,6 @@ import google.registry.persistence.PersistenceModule;
|
||||
import google.registry.privileges.secretmanager.SecretManagerModule;
|
||||
import google.registry.request.Modules.GsonModule;
|
||||
import google.registry.request.Modules.UrlConnectionServiceModule;
|
||||
import google.registry.request.Modules.UserServiceModule;
|
||||
import google.registry.request.auth.AuthModule;
|
||||
import google.registry.util.UtilsModule;
|
||||
import javax.inject.Singleton;
|
||||
@@ -48,7 +47,6 @@ import javax.inject.Singleton;
|
||||
SecretManagerModule.class,
|
||||
StackdriverModule.class,
|
||||
UrlConnectionServiceModule.class,
|
||||
UserServiceModule.class,
|
||||
UtilsModule.class
|
||||
})
|
||||
interface BsaComponent {
|
||||
|
||||
@@ -35,7 +35,6 @@ import google.registry.monitoring.whitebox.StackdriverModule;
|
||||
import google.registry.privileges.secretmanager.SecretManagerModule;
|
||||
import google.registry.request.Modules.GsonModule;
|
||||
import google.registry.request.Modules.NetHttpTransportModule;
|
||||
import google.registry.request.Modules.UserServiceModule;
|
||||
import google.registry.request.auth.AuthModule;
|
||||
import google.registry.ui.ConsoleDebug.ConsoleConfigModule;
|
||||
import google.registry.util.UtilsModule;
|
||||
@@ -66,7 +65,6 @@ import javax.inject.Singleton;
|
||||
SecretManagerModule.class,
|
||||
ServerTridProviderModule.class,
|
||||
StackdriverModule.class,
|
||||
UserServiceModule.class,
|
||||
UtilsModule.class
|
||||
})
|
||||
interface FrontendComponent {
|
||||
|
||||
@@ -34,7 +34,6 @@ import google.registry.persistence.PersistenceModule;
|
||||
import google.registry.privileges.secretmanager.SecretManagerModule;
|
||||
import google.registry.request.Modules.GsonModule;
|
||||
import google.registry.request.Modules.NetHttpTransportModule;
|
||||
import google.registry.request.Modules.UserServiceModule;
|
||||
import google.registry.request.auth.AuthModule;
|
||||
import google.registry.util.UtilsModule;
|
||||
import javax.inject.Singleton;
|
||||
@@ -61,7 +60,6 @@ import javax.inject.Singleton;
|
||||
SecretManagerModule.class,
|
||||
ServerTridProviderModule.class,
|
||||
StackdriverModule.class,
|
||||
UserServiceModule.class,
|
||||
UtilsModule.class
|
||||
})
|
||||
interface PubApiComponent {
|
||||
|
||||
@@ -35,7 +35,6 @@ import google.registry.monitoring.whitebox.StackdriverModule;
|
||||
import google.registry.privileges.secretmanager.SecretManagerModule;
|
||||
import google.registry.request.Modules.GsonModule;
|
||||
import google.registry.request.Modules.NetHttpTransportModule;
|
||||
import google.registry.request.Modules.UserServiceModule;
|
||||
import google.registry.request.auth.AuthModule;
|
||||
import google.registry.util.UtilsModule;
|
||||
import javax.inject.Singleton;
|
||||
@@ -63,7 +62,6 @@ import javax.inject.Singleton;
|
||||
ServerTridProviderModule.class,
|
||||
StackdriverModule.class,
|
||||
ToolsRequestComponentModule.class,
|
||||
UserServiceModule.class,
|
||||
UtilsModule.class
|
||||
})
|
||||
interface ToolsComponent {
|
||||
|
||||
@@ -36,6 +36,7 @@ import google.registry.tools.server.ListReservedListsAction;
|
||||
import google.registry.tools.server.ListTldsAction;
|
||||
import google.registry.tools.server.RefreshDnsForAllDomainsAction;
|
||||
import google.registry.tools.server.ToolsServerModule;
|
||||
import google.registry.tools.server.UpdateUserGroupAction;
|
||||
import google.registry.tools.server.VerifyOteAction;
|
||||
|
||||
/** Dagger component with per-request lifetime for "tools" App Engine module. */
|
||||
@@ -50,9 +51,10 @@ import google.registry.tools.server.VerifyOteAction;
|
||||
WhiteboxModule.class,
|
||||
})
|
||||
public interface ToolsRequestComponent {
|
||||
FlowComponent.Builder flowComponentBuilder();
|
||||
|
||||
CreateGroupsAction createGroupsAction();
|
||||
EppToolAction eppToolAction();
|
||||
FlowComponent.Builder flowComponentBuilder();
|
||||
GenerateZoneFilesAction generateZoneFilesAction();
|
||||
ListDomainsAction listDomainsAction();
|
||||
ListHostsAction listHostsAction();
|
||||
@@ -62,6 +64,9 @@ public interface ToolsRequestComponent {
|
||||
ListTldsAction listTldsAction();
|
||||
LoadTestAction loadTestAction();
|
||||
RefreshDnsForAllDomainsAction refreshDnsForAllDomainsAction();
|
||||
|
||||
UpdateUserGroupAction updateUserGroupAction();
|
||||
|
||||
VerifyOteAction verifyOteAction();
|
||||
|
||||
@Subcomponent.Builder
|
||||
|
||||
@@ -18,11 +18,11 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.RequestParameters;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -101,11 +101,11 @@ public final class RdapModule {
|
||||
@Provides
|
||||
static RdapAuthorization provideRdapAuthorization(
|
||||
AuthResult authResult, AuthenticatedRegistrarAccessor registrarAccessor) {
|
||||
if (authResult.userAuthInfo().isEmpty()) {
|
||||
if (authResult.user().isEmpty()) {
|
||||
return RdapAuthorization.PUBLIC_AUTHORIZATION;
|
||||
}
|
||||
UserAuthInfo userAuthInfo = authResult.userAuthInfo().get();
|
||||
if (userAuthInfo.isUserAdmin()) {
|
||||
User user = authResult.user().get();
|
||||
if (user.getUserRoles().isAdmin()) {
|
||||
return RdapAuthorization.ADMINISTRATOR_AUTHORIZATION;
|
||||
}
|
||||
ImmutableSet<String> clientIds = registrarAccessor.getAllRegistrarIdsWithRoles().keySet();
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
|
||||
package google.registry.rdap;
|
||||
|
||||
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_OK;
|
||||
import static com.google.common.net.HttpHeaders.ACCEPT_ENCODING;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.UrlConnectionUtils.gUnzipBytes;
|
||||
import static google.registry.request.UrlConnectionUtils.isGZipped;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
@@ -55,7 +55,7 @@ import org.apache.commons.csv.CSVRecord;
|
||||
service = Action.Service.BACKEND,
|
||||
path = "/_dr/task/updateRegistrarRdapBaseUrls",
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
|
||||
private static final String RDAP_IDS_URL =
|
||||
@@ -114,7 +114,7 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
connection.setRequestProperty(ACCEPT_ENCODING, "gzip");
|
||||
String csvString;
|
||||
try {
|
||||
if (connection.getResponseCode() != STATUS_CODE_OK) {
|
||||
if (connection.getResponseCode() != SC_OK) {
|
||||
throw new UrlConnectionException("Failed to load RDAP base URLs from ICANN", connection);
|
||||
}
|
||||
// With GZIP encoding header in the request (see above) ICANN had still sent response in plain
|
||||
|
||||
@@ -66,7 +66,7 @@ import org.joda.time.DateTime;
|
||||
path = BrdaCopyAction.PATH,
|
||||
method = POST,
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class BrdaCopyAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/brdaCopy";
|
||||
|
||||
@@ -56,7 +56,7 @@ import org.joda.time.Duration;
|
||||
service = Action.Service.BACKEND,
|
||||
path = RdeReportAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class RdeReportAction implements Runnable, EscrowTask {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
|
||||
package google.registry.rde;
|
||||
|
||||
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_BAD_REQUEST;
|
||||
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_OK;
|
||||
import static google.registry.request.UrlConnectionUtils.getResponseBytes;
|
||||
import static google.registry.request.UrlConnectionUtils.setBasicAuth;
|
||||
import static google.registry.request.UrlConnectionUtils.setPayload;
|
||||
import static google.registry.util.DomainNameUtils.canonicalizeHostname;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.api.client.http.HttpMethods;
|
||||
@@ -85,7 +85,7 @@ public class RdeReporter {
|
||||
|
||||
try {
|
||||
responseCode = connection.getResponseCode();
|
||||
if (responseCode != STATUS_CODE_OK && responseCode != STATUS_CODE_BAD_REQUEST) {
|
||||
if (responseCode != SC_OK && responseCode != SC_BAD_REQUEST) {
|
||||
logger.atWarning().log("Connection to RDE report server failed: %d", responseCode);
|
||||
throw new UrlConnectionException("PUT failed", connection);
|
||||
}
|
||||
@@ -96,7 +96,7 @@ public class RdeReporter {
|
||||
|
||||
// We know that an HTTP 200 response can only contain a result code of
|
||||
// 1000 (i. e. success), there is no need to parse it.
|
||||
if (responseCode != STATUS_CODE_OK) {
|
||||
if (responseCode != SC_OK) {
|
||||
XjcIirdeaResult result = parseResult(responseBytes);
|
||||
logger.atWarning().log(
|
||||
"Rejected when trying to PUT RDE report to ICANN server: %d %s\n%s",
|
||||
|
||||
@@ -207,7 +207,7 @@ import org.joda.time.Duration;
|
||||
service = Action.Service.BACKEND,
|
||||
path = RdeStagingAction.PATH,
|
||||
method = {GET, POST},
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class RdeStagingAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/rdeStaging";
|
||||
|
||||
@@ -87,7 +87,7 @@ import org.joda.time.Duration;
|
||||
service = Action.Service.BACKEND,
|
||||
path = RdeUploadAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class RdeUploadAction implements Runnable, EscrowTask {
|
||||
|
||||
public static final String PATH = "/_dr/task/rdeUpload";
|
||||
|
||||
@@ -47,7 +47,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.BACKEND,
|
||||
path = CopyDetailReportsAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class CopyDetailReportsAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/copyDetailReports";
|
||||
|
||||
@@ -54,7 +54,7 @@ import org.joda.time.YearMonth;
|
||||
service = Action.Service.BACKEND,
|
||||
path = GenerateInvoicesAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class GenerateInvoicesAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -52,7 +52,7 @@ import org.joda.time.YearMonth;
|
||||
service = Action.Service.BACKEND,
|
||||
path = PublishInvoicesAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class PublishInvoicesAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
package google.registry.reporting.icann;
|
||||
|
||||
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_OK;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.net.MediaType.CSV_UTF_8;
|
||||
import static google.registry.model.tld.Tlds.assertTldExists;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.api.client.http.HttpMethods;
|
||||
import com.google.common.base.Ascii;
|
||||
@@ -95,7 +95,7 @@ public class IcannHttpReporter {
|
||||
try {
|
||||
responseCode = connection.getResponseCode();
|
||||
content = UrlConnectionUtils.getResponseBytes(connection);
|
||||
if (responseCode != STATUS_CODE_OK) {
|
||||
if (responseCode != SC_OK) {
|
||||
XjcIirdeaResult result = parseResult(content);
|
||||
logger.atWarning().log(
|
||||
"PUT rejected, status code %s:\n%s\n%s",
|
||||
|
||||
@@ -67,7 +67,7 @@ import org.joda.time.format.DateTimeFormat;
|
||||
service = Action.Service.BACKEND,
|
||||
path = IcannReportingStagingAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class IcannReportingStagingAction implements Runnable {
|
||||
|
||||
static final String PATH = "/_dr/task/icannReportingStaging";
|
||||
|
||||
@@ -70,7 +70,7 @@ import org.joda.time.Duration;
|
||||
service = Action.Service.BACKEND,
|
||||
path = IcannReportingUploadAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class IcannReportingUploadAction implements Runnable {
|
||||
|
||||
static final String PATH = "/_dr/task/icannReportingUpload";
|
||||
|
||||
@@ -53,7 +53,7 @@ import org.joda.time.LocalDate;
|
||||
service = Action.Service.BACKEND,
|
||||
path = GenerateSpec11ReportAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class GenerateSpec11ReportAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -59,7 +59,7 @@ import org.json.JSONException;
|
||||
service = Action.Service.BACKEND,
|
||||
path = PublishSpec11ReportAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class PublishSpec11ReportAction implements Runnable {
|
||||
|
||||
static final String PATH = "/_dr/task/publishSpec11";
|
||||
|
||||
@@ -18,8 +18,6 @@ import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import com.google.api.client.json.JsonFactory;
|
||||
import com.google.api.client.json.gson.GsonFactory;
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import com.google.appengine.api.users.UserServiceFactory;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import java.net.HttpURLConnection;
|
||||
@@ -47,17 +45,6 @@ public final class Modules {
|
||||
}
|
||||
}
|
||||
|
||||
/** Dagger module for {@link UserService}. */
|
||||
@Module
|
||||
public static final class UserServiceModule {
|
||||
private static final UserService userService = UserServiceFactory.getUserService();
|
||||
|
||||
@Provides
|
||||
static UserService provideUserService() {
|
||||
return userService;
|
||||
}
|
||||
}
|
||||
|
||||
/** Dagger module that causes the Google GSON parser to be used for Google APIs requests. */
|
||||
@Module
|
||||
public static final class GsonModule {
|
||||
@@ -67,10 +54,7 @@ public final class Modules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dagger module that provides standard {@link NetHttpTransport}. Used in non App Engine
|
||||
* environment.
|
||||
*/
|
||||
/** Dagger module that provides standard {@link NetHttpTransport}. */
|
||||
@Module
|
||||
public static final class NetHttpTransportModule {
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import java.util.Map;
|
||||
* Utility class to help in dumping routing maps.
|
||||
*
|
||||
* <p>Each of the App Engine services (frontend, backend, and tools) has a Dagger component used for
|
||||
* routing requests (e.g. FrontendRequestComponent). This class produces a text file representation
|
||||
* routing requests (e.g., FrontendRequestComponent). This class produces a text file representation
|
||||
* of the routing configuration, showing what paths map to what action classes, as well as the
|
||||
* properties of the action classes' annotations (which cover things like allowable HTTP methods,
|
||||
* authentication settings, etc.). The text file can be useful for documentation, and is also used
|
||||
@@ -37,13 +37,12 @@ import java.util.Map;
|
||||
* the content to be displayed. The columns are:
|
||||
*
|
||||
* <ol>
|
||||
* <li>the URL path which maps to this action (with a "(*)" after it if the prefix flag is set)
|
||||
* <li>the simple name of the action class
|
||||
* <li>the allowable HTTP methods
|
||||
* <li>whether to automatically print "ok" in the response
|
||||
* <li>the allowable authentication methods
|
||||
* <li>the minimum authentication level
|
||||
* <li>the user policy
|
||||
* <li>the URL path which maps to this action (with a "(*)" after it if the prefix flag is set)
|
||||
* <li>the simple name of the action class
|
||||
* <li>the allowable HTTP methods
|
||||
* <li>whether to automatically print "ok" in the response
|
||||
* <li>the minimum authentication level
|
||||
* <li>the user policy
|
||||
* </ol>
|
||||
*
|
||||
* <p>See the Auth class for more information about authentication settings.
|
||||
@@ -53,11 +52,9 @@ public class RouterDisplayHelper {
|
||||
private static final String PATH = "path";
|
||||
private static final String CLASS = "class";
|
||||
private static final String METHODS = "methods";
|
||||
private static final String AUTH_METHODS = "authMethods";
|
||||
private static final String MINIMUM_LEVEL = "minLevel";
|
||||
|
||||
private static final String FORMAT =
|
||||
"%%-%ds %%-%ds %%-%ds %%-2s %%-%ds %%-%ds %%s";
|
||||
private static final String FORMAT = "%%-%ds %%-%ds %%-%ds %%-2s %%-%ds %%s";
|
||||
|
||||
/** Returns a string representation of the routing map in the specified component. */
|
||||
public static String extractHumanReadableRoutesFromComponent(Class<?> componentClass) {
|
||||
@@ -82,7 +79,6 @@ public class RouterDisplayHelper {
|
||||
columnWidths.get(PATH),
|
||||
columnWidths.get(CLASS),
|
||||
columnWidths.get(METHODS),
|
||||
columnWidths.get(AUTH_METHODS),
|
||||
columnWidths.get(MINIMUM_LEVEL));
|
||||
}
|
||||
|
||||
@@ -93,7 +89,6 @@ public class RouterDisplayHelper {
|
||||
"CLASS",
|
||||
"METHODS",
|
||||
"OK",
|
||||
"AUTH_METHODS",
|
||||
"MIN",
|
||||
"USER_POLICY");
|
||||
}
|
||||
@@ -105,7 +100,6 @@ public class RouterDisplayHelper {
|
||||
route.actionClass().getSimpleName(),
|
||||
Joiner.on(",").join(route.action().method()),
|
||||
route.action().automaticallyPrintOk() ? "y" : "n",
|
||||
Joiner.on(",").join(route.action().auth().authSettings().methods()),
|
||||
route.action().auth().authSettings().minimumLevel(),
|
||||
route.action().auth().authSettings().userPolicy());
|
||||
}
|
||||
@@ -116,7 +110,6 @@ public class RouterDisplayHelper {
|
||||
int pathWidth = 4;
|
||||
int classWidth = 5;
|
||||
int methodsWidth = 7;
|
||||
int authMethodsWidth = 12;
|
||||
int minLevelWidth = 3;
|
||||
for (Route route : routes) {
|
||||
int len =
|
||||
@@ -134,10 +127,6 @@ public class RouterDisplayHelper {
|
||||
if (len > methodsWidth) {
|
||||
methodsWidth = len;
|
||||
}
|
||||
len = Joiner.on(",").join(route.action().auth().authSettings().methods()).length();
|
||||
if (len > authMethodsWidth) {
|
||||
authMethodsWidth = len;
|
||||
}
|
||||
len = route.action().auth().authSettings().minimumLevel().toString().length();
|
||||
if (len > minLevelWidth) {
|
||||
minLevelWidth = len;
|
||||
@@ -149,7 +138,6 @@ public class RouterDisplayHelper {
|
||||
.put(PATH, pathWidth)
|
||||
.put(CLASS, classWidth)
|
||||
.put(METHODS, methodsWidth)
|
||||
.put(AUTH_METHODS, authMethodsWidth)
|
||||
.put(MINIMUM_LEVEL, minLevelWidth)
|
||||
.build());
|
||||
return headerToString(formatString)
|
||||
|
||||
@@ -14,12 +14,8 @@
|
||||
|
||||
package google.registry.request.auth;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.AuthSettings.AuthMethod;
|
||||
import google.registry.request.auth.AuthSettings.UserPolicy;
|
||||
import google.registry.ui.server.registrar.HtmlAction;
|
||||
import google.registry.ui.server.registrar.JsonGetAction;
|
||||
|
||||
/** Enum used to configure authentication settings for Actions. */
|
||||
public enum Auth {
|
||||
@@ -27,35 +23,17 @@ public enum Auth {
|
||||
/**
|
||||
* Allows anyone to access.
|
||||
*
|
||||
* <p>If a user is logged in, will authenticate (and return) them. Otherwise, access is still
|
||||
* granted, but NOT_AUTHENTICATED is returned.
|
||||
*
|
||||
* <p>User-facing legacy console endpoints (those that extend {@link HtmlAction}) use it. They
|
||||
* need to allow requests from signed-out users so that they can redirect users to the login page.
|
||||
* After a user is logged in, they check if the user actually has access to the specific console
|
||||
* using {@link AuthenticatedRegistrarAccessor}.
|
||||
*
|
||||
* @see HtmlAction
|
||||
* <p>This is used for public HTML endpoints like RDAP, the check API, and web WHOIS.
|
||||
*/
|
||||
AUTH_PUBLIC_LEGACY(
|
||||
ImmutableList.of(AuthMethod.API, AuthMethod.LEGACY), AuthLevel.NONE, UserPolicy.PUBLIC),
|
||||
AUTH_PUBLIC(AuthLevel.NONE, UserPolicy.PUBLIC),
|
||||
|
||||
/**
|
||||
* Allows anyone to access, as long as they are logged in.
|
||||
*
|
||||
* <p>This is used by legacy registrar console programmatic endpoints (those that extend {@link
|
||||
* JsonGetAction}), which are accessed via XHR requests sent from a logged-in user when performing
|
||||
* actions on the console.
|
||||
* <p>Note that the action might use {@link AuthenticatedRegistrarAccessor} to impose a more
|
||||
* fine-grained access control pattern than merely whether the user is logged in/out.
|
||||
*/
|
||||
AUTH_PUBLIC_LOGGED_IN(
|
||||
ImmutableList.of(AuthMethod.API, AuthMethod.LEGACY), AuthLevel.USER, UserPolicy.PUBLIC),
|
||||
|
||||
/**
|
||||
* Allows anyone to access.
|
||||
*
|
||||
* <p>This is used for public HTML endpoints like RDAP, the check API, and web WHOIS.
|
||||
*/
|
||||
AUTH_PUBLIC(ImmutableList.of(AuthMethod.API), AuthLevel.NONE, UserPolicy.PUBLIC),
|
||||
AUTH_PUBLIC_LOGGED_IN(AuthLevel.USER, UserPolicy.PUBLIC),
|
||||
|
||||
/**
|
||||
* Allows only the app itself (via service accounts) or admins to access.
|
||||
@@ -64,12 +42,12 @@ public enum Auth {
|
||||
* associated service account needs to be allowlisted in the {@code
|
||||
* auth.allowedServiceAccountEmails} field in the config YAML file.
|
||||
*/
|
||||
AUTH_API_ADMIN(ImmutableList.of(AuthMethod.API), AuthLevel.APP, UserPolicy.ADMIN);
|
||||
AUTH_ADMIN(AuthLevel.APP, UserPolicy.ADMIN);
|
||||
|
||||
private final AuthSettings authSettings;
|
||||
|
||||
Auth(ImmutableList<AuthMethod> methods, AuthLevel minimumLevel, UserPolicy userPolicy) {
|
||||
authSettings = AuthSettings.create(methods, minimumLevel, userPolicy);
|
||||
Auth(AuthLevel minimumLevel, UserPolicy userPolicy) {
|
||||
authSettings = new AuthSettings(minimumLevel, userPolicy);
|
||||
}
|
||||
|
||||
public AuthSettings authSettings() {
|
||||
|
||||
@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.request.auth.AuthSettings.AuthLevel.APP;
|
||||
import static google.registry.request.auth.AuthSettings.AuthLevel.USER;
|
||||
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -26,24 +27,23 @@ import javax.annotation.Nullable;
|
||||
* Results of authentication for a given HTTP request, as emitted by an {@link
|
||||
* AuthenticationMechanism}.
|
||||
*
|
||||
* @param userAuthInfo Information about the authenticated user, if there is one.
|
||||
* @param appServiceAccount Service account email of the authenticated app, if there is one. This
|
||||
* will be logged upon successful login.
|
||||
* @param authLevel the level of authentication obtained
|
||||
* @param user information about the authenticated user, if there is one
|
||||
* @param serviceAccountEmail service account email of the authenticated app, if there is one
|
||||
*/
|
||||
public record AuthResult(
|
||||
AuthLevel authLevel, Optional<UserAuthInfo> userAuthInfo, Optional<String> appServiceAccount) {
|
||||
AuthLevel authLevel, Optional<User> user, Optional<String> serviceAccountEmail) {
|
||||
|
||||
public boolean isAuthenticated() {
|
||||
return authLevel() != AuthLevel.NONE;
|
||||
}
|
||||
|
||||
public String userIdForLogging() {
|
||||
return userAuthInfo()
|
||||
.map(
|
||||
userAuthInfo ->
|
||||
return user.map(
|
||||
user ->
|
||||
String.format(
|
||||
"%s %s",
|
||||
userAuthInfo.isUserAdmin() ? "admin" : "user", userAuthInfo.getEmailAddress()))
|
||||
user.getUserRoles().isAdmin() ? "admin" : "user", user.getEmailAddress()))
|
||||
.orElse("<logged-out user>");
|
||||
}
|
||||
|
||||
@@ -51,22 +51,21 @@ public record AuthResult(
|
||||
return create(APP, null, email);
|
||||
}
|
||||
|
||||
public static AuthResult createUser(UserAuthInfo userAuthInfo) {
|
||||
return create(USER, userAuthInfo, null);
|
||||
public static AuthResult createUser(User user) {
|
||||
return create(USER, user, null);
|
||||
}
|
||||
|
||||
private static AuthResult create(
|
||||
AuthLevel authLevel, @Nullable UserAuthInfo userAuthInfo, @Nullable String email) {
|
||||
AuthLevel authLevel, @Nullable User user, @Nullable String serviceAccountEmail) {
|
||||
checkArgument(
|
||||
userAuthInfo == null || email == null,
|
||||
"User auth info and service account email cannot be specificed at the same time");
|
||||
user == null || serviceAccountEmail == null,
|
||||
"User and service account email cannot be specified at the same time");
|
||||
checkArgument(authLevel != USER || user != null, "User must be specified for auth level USER");
|
||||
checkArgument(
|
||||
authLevel != USER || userAuthInfo != null,
|
||||
"User auth info must be specified for auth level USER");
|
||||
checkArgument(
|
||||
authLevel != APP || email != null,
|
||||
authLevel != APP || serviceAccountEmail != null,
|
||||
"Service account email must be specified for auth level APP");
|
||||
return new AuthResult(authLevel, Optional.ofNullable(userAuthInfo), Optional.ofNullable(email));
|
||||
return new AuthResult(
|
||||
authLevel, Optional.ofNullable(user), Optional.ofNullable(serviceAccountEmail));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.request.auth;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.annotations.Immutable;
|
||||
import google.registry.model.console.UserRoles;
|
||||
|
||||
@@ -25,26 +24,7 @@ import google.registry.model.console.UserRoles;
|
||||
* values.
|
||||
*/
|
||||
@Immutable
|
||||
public record AuthSettings(
|
||||
ImmutableList<AuthMethod> methods, AuthLevel minimumLevel, UserPolicy userPolicy) {
|
||||
|
||||
static AuthSettings create(
|
||||
ImmutableList<AuthMethod> methods, AuthLevel minimumLevel, UserPolicy userPolicy) {
|
||||
return new AuthSettings(methods, minimumLevel, userPolicy);
|
||||
}
|
||||
|
||||
/** Available methods for authentication. */
|
||||
public enum AuthMethod {
|
||||
|
||||
/**
|
||||
* Authentication methods suitable for API-style access, such as {@link
|
||||
* OidcTokenAuthenticationMechanism}.
|
||||
*/
|
||||
API,
|
||||
|
||||
/** Legacy authentication using cookie-based App Engine Users API. Must come last if present. */
|
||||
LEGACY
|
||||
}
|
||||
public record AuthSettings(AuthLevel minimumLevel, UserPolicy userPolicy) {
|
||||
|
||||
/**
|
||||
* Authentication level.
|
||||
@@ -90,16 +70,7 @@ public record AuthSettings(
|
||||
/** No user policy is enforced; anyone can access this action. */
|
||||
PUBLIC,
|
||||
|
||||
/**
|
||||
* If there is a user, it must be an admin, as determined by {@link UserAuthInfo#isUserAdmin()}.
|
||||
*
|
||||
* <p>Note that, if the user returned is an App Engine {@link
|
||||
* com.google.appengine.api.users.User} , anybody with access to the app in the GCP Console,
|
||||
* including editors and viewers, is an admin.
|
||||
*
|
||||
* <p>On the other hand, if the user is a {@link google.registry.model.console.User}, the admin
|
||||
* role is explicitly defined in that object via the {@link UserRoles#isAdmin()} method.
|
||||
*/
|
||||
/** If there is a user, it must be an admin, as determined by {@link UserRoles#isAdmin()}. */
|
||||
ADMIN
|
||||
}
|
||||
}
|
||||
|
||||
+34
-73
@@ -18,18 +18,16 @@ import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import dagger.Lazy;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.groups.GroupsConnection;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarBase.State;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
@@ -37,24 +35,23 @@ import javax.inject.Inject;
|
||||
/**
|
||||
* Allows access only to {@link Registrar}s the current user has access to.
|
||||
*
|
||||
* <p>A user has OWNER role on a Registrar if there exists a {@link RegistrarPoc} with that user's
|
||||
* gaeId and the registrar as a parent.
|
||||
* <p>A user has OWNER role on a Registrar if there exists a mapping to the registrar in its {@link
|
||||
* google.registry.model.console.UserRoles} map, regardless of the role.
|
||||
*
|
||||
* <p>An "admin" has in addition OWNER role on {@code #registryAdminRegistrarId} and to all
|
||||
* <p>An "admin" has, in addition, OWNER role on {@code #registryAdminRegistrarId} and to all
|
||||
* non-{@code REAL} registrars (see {@link Registrar#getType}).
|
||||
*
|
||||
* <p>An "admin" also has ADMIN role on ALL registrars.
|
||||
*
|
||||
* <p>A user is an "admin" if they are a GAE-admin, or if their email is in the "Support" G Suite
|
||||
* group.
|
||||
* <p>A user is an "admin" if it has global admin permission, or if their email is in the "Support"
|
||||
* G Suite group.
|
||||
*
|
||||
* <p>NOTE: to check whether the user is in the "Support" G Suite group, we need a connection to G
|
||||
* Suite. This in turn requires we have valid JsonCredentials, which not all environments have set
|
||||
* up. This connection will be created lazily (only if needed).
|
||||
* Suite. This, in turn, requires us to have valid JsonCredentials, which not all environments have
|
||||
* set up. This connection will be created lazily (only if needed).
|
||||
*
|
||||
* <p>Specifically, we don't instantiate the connection if: (a) gSuiteSupportGroupEmailAddress isn't
|
||||
* defined, or (b) the user is logged out, or (c) the user is a GAE-admin, or (d) bypassAdminCheck
|
||||
* is true.
|
||||
* defined, or (b) the user is logged out, or (c) the user is an admin.
|
||||
*/
|
||||
@Immutable
|
||||
public class AuthenticatedRegistrarAccessor {
|
||||
@@ -70,8 +67,8 @@ public class AuthenticatedRegistrarAccessor {
|
||||
private final String userIdForLogging;
|
||||
|
||||
/**
|
||||
* Whether this user is an Admin, meaning either a GAE-admin or a member of the Support G Suite
|
||||
* group.
|
||||
* Whether this user is an admin, meaning either they have global admin permission or a member of
|
||||
* the Support G Suite group.
|
||||
*/
|
||||
private final boolean isAdmin;
|
||||
|
||||
@@ -84,26 +81,6 @@ public class AuthenticatedRegistrarAccessor {
|
||||
*/
|
||||
private final ImmutableSetMultimap<String, Role> roleMap;
|
||||
|
||||
/**
|
||||
* Bypass the "isAdmin" check making all users NOT admins.
|
||||
*
|
||||
* <p>Currently our test server doesn't let you change the user after the test server was created.
|
||||
* This means we'd need multiple test files to test the same actions as both a "regular" user and
|
||||
* an admin.
|
||||
*
|
||||
* <p>To overcome this - we add a flag that lets you dynamically choose whether a user is an admin
|
||||
* or not by creating a fake "GAE-admin" user and then bypassing the admin check if they want to
|
||||
* fake a "regular" user.
|
||||
*
|
||||
* <p>The reason we don't do it the other way around (have a flag that makes anyone an admin) is
|
||||
* that such a flag would be a security risk, especially since VisibleForTesting is unenforced
|
||||
* (and you could set it with reflection anyway).
|
||||
*
|
||||
* <p>Instead of having a test flag that elevates permissions (which has security concerns) we add
|
||||
* this flag that reduces permissions.
|
||||
*/
|
||||
@VisibleForTesting public static boolean bypassAdminCheck = false;
|
||||
|
||||
@Inject
|
||||
public AuthenticatedRegistrarAccessor(
|
||||
AuthResult authResult,
|
||||
@@ -140,9 +117,7 @@ public class AuthenticatedRegistrarAccessor {
|
||||
return new AuthenticatedRegistrarAccessor("TestUserId", isAdmin, roleMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this user is allowed to create new Registrars and TLDs.
|
||||
*/
|
||||
/** Returns whether this user is allowed to create new Registrars and TLDs. */
|
||||
public boolean isAdmin() {
|
||||
return isAdmin;
|
||||
}
|
||||
@@ -282,53 +257,39 @@ public class AuthenticatedRegistrarAccessor {
|
||||
AuthResult authResult,
|
||||
Optional<String> gSuiteSupportGroupEmailAddress,
|
||||
Lazy<GroupsConnection> lazyGroupsConnection) {
|
||||
if (authResult.userAuthInfo().isEmpty()) {
|
||||
if (authResult.user().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UserAuthInfo userAuthInfo = authResult.userAuthInfo().get();
|
||||
// both GAE project admin and members of the gSuiteSupportGroupEmailAddress are considered
|
||||
// admins for the RegistrarConsole.
|
||||
return !bypassAdminCheck
|
||||
&& (userAuthInfo.isUserAdmin()
|
||||
|| checkIsSupport(
|
||||
lazyGroupsConnection,
|
||||
userAuthInfo.getEmailAddress(),
|
||||
gSuiteSupportGroupEmailAddress));
|
||||
User user = authResult.user().get();
|
||||
// both user object with admin permission and members of the gSuiteSupportGroupEmailAddress are
|
||||
// considered admins for the RegistrarConsole.
|
||||
return user.getUserRoles().isAdmin()
|
||||
|| checkIsSupport(
|
||||
lazyGroupsConnection, user.getEmailAddress(), gSuiteSupportGroupEmailAddress);
|
||||
}
|
||||
|
||||
/** Returns a map of registrar IDs to roles for all registrars that the user has access to. */
|
||||
private static ImmutableSetMultimap<String, Role> createRoleMap(
|
||||
AuthResult authResult, boolean isAdmin, String registryAdminRegistrarId) {
|
||||
if (authResult.userAuthInfo().isEmpty()) {
|
||||
if (authResult.user().isEmpty()) {
|
||||
return ImmutableSetMultimap.of();
|
||||
}
|
||||
ImmutableSetMultimap.Builder<String, Role> builder = new ImmutableSetMultimap.Builder<>();
|
||||
UserAuthInfo userAuthInfo = authResult.userAuthInfo().get();
|
||||
if (userAuthInfo.appEngineUser().isPresent()) {
|
||||
User user = userAuthInfo.appEngineUser().get();
|
||||
logger.atInfo().log("Checking registrar contacts for user ID %s.", user.getEmail());
|
||||
|
||||
// Find all registrars that have a registrar contact with this user's ID.
|
||||
tm().transact(
|
||||
() ->
|
||||
tm().query(
|
||||
"SELECT r FROM Registrar r INNER JOIN RegistrarPoc rp ON r.registrarId ="
|
||||
+ " rp.registrarId WHERE lower(rp.loginEmailAddress) = :email AND"
|
||||
+ " r.state != :state",
|
||||
Registrar.class)
|
||||
.setParameter("email", Ascii.toLowerCase(user.getEmail()))
|
||||
.setParameter("state", State.DISABLED)
|
||||
.getResultStream()
|
||||
.forEach(registrar -> builder.put(registrar.getRegistrarId(), Role.OWNER)));
|
||||
} else {
|
||||
userAuthInfo
|
||||
.consoleUser()
|
||||
.get()
|
||||
.getUserRoles()
|
||||
.getRegistrarRoles()
|
||||
.forEach((k, v) -> builder.put(k, Role.OWNER));
|
||||
}
|
||||
authResult
|
||||
.user()
|
||||
.get()
|
||||
.getUserRoles()
|
||||
.getRegistrarRoles()
|
||||
.forEach(
|
||||
(k, v) ->
|
||||
Registrar.loadByRegistrarId(k)
|
||||
.ifPresent(
|
||||
registrar -> {
|
||||
if (registrar.getState() != State.DISABLED) {
|
||||
builder.put(k, Role.OWNER);
|
||||
}
|
||||
}));
|
||||
|
||||
// Admins have ADMIN access to all registrars, and also OWNER access to the registry registrar
|
||||
// and all non-REAL or non-live registrars.
|
||||
|
||||
@@ -1,84 +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.
|
||||
|
||||
package google.registry.request.auth;
|
||||
|
||||
import static com.google.common.base.Strings.emptyToNull;
|
||||
import static com.google.common.base.Strings.nullToEmpty;
|
||||
import static google.registry.request.auth.AuthResult.NOT_AUTHENTICATED;
|
||||
import static google.registry.security.XsrfTokenManager.P_CSRF_TOKEN;
|
||||
import static google.registry.security.XsrfTokenManager.X_CSRF_TOKEN;
|
||||
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Authentication mechanism for legacy cookie-based App Engine authentication.
|
||||
*
|
||||
* <p>Just use the values returned by UserService.
|
||||
*/
|
||||
public class LegacyAuthenticationMechanism implements AuthenticationMechanism {
|
||||
|
||||
private final UserService userService;
|
||||
private final XsrfTokenManager xsrfTokenManager;
|
||||
|
||||
/** HTTP methods which are considered safe, and do not require XSRF protection. */
|
||||
private static final ImmutableSet<String> SAFE_METHODS = ImmutableSet.of("GET", "HEAD");
|
||||
|
||||
@Inject
|
||||
public LegacyAuthenticationMechanism(UserService userService, XsrfTokenManager xsrfTokenManager) {
|
||||
this.userService = userService;
|
||||
this.xsrfTokenManager = xsrfTokenManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResult authenticate(HttpServletRequest request) {
|
||||
if (!userService.isUserLoggedIn()) {
|
||||
return NOT_AUTHENTICATED;
|
||||
}
|
||||
|
||||
if (!SAFE_METHODS.contains(request.getMethod()) && !validateXsrf(request)) {
|
||||
return NOT_AUTHENTICATED;
|
||||
}
|
||||
|
||||
return AuthResult.createUser(
|
||||
UserAuthInfo.create(userService.getCurrentUser(), userService.isUserAdmin()));
|
||||
}
|
||||
|
||||
private boolean validateXsrf(HttpServletRequest request) {
|
||||
String headerToken = emptyToNull(request.getHeader(X_CSRF_TOKEN));
|
||||
if (headerToken != null) {
|
||||
return xsrfTokenManager.validateToken(headerToken);
|
||||
}
|
||||
// If we got here - the header didn't have the token.
|
||||
// It might be in the POST data - however even checking whether the POST data has this entry
|
||||
// could break the Action!
|
||||
//
|
||||
// Reason: if we do request.getParameter, any Action that injects @Payload or @JsonPayload
|
||||
// would break since it uses request.getReader - and it's an error to call both getReader and
|
||||
// getParameter!
|
||||
//
|
||||
// However, in this case it's acceptable since if we got here - the POST request didn't even
|
||||
// have the XSRF header meaning if it doesn't have POST data - it's not from a valid source at
|
||||
// all (a valid but outdated source would have a bad header value, but getting here means we had
|
||||
// no value at all)
|
||||
//
|
||||
// TODO(b/120201577): Once we know from the @Action whether we can use getParameter or not -
|
||||
// only check getParameter if that's how this @Action uses getParameters.
|
||||
return xsrfTokenManager.validateToken(nullToEmpty(request.getParameter(P_CSRF_TOKEN)));
|
||||
}
|
||||
}
|
||||
+9
-1
@@ -14,6 +14,8 @@
|
||||
|
||||
package google.registry.request.auth;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import com.google.api.client.json.webtoken.JsonWebSignature;
|
||||
import com.google.auth.oauth2.TokenVerifier;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
@@ -117,7 +119,7 @@ public abstract class OidcTokenAuthenticationMechanism implements Authentication
|
||||
}
|
||||
Optional<User> maybeUser = UserDao.loadUser(email);
|
||||
if (maybeUser.isPresent()) {
|
||||
return AuthResult.createUser(UserAuthInfo.create(maybeUser.get()));
|
||||
return AuthResult.createUser(maybeUser.get());
|
||||
}
|
||||
logger.atInfo().log("No end user found for email address %s", email);
|
||||
if (serviceAccountEmails.stream().anyMatch(e -> e.equals(email))) {
|
||||
@@ -131,11 +133,17 @@ public abstract class OidcTokenAuthenticationMechanism implements Authentication
|
||||
|
||||
@VisibleForTesting
|
||||
public static void setAuthResultForTesting(@Nullable AuthResult authResult) {
|
||||
checkState(
|
||||
RegistryEnvironment.get() == RegistryEnvironment.UNITTEST,
|
||||
"Explicitly setting auth result is only supported in tests");
|
||||
authResultForTesting = authResult;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static void unsetAuthResultForTesting() {
|
||||
checkState(
|
||||
RegistryEnvironment.get() == RegistryEnvironment.UNITTEST,
|
||||
"Explicitly unsetting auth result is only supported in tests");
|
||||
authResultForTesting = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,7 @@ import static google.registry.request.auth.AuthSettings.AuthLevel.USER;
|
||||
import static google.registry.request.auth.AuthSettings.UserPolicy.ADMIN;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.request.auth.AuthSettings.AuthMethod;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
@@ -32,16 +30,12 @@ import javax.inject.Inject;
|
||||
public class RequestAuthenticator {
|
||||
|
||||
private final ImmutableList<AuthenticationMechanism> apiAuthenticationMechanisms;
|
||||
private final LegacyAuthenticationMechanism legacyAuthenticationMechanism;
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@Inject
|
||||
public RequestAuthenticator(
|
||||
ImmutableList<AuthenticationMechanism> apiAuthenticationMechanisms,
|
||||
LegacyAuthenticationMechanism legacyAuthenticationMechanism) {
|
||||
public RequestAuthenticator(ImmutableList<AuthenticationMechanism> apiAuthenticationMechanisms) {
|
||||
this.apiAuthenticationMechanisms = apiAuthenticationMechanisms;
|
||||
this.legacyAuthenticationMechanism = legacyAuthenticationMechanism;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,8 +60,8 @@ public class RequestAuthenticator {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (auth.userPolicy() == ADMIN
|
||||
&& authResult.userAuthInfo().isPresent()
|
||||
&& !authResult.userAuthInfo().get().isUserAdmin()) {
|
||||
&& authResult.user().isPresent()
|
||||
&& !authResult.user().get().getUserRoles().isAdmin()) {
|
||||
logger.atWarning().log(
|
||||
"Not authorized; user policy is ADMIN, but the user was not an admin.");
|
||||
return Optional.empty();
|
||||
@@ -84,28 +78,13 @@ public class RequestAuthenticator {
|
||||
*/
|
||||
AuthResult authenticate(AuthSettings auth, HttpServletRequest req) {
|
||||
checkAuthConfig(auth);
|
||||
for (AuthMethod authMethod : auth.methods()) {
|
||||
AuthResult authResult;
|
||||
switch (authMethod) {
|
||||
// API-based user authentication mechanisms, such as OIDC.
|
||||
case API -> {
|
||||
for (AuthenticationMechanism authMechanism : apiAuthenticationMechanisms) {
|
||||
authResult = authMechanism.authenticate(req);
|
||||
if (authResult.isAuthenticated()) {
|
||||
logger.atInfo().log(
|
||||
"Authenticated via %s: %s", authMechanism.getClass().getSimpleName(), authResult);
|
||||
return authResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Legacy authentication via UserService
|
||||
case LEGACY -> {
|
||||
authResult = legacyAuthenticationMechanism.authenticate(req);
|
||||
if (authResult.isAuthenticated()) {
|
||||
logger.atInfo().log("Authenticated via legacy auth: %s", authResult);
|
||||
return authResult;
|
||||
}
|
||||
}
|
||||
AuthResult authResult;
|
||||
for (AuthenticationMechanism authMechanism : apiAuthenticationMechanisms) {
|
||||
authResult = authMechanism.authenticate(req);
|
||||
if (authResult.isAuthenticated()) {
|
||||
logger.atInfo().log(
|
||||
"Authenticated via %s: %s", authMechanism.getClass().getSimpleName(), authResult);
|
||||
return authResult;
|
||||
}
|
||||
}
|
||||
logger.atInfo().log("No authentication found.");
|
||||
@@ -114,10 +93,6 @@ public class RequestAuthenticator {
|
||||
|
||||
/** Validates an AuthSettings object, checking for invalid setting combinations. */
|
||||
static void checkAuthConfig(AuthSettings auth) {
|
||||
checkArgument(!auth.methods().isEmpty(), "Must specify at least one auth method");
|
||||
checkArgument(
|
||||
Ordering.explicit(AuthMethod.API, AuthMethod.LEGACY).isStrictlyOrdered(auth.methods()),
|
||||
"Auth methods must be unique and strictly in order - API, LEGACY");
|
||||
checkArgument(
|
||||
(auth.minimumLevel() != NONE) || (auth.userPolicy() != ADMIN),
|
||||
"Actions with minimal auth level at NONE should not specify ADMIN user policy");
|
||||
|
||||
@@ -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.
|
||||
|
||||
package google.registry.request.auth;
|
||||
|
||||
import com.google.appengine.api.users.User;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Extra information provided by the authentication mechanism about the user.
|
||||
*
|
||||
* @param appEngineUser User object from the AppEngine Users API.
|
||||
* @param isUserAdmin Whether the user is an admin.
|
||||
* <p>Note that, in App Engine parlance, an admin is any user who is a project owner, editor, OR
|
||||
* viewer (as well as the specific role App Engine Admin). So even users with read-only access
|
||||
* to the App Engine product qualify as an "admin".
|
||||
*/
|
||||
public record UserAuthInfo(
|
||||
Optional<google.registry.model.console.User> consoleUser,
|
||||
Optional<User> appEngineUser,
|
||||
boolean isUserAdmin) {
|
||||
|
||||
public String getEmailAddress() {
|
||||
return appEngineUser()
|
||||
.map(User::getEmail)
|
||||
.orElseGet(() -> consoleUser().get().getEmailAddress());
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return appEngineUser()
|
||||
.map(User::getNickname)
|
||||
.orElseGet(() -> consoleUser().get().getEmailAddress());
|
||||
}
|
||||
|
||||
public static UserAuthInfo create(User user, boolean isUserAdmin) {
|
||||
return new UserAuthInfo(Optional.empty(), Optional.of(user), isUserAdmin);
|
||||
}
|
||||
|
||||
public static UserAuthInfo create(google.registry.model.console.User user) {
|
||||
return new UserAuthInfo(Optional.of(user), Optional.empty(), user.getUserRoles().isAdmin());
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
@@ -49,12 +48,10 @@ public final class XsrfTokenManager {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private final Clock clock;
|
||||
private final UserService userService;
|
||||
|
||||
@Inject
|
||||
public XsrfTokenManager(Clock clock, UserService userService) {
|
||||
public XsrfTokenManager(Clock clock) {
|
||||
this.clock = clock;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
/** Generates an XSRF token for a given user based on email address. */
|
||||
@@ -81,7 +78,7 @@ public final class XsrfTokenManager {
|
||||
}
|
||||
|
||||
/** Validates an XSRF token against the current logged-in user. */
|
||||
public boolean validateToken(String token) {
|
||||
public boolean validateToken(String email, String token) {
|
||||
checkArgumentNotNull(token);
|
||||
List<String> tokenParts = Splitter.on(':').splitToList(token);
|
||||
if (tokenParts.size() != 3) {
|
||||
@@ -104,12 +101,8 @@ public final class XsrfTokenManager {
|
||||
logger.atInfo().log("Expired timestamp in XSRF token: %s", token);
|
||||
return false;
|
||||
}
|
||||
String currentUserEmail =
|
||||
userService.isUserLoggedIn() ? userService.getCurrentUser().getEmail() : "";
|
||||
|
||||
// Reconstruct the token to verify validity.
|
||||
String reconstructedToken =
|
||||
encodeToken(ServerSecret.get().asBytes(), currentUserEmail, timestampMillis);
|
||||
String reconstructedToken = encodeToken(ServerSecret.get().asBytes(), email, timestampMillis);
|
||||
if (!token.equals(reconstructedToken)) {
|
||||
logger.atWarning().log(
|
||||
"Reconstructed XSRF mismatch (got != expected): %s != %s", token, reconstructedToken);
|
||||
|
||||
@@ -70,7 +70,7 @@ import org.joda.time.Duration;
|
||||
path = NordnUploadAction.PATH,
|
||||
method = Action.Method.POST,
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class NordnUploadAction implements Runnable {
|
||||
|
||||
static final String PATH = "/_dr/task/nordnUpload";
|
||||
|
||||
@@ -54,7 +54,7 @@ import javax.inject.Inject;
|
||||
path = NordnVerifyAction.PATH,
|
||||
method = Action.Method.POST,
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class NordnVerifyAction implements Runnable {
|
||||
|
||||
static final String PATH = "/_dr/task/nordnVerify";
|
||||
|
||||
@@ -32,7 +32,7 @@ import javax.inject.Inject;
|
||||
path = "/_dr/task/tmchCrl",
|
||||
method = POST,
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class TmchCrlAction implements Runnable {
|
||||
|
||||
@Inject Marksdb marksdb;
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.bouncycastle.openpgp.PGPException;
|
||||
path = "/_dr/task/tmchDnl",
|
||||
method = POST,
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class TmchDnlAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.bouncycastle.openpgp.PGPException;
|
||||
path = "/_dr/task/tmchSmdrl",
|
||||
method = POST,
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class TmchSmdrlAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -17,19 +17,32 @@ package google.registry.tools;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.tools.server.UpdateUserGroupAction;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Command to create a new User. */
|
||||
@Parameters(separators = " =", commandDescription = "Update a user account")
|
||||
public class CreateUserCommand extends CreateOrUpdateUserCommand {
|
||||
public class CreateUserCommand extends CreateOrUpdateUserCommand implements CommandWithConnection {
|
||||
|
||||
static final String IAP_SECURED_WEB_APP_USER_ROLE = "roles/iap.httpsResourceAccessor";
|
||||
static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private ServiceConnection connection;
|
||||
|
||||
@Inject IamClient iamClient;
|
||||
|
||||
@Inject
|
||||
@Config("gSuiteConsoleUserGroupEmailAddress")
|
||||
Optional<String> maybeGroupEmailAddress;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
User getExistingUser(String email) {
|
||||
@@ -40,7 +53,29 @@ public class CreateUserCommand extends CreateOrUpdateUserCommand {
|
||||
@Override
|
||||
protected String execute() throws Exception {
|
||||
String ret = super.execute();
|
||||
iamClient.addBinding(email, IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
String groupEmailAddress = maybeGroupEmailAddress.orElse(null);
|
||||
if (groupEmailAddress != null) {
|
||||
logger.atInfo().log("Adding %s to group %s", email, groupEmailAddress);
|
||||
connection.sendPostRequest(
|
||||
UpdateUserGroupAction.PATH,
|
||||
ImmutableMap.of(
|
||||
"userEmailAddress",
|
||||
email,
|
||||
"groupEmailAddress",
|
||||
groupEmailAddress,
|
||||
"groupUpdateMode",
|
||||
"ADD"),
|
||||
MediaType.PLAIN_TEXT_UTF_8,
|
||||
new byte[0]);
|
||||
} else {
|
||||
logger.atInfo().log("Granting IAP role to user %s", email);
|
||||
iamClient.addBinding(email, IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConnection(ServiceConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,22 +21,39 @@ import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.tools.server.UpdateUserGroupAction;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Deletes a {@link User}. */
|
||||
@Parameters(separators = " =", commandDescription = "Delete a user account")
|
||||
public class DeleteUserCommand extends ConfirmingCommand {
|
||||
public class DeleteUserCommand extends ConfirmingCommand implements CommandWithConnection {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private ServiceConnection connection;
|
||||
@Inject IamClient iamClient;
|
||||
|
||||
@Inject
|
||||
@Config("gSuiteConsoleUserGroupEmailAddress")
|
||||
Optional<String> maybeGroupEmailAddress;
|
||||
|
||||
@Nullable
|
||||
@Parameter(names = "--email", description = "Email address of the user", required = true)
|
||||
String email;
|
||||
|
||||
@Override
|
||||
public void setConnection(ServiceConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String prompt() {
|
||||
checkArgumentNotNull(email, "Email must be provided");
|
||||
@@ -52,7 +69,24 @@ public class DeleteUserCommand extends ConfirmingCommand {
|
||||
checkArgumentPresent(optionalUser, "Email no longer corresponds to a valid user");
|
||||
tm().delete(optionalUser.get());
|
||||
});
|
||||
iamClient.removeBinding(email, IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
String groupEmailAddress = maybeGroupEmailAddress.orElse(null);
|
||||
if (groupEmailAddress != null) {
|
||||
logger.atInfo().log("Removing %s from group %s", email, groupEmailAddress);
|
||||
connection.sendPostRequest(
|
||||
UpdateUserGroupAction.PATH,
|
||||
ImmutableMap.of(
|
||||
"userEmailAddress",
|
||||
email,
|
||||
"groupEmailAddress",
|
||||
groupEmailAddress,
|
||||
"groupUpdateMode",
|
||||
"REMOVE"),
|
||||
MediaType.PLAIN_TEXT_UTF_8,
|
||||
new byte[0]);
|
||||
} else {
|
||||
logger.atInfo().log("Removing IAP role from user %s", email);
|
||||
iamClient.removeBinding(email, IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
}
|
||||
return String.format("Deleted user with email %s", email);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ import google.registry.privileges.secretmanager.SecretManagerModule;
|
||||
import google.registry.rde.RdeModule;
|
||||
import google.registry.request.Modules.GsonModule;
|
||||
import google.registry.request.Modules.UrlConnectionServiceModule;
|
||||
import google.registry.request.Modules.UserServiceModule;
|
||||
import google.registry.tools.AuthModule.LocalCredentialModule;
|
||||
import google.registry.util.UtilsModule;
|
||||
import google.registry.whois.NonCachingWhoisModule;
|
||||
@@ -75,7 +74,6 @@ import javax.inject.Singleton;
|
||||
SecretManagerKeyringModule.class,
|
||||
SecretManagerModule.class,
|
||||
UrlConnectionServiceModule.class,
|
||||
UserServiceModule.class,
|
||||
UtilsModule.class,
|
||||
VoidDnsWriterModule.class,
|
||||
NonCachingWhoisModule.class
|
||||
|
||||
@@ -43,7 +43,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.TOOLS,
|
||||
path = CreateGroupsAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class CreateGroupsAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/admin/createGroups";
|
||||
|
||||
@@ -65,7 +65,7 @@ import org.joda.time.Duration;
|
||||
service = Action.Service.TOOLS,
|
||||
path = GenerateZoneFilesAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class GenerateZoneFilesAction implements Runnable, JsonActionRunner.JsonAction {
|
||||
|
||||
private static final FluentLogger log = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -39,7 +39,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.TOOLS,
|
||||
path = ListDomainsAction.PATH,
|
||||
method = {GET, POST},
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class ListDomainsAction extends ListObjectsAction<Domain> {
|
||||
|
||||
/** An App Engine limitation on how many subqueries can be used in a single query. */
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.joda.time.DateTime;
|
||||
service = Action.Service.TOOLS,
|
||||
path = ListHostsAction.PATH,
|
||||
method = {GET, POST},
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class ListHostsAction extends ListObjectsAction<Host> {
|
||||
|
||||
public static final String PATH = "/_dr/admin/list/hosts";
|
||||
|
||||
@@ -35,7 +35,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.TOOLS,
|
||||
path = ListPremiumListsAction.PATH,
|
||||
method = {GET, POST},
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class ListPremiumListsAction extends ListObjectsAction<PremiumList> {
|
||||
|
||||
public static final String PATH = "/_dr/admin/list/premiumLists";
|
||||
|
||||
@@ -30,7 +30,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.TOOLS,
|
||||
path = ListRegistrarsAction.PATH,
|
||||
method = {GET, POST},
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class ListRegistrarsAction extends ListObjectsAction<Registrar> {
|
||||
|
||||
public static final String PATH = "/_dr/admin/list/registrars";
|
||||
|
||||
@@ -33,7 +33,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.TOOLS,
|
||||
path = ListReservedListsAction.PATH,
|
||||
method = {GET, POST},
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class ListReservedListsAction extends ListObjectsAction<ReservedList> {
|
||||
|
||||
public static final String PATH = "/_dr/admin/list/reservedLists";
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.joda.time.DateTime;
|
||||
service = Action.Service.TOOLS,
|
||||
path = ListTldsAction.PATH,
|
||||
method = {GET, POST},
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public final class ListTldsAction extends ListObjectsAction<Tld> {
|
||||
|
||||
public static final String PATH = "/_dr/admin/list/tlds";
|
||||
|
||||
@@ -54,7 +54,7 @@ import org.joda.time.Duration;
|
||||
@Action(
|
||||
service = Action.Service.TOOLS,
|
||||
path = "/_dr/task/refreshDnsForAllDomains",
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class RefreshDnsForAllDomainsAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -23,12 +23,11 @@ import static google.registry.request.RequestParameters.extractRequiredParameter
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.tools.server.UpdateUserGroupAction.Mode;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Dagger module for the tools package.
|
||||
*/
|
||||
/** Dagger module for the tools package. */
|
||||
@Module
|
||||
public class ToolsServerModule {
|
||||
|
||||
@@ -75,4 +74,21 @@ public class ToolsServerModule {
|
||||
static Optional<Integer> provideRefreshQps(HttpServletRequest req) {
|
||||
return extractOptionalIntParameter(req, "refreshQps");
|
||||
}
|
||||
|
||||
@Provides
|
||||
static Mode provideGroupUpdateMode(HttpServletRequest req) {
|
||||
return Mode.valueOf(extractRequiredParameter(req, "groupUpdateMode"));
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter("userEmailAddress")
|
||||
static String provideUserEmailAddress(HttpServletRequest req) {
|
||||
return extractRequiredParameter(req, "userEmailAddress");
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter("groupEmailAddress")
|
||||
static String provideGroupEmailAddress(HttpServletRequest req) {
|
||||
return extractRequiredParameter(req, "groupEmailAddress");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.tools.server;
|
||||
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.groups.GroupsConnection;
|
||||
import google.registry.groups.GroupsConnection.Role;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Action that adds or deletes a console user to/from the group that has IAP permissions. */
|
||||
@Action(
|
||||
service = Action.Service.TOOLS,
|
||||
path = UpdateUserGroupAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class UpdateUserGroupAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/admin/updateUserGroup";
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@Inject GroupsConnection groupsConnection;
|
||||
@Inject Response response;
|
||||
|
||||
@Inject
|
||||
@Parameter("userEmailAddress")
|
||||
String userEmailAddress;
|
||||
|
||||
@Inject
|
||||
@Parameter("groupEmailAddress")
|
||||
String groupEmailAddress;
|
||||
|
||||
@Inject Mode mode;
|
||||
|
||||
@Inject
|
||||
UpdateUserGroupAction() {}
|
||||
|
||||
enum Mode {
|
||||
ADD,
|
||||
REMOVE
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
logger.atInfo().log(
|
||||
"Updating group %s: %s user %s",
|
||||
groupEmailAddress, mode == Mode.ADD ? "adding" : "removing", userEmailAddress);
|
||||
try {
|
||||
if (mode == Mode.ADD) {
|
||||
// The group will be created if it does not exist.
|
||||
groupsConnection.addMemberToGroup(groupEmailAddress, userEmailAddress, Role.MEMBER);
|
||||
} else {
|
||||
if (groupsConnection.isMemberOfGroup(userEmailAddress, groupEmailAddress)) {
|
||||
groupsConnection.removeMemberFromGroup(groupEmailAddress, userEmailAddress);
|
||||
} else {
|
||||
logger.atInfo().log(
|
||||
"Ignoring request to remove non-member %s from group %s",
|
||||
userEmailAddress, groupEmailAddress);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Cannot update group", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ import javax.inject.Inject;
|
||||
service = Action.Service.TOOLS,
|
||||
path = VerifyOteAction.PATH,
|
||||
method = Action.Method.POST,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class VerifyOteAction implements Runnable, JsonAction {
|
||||
|
||||
public static final String PATH = "/_dr/admin/verifyOte";
|
||||
|
||||
@@ -35,7 +35,7 @@ import javax.mail.internet.InternetAddress;
|
||||
public class SendEmailUtils {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private final GmailClient gmailClient;
|
||||
public final GmailClient gmailClient;
|
||||
private final ImmutableList<String> registrarChangesNotificationEmailAddresses;
|
||||
|
||||
@Inject
|
||||
|
||||
@@ -14,24 +14,44 @@
|
||||
|
||||
package google.registry.ui.server.console;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||
|
||||
import com.google.api.client.http.HttpStatusCodes;
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.batch.CloudTasksUtils;
|
||||
import google.registry.export.sheet.SyncRegistrarsSheetAction;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.model.registrar.RegistrarPocBase;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.request.HttpException;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
import google.registry.ui.server.registrar.ConsoleApiParams;
|
||||
import google.registry.ui.server.registrar.ConsoleUiAction;
|
||||
import google.registry.util.DiffUtils;
|
||||
import google.registry.util.RegistryEnvironment;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Base class for handling Console API requests */
|
||||
public abstract class ConsoleApiAction implements Runnable {
|
||||
@@ -40,6 +60,8 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
|
||||
protected ConsoleApiParams consoleApiParams;
|
||||
|
||||
@Inject CloudTasksUtils cloudTasksUtils;
|
||||
|
||||
public ConsoleApiAction(ConsoleApiParams consoleApiParams) {
|
||||
this.consoleApiParams = consoleApiParams;
|
||||
}
|
||||
@@ -47,13 +69,11 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
@Override
|
||||
public final void run() {
|
||||
// Shouldn't be even possible because of Auth annotations on the various implementing classes
|
||||
AuthResult authResult = consoleApiParams.authResult();
|
||||
if (authResult.userAuthInfo().isEmpty()
|
||||
|| authResult.userAuthInfo().get().consoleUser().isEmpty()) {
|
||||
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
|
||||
if (consoleApiParams.authResult().user().isEmpty()) {
|
||||
consoleApiParams.response().setStatus(SC_UNAUTHORIZED);
|
||||
return;
|
||||
}
|
||||
User user = consoleApiParams.authResult().userAuthInfo().get().consoleUser().get();
|
||||
User user = consoleApiParams.authResult().user().get();
|
||||
|
||||
// This allows us to enable console to a selected cohort of users with release
|
||||
// We can ignore it in tests
|
||||
@@ -71,21 +91,19 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
if (consoleApiParams.request().getMethod().equals(GET.toString())) {
|
||||
getHandler(user);
|
||||
} else {
|
||||
if (verifyXSRF()) {
|
||||
if (verifyXSRF(user)) {
|
||||
postHandler(user);
|
||||
}
|
||||
}
|
||||
} catch (ConsolePermissionForbiddenException e) {
|
||||
logger.atWarning().withCause(e).log("Forbidden");
|
||||
setFailedResponse("", HttpStatusCodes.STATUS_CODE_FORBIDDEN);
|
||||
setFailedResponse("", SC_FORBIDDEN);
|
||||
} catch (HttpException.BadRequestException | IllegalArgumentException e) {
|
||||
logger.atWarning().withCause(e).log("Error in request");
|
||||
setFailedResponse(
|
||||
Throwables.getRootCause(e).getMessage(), HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
|
||||
setFailedResponse(Throwables.getRootCause(e).getMessage(), SC_BAD_REQUEST);
|
||||
} catch (Throwable t) {
|
||||
logger.atWarning().withCause(t).log("Internal server error");
|
||||
setFailedResponse(
|
||||
Throwables.getRootCause(t).getMessage(), HttpStatusCodes.STATUS_CODE_SERVER_ERROR);
|
||||
setFailedResponse(Throwables.getRootCause(t).getMessage(), SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,23 +129,130 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
consoleApiParams.response().setPayload(message);
|
||||
}
|
||||
|
||||
private boolean verifyXSRF() {
|
||||
private boolean verifyXSRF(User user) {
|
||||
Optional<Cookie> maybeCookie =
|
||||
Arrays.stream(consoleApiParams.request().getCookies())
|
||||
.filter(c -> XsrfTokenManager.X_CSRF_TOKEN.equals(c.getName()))
|
||||
.findFirst();
|
||||
if (maybeCookie.isEmpty()
|
||||
|| !consoleApiParams.xsrfTokenManager().validateToken(maybeCookie.get().getValue())) {
|
||||
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
|
||||
|| !consoleApiParams
|
||||
.xsrfTokenManager()
|
||||
.validateToken(user.getEmailAddress(), maybeCookie.get().getValue())) {
|
||||
consoleApiParams.response().setStatus(SC_UNAUTHORIZED);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Map<String, Object> expandRegistrarWithContacts(
|
||||
ImmutableSet<RegistrarPoc> contacts, Registrar registrar) {
|
||||
|
||||
ImmutableSet<Map<String, Object>> expandedContacts =
|
||||
contacts.stream()
|
||||
.map(RegistrarPoc::toDiffableFieldMap)
|
||||
// Note: per the javadoc, toDiffableFieldMap includes sensitive data, but we don't want
|
||||
// to display it here
|
||||
.peek(
|
||||
map -> {
|
||||
map.remove("registryLockPasswordHash");
|
||||
map.remove("registryLockPasswordSalt");
|
||||
})
|
||||
.collect(toImmutableSet());
|
||||
|
||||
Map<String, Object> registrarDiffMap = registrar.toDiffableFieldMap();
|
||||
Stream.of("passwordHash", "salt") // fields to remove from final diff
|
||||
.forEach(fieldToBeRemoved -> registrarDiffMap.remove(fieldToBeRemoved));
|
||||
|
||||
// Use LinkedHashMap here to preserve ordering; null values mean we can't use ImmutableMap.
|
||||
LinkedHashMap<String, Object> result = new LinkedHashMap<>(registrarDiffMap);
|
||||
result.put("contacts", expandedContacts);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void sendExternalUpdates(
|
||||
Map<?, ?> diffs, Registrar registrar, ImmutableSet<RegistrarPoc> contacts) {
|
||||
|
||||
if (!consoleApiParams.sendEmailUtils().hasRecipients() && contacts.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!RegistryEnvironment.UNITTEST.equals(RegistryEnvironment.get())
|
||||
&& cloudTasksUtils != null) {
|
||||
// Enqueues a sync registrar sheet task if enqueuing is not triggered by console tests and
|
||||
// there's an update besides the lastUpdateTime
|
||||
cloudTasksUtils.enqueue(
|
||||
SyncRegistrarsSheetAction.QUEUE,
|
||||
cloudTasksUtils.createGetTask(
|
||||
SyncRegistrarsSheetAction.PATH, Service.BACKEND, ImmutableMultimap.of()));
|
||||
}
|
||||
|
||||
String environment = Ascii.toLowerCase(String.valueOf(RegistryEnvironment.get()));
|
||||
consoleApiParams
|
||||
.sendEmailUtils()
|
||||
.sendEmail(
|
||||
String.format(
|
||||
"Registrar %s (%s) updated in registry %s environment",
|
||||
registrar.getRegistrarName(), registrar.getRegistrarId(), environment),
|
||||
String.format(
|
||||
"""
|
||||
The following changes were made in registry %s environment to the registrar %s by\
|
||||
%s:
|
||||
|
||||
%s""",
|
||||
environment,
|
||||
registrar.getRegistrarId(),
|
||||
consoleApiParams.authResult().userIdForLogging(),
|
||||
DiffUtils.prettyPrintDiffedMap(diffs, null)),
|
||||
contacts.stream()
|
||||
.filter(c -> c.getTypes().contains(RegistrarPocBase.Type.ADMIN))
|
||||
.map(RegistrarPoc::getEmailAddress)
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if any changes were made to the registrar besides the lastUpdateTime, and if so,
|
||||
* sends an email with a diff of the changes to the configured notification email address and all
|
||||
* contact addresses and enqueues a task to re-sync the registrar sheet.
|
||||
*/
|
||||
protected void sendExternalUpdatesIfNecessary(EmailInfo emailInfo) {
|
||||
ImmutableSet<RegistrarPoc> existingContacts = emailInfo.contacts();
|
||||
Registrar existingRegistrar = emailInfo.registrar();
|
||||
|
||||
Map<?, ?> diffs =
|
||||
DiffUtils.deepDiff(
|
||||
expandRegistrarWithContacts(existingContacts, existingRegistrar),
|
||||
expandRegistrarWithContacts(emailInfo.updatedContacts(), emailInfo.updatedRegistrar()),
|
||||
true);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> changedKeys = (Set<String>) diffs.keySet();
|
||||
if (Sets.difference(changedKeys, ImmutableSet.of("lastUpdateTime")).isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
sendExternalUpdates(diffs, existingRegistrar, existingContacts);
|
||||
}
|
||||
|
||||
protected record EmailInfo(
|
||||
Registrar registrar,
|
||||
Registrar updatedRegistrar,
|
||||
ImmutableSet<RegistrarPoc> contacts,
|
||||
ImmutableSet<RegistrarPoc> updatedContacts) {
|
||||
|
||||
public static EmailInfo create(
|
||||
Registrar registrar,
|
||||
Registrar updatedRegistrar,
|
||||
ImmutableSet<RegistrarPoc> contacts,
|
||||
ImmutableSet<RegistrarPoc> updatedContacts) {
|
||||
return new EmailInfo(registrar, updatedRegistrar, contacts, updatedContacts);
|
||||
}
|
||||
}
|
||||
|
||||
/** Specialized exception class used for failure when a user doesn't have the right permission. */
|
||||
private static class ConsolePermissionForbiddenException extends RuntimeException {
|
||||
private ConsolePermissionForbiddenException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
package google.registry.ui.server.console;
|
||||
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.api.client.http.HttpStatusCodes;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.model.EppResourceUtils;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
@@ -59,16 +60,16 @@ public class ConsoleDomainGetAction extends ConsoleApiAction {
|
||||
EppResourceUtils.loadByForeignKeyCached(
|
||||
Domain.class, paramDomain, tm().getTransactionTime()));
|
||||
if (possibleDomain.isEmpty()) {
|
||||
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_NOT_FOUND);
|
||||
consoleApiParams.response().setStatus(SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
Domain domain = possibleDomain.get();
|
||||
if (!user.getUserRoles()
|
||||
.hasPermission(domain.getCurrentSponsorRegistrarId(), ConsolePermission.DOWNLOAD_DOMAINS)) {
|
||||
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_NOT_FOUND);
|
||||
consoleApiParams.response().setStatus(SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
consoleApiParams.response().setPayload(gson.toJson(domain));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ package google.registry.ui.server.console;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.model.console.ConsolePermission.DOWNLOAD_DOMAINS;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.api.client.http.HttpStatusCodes;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.gson.Gson;
|
||||
@@ -118,7 +118,7 @@ public class ConsoleDomainListAction extends ConsoleApiAction {
|
||||
consoleApiParams
|
||||
.response()
|
||||
.setPayload(gson.toJson(new DomainListResult(domains, checkpoint, actualTotalResults)));
|
||||
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
/** Creates the query to get the total number of matching domains, interpolating as necessary. */
|
||||
|
||||
+16
-19
@@ -17,13 +17,16 @@ package google.registry.ui.server.console;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.api.client.http.HttpStatusCodes;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import google.registry.flows.EppException.AuthenticationErrorException;
|
||||
import google.registry.flows.PasswordOnlyTransportCredentials;
|
||||
import google.registry.groups.GmailClient;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.request.Action;
|
||||
@@ -32,10 +35,9 @@ import google.registry.request.auth.Auth;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException;
|
||||
import google.registry.ui.server.registrar.ConsoleApiParams;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.DiffUtils;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
|
||||
@Action(
|
||||
service = Action.Service.DEFAULT,
|
||||
@@ -43,16 +45,12 @@ import javax.mail.internet.InternetAddress;
|
||||
method = {POST},
|
||||
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
||||
public class ConsoleEppPasswordAction extends ConsoleApiAction {
|
||||
protected static final String EMAIL_SUBJ = "EPP password update confirmation";
|
||||
protected static final String EMAIL_BODY =
|
||||
"Dear %s,\n" + "This is to confirm that your account password has been changed.";
|
||||
|
||||
public static final String PATH = "/console-api/eppPassword";
|
||||
|
||||
private final PasswordOnlyTransportCredentials credentials =
|
||||
new PasswordOnlyTransportCredentials();
|
||||
private final AuthenticatedRegistrarAccessor registrarAccessor;
|
||||
private final GmailClient gmailClient;
|
||||
|
||||
private final Optional<EppPasswordData> eppPasswordChangeRequest;
|
||||
|
||||
@@ -60,11 +58,9 @@ public class ConsoleEppPasswordAction extends ConsoleApiAction {
|
||||
public ConsoleEppPasswordAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
AuthenticatedRegistrarAccessor registrarAccessor,
|
||||
GmailClient gmailClient,
|
||||
@Parameter("eppPasswordChangeRequest") Optional<EppPasswordData> eppPasswordChangeRequest) {
|
||||
super(consoleApiParams);
|
||||
this.registrarAccessor = registrarAccessor;
|
||||
this.gmailClient = gmailClient;
|
||||
this.eppPasswordChangeRequest = eppPasswordChangeRequest;
|
||||
}
|
||||
|
||||
@@ -92,28 +88,29 @@ public class ConsoleEppPasswordAction extends ConsoleApiAction {
|
||||
try {
|
||||
registrar = registrarAccessor.getRegistrar(eppRequestBody.registrarId());
|
||||
} catch (RegistrarAccessDeniedException e) {
|
||||
setFailedResponse(e.getMessage(), HttpStatusCodes.STATUS_CODE_NOT_FOUND);
|
||||
setFailedResponse(e.getMessage(), SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
credentials.validate(registrar, eppRequestBody.oldPassword());
|
||||
} catch (AuthenticationErrorException e) {
|
||||
setFailedResponse(e.getMessage(), HttpStatusCodes.STATUS_CODE_FORBIDDEN);
|
||||
setFailedResponse(e.getMessage(), SC_FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
|
||||
tm().transact(
|
||||
() -> {
|
||||
tm().put(registrar.asBuilder().setPassword(eppRequestBody.newPassword()).build());
|
||||
this.gmailClient.sendEmail(
|
||||
EmailMessage.create(
|
||||
EMAIL_SUBJ,
|
||||
String.format(EMAIL_BODY, registrar.getRegistrarName()),
|
||||
new InternetAddress(registrar.getEmailAddress(), true)));
|
||||
Registrar updatedRegistrar =
|
||||
registrar.asBuilder().setPassword(eppRequestBody.newPassword()).build();
|
||||
tm().put(updatedRegistrar);
|
||||
sendExternalUpdates(
|
||||
ImmutableMap.of("password", new DiffUtils.DiffPair("********", "••••••••")),
|
||||
registrar,
|
||||
ImmutableSet.of());
|
||||
});
|
||||
|
||||
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
public record EppPasswordData(
|
||||
|
||||
@@ -24,8 +24,9 @@ import static google.registry.request.RequestParameters.extractOptionalLongParam
|
||||
import static google.registry.request.RequestParameters.extractOptionalParameter;
|
||||
import static google.registry.request.RequestParameters.extractRequiredParameter;
|
||||
import static google.registry.ui.server.registrar.RegistryLockPostAction.VERIFICATION_EMAIL_TEMPLATE;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||
|
||||
import com.google.api.client.http.HttpStatusCodes;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.flows.EppException;
|
||||
@@ -90,7 +91,7 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
protected void getHandler(User user) {
|
||||
checkPermission(user, registrarId, ConsolePermission.REGISTRY_LOCK);
|
||||
consoleApiParams.response().setPayload(gson.toJson(getLockedDomains()));
|
||||
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -124,8 +125,7 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
if (!isAdmin) {
|
||||
checkArgument(maybePassword.isPresent(), "No password provided");
|
||||
if (!user.verifyRegistryLockPassword(maybePassword.get())) {
|
||||
setFailedResponse(
|
||||
"Incorrect registry lock password", HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
|
||||
setFailedResponse("Incorrect registry lock password", SC_UNAUTHORIZED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -147,7 +147,7 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
relockDurationMillis.map(Duration::new));
|
||||
sendVerificationEmail(registryLock, registryLockEmail, isLock);
|
||||
});
|
||||
response.setStatus(HttpStatusCodes.STATUS_CODE_OK);
|
||||
response.setStatus(SC_OK);
|
||||
}
|
||||
|
||||
private void sendVerificationEmail(RegistryLock lock, String userEmail, boolean isLock) {
|
||||
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.ui.server.console;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
|
||||
import static org.apache.http.HttpStatus.SC_OK;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.HttpException.BadRequestException;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.ui.server.registrar.ConsoleApiParams;
|
||||
import google.registry.util.DomainNameUtils;
|
||||
import google.registry.util.RegistryEnvironment;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
|
||||
@Action(
|
||||
service = Action.Service.DEFAULT,
|
||||
path = ConsoleEppPasswordAction.PATH,
|
||||
method = {POST},
|
||||
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
||||
public class ConsoleUpdateRegistrarAction extends ConsoleApiAction {
|
||||
static final String PATH = "/console-api/registrar";
|
||||
private final Optional<Registrar> registrar;
|
||||
|
||||
@Inject
|
||||
ConsoleUpdateRegistrarAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
@Parameter("registrar") Optional<Registrar> registrar) {
|
||||
super(consoleApiParams);
|
||||
this.registrar = registrar;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postHandler(User user) {
|
||||
var errorMsg = "Missing param(s): %s";
|
||||
Registrar registrarParam =
|
||||
registrar.orElseThrow(() -> new BadRequestException(String.format(errorMsg, "registrar")));
|
||||
checkArgument(!Strings.isNullOrEmpty(registrarParam.getRegistrarId()), errorMsg, "registrarId");
|
||||
checkPermission(
|
||||
user, registrarParam.getRegistrarId(), ConsolePermission.EDIT_REGISTRAR_DETAILS);
|
||||
|
||||
tm().transact(
|
||||
() -> {
|
||||
Optional<Registrar> existingRegistrar =
|
||||
Registrar.loadByRegistrarId(registrarParam.getRegistrarId());
|
||||
checkArgument(
|
||||
!existingRegistrar.isEmpty(),
|
||||
"Registrar with registrarId %s doesn't exists",
|
||||
registrarParam.getRegistrarId());
|
||||
|
||||
// Only allow modifying allowed TLDs if we're in a non-PRODUCTION environment, if the
|
||||
// registrar is not REAL, or the registrar has a WHOIS abuse contact set.
|
||||
if (!registrarParam.getAllowedTlds().isEmpty()) {
|
||||
boolean isRealRegistrar =
|
||||
Registrar.Type.REAL.equals(existingRegistrar.get().getType());
|
||||
if (RegistryEnvironment.PRODUCTION.equals(RegistryEnvironment.get())
|
||||
&& isRealRegistrar) {
|
||||
checkArgumentPresent(
|
||||
existingRegistrar.get().getWhoisAbuseContact(),
|
||||
"Cannot modify allowed TLDs if there is no WHOIS abuse contact set. Please"
|
||||
+ " use the \"nomulus registrar_contact\" command on this registrar to"
|
||||
+ " set a WHOIS abuse contact.");
|
||||
}
|
||||
}
|
||||
|
||||
Registrar updatedRegistrar =
|
||||
existingRegistrar
|
||||
.get()
|
||||
.asBuilder()
|
||||
.setAllowedTlds(
|
||||
registrarParam.getAllowedTlds().stream()
|
||||
.map(DomainNameUtils::canonicalizeHostname)
|
||||
.collect(Collectors.toSet()))
|
||||
.setRegistryLockAllowed(registrarParam.isRegistryLockAllowed())
|
||||
.build();
|
||||
|
||||
tm().put(updatedRegistrar);
|
||||
sendExternalUpdatesIfNecessary(
|
||||
EmailInfo.create(
|
||||
existingRegistrar.get(),
|
||||
updatedRegistrar,
|
||||
ImmutableSet.of(),
|
||||
ImmutableSet.of()));
|
||||
});
|
||||
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user