mirror of
https://github.com/google/nomulus
synced 2026-07-06 08:06:33 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b34659a8f | |||
| 808432e709 | |||
| 73d3b76a89 | |||
| ca072b4861 | |||
| 54c896cbb9 | |||
| 2c7bf2cfdb | |||
| 49d2e34e12 | |||
| 5511b41f93 | |||
| 147cdff555 | |||
| 4b6ade0b14 | |||
| 570618705e | |||
| e791608098 | |||
| 03b358726a | |||
| d121f8f547 | |||
| b27218d799 | |||
| e78ce42dd5 | |||
| 55fade497d | |||
| e7501b621a |
@@ -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.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit:junit-bom:5.10.2=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.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.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-commons:9.6=jacocoAnt
|
||||
org.ow2.asm:asm-tree:9.6=jacocoAnt
|
||||
|
||||
@@ -175,14 +175,7 @@ public class TextDiffSubject extends Subject {
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
private static class SideBySideRowFormatter {
|
||||
private final int maxExpectedLineLength;
|
||||
private final int maxActualLineLength;
|
||||
|
||||
private SideBySideRowFormatter(int maxExpectedLineLength, int maxActualLineLength) {
|
||||
this.maxExpectedLineLength = maxExpectedLineLength;
|
||||
this.maxActualLineLength = maxActualLineLength;
|
||||
}
|
||||
private record SideBySideRowFormatter(int maxExpectedLineLength, int maxActualLineLength) {
|
||||
|
||||
public String formatRow(String expected, String actual, char padChar) {
|
||||
return String.format(
|
||||
|
||||
@@ -262,6 +262,9 @@
|
||||
{
|
||||
"moduleLicense": "Unicode/ICU License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Unicode-3.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Public Domain",
|
||||
"moduleName": "aopalliance:aopalliance"
|
||||
|
||||
@@ -178,6 +178,18 @@ PRESUBMITS = {
|
||||
{"/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.",
|
||||
PresubmitCheck(
|
||||
r".*com\.google\.common\.truth\.Truth8.*",
|
||||
"java",
|
||||
|
||||
@@ -36,6 +36,7 @@ yarn-error.log
|
||||
/libpeerconnection.log
|
||||
testem.log
|
||||
/typings
|
||||
.nx/
|
||||
|
||||
# System files
|
||||
.DS_Store
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<app-selected-registrar-wrapper>
|
||||
<h1 class="mat-headline-4">Domains</h1>
|
||||
<div class="console-domains">
|
||||
<h1 class="mat-headline-4">Domains</h1>
|
||||
@if (totalResults === 0) {
|
||||
<div class="console-app__empty-domains">
|
||||
<h1>
|
||||
@@ -13,6 +13,17 @@
|
||||
} @else if(isLoading) {
|
||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||
} @else {
|
||||
<a
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
href="/console-api/dum-download?registrarId={{
|
||||
registrarService.registrarId()
|
||||
}}"
|
||||
class="console-app-domains__download"
|
||||
>
|
||||
<mat-icon>download</mat-icon>
|
||||
Download domains (.csv)
|
||||
</a>
|
||||
<mat-form-field class="console-app__domains-filter">
|
||||
<mat-label>Filter</mat-label>
|
||||
<input
|
||||
|
||||
@@ -12,6 +12,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-domains {
|
||||
position: relative;
|
||||
&__download {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__domains {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
|
||||
@@ -54,7 +54,7 @@ export class DomainListComponent {
|
||||
constructor(
|
||||
private backendService: BackendService,
|
||||
private domainListService: DomainListService,
|
||||
private registrarService: RegistrarService,
|
||||
protected registrarService: RegistrarService,
|
||||
private _snackBar: MatSnackBar
|
||||
) {
|
||||
effect(() => {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*matTreeNodeDef="let node"
|
||||
matTreeNodeToggle
|
||||
(click)="onClick(node)"
|
||||
[class.active]="router.url.endsWith(node.path)"
|
||||
[class.active]="router.url.includes(node.path)"
|
||||
>
|
||||
<mat-icon class="console-app__nav-icon" *ngIf="node.iconName">
|
||||
{{ node.iconName }}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { Component } from '@angular/core';
|
||||
import {
|
||||
AbstractControl,
|
||||
@@ -68,9 +69,12 @@ export default class EppPasswordEditComponent {
|
||||
) {
|
||||
this.passwordUpdateForm?.get('newPasswordRepeat')?.setErrors(null);
|
||||
} else {
|
||||
this.passwordUpdateForm
|
||||
?.get('newPasswordRepeat')
|
||||
?.setErrors({ passwordsDontMatch: control.value });
|
||||
// latest angular just won't detect the error without setTimeout
|
||||
setTimeout(() => {
|
||||
this.passwordUpdateForm
|
||||
?.get('newPasswordRepeat')
|
||||
?.setErrors({ passwordsDontMatch: control.value });
|
||||
});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -92,15 +96,24 @@ export default class EppPasswordEditComponent {
|
||||
});
|
||||
|
||||
save() {
|
||||
debugger;
|
||||
// this.securityService.saveEppPassword().subscribe({
|
||||
// complete: () => {
|
||||
// this.goBack();
|
||||
// },
|
||||
// error: (err: HttpErrorResponse) => {
|
||||
// this._snackBar.open(err.error);
|
||||
// },
|
||||
// });
|
||||
const { oldPassword, newPassword, newPasswordRepeat } =
|
||||
this.passwordUpdateForm.value;
|
||||
if (!oldPassword || !newPassword || !newPasswordRepeat) return;
|
||||
this.securityService
|
||||
.saveEppPassword({
|
||||
registrarId: this.registrarService.registrarId(),
|
||||
oldPassword,
|
||||
newPassword,
|
||||
newPasswordRepeat,
|
||||
})
|
||||
.subscribe({
|
||||
complete: () => {
|
||||
this.goBack();
|
||||
},
|
||||
error: (err: HttpErrorResponse) => {
|
||||
this._snackBar.open(err.error);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
goBack() {
|
||||
|
||||
@@ -22,6 +22,13 @@ import {
|
||||
} from 'src/app/registrar/registrar.service';
|
||||
import { BackendService } from 'src/app/shared/services/backend.service';
|
||||
|
||||
export interface EppPasswordBackendModel {
|
||||
registrarId: string;
|
||||
oldPassword: string;
|
||||
newPassword: string;
|
||||
newPasswordRepeat: string;
|
||||
}
|
||||
|
||||
export function apiToUiConverter(
|
||||
securitySettings: SecuritySettingsBackendModel = {}
|
||||
): SecuritySettings {
|
||||
@@ -68,5 +75,11 @@ export class SecurityService {
|
||||
);
|
||||
}
|
||||
|
||||
saveEppPassword() {}
|
||||
saveEppPassword(data: EppPasswordBackendModel) {
|
||||
return this.backend.postEppPasswordUpdate(data).pipe(
|
||||
switchMap(() => {
|
||||
return this.registrarService.loadRegistrars();
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,14 @@ import { Injectable } from '@angular/core';
|
||||
import { Observable, catchError, of, throwError } from 'rxjs';
|
||||
|
||||
import { DomainListResult } from 'src/app/domains/domainList.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import {
|
||||
Registrar,
|
||||
SecuritySettingsBackendModel,
|
||||
WhoisRegistrarFields,
|
||||
} from '../../registrar/registrar.service';
|
||||
import { Contact } from '../../settings/contact/contact.service';
|
||||
import { EppPasswordBackendModel } from '../../settings/security/security.service';
|
||||
import { UserData } from './userData.service';
|
||||
|
||||
@Injectable()
|
||||
@@ -33,6 +35,15 @@ export class BackendService {
|
||||
error: HttpErrorResponse,
|
||||
mockData?: Type
|
||||
): Observable<Type> {
|
||||
// This is a temporary redirect to the old console untill the new console
|
||||
// is fully released and enabled
|
||||
if (
|
||||
environment.production &&
|
||||
error.url &&
|
||||
window.location.href.indexOf(error.url) < 0
|
||||
) {
|
||||
window.location.href = error.url;
|
||||
}
|
||||
if (error.error instanceof Error) {
|
||||
// A client-side or network error occurred. Handle it accordingly.
|
||||
console.error('An error occurred:', error.error.message);
|
||||
@@ -134,6 +145,15 @@ export class BackendService {
|
||||
);
|
||||
}
|
||||
|
||||
postEppPasswordUpdate(
|
||||
data: EppPasswordBackendModel
|
||||
): Observable<EppPasswordBackendModel> {
|
||||
return this.http.post<EppPasswordBackendModel>(
|
||||
`/console-api/eppPassword`,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
getUserData(): Observable<UserData> {
|
||||
return this.http
|
||||
.get<UserData>('/console-api/userdata')
|
||||
|
||||
@@ -30,7 +30,7 @@ export interface GlobalLoader {
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class GlobalLoaderService {
|
||||
private static readonly TIMEOUT_MS = 3000;
|
||||
private static readonly TIMEOUT_MS = 10000;
|
||||
private loaders = new Map<GlobalLoader, Subscription>();
|
||||
public isLoading: boolean = false;
|
||||
|
||||
|
||||
@@ -159,6 +159,7 @@ dependencies {
|
||||
implementation deps['com.google.cloud.bigdataoss:util']
|
||||
implementation deps['com.google.cloud.sql:jdbc-socket-factory-core']
|
||||
runtimeOnly deps['com.google.cloud.sql:postgres-socket-factory']
|
||||
implementation deps['com.google.cloud:google-cloud-logging']
|
||||
implementation deps['com.google.cloud:google-cloud-secretmanager']
|
||||
implementation deps['com.google.code.gson:gson']
|
||||
implementation deps['com.google.auto.service:auto-service-annotations']
|
||||
|
||||
+82
-63
@@ -8,14 +8,22 @@ args4j:args4j:2.0.26=css
|
||||
args4j:args4j:2.33=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
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,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,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-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-databind:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.17.0=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-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.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-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:jackson-bom:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.17.0=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
|
||||
@@ -32,12 +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.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-appengine:2.4.1=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.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-servlet:2.4.1=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,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.37.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.173.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.173.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -47,8 +56,9 @@ com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.12.22=compileClasspath,dep
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.58.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.58.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.58.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,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.37.1=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.37.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.38.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.173.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.173.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -56,43 +66,46 @@ com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.33.0=compileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.33.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-datastore-v1:0.109.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-firestore-v1:3.16.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-logging-v2:0.106.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:1.64.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.36.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.108.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.12.22=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.42.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.42.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.58.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.58.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-executor-v1:6.58.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:6.58.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,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.131.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.131.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.37.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.32.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:api-common:2.29.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-grpc:2.46.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:2.46.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.46.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev20240304-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-appengine:v1-rev20240226-2.0.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.37.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.42.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.132.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.132.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.38.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.33.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:api-common:2.30.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-grpc:2.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:2.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev20240429-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-rev20240124-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20240128-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20240113-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-rev20231218-2.0.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-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-rev20240414-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-rev20240402-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-sqladmin:v1beta4-rev20240324-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240205-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240205-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.26=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-stubs:2.0.26=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-remote-api:2.0.26=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -117,19 +130,22 @@ com.google.cloud.sql:postgres-socket-factory:1.18.0=deploy_jar,runtimeClasspath,
|
||||
com.google.cloud:google-cloud-bigquerystorage:3.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable-stats:2.33.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable:2.33.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.32.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.32.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,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.37.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-firestore:3.16.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-logging:3.17.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.36.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-nio:0.127.15=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-nio:0.127.16=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsub:1.126.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsublite:1.12.22=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.42.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-spanner:6.58.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.32.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.41.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.37.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.42.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.16.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.findbugs:jsr305:3.0.1=css
|
||||
@@ -167,10 +183,12 @@ com.google.guava:guava:33.0.0-jre=annotationProcessor,testAnnotationProcessor
|
||||
com.google.guava:guava:33.1.0-jre=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,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,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-gson:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.44.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-protobuf:1.43.3=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.inject.extensions:guice-multibindings:4.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -192,11 +210,11 @@ com.google.oauth-client:google-oauth-client-java6:1.35.0=compileClasspath,deploy
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client:1.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java-util:3.25.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java-util:3.25.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java:2.5.0=css
|
||||
com.google.protobuf:protobuf-java:3.13.0=soy
|
||||
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.protobuf:protobuf-java:3.25.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java:3.25.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.re2j:re2j:1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.template:soy:2021-02-01=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.truth:truth:1.4.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -265,7 +283,8 @@ io.grpc:grpc-netty-shaded:1.62.2=compileClasspath,deploy_jar,nonprodCompileClass
|
||||
io.grpc:grpc-netty:1.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf-lite:1.62.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-rls:1.61.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-rls:1.61.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.grpc:grpc-rls:1.62.2=testRuntimeClasspath
|
||||
io.grpc:grpc-services:1.61.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-services:1.62.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-stub:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -298,8 +317,8 @@ io.opencensus:opencensus-exporter-stats-stackdriver:0.31.0=compileClasspath,depl
|
||||
io.opencensus:opencensus-impl-core:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-impl:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-proto:0.2.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-api:1.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-context:1.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-api:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-context:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.outfoxx:swiftpoet:1.3.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.perfmark:perfmark-api:0.27.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
jakarta-regexp:jakarta-regexp:1.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -375,10 +394,10 @@ org.apache.sshd:sshd-scp:2.12.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-sftp:2.12.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.tomcat:tomcat-annotations-api:11.0.0-M19=testCompileClasspath,testRuntimeClasspath
|
||||
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
|
||||
org.bouncycastle:bcpg-jdk18on:1.78=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpkix-jdk18on:1.78=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcprov-jdk18on:1.78=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcutil-jdk18on:1.78=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpg-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpkix-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcprov-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcutil-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-compat-qual:2.5.3=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
org.checkerframework:checker-compat-qual:2.5.5=annotationProcessor,testAnnotationProcessor
|
||||
org.checkerframework:checker-compat-qual:2.5.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
@@ -402,8 +421,8 @@ org.eclipse.jetty:jetty-server:12.0.8=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-session:12.0.8=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util:12.0.8=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-xml:12.0.8=testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-core:10.11.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-database-postgresql:10.11.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-core:10.12.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-database-postgresql:10.12.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:jaxb-runtime:2.3.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:txw2:2.3.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.gwtproject:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -442,23 +461,23 @@ org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.0.1=deploy_jar,nonprodRun
|
||||
org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.jetbrains:annotations:13.0=annotationProcessor,testAnnotationProcessor
|
||||
org.jetbrains:annotations:17.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jline:jline:3.25.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jline:jline:3.26.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.joda:joda-money:1.0.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.json:json:20160212=soy
|
||||
org.json:json:20231013=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.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-migrationsupport:5.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-params:5.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-launcher:1.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-runner:1.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-api:1.10.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-commons:1.10.2=testRuntimeClasspath
|
||||
org.junit:junit-bom:5.10.2=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.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.11.0=testCompileClasspath,testRuntimeClasspath
|
||||
@@ -505,7 +524,7 @@ org.testcontainers:junit-jupiter:1.19.7=testCompileClasspath,testRuntimeClasspat
|
||||
org.testcontainers:postgresql:1.19.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:selenium:1.19.7=testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:testcontainers:1.19.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.threeten:threetenbp:1.6.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.threeten:threetenbp:1.6.9=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.tukaani:xz:1.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.w3c.css:sac:1.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.webjars.npm:viz.js-graphviz-java:2.1.3=testRuntimeClasspath
|
||||
|
||||
@@ -187,18 +187,12 @@ public class CheckBulkComplianceAction implements Runnable {
|
||||
.getLastNotificationSent()
|
||||
.map(sentDate -> Days.daysBetween(sentDate, clock.nowUtc()).getDays())
|
||||
.orElse(Integer.MAX_VALUE);
|
||||
if (daysSinceLastNotification < THIRTY_DAYS) {
|
||||
// Don't send an email if notification was already sent within the last 30
|
||||
// days
|
||||
continue;
|
||||
} else if (daysSinceLastNotification < FORTY_DAYS) {
|
||||
// Send an upgrade email if last email was between 30 and 40 days ago
|
||||
// Send a warning email if 30-39 days since last notification and an upgrade email if 40+ days
|
||||
if (daysSinceLastNotification >= THIRTY_DAYS) {
|
||||
sendActiveDomainOverageEmail(
|
||||
/* warning= */ false, bulkPricingPackage, overageList.get(bulkPricingPackage));
|
||||
} else {
|
||||
// Send a warning email
|
||||
sendActiveDomainOverageEmail(
|
||||
/* warning= */ true, bulkPricingPackage, overageList.get(bulkPricingPackage));
|
||||
/* warning= */ daysSinceLastNotification >= FORTY_DAYS,
|
||||
bulkPricingPackage,
|
||||
overageList.get(bulkPricingPackage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,11 +66,15 @@ public class RelockDomainAction implements Runnable {
|
||||
private static final Duration ONE_HOUR = Duration.standardHours(1);
|
||||
|
||||
private static final String RELOCK_SUCCESS_EMAIL_TEMPLATE =
|
||||
"The domain %s was successfully re-locked.\n\nPlease contact support at %s if you have any "
|
||||
+ "questions.";
|
||||
"""
|
||||
The domain %s was successfully re-locked.
|
||||
|
||||
Please contact support at %s if you have any questions.""";
|
||||
private static final String RELOCK_NON_RETRYABLE_FAILURE_EMAIL_TEMPLATE =
|
||||
"There was an error when automatically re-locking %s. Error message: %s\n\nPlease contact "
|
||||
+ "support at %s if you have any questions.";
|
||||
"""
|
||||
There was an error when automatically re-locking %s. Error message: %s
|
||||
|
||||
Please contact support at %s if you have any questions.""";
|
||||
private static final String RELOCK_TRANSIENT_FAILURE_EMAIL_TEMPLATE =
|
||||
"There was an unexpected error when automatically re-locking %s. We will continue retrying "
|
||||
+ "the lock for five hours. Please contact support at %s if you have any questions";
|
||||
|
||||
+11
-11
@@ -33,7 +33,7 @@ import google.registry.flows.certs.CertificateChecker;
|
||||
import google.registry.groups.GmailClient;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.model.registrar.RegistrarPoc.Type;
|
||||
import google.registry.model.registrar.RegistrarPocBase.Type;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
@@ -206,7 +206,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
|
||||
() -> {
|
||||
Registrar.Builder newRegistrar = tm().loadByEntity(registrar).asBuilder();
|
||||
switch (certificateType) {
|
||||
case PRIMARY:
|
||||
case PRIMARY -> {
|
||||
newRegistrar.setLastExpiringCertNotificationSentDate(now);
|
||||
tm().put(newRegistrar.build());
|
||||
logger.atInfo().log(
|
||||
@@ -215,8 +215,8 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
|
||||
DATE_FORMATTER.print(now),
|
||||
certificateType.getDisplayName(),
|
||||
registrar.getRegistrarName());
|
||||
break;
|
||||
case FAILOVER:
|
||||
}
|
||||
case FAILOVER -> {
|
||||
newRegistrar.setLastExpiringFailoverCertNotificationSentDate(now);
|
||||
tm().put(newRegistrar.build());
|
||||
logger.atInfo().log(
|
||||
@@ -225,13 +225,13 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
|
||||
DATE_FORMATTER.print(now),
|
||||
certificateType.getDisplayName(),
|
||||
registrar.getRegistrarName());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Unsupported certificate type: %s being passed in when updating "
|
||||
+ "the last notification sent date to registrar %s.",
|
||||
certificateType.toString(), registrar.getRegistrarName()));
|
||||
}
|
||||
default ->
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Unsupported certificate type: %s being passed in when updating "
|
||||
+ "the last notification sent date to registrar %s.",
|
||||
certificateType.toString(), registrar.getRegistrarName()));
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.beam.billing;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.reporting.billing.BillingModule;
|
||||
@@ -34,9 +33,39 @@ import org.joda.time.DateTime;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
|
||||
/** A POJO representing a single billable event, parsed from a {@code SchemaAndRecord}. */
|
||||
@AutoValue
|
||||
public abstract class BillingEvent {
|
||||
/**
|
||||
* A record representing a single billable event, parsed from a {@code SchemaAndRecord}.
|
||||
*
|
||||
* @param id The unique ID for the {@code BillingEvent} associated with this event.
|
||||
* @param billingTime The DateTime (in UTC) this event becomes billable.
|
||||
* @param eventTime The DateTime (in UTC) this event was generated.
|
||||
* @param registrarId The billed registrar's name.
|
||||
* @param billingId The billed registrar's billing account key.
|
||||
* @param poNumber The Purchase Order number.
|
||||
* @param tld The TLD this event was generated for.
|
||||
* @param action The billable action this event was generated for (CREATE, RENEW, TRANSFER...).
|
||||
* @param domain The fully qualified domain name this event was generated for.
|
||||
* @param repositoryId The unique RepoID associated with the billed domain.
|
||||
* @param years The number of years this billing event is made out for.
|
||||
* @param currency The 3-letter currency code for the billing event (USD or JPY).
|
||||
* @param amount The total cost associated with this billing event.
|
||||
* @param flags A list of space-delimited flags associated with the event.
|
||||
*/
|
||||
public record BillingEvent(
|
||||
long id,
|
||||
DateTime billingTime,
|
||||
DateTime eventTime,
|
||||
String registrarId,
|
||||
String billingId,
|
||||
String poNumber,
|
||||
String tld,
|
||||
String action,
|
||||
String domain,
|
||||
String repositoryId,
|
||||
int years,
|
||||
String currency,
|
||||
double amount,
|
||||
String flags) {
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER =
|
||||
DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss zzz");
|
||||
@@ -60,48 +89,6 @@ public abstract class BillingEvent {
|
||||
"amount",
|
||||
"flags");
|
||||
|
||||
/** Returns the unique ID for the {@code BillingEvent} associated with this event. */
|
||||
abstract long id();
|
||||
|
||||
/** Returns the UTC DateTime this event becomes billable. */
|
||||
abstract DateTime billingTime();
|
||||
|
||||
/** Returns the UTC DateTime this event was generated. */
|
||||
abstract DateTime eventTime();
|
||||
|
||||
/** Returns the billed registrar's name. */
|
||||
abstract String registrarId();
|
||||
|
||||
/** Returns the billed registrar's billing account key. */
|
||||
abstract String billingId();
|
||||
|
||||
/** Returns the Purchase Order number. */
|
||||
abstract String poNumber();
|
||||
|
||||
/** Returns the tld this event was generated for. */
|
||||
abstract String tld();
|
||||
|
||||
/** Returns the billable action this event was generated for (i.e., RENEW, CREATE, TRANSFER...) */
|
||||
abstract String action();
|
||||
|
||||
/** Returns the fully qualified domain name this event was generated for. */
|
||||
abstract String domain();
|
||||
|
||||
/** Returns the unique RepoID associated with the billed domain. */
|
||||
abstract String repositoryId();
|
||||
|
||||
/** Returns the number of years this billing event is made out for. */
|
||||
abstract int years();
|
||||
|
||||
/** Returns the 3-letter currency code for the billing event (i.e., USD or JPY.) */
|
||||
abstract String currency();
|
||||
|
||||
/** Returns the cost associated with this billing event. */
|
||||
abstract double amount();
|
||||
|
||||
/** Returns a list of space-delimited flags associated with the event. */
|
||||
abstract String flags();
|
||||
|
||||
/** Creates a concrete {@link BillingEvent}. */
|
||||
static BillingEvent create(
|
||||
long id,
|
||||
@@ -118,7 +105,7 @@ public abstract class BillingEvent {
|
||||
String currency,
|
||||
double amount,
|
||||
String flags) {
|
||||
return new AutoValue_BillingEvent(
|
||||
return new BillingEvent(
|
||||
id,
|
||||
billingTime,
|
||||
eventTime,
|
||||
@@ -338,7 +325,7 @@ public abstract class BillingEvent {
|
||||
|
||||
@Override
|
||||
public BillingEvent decode(InputStream inStream) throws IOException {
|
||||
return new AutoValue_BillingEvent(
|
||||
return new BillingEvent(
|
||||
longCoder.decode(inStream),
|
||||
DATE_TIME_FORMATTER.parseDateTime(stringCoder.decode(inStream)),
|
||||
DATE_TIME_FORMATTER.parseDateTime(stringCoder.decode(inStream)),
|
||||
|
||||
+11
-10
@@ -50,16 +50,17 @@ public class RegistryPipelineWorkerInitializer implements JvmInitializer {
|
||||
environment.setup();
|
||||
RegistryPipelineComponent registryPipelineComponent =
|
||||
toRegistryPipelineComponent(registryOptions);
|
||||
Lazy<JpaTransactionManager> transactionManagerLazy;
|
||||
switch (registryOptions.getJpaTransactionManagerType()) {
|
||||
case READ_ONLY_REPLICA:
|
||||
transactionManagerLazy =
|
||||
registryPipelineComponent.getReadOnlyReplicaJpaTransactionManager();
|
||||
break;
|
||||
case REGULAR:
|
||||
default:
|
||||
transactionManagerLazy = registryPipelineComponent.getJpaTransactionManager();
|
||||
}
|
||||
Lazy<JpaTransactionManager> transactionManagerLazy =
|
||||
switch (registryOptions.getJpaTransactionManagerType()) {
|
||||
case READ_ONLY_REPLICA ->
|
||||
registryPipelineComponent.getReadOnlyReplicaJpaTransactionManager();
|
||||
case REGULAR -> registryPipelineComponent.getJpaTransactionManager();
|
||||
default ->
|
||||
throw new IllegalStateException(
|
||||
String.format(
|
||||
"Unknown JPA transaction manager type: %s",
|
||||
registryOptions.getJpaTransactionManagerType()));
|
||||
};
|
||||
TransactionManagerFactory.setJpaTmOnBeamWorker(transactionManagerLazy::get);
|
||||
SystemPropertySetter.PRODUCTION_IMPL.setProperty(PROPERTY, "true");
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ import google.registry.model.host.Host;
|
||||
import google.registry.model.host.HostHistory;
|
||||
import google.registry.model.rde.RdeMode;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.Type;
|
||||
import google.registry.model.registrar.RegistrarBase.Type;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
|
||||
@@ -688,27 +688,26 @@ public class RdePipeline implements Serializable {
|
||||
protected abstract static class TupleTags {
|
||||
|
||||
protected static final TupleTag<KV<PendingDeposit, DepositFragment>> DOMAIN_FRAGMENTS =
|
||||
new TupleTag<KV<PendingDeposit, DepositFragment>>() {};
|
||||
new TupleTag<>() {};
|
||||
|
||||
protected static final TupleTag<KV<String, PendingDeposit>> REFERENCED_CONTACTS =
|
||||
new TupleTag<KV<String, PendingDeposit>>() {};
|
||||
new TupleTag<>() {};
|
||||
|
||||
protected static final TupleTag<KV<String, PendingDeposit>> REFERENCED_HOSTS =
|
||||
new TupleTag<KV<String, PendingDeposit>>() {};
|
||||
new TupleTag<>() {};
|
||||
|
||||
protected static final TupleTag<KV<String, KV<String, CoGbkResult>>> SUPERORDINATE_DOMAINS =
|
||||
new TupleTag<KV<String, KV<String, CoGbkResult>>>() {};
|
||||
new TupleTag<>() {};
|
||||
|
||||
protected static final TupleTag<KV<PendingDeposit, DepositFragment>> EXTERNAL_HOST_FRAGMENTS =
|
||||
new TupleTag<KV<PendingDeposit, DepositFragment>>() {};
|
||||
new TupleTag<>() {};
|
||||
|
||||
protected static final TupleTag<PendingDeposit> PENDING_DEPOSIT =
|
||||
new TupleTag<PendingDeposit>() {};
|
||||
protected static final TupleTag<PendingDeposit> PENDING_DEPOSIT = new TupleTag<>() {};
|
||||
|
||||
protected static final TupleTag<KV<String, CoGbkResult>> HOST_TO_PENDING_DEPOSIT =
|
||||
new TupleTag<KV<String, CoGbkResult>>() {};
|
||||
new TupleTag<>() {};
|
||||
|
||||
protected static final TupleTag<Long> REVISION_ID = new TupleTag<Long>() {};
|
||||
protected static final TupleTag<Long> REVISION_ID = new TupleTag<>() {};
|
||||
}
|
||||
|
||||
@Singleton
|
||||
|
||||
@@ -14,30 +14,23 @@
|
||||
|
||||
package google.registry.beam.spec11;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* A POJO representing a domain name and associated info, parsed from a {@code SchemaAndRecord}.
|
||||
* A record representing a domain name and associated info, parsed from a {@code SchemaAndRecord}.
|
||||
*
|
||||
* <p>This is a trivially serializable class that allows Beam to transform the results of a SQL
|
||||
* query into a standard Java representation.
|
||||
*
|
||||
* @param domainName The fully qualified domain name.
|
||||
* @param domainRepoId The domain repo ID (the primary key of the domain table).
|
||||
* @param registrarId The registrar ID of the associated registrar for this domain.
|
||||
* @param registrarEmailAddress The email address of the registrar associated with this domain.
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class DomainNameInfo implements Serializable {
|
||||
|
||||
/** Returns the fully qualified domain name. */
|
||||
abstract String domainName();
|
||||
|
||||
/** Returns the domain repo ID (the primary key of the domain table). */
|
||||
abstract String domainRepoId();
|
||||
|
||||
/** Returns the registrar ID of the associated registrar for this domain. */
|
||||
abstract String registrarId();
|
||||
|
||||
/** Returns the email address of the registrar associated with this domain. */
|
||||
abstract String registrarEmailAddress();
|
||||
public record DomainNameInfo(
|
||||
String domainName, String domainRepoId, String registrarId, String registrarEmailAddress)
|
||||
implements Serializable {
|
||||
|
||||
/**
|
||||
* Creates a concrete {@link DomainNameInfo}.
|
||||
@@ -45,7 +38,6 @@ public abstract class DomainNameInfo implements Serializable {
|
||||
@VisibleForTesting
|
||||
static DomainNameInfo create(
|
||||
String domainName, String domainRepoId, String registrarId, String registrarEmailAddress) {
|
||||
return new AutoValue_DomainNameInfo(
|
||||
domainName, domainRepoId, registrarId, registrarEmailAddress);
|
||||
return new DomainNameInfo(domainName, domainRepoId, registrarId, registrarEmailAddress);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,28 +14,26 @@
|
||||
|
||||
package google.registry.beam.spec11;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.io.Serializable;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/** A POJO representing a threat match response from the {@code SafeBrowsing API}. */
|
||||
@AutoValue
|
||||
public abstract class ThreatMatch implements Serializable {
|
||||
/**
|
||||
* A record representing a threat match response from the {@code SafeBrowsing API}.
|
||||
*
|
||||
* @param threatType What kind of threat this is (malware, phishing, etc.).
|
||||
* @param domainName The fully qualified domain name of the matched threat.
|
||||
*/
|
||||
public record ThreatMatch(String threatType, String domainName) implements Serializable {
|
||||
|
||||
private static final String THREAT_TYPE_FIELD = "threatType";
|
||||
private static final String DOMAIN_NAME_FIELD = "domainName";
|
||||
private static final String OUTDATED_NAME_FIELD = "fullyQualifiedDomainName";
|
||||
|
||||
/** Returns what kind of threat it is (malware, phishing etc.) */
|
||||
public abstract String threatType();
|
||||
/** Returns the fully qualified domain name [SLD].[TLD] of the matched threat. */
|
||||
public abstract String domainName();
|
||||
|
||||
@VisibleForTesting
|
||||
static ThreatMatch create(String threatType, String domainName) {
|
||||
return new AutoValue_ThreatMatch(threatType, domainName);
|
||||
return new ThreatMatch(threatType, domainName);
|
||||
}
|
||||
|
||||
/** Returns a {@link JSONObject} representing a subset of this object's data. */
|
||||
@@ -49,7 +47,7 @@ public abstract class ThreatMatch implements Serializable {
|
||||
public static ThreatMatch fromJSON(JSONObject threatMatch) throws JSONException {
|
||||
// TODO: delete OUTDATED_NAME_FIELD once we no longer process reports saved with
|
||||
// fullyQualifiedDomainName in them, likely 2023
|
||||
return new AutoValue_ThreatMatch(
|
||||
return new ThreatMatch(
|
||||
threatMatch.getString(THREAT_TYPE_FIELD),
|
||||
threatMatch.has(OUTDATED_NAME_FIELD)
|
||||
? threatMatch.getString(OUTDATED_NAME_FIELD)
|
||||
|
||||
@@ -62,7 +62,7 @@ class BsaDiffCreator {
|
||||
this.gcsClient = gcsClient;
|
||||
}
|
||||
|
||||
private <K, V extends Comparable> Multimap<K, V> listBackedMultiMap() {
|
||||
private <K, V extends Comparable<?>> Multimap<K, V> listBackedMultiMap() {
|
||||
return newListMultimap(newHashMap(), Lists::newArrayList);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ public class IdnChecker {
|
||||
}
|
||||
|
||||
private static ImmutableMap<IdnTableEnum, ImmutableSet<Tld>> getIdnToTldMap(DateTime now) {
|
||||
ImmutableMultimap.Builder<IdnTableEnum, Tld> idnToTldMap = new ImmutableMultimap.Builder();
|
||||
var idnToTldMap = new ImmutableMultimap.Builder<IdnTableEnum, Tld>();
|
||||
Tlds.getTldEntitiesOfType(TldType.REAL).stream()
|
||||
.filter(tld -> isEnrolledWithBsa(tld, now))
|
||||
.forEach(
|
||||
|
||||
@@ -34,7 +34,7 @@ public record BlockOrder(long orderId, OrderType orderType) {
|
||||
public static BlockOrder deserialize(String text) {
|
||||
List<String> items = SPLITTER.splitToList(text);
|
||||
try {
|
||||
return create(Long.valueOf(items.get(0)), OrderType.valueOf(items.get(1)));
|
||||
return create(Long.parseLong(items.get(0)), OrderType.valueOf(items.get(1)));
|
||||
} catch (NumberFormatException ne) {
|
||||
throw new IllegalArgumentException(text);
|
||||
}
|
||||
|
||||
@@ -96,10 +96,9 @@ class BsaDomainRefresh {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof BsaDomainRefresh)) {
|
||||
if (!(o instanceof BsaDomainRefresh that)) {
|
||||
return false;
|
||||
}
|
||||
BsaDomainRefresh that = (BsaDomainRefresh) o;
|
||||
return Objects.equal(jobId, that.jobId)
|
||||
&& Objects.equal(creationTime, that.creationTime)
|
||||
&& Objects.equal(updateTime, that.updateTime)
|
||||
|
||||
@@ -120,10 +120,9 @@ class BsaDownload {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof BsaDownload)) {
|
||||
if (!(o instanceof BsaDownload that)) {
|
||||
return false;
|
||||
}
|
||||
BsaDownload that = (BsaDownload) o;
|
||||
return Objects.equal(creationTime, that.creationTime)
|
||||
&& Objects.equal(updateTime, that.updateTime)
|
||||
&& Objects.equal(blockListChecksums, that.blockListChecksums)
|
||||
@@ -136,6 +135,6 @@ class BsaDownload {
|
||||
}
|
||||
|
||||
static VKey<BsaDownload> vKey(long jobId) {
|
||||
return VKey.create(BsaDownload.class, Long.valueOf(jobId));
|
||||
return VKey.create(BsaDownload.class, jobId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,10 +61,9 @@ final class BsaLabel {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof BsaLabel)) {
|
||||
if (!(o instanceof BsaLabel label1)) {
|
||||
return false;
|
||||
}
|
||||
BsaLabel label1 = (BsaLabel) o;
|
||||
return Objects.equal(label, label1.label) && Objects.equal(creationTime, label1.creationTime);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,10 +84,9 @@ class BsaUnblockableDomain {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof BsaUnblockableDomain)) {
|
||||
if (!(o instanceof BsaUnblockableDomain that)) {
|
||||
return false;
|
||||
}
|
||||
BsaUnblockableDomain that = (BsaUnblockableDomain) o;
|
||||
return Objects.equal(label, that.label)
|
||||
&& Objects.equal(tld, that.tld)
|
||||
&& reason == that.reason
|
||||
@@ -142,10 +141,9 @@ class BsaUnblockableDomain {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof BsaUnblockableDomainId)) {
|
||||
if (!(o instanceof BsaUnblockableDomainId that)) {
|
||||
return false;
|
||||
}
|
||||
BsaUnblockableDomainId that = (BsaUnblockableDomainId) o;
|
||||
return Objects.equal(label, that.label) && Objects.equal(tld, that.tld);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ public final class LabelDiffUpdates {
|
||||
for (Map.Entry<LabelType, ImmutableList<BlockLabel>> entry :
|
||||
labelsByType.entrySet()) {
|
||||
switch (entry.getKey()) {
|
||||
case CREATE:
|
||||
case CREATE -> {
|
||||
// With current Cloud SQL, label upsert throughput is about 200/second. If
|
||||
// better performance is needed, consider bulk insert in native SQL.
|
||||
tm().putAll(
|
||||
@@ -86,8 +86,8 @@ public final class LabelDiffUpdates {
|
||||
// cached BsaLabels. Eventually will be consistent.
|
||||
nonBlockedDomains.addAll(
|
||||
tallyUnblockableDomainsForNewLabels(entry.getValue(), idnChecker, now));
|
||||
break;
|
||||
case DELETE:
|
||||
}
|
||||
case DELETE -> {
|
||||
ImmutableSet<String> deletedLabels =
|
||||
entry.getValue().stream()
|
||||
.filter(label -> isValidInAtLeastOneTld(label, idnChecker))
|
||||
@@ -100,8 +100,8 @@ public final class LabelDiffUpdates {
|
||||
"Only found %s entities among the %s labels: [%s]",
|
||||
nDeleted, deletedLabels.size(), deletedLabels);
|
||||
}
|
||||
break;
|
||||
case NEW_ORDER_ASSOCIATION:
|
||||
}
|
||||
case NEW_ORDER_ASSOCIATION -> {
|
||||
ImmutableSet<String> affectedLabels =
|
||||
entry.getValue().stream()
|
||||
.filter(label -> isValidInAtLeastOneTld(label, idnChecker))
|
||||
@@ -120,13 +120,12 @@ public final class LabelDiffUpdates {
|
||||
Queries.queryBsaUnblockableDomainByLabels(affectedLabels)
|
||||
.map(BsaUnblockableDomain::toUnblockableDomain)
|
||||
.forEach(nonBlockedDomains::add);
|
||||
|
||||
for (BlockLabel label : entry.getValue()) {
|
||||
getInvalidTldsForLabel(label, idnChecker)
|
||||
.map(tld -> UnblockableDomain.of(label.label(), tld, Reason.INVALID))
|
||||
.forEach(nonBlockedDomains::add);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -103,7 +103,7 @@ public final class Queries {
|
||||
|
||||
static ImmutableList<BsaUnblockableDomain> batchReadUnblockables(
|
||||
Optional<BsaUnblockableDomain> lastRead, int batchSize) {
|
||||
return ImmutableList.copyOf(
|
||||
return ImmutableList.<BsaUnblockableDomain>copyOf(
|
||||
bsaQuery(
|
||||
() ->
|
||||
tm().getEntityManager()
|
||||
|
||||
@@ -203,6 +203,17 @@ public final class RegistryConfig {
|
||||
return config.registrarConsole.announcementsEmailAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* The DUM file name, used as a file name base for DUM csv file
|
||||
*
|
||||
* @see google.registry.ui.server.console.ConsoleDumDownloadAction
|
||||
*/
|
||||
@Provides
|
||||
@Config("dumFileName")
|
||||
public static String provideDumFileName(RegistryConfigSettings config) {
|
||||
return config.registrarConsole.dumFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The contact phone number. Used in the "contact-us" section of the registrar console.
|
||||
*
|
||||
|
||||
@@ -185,6 +185,7 @@ public class RegistryConfigSettings {
|
||||
|
||||
/** Configuration for the web-based registrar console. */
|
||||
public static class RegistrarConsole {
|
||||
public String dumFileName;
|
||||
public String logoFilename;
|
||||
public String supportPhoneNumber;
|
||||
public String supportEmailAddress;
|
||||
|
||||
@@ -396,6 +396,9 @@ rde:
|
||||
sshIdentityEmailAddress: rde@example.com
|
||||
|
||||
registrarConsole:
|
||||
# DUM download file name, excluding the extension
|
||||
dumFileName: dum_file_name
|
||||
|
||||
# Filename of the logo to use in the header of the console. This filename is
|
||||
# relative to ui/assets/images/
|
||||
logoFilename: logo.png
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.dns;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.persistence.PersistenceModule.TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
@@ -98,7 +99,9 @@ public final class DnsUtils {
|
||||
*/
|
||||
public static ImmutableList<DnsRefreshRequest> readAndUpdateRequestsWithLatestProcessTime(
|
||||
String tld, Duration cooldown, int batchSize) {
|
||||
// It is critical that below query use repeatable-read. See b/337894387.
|
||||
return tm().transact(
|
||||
TRANSACTION_REPEATABLE_READ,
|
||||
() -> {
|
||||
DateTime transactionTime = tm().getTransactionTime();
|
||||
ImmutableList<DnsRefreshRequest> requests =
|
||||
@@ -131,7 +134,9 @@ public final class DnsUtils {
|
||||
* error because all we care about is that it no longer exists after the method runs.
|
||||
*/
|
||||
public static void deleteRequests(Collection<DnsRefreshRequest> requests) {
|
||||
// It is critical that below query use repeatable-read. See b/337894387.
|
||||
tm().transact(
|
||||
TRANSACTION_REPEATABLE_READ,
|
||||
() ->
|
||||
tm().delete(
|
||||
requests.stream()
|
||||
|
||||
@@ -38,7 +38,7 @@ public final class DnsWriterProxy {
|
||||
/**
|
||||
* Returns the instance of {@link DnsWriter} by class name.
|
||||
*
|
||||
* If the DnsWriter doesn't belong to this TLD, will return null.
|
||||
* <p>If the DnsWriter doesn't belong to this TLD, will return null.
|
||||
*/
|
||||
public DnsWriter getByClassNameForTld(String className, String tld) {
|
||||
if (!Tld.get(tld).getDnsWriters().contains(className)) {
|
||||
|
||||
@@ -50,6 +50,7 @@ import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.model.registrar.RegistrarPocBase;
|
||||
import google.registry.model.tld.Tld;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Service;
|
||||
@@ -295,7 +296,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
|
||||
ImmutableList<InternetAddress> recipients =
|
||||
registrar.get().getContacts().stream()
|
||||
.filter(c -> c.getTypes().contains(RegistrarPoc.Type.ADMIN))
|
||||
.filter(c -> c.getTypes().contains(RegistrarPocBase.Type.ADMIN))
|
||||
.map(RegistrarPoc::getEmailAddress)
|
||||
.map(PublishDnsUpdatesAction::emailToInternetAddress)
|
||||
.collect(toImmutableList());
|
||||
|
||||
@@ -63,16 +63,15 @@ public final class RefreshDnsAction implements Runnable {
|
||||
tm().transact(
|
||||
() -> {
|
||||
switch (type) {
|
||||
case DOMAIN:
|
||||
case DOMAIN -> {
|
||||
loadAndVerifyExistence(Domain.class, domainOrHostName);
|
||||
requestDomainDnsRefresh(domainOrHostName);
|
||||
break;
|
||||
case HOST:
|
||||
}
|
||||
case HOST -> {
|
||||
verifyHostIsSubordinate(loadAndVerifyExistence(Host.class, domainOrHostName));
|
||||
requestHostDnsRefresh(domainOrHostName);
|
||||
break;
|
||||
default:
|
||||
throw new BadRequestException("Unsupported type: " + type);
|
||||
}
|
||||
default -> throw new BadRequestException("Unsupported type: " + type);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -55,14 +55,14 @@ import org.xbill.DNS.Type;
|
||||
import org.xbill.DNS.Update;
|
||||
|
||||
/**
|
||||
* A DnsWriter that implements the DNS UPDATE protocol as specified in
|
||||
* <a href="https://tools.ietf.org/html/rfc2136">RFC 2136</a>. Publishes changes in the
|
||||
* domain-registry to a (capable) external DNS server, sometimes called a "hidden master". DNS
|
||||
* UPDATE messages are sent via a supplied "transport" class.
|
||||
* A DnsWriter that implements the DNS UPDATE protocol as specified in <a
|
||||
* href="https://tools.ietf.org/html/rfc2136">RFC 2136</a>. Publishes changes in the domain-registry
|
||||
* to a (capable) external DNS server, sometimes called a "hidden master". DNS UPDATE messages are
|
||||
* sent via a supplied "transport" class.
|
||||
*
|
||||
* On call to {@link #commit()}, a single UPDATE message is created containing the records required
|
||||
* to "synchronize" the DNS with the current (at the time of processing) state of the registry, for
|
||||
* the supplied domain/host.
|
||||
* <p>On call to {@link #commit()}, a single UPDATE message is created containing the records
|
||||
* required to "synchronize" the DNS with the current (at the time of processing) state of the
|
||||
* registry, for the supplied domain/host.
|
||||
*
|
||||
* <p>The general strategy of the publish methods is to delete <em>all</em> resource records of any
|
||||
* <em>type</em> that match the exact domain/host name supplied. And then for create/update cases,
|
||||
@@ -73,8 +73,8 @@ import org.xbill.DNS.Update;
|
||||
* <p>Only NS, DS, A, and AAAA records are published, and in particular no DNSSEC signing is done
|
||||
* assuming that this will be done by a third party DNS provider.
|
||||
*
|
||||
* <p>Each commit call is treated as an atomic update to the DNS. If a commit fails an exception
|
||||
* is thrown. The SOA record serial number is implicitly incremented by the server on each UPDATE
|
||||
* <p>Each commit call is treated as an atomic update to the DNS. If a commit fails an exception is
|
||||
* thrown. The SOA record serial number is implicitly incremented by the server on each UPDATE
|
||||
* message, as required by RFC 2136. Care must be taken to make sure the SOA serial number does not
|
||||
* go backwards if the entire TLD (zone) is "reset" to empty and republished.
|
||||
*/
|
||||
|
||||
@@ -33,6 +33,7 @@ import google.registry.groups.GroupsConnection;
|
||||
import google.registry.groups.GroupsConnection.Role;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.model.registrar.RegistrarPocBase;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
@@ -99,7 +100,7 @@ public final class SyncGroupMembersAction implements Runnable {
|
||||
* Returns the Google Groups email address for the given registrar ID and RegistrarContact.Type.
|
||||
*/
|
||||
public static String getGroupEmailAddressForContactType(
|
||||
String registrarId, RegistrarPoc.Type type, String gSuiteDomainName) {
|
||||
String registrarId, RegistrarPocBase.Type type, String gSuiteDomainName) {
|
||||
// Take the registrar's ID, make it lowercase, and remove all characters that aren't
|
||||
// alphanumeric, hyphens, or underscores.
|
||||
return String.format(
|
||||
@@ -174,7 +175,7 @@ public final class SyncGroupMembersAction implements Runnable {
|
||||
Set<RegistrarPoc> registrarPocs = registrar.getContacts();
|
||||
long totalAdded = 0;
|
||||
long totalRemoved = 0;
|
||||
for (final RegistrarPoc.Type type : RegistrarPoc.Type.values()) {
|
||||
for (final RegistrarPocBase.Type type : RegistrarPocBase.Type.values()) {
|
||||
groupKey =
|
||||
getGroupEmailAddressForContactType(registrar.getRegistrarId(), type, gSuiteDomainName);
|
||||
Set<String> currentMembers = groupsConnection.getMembersOfGroup(groupKey);
|
||||
|
||||
@@ -17,13 +17,13 @@ package google.registry.export.sheet;
|
||||
import static com.google.common.base.MoreObjects.firstNonNull;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.model.common.Cursor.CursorType.SYNC_REGISTRAR_SHEET;
|
||||
import static google.registry.model.registrar.RegistrarPoc.Type.ABUSE;
|
||||
import static google.registry.model.registrar.RegistrarPoc.Type.ADMIN;
|
||||
import static google.registry.model.registrar.RegistrarPoc.Type.BILLING;
|
||||
import static google.registry.model.registrar.RegistrarPoc.Type.LEGAL;
|
||||
import static google.registry.model.registrar.RegistrarPoc.Type.MARKETING;
|
||||
import static google.registry.model.registrar.RegistrarPoc.Type.TECH;
|
||||
import static google.registry.model.registrar.RegistrarPoc.Type.WHOIS;
|
||||
import static google.registry.model.registrar.RegistrarPocBase.Type.ABUSE;
|
||||
import static google.registry.model.registrar.RegistrarPocBase.Type.ADMIN;
|
||||
import static google.registry.model.registrar.RegistrarPocBase.Type.BILLING;
|
||||
import static google.registry.model.registrar.RegistrarPocBase.Type.LEGAL;
|
||||
import static google.registry.model.registrar.RegistrarPocBase.Type.MARKETING;
|
||||
import static google.registry.model.registrar.RegistrarPocBase.Type.TECH;
|
||||
import static google.registry.model.registrar.RegistrarPocBase.Type.WHOIS;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
@@ -36,6 +36,7 @@ import google.registry.model.common.Cursor;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarAddress;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.model.registrar.RegistrarPocBase;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.DateTimeUtils;
|
||||
import java.io.IOException;
|
||||
@@ -173,7 +174,7 @@ class SyncRegistrarsSheet {
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static Predicate<RegistrarPoc> byType(final RegistrarPoc.Type type) {
|
||||
private static Predicate<RegistrarPoc> byType(final RegistrarPocBase.Type type) {
|
||||
return contact -> contact.getTypes().contains(type);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ public interface TransportCredentials {
|
||||
/**
|
||||
* Check that these credentials are valid for the registrar and optionally check the password.
|
||||
*
|
||||
* Called by {@link google.registry.flows.session.LoginFlow LoginFlow} to check the transport
|
||||
* credentials against the stored registrar's credentials. If they do not match, throw an
|
||||
* {@link AuthenticationErrorException}.
|
||||
* <p>Called by {@link google.registry.flows.session.LoginFlow LoginFlow} to check the transport
|
||||
* credentials against the stored registrar's credentials. If they do not match, throw an {@link
|
||||
* AuthenticationErrorException}.
|
||||
*/
|
||||
void validate(Registrar registrar, String password) throws AuthenticationErrorException;
|
||||
|
||||
|
||||
@@ -16,12 +16,10 @@ package google.registry.flows.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Predicates.equalTo;
|
||||
import static com.google.common.base.Strings.emptyToNull;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSetMultimap.toImmutableSetMultimap;
|
||||
import static com.google.common.collect.Iterables.any;
|
||||
import static com.google.common.collect.Sets.difference;
|
||||
import static com.google.common.collect.Sets.intersection;
|
||||
import static com.google.common.collect.Sets.union;
|
||||
@@ -95,6 +93,7 @@ import google.registry.model.domain.DomainCommand.Update;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.ForeignKeyedDesignatedContact;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.domain.Period.Unit;
|
||||
import google.registry.model.domain.fee.BaseFee;
|
||||
import google.registry.model.domain.fee.BaseFee.FeeType;
|
||||
import google.registry.model.domain.fee.Credit;
|
||||
@@ -121,9 +120,9 @@ import google.registry.model.domain.token.AllocationToken.RegistrationBehavior;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.poll.PollMessage.Autorenew;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.State;
|
||||
import google.registry.model.registrar.RegistrarBase.State;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
@@ -206,7 +205,7 @@ public class DomainFlowUtils {
|
||||
if (parts.size() <= 1) {
|
||||
throw new BadDomainNamePartsCountException();
|
||||
}
|
||||
if (any(parts, equalTo(""))) {
|
||||
if (parts.stream().anyMatch(String::isEmpty)) {
|
||||
throw new EmptyDomainNamePartException();
|
||||
}
|
||||
validateFirstLabel(parts.get(0));
|
||||
@@ -329,7 +328,7 @@ public class DomainFlowUtils {
|
||||
/** Check if the registrar running the flow has access to the TLD in question. */
|
||||
public static void checkAllowedAccessToTld(String registrarId, String tld) throws EppException {
|
||||
if (!Registrar.loadByRegistrarIdCached(registrarId).get().getAllowedTlds().contains(tld)) {
|
||||
throw new DomainFlowUtils.NotAuthorizedForTldException(tld);
|
||||
throw new NotAuthorizedForTldException(tld);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,7 +343,7 @@ public class DomainFlowUtils {
|
||||
.get()
|
||||
.getBillingAccountMap()
|
||||
.containsKey(tld.getCurrency())) {
|
||||
throw new DomainFlowUtils.MissingBillingAccountMapException(tld.getCurrency());
|
||||
throw new MissingBillingAccountMapException(tld.getCurrency());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,7 +404,7 @@ public class DomainFlowUtils {
|
||||
|
||||
/** We only allow specifying years in a period. */
|
||||
static Period verifyUnitIsYears(Period period) throws EppException {
|
||||
if (!checkNotNull(period).getUnit().equals(Period.Unit.YEARS)) {
|
||||
if (!checkNotNull(period).getUnit().equals(Unit.YEARS)) {
|
||||
throw new BadPeriodUnitException();
|
||||
}
|
||||
return period;
|
||||
@@ -534,7 +533,7 @@ public class DomainFlowUtils {
|
||||
|
||||
public static boolean isReserved(InternetDomainName domainName, boolean isSunrise) {
|
||||
ImmutableSet<ReservationType> types = getReservationTypes(domainName);
|
||||
return !Sets.intersection(types, RESERVED_TYPES).isEmpty()
|
||||
return !intersection(types, RESERVED_TYPES).isEmpty()
|
||||
|| !(isSunrise || intersection(TYPES_ALLOWED_FOR_CREATE_ONLY_IN_SUNRISE, types).isEmpty());
|
||||
}
|
||||
|
||||
@@ -601,8 +600,8 @@ public class DomainFlowUtils {
|
||||
* Fills in a builder with the data needed for an autorenew poll message for this domain. This
|
||||
* does not copy over the id of the current autorenew poll message.
|
||||
*/
|
||||
public static PollMessage.Autorenew.Builder newAutorenewPollMessage(Domain domain) {
|
||||
return new PollMessage.Autorenew.Builder()
|
||||
public static Autorenew.Builder newAutorenewPollMessage(Domain domain) {
|
||||
return new Autorenew.Builder()
|
||||
.setTargetId(domain.getDomainName())
|
||||
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
|
||||
.setEventTime(domain.getRegistrationExpirationTime())
|
||||
@@ -623,7 +622,7 @@ public class DomainFlowUtils {
|
||||
BillingRecurrence existingBillingRecurrence,
|
||||
DateTime newEndTime,
|
||||
@Nullable HistoryEntryId historyId) {
|
||||
Optional<PollMessage.Autorenew> autorenewPollMessage =
|
||||
Optional<Autorenew> autorenewPollMessage =
|
||||
tm().loadByKeyIfPresent(domain.getAutorenewPollMessage());
|
||||
|
||||
// Construct an updated autorenew poll message. If the autorenew poll message no longer exists,
|
||||
@@ -632,7 +631,7 @@ public class DomainFlowUtils {
|
||||
// message to be deleted), and then subsequently the transfer was canceled, rejected, or deleted
|
||||
// (which would cause the poll message to be recreated here). In the latter case, the history id
|
||||
// of the event that created the new poll message will also be used.
|
||||
PollMessage.Autorenew updatedAutorenewPollMessage;
|
||||
Autorenew updatedAutorenewPollMessage;
|
||||
if (autorenewPollMessage.isPresent()) {
|
||||
updatedAutorenewPollMessage =
|
||||
autorenewPollMessage.get().asBuilder().setAutorenewEndTime(newEndTime).build();
|
||||
@@ -706,7 +705,7 @@ public class DomainFlowUtils {
|
||||
String feeClass = null;
|
||||
ImmutableList<Fee> fees = ImmutableList.of();
|
||||
switch (feeRequest.getCommandName()) {
|
||||
case CREATE:
|
||||
case CREATE -> {
|
||||
// Don't return a create price for reserved names.
|
||||
if (isReserved(domainName, isSunrise) && !isAvailable) {
|
||||
feeClass = "reserved";
|
||||
@@ -726,16 +725,16 @@ public class DomainFlowUtils {
|
||||
allocationToken)
|
||||
.getFees();
|
||||
}
|
||||
break;
|
||||
case RENEW:
|
||||
}
|
||||
case RENEW -> {
|
||||
builder.setAvailIfSupported(true);
|
||||
fees =
|
||||
pricingLogic
|
||||
.getRenewPrice(
|
||||
tld, domainNameString, now, years, billingRecurrence, allocationToken)
|
||||
.getFees();
|
||||
break;
|
||||
case RESTORE:
|
||||
}
|
||||
case RESTORE -> {
|
||||
// The minimum allowable period per the EPP spec is 1, so, strangely, 1 year still has to be
|
||||
// passed in as the period for a restore even if the domain would *not* be renewed as part
|
||||
// of a restore. This is fixed in RFC 8748 (which is a more recent version of the fee
|
||||
@@ -751,21 +750,20 @@ public class DomainFlowUtils {
|
||||
boolean isExpired =
|
||||
domain.isPresent() && domain.get().getRegistrationExpirationTime().isBefore(now);
|
||||
fees = pricingLogic.getRestorePrice(tld, domainNameString, now, isExpired).getFees();
|
||||
break;
|
||||
case TRANSFER:
|
||||
}
|
||||
case TRANSFER -> {
|
||||
if (years != 1) {
|
||||
throw new TransfersAreAlwaysForOneYearException();
|
||||
}
|
||||
builder.setAvailIfSupported(true);
|
||||
fees =
|
||||
pricingLogic.getTransferPrice(tld, domainNameString, now, billingRecurrence).getFees();
|
||||
break;
|
||||
case UPDATE:
|
||||
}
|
||||
case UPDATE -> {
|
||||
builder.setAvailIfSupported(true);
|
||||
fees = pricingLogic.getUpdatePrice(tld, domainNameString, now).getFees();
|
||||
break;
|
||||
default:
|
||||
throw new UnknownFeeCommandException(feeRequest.getUnparsedCommandName());
|
||||
}
|
||||
default -> throw new UnknownFeeCommandException(feeRequest.getUnparsedCommandName());
|
||||
}
|
||||
|
||||
if (feeClass == null) {
|
||||
|
||||
@@ -138,14 +138,14 @@ public final class DomainPricingLogic {
|
||||
isRenewCostPremiumPrice = domainPrices.isPremium();
|
||||
} else {
|
||||
switch (billingRecurrence.getRenewalPriceBehavior()) {
|
||||
case DEFAULT:
|
||||
case DEFAULT -> {
|
||||
renewCost =
|
||||
getDomainRenewCostWithDiscount(tld, domainPrices, dateTime, years, allocationToken);
|
||||
isRenewCostPremiumPrice = domainPrices.isPremium();
|
||||
break;
|
||||
}
|
||||
// if the renewal price behavior is specified, then the renewal price should be the same
|
||||
// as the creation price, which is stored in the billing event as the renewal price
|
||||
case SPECIFIED:
|
||||
case SPECIFIED -> {
|
||||
checkArgumentPresent(
|
||||
billingRecurrence.getRenewalPrice(),
|
||||
"Unexpected behavior: renewal price cannot be null when renewal behavior is"
|
||||
@@ -153,20 +153,20 @@ public final class DomainPricingLogic {
|
||||
// Don't apply allocation token to renewal price when SPECIFIED
|
||||
renewCost = billingRecurrence.getRenewalPrice().get().multipliedBy(years);
|
||||
isRenewCostPremiumPrice = false;
|
||||
break;
|
||||
}
|
||||
// if the renewal price behavior is nonpremium, it means that the domain should be renewed
|
||||
// at standard price of domains at the time, even if the domain is premium
|
||||
case NONPREMIUM:
|
||||
case NONPREMIUM -> {
|
||||
renewCost =
|
||||
getDomainCostWithDiscount(
|
||||
false, years, allocationToken, tld.getStandardRenewCost(dateTime));
|
||||
isRenewCostPremiumPrice = false;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Unknown RenewalPriceBehavior enum value: %s",
|
||||
billingRecurrence.getRenewalPriceBehavior()));
|
||||
}
|
||||
default ->
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Unknown RenewalPriceBehavior enum value: %s",
|
||||
billingRecurrence.getRenewalPriceBehavior()));
|
||||
}
|
||||
}
|
||||
return customLogic.customizeRenewPrice(
|
||||
|
||||
@@ -124,22 +124,21 @@ public class FlowPicker {
|
||||
}};
|
||||
|
||||
/** Poll flows have an {@link InnerCommand} of type {@link Poll}. */
|
||||
private static final FlowProvider POLL_FLOW_PROVIDER = new FlowProvider() {
|
||||
@Override
|
||||
Class<? extends Flow> get(
|
||||
EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) {
|
||||
if (!(innerCommand instanceof Poll)) {
|
||||
return null;
|
||||
}
|
||||
switch (((Poll) innerCommand).getPollOp()) {
|
||||
case ACK:
|
||||
return PollAckFlow.class;
|
||||
case REQUEST:
|
||||
return PollRequestFlow.class;
|
||||
default:
|
||||
return UnimplementedFlow.class;
|
||||
}
|
||||
}};
|
||||
private static final FlowProvider POLL_FLOW_PROVIDER =
|
||||
new FlowProvider() {
|
||||
@Override
|
||||
Class<? extends Flow> get(
|
||||
EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) {
|
||||
if (!(innerCommand instanceof Poll)) {
|
||||
return null;
|
||||
}
|
||||
return switch (((Poll) innerCommand).getPollOp()) {
|
||||
case ACK -> PollAckFlow.class;
|
||||
case REQUEST -> PollRequestFlow.class;
|
||||
default -> UnimplementedFlow.class;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The domain restore command is technically a domain {@literal <update>}, but logically a totally
|
||||
|
||||
@@ -54,8 +54,7 @@ public final class PollFlowUtils {
|
||||
if (pollMessage instanceof PollMessage.OneTime) {
|
||||
// One-time poll messages are deleted once acked.
|
||||
tm().delete(pollMessage.createVKey());
|
||||
} else if (pollMessage instanceof PollMessage.Autorenew) {
|
||||
PollMessage.Autorenew autorenewPollMessage = (PollMessage.Autorenew) pollMessage;
|
||||
} else if (pollMessage instanceof PollMessage.Autorenew autorenewPollMessage) {
|
||||
|
||||
// Move the eventTime of this autorenew poll message forward by a year.
|
||||
DateTime nextEventTime = autorenewPollMessage.getEventTime().plusYears(1);
|
||||
|
||||
@@ -130,23 +130,22 @@ public final class PgpHelper {
|
||||
while (keys.hasNext()) {
|
||||
PGPPublicKey key = keys.next();
|
||||
switch (want) {
|
||||
case ENCRYPT:
|
||||
case ENCRYPT -> {
|
||||
if (key.isEncryptionKey()) {
|
||||
return Optional.of(key);
|
||||
}
|
||||
break;
|
||||
case SIGN:
|
||||
}
|
||||
case SIGN -> {
|
||||
if (isSigningKey(key)) {
|
||||
return Optional.of(key);
|
||||
}
|
||||
break;
|
||||
case ENCRYPT_SIGN:
|
||||
}
|
||||
case ENCRYPT_SIGN -> {
|
||||
if (key.isEncryptionKey() && isSigningKey(key)) {
|
||||
return Optional.of(key);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
default -> throw new AssertionError();
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
@@ -154,14 +153,9 @@ public final class PgpHelper {
|
||||
|
||||
/** Returns {@code true} if this key can be used for signing. */
|
||||
public static boolean isSigningKey(PGPPublicKey key) {
|
||||
switch (key.getAlgorithm()) {
|
||||
case RSA_GENERAL:
|
||||
case RSA_SIGN:
|
||||
case DSA:
|
||||
case ELGAMAL_GENERAL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return switch (key.getAlgorithm()) {
|
||||
case RSA_GENERAL, RSA_SIGN, DSA, ELGAMAL_GENERAL -> true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,16 +109,18 @@ public class ModelUtils {
|
||||
if (value != null && value.getClass().isArray()) {
|
||||
// It's surprisingly difficult to convert arrays into lists if the array might be primitive.
|
||||
final Object arrayValue = value;
|
||||
value = new AbstractList<Object>() {
|
||||
@Override
|
||||
public Object get(int index) {
|
||||
return Array.get(arrayValue, index);
|
||||
}
|
||||
value =
|
||||
new AbstractList<>() {
|
||||
@Override
|
||||
public Object get(int index) {
|
||||
return Array.get(arrayValue, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return Array.getLength(arrayValue);
|
||||
}};
|
||||
@Override
|
||||
public int size() {
|
||||
return Array.getLength(arrayValue);
|
||||
}
|
||||
};
|
||||
}
|
||||
values.put(field, value);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// 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.model.console;
|
||||
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.persistence.VKey;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* A persisted history object representing an EPP action via the console.
|
||||
*
|
||||
* <p>In addition to the generic history fields (time, URL, etc.) we also persist a reference to the
|
||||
* history entry so that we can refer to it if necessary.
|
||||
*/
|
||||
@Access(AccessType.FIELD)
|
||||
@Entity
|
||||
@Table(
|
||||
indexes = {
|
||||
@Index(columnList = "historyActingUser"),
|
||||
@Index(columnList = "repoId"),
|
||||
@Index(columnList = "revisionId")
|
||||
})
|
||||
public class ConsoleEppActionHistory extends ConsoleUpdateHistory {
|
||||
|
||||
@AttributeOverride(name = "repoId", column = @Column(nullable = false))
|
||||
HistoryEntryId historyEntryId;
|
||||
|
||||
@Column(nullable = false)
|
||||
Class<? extends HistoryEntry> historyEntryClass;
|
||||
|
||||
public HistoryEntryId getHistoryEntryId() {
|
||||
return historyEntryId;
|
||||
}
|
||||
|
||||
public Class<? extends HistoryEntry> getHistoryEntryClass() {
|
||||
return historyEntryClass;
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance for this entity. */
|
||||
@Override
|
||||
public VKey<ConsoleEppActionHistory> createVKey() {
|
||||
return VKey.create(ConsoleEppActionHistory.class, getRevisionId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
return new Builder(clone(this));
|
||||
}
|
||||
|
||||
/** Builder for the immutable UserUpdateHistory. */
|
||||
public static class Builder
|
||||
extends ConsoleUpdateHistory.Builder<ConsoleEppActionHistory, Builder> {
|
||||
|
||||
public Builder() {}
|
||||
|
||||
public Builder(ConsoleEppActionHistory instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConsoleEppActionHistory build() {
|
||||
checkArgumentNotNull(getInstance().historyEntryId, "History entry ID must be specified");
|
||||
checkArgumentNotNull(
|
||||
getInstance().historyEntryClass, "History entry class must be specified");
|
||||
return super.build();
|
||||
}
|
||||
|
||||
public Builder setHistoryEntryId(HistoryEntryId historyEntryId) {
|
||||
getInstance().historyEntryId = historyEntryId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setHistoryEntryClass(Class<? extends HistoryEntry> historyEntryClass) {
|
||||
getInstance().historyEntryClass = historyEntryClass;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
// 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.model.console;
|
||||
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.IdAllocation;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* A record of a resource that was updated through the console.
|
||||
*
|
||||
* <p>This abstract class has several subclasses that (mostly) include the modified resource itself
|
||||
* so that the entire object history is persisted to SQL.
|
||||
*/
|
||||
@Access(AccessType.FIELD)
|
||||
@MappedSuperclass
|
||||
public abstract class ConsoleUpdateHistory extends ImmutableObject implements Buildable {
|
||||
|
||||
public enum Type {
|
||||
EPP_ACTION,
|
||||
POC_CREATE,
|
||||
POC_UPDATE,
|
||||
POC_DELETE,
|
||||
REGISTRAR_UPDATE,
|
||||
USER_CREATE,
|
||||
USER_DELETE,
|
||||
USER_UPDATE
|
||||
}
|
||||
|
||||
/** Autogenerated ID of this event. */
|
||||
@Id
|
||||
@IdAllocation
|
||||
@Column(nullable = false, name = "historyRevisionId")
|
||||
protected Long revisionId;
|
||||
|
||||
/** The user that performed the modification. */
|
||||
@JoinColumn(name = "historyActingUser", referencedColumnName = "emailAddress", nullable = false)
|
||||
@ManyToOne
|
||||
User actingUser;
|
||||
|
||||
/** The URL of the action that was used to make the modification. */
|
||||
@Column(nullable = false, name = "historyUrl")
|
||||
String url;
|
||||
|
||||
/** The HTTP method (e.g. POST, PUT) used to make this modification. */
|
||||
@Column(nullable = false, name = "historyMethod")
|
||||
String method;
|
||||
|
||||
/** The raw body of the request that was used to make this modification. */
|
||||
@Column(name = "historyRequestBody")
|
||||
String requestBody;
|
||||
|
||||
/** The time at which the modification was mode. */
|
||||
@Column(nullable = false, name = "historyModificationTime")
|
||||
DateTime modificationTime;
|
||||
|
||||
/** The type of modification. */
|
||||
@Column(nullable = false, name = "historyType")
|
||||
@Enumerated(EnumType.STRING)
|
||||
Type type;
|
||||
|
||||
public long getRevisionId() {
|
||||
return revisionId;
|
||||
}
|
||||
|
||||
public User getActingUser() {
|
||||
return actingUser;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public String getRequestBody() {
|
||||
return requestBody;
|
||||
}
|
||||
|
||||
public DateTime getModificationTime() {
|
||||
return modificationTime;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract Builder<? extends ConsoleUpdateHistory, ?> asBuilder();
|
||||
|
||||
/** Builder for the immutable ConsoleUpdateHistory. */
|
||||
public abstract static class Builder<
|
||||
T extends ConsoleUpdateHistory, B extends ConsoleUpdateHistory.Builder<?, ?>>
|
||||
extends GenericBuilder<T, B> {
|
||||
|
||||
protected Builder() {}
|
||||
|
||||
protected Builder(T instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T build() {
|
||||
checkArgumentNotNull(getInstance().actingUser, "Acting user must be specified");
|
||||
checkArgumentNotNull(getInstance().url, "URL must be specified");
|
||||
checkArgumentNotNull(getInstance().method, "HTTP method must be specified");
|
||||
checkArgumentNotNull(getInstance().modificationTime, "modificationTime must be specified");
|
||||
checkArgumentNotNull(getInstance().type, "Console History type must be specified");
|
||||
return super.build();
|
||||
}
|
||||
|
||||
public B setActingUser(User actingUser) {
|
||||
getInstance().actingUser = actingUser;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setUrl(String url) {
|
||||
getInstance().url = url;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setMethod(String method) {
|
||||
getInstance().method = method;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setRequestBody(String requestBody) {
|
||||
getInstance().requestBody = requestBody;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setModificationTime(DateTime modificationTime) {
|
||||
getInstance().modificationTime = modificationTime;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setType(Type type) {
|
||||
getInstance().type = type;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// 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.model.console;
|
||||
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.model.registrar.RegistrarPocBase;
|
||||
import google.registry.persistence.VKey;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* A persisted history object representing an update to a RegistrarPoc.
|
||||
*
|
||||
* <p>In addition to the generic history fields (time, URL, etc.) we also persist a copy of the
|
||||
* modified RegistrarPoc object at this point in time.
|
||||
*/
|
||||
@Access(AccessType.FIELD)
|
||||
@Entity
|
||||
@Table(
|
||||
indexes = {
|
||||
@Index(columnList = "historyActingUser"),
|
||||
@Index(columnList = "emailAddress"),
|
||||
@Index(columnList = "registrarId")
|
||||
})
|
||||
public class RegistrarPocUpdateHistory extends ConsoleUpdateHistory {
|
||||
|
||||
RegistrarPocBase registrarPoc;
|
||||
|
||||
// These fields exist so that they can be populated in the SQL table
|
||||
@Column(nullable = false)
|
||||
String emailAddress;
|
||||
|
||||
@Column(nullable = false)
|
||||
String registrarId;
|
||||
|
||||
public RegistrarPocBase getRegistrarPoc() {
|
||||
return registrarPoc;
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
registrarPoc.setEmailAddress(emailAddress);
|
||||
registrarPoc.setRegistrarId(registrarId);
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance for this entity. */
|
||||
@Override
|
||||
public VKey<RegistrarPocUpdateHistory> createVKey() {
|
||||
return VKey.create(RegistrarPocUpdateHistory.class, getRevisionId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
return new Builder(clone(this));
|
||||
}
|
||||
|
||||
/** Builder for the immutable UserUpdateHistory. */
|
||||
public static class Builder
|
||||
extends ConsoleUpdateHistory.Builder<RegistrarPocUpdateHistory, Builder> {
|
||||
|
||||
public Builder() {}
|
||||
|
||||
public Builder(RegistrarPocUpdateHistory instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistrarPocUpdateHistory build() {
|
||||
checkArgumentNotNull(getInstance().registrarPoc, "Registrar POC must be specified");
|
||||
return super.build();
|
||||
}
|
||||
|
||||
public Builder setRegistrarPoc(RegistrarPoc registrarPoc) {
|
||||
getInstance().registrarPoc = registrarPoc;
|
||||
getInstance().registrarId = registrarPoc.getRegistrarId();
|
||||
getInstance().emailAddress = registrarPoc.getEmailAddress();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
// 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.model.console;
|
||||
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import google.registry.model.registrar.RegistrarBase;
|
||||
import google.registry.persistence.VKey;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* A persisted history object representing an update to a Registrar.
|
||||
*
|
||||
* <p>In addition to the generic history fields (time, URL, etc.) we also persist a copy of the
|
||||
* modified Registrar object at this point in time.
|
||||
*/
|
||||
@Access(AccessType.FIELD)
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "historyActingUser"), @Index(columnList = "registrarId")})
|
||||
public class RegistrarUpdateHistory extends ConsoleUpdateHistory {
|
||||
|
||||
RegistrarBase registrar;
|
||||
|
||||
// This field exists so that it exists in the SQL table
|
||||
@Column(nullable = false)
|
||||
@SuppressWarnings("unused")
|
||||
private String registrarId;
|
||||
|
||||
public RegistrarBase getRegistrar() {
|
||||
return registrar;
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
registrar.setRegistrarId(registrarId);
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance for this entity. */
|
||||
@Override
|
||||
public VKey<RegistrarUpdateHistory> createVKey() {
|
||||
return VKey.create(RegistrarUpdateHistory.class, getRevisionId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
return new RegistrarUpdateHistory.Builder(clone(this));
|
||||
}
|
||||
|
||||
/** Builder for the immutable UserUpdateHistory. */
|
||||
public static class Builder
|
||||
extends ConsoleUpdateHistory.Builder<RegistrarUpdateHistory, Builder> {
|
||||
|
||||
public Builder() {}
|
||||
|
||||
public Builder(RegistrarUpdateHistory instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistrarUpdateHistory build() {
|
||||
checkArgumentNotNull(getInstance().registrar, "Registrar must be specified");
|
||||
return super.build();
|
||||
}
|
||||
|
||||
public Builder setRegistrar(RegistrarBase registrar) {
|
||||
getInstance().registrar = registrar;
|
||||
getInstance().registrarId = registrar.getRegistrarId();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,19 +14,10 @@
|
||||
|
||||
package google.registry.model.console;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static com.google.common.io.BaseEncoding.base64;
|
||||
import static google.registry.model.registrar.Registrar.checkValidEmail;
|
||||
import static google.registry.util.PasswordUtils.SALT_SUPPLIER;
|
||||
import static google.registry.util.PasswordUtils.hashPassword;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.UpdateAutoTimestampEntity;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.util.PasswordUtils;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
@@ -35,74 +26,17 @@ import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/** A console user, either a registry employee or a registrar partner. */
|
||||
@Embeddable
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "emailAddress", name = "user_email_address_idx")})
|
||||
public class User extends UpdateAutoTimestampEntity implements Buildable {
|
||||
public class User extends UserBase {
|
||||
|
||||
private static final long serialVersionUID = 6936728603828566721L;
|
||||
|
||||
/** Autogenerated unique ID of this user. */
|
||||
@Override
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
/** Email address of the user in question. */
|
||||
@Column(nullable = false)
|
||||
private String emailAddress;
|
||||
|
||||
/** Roles (which grant permissions) associated with this user. */
|
||||
@Column(nullable = false)
|
||||
private UserRoles userRoles;
|
||||
|
||||
/**
|
||||
* A hashed password that exists iff this contact is registry-lock-enabled. The hash is a base64
|
||||
* encoded SHA256 string.
|
||||
*/
|
||||
String registryLockPasswordHash;
|
||||
|
||||
/** Randomly generated hash salt. */
|
||||
String registryLockPasswordSalt;
|
||||
|
||||
@Access(AccessType.PROPERTY)
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getEmailAddress() {
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
public UserRoles getUserRoles() {
|
||||
return userRoles;
|
||||
}
|
||||
|
||||
public boolean hasRegistryLockPassword() {
|
||||
return !isNullOrEmpty(registryLockPasswordHash) && !isNullOrEmpty(registryLockPasswordSalt);
|
||||
}
|
||||
|
||||
public boolean verifyRegistryLockPassword(String registryLockPassword) {
|
||||
if (isNullOrEmpty(registryLockPassword)
|
||||
|| isNullOrEmpty(registryLockPasswordSalt)
|
||||
|| isNullOrEmpty(registryLockPasswordHash)) {
|
||||
return false;
|
||||
}
|
||||
return PasswordUtils.verifyPassword(
|
||||
registryLockPassword, registryLockPasswordHash, registryLockPasswordSalt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the user has the registry lock permission on any registrar or globally.
|
||||
*
|
||||
* <p>If so, they should be allowed to (re)set their registry lock password.
|
||||
*/
|
||||
public boolean hasAnyRegistryLockPermission() {
|
||||
if (userRoles == null) {
|
||||
return false;
|
||||
}
|
||||
if (userRoles.isAdmin() || userRoles.hasGlobalPermission(ConsolePermission.REGISTRY_LOCK)) {
|
||||
return true;
|
||||
}
|
||||
return userRoles.getRegistrarRoles().values().stream()
|
||||
.anyMatch(role -> role.hasPermission(ConsolePermission.REGISTRY_LOCK));
|
||||
return super.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,49 +50,12 @@ public class User extends UpdateAutoTimestampEntity implements Buildable {
|
||||
}
|
||||
|
||||
/** Builder for constructing immutable {@link User} objects. */
|
||||
public static class Builder extends Buildable.Builder<User> {
|
||||
public static class Builder extends UserBase.Builder<User, Builder> {
|
||||
|
||||
public Builder() {}
|
||||
|
||||
public Builder(User user) {
|
||||
super(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User build() {
|
||||
checkArgumentNotNull(getInstance().emailAddress, "Email address cannot be null");
|
||||
checkArgumentNotNull(getInstance().userRoles, "User roles cannot be null");
|
||||
return super.build();
|
||||
}
|
||||
|
||||
public Builder setEmailAddress(String emailAddress) {
|
||||
getInstance().emailAddress = checkValidEmail(emailAddress);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUserRoles(UserRoles userRoles) {
|
||||
checkArgumentNotNull(userRoles, "User roles cannot be null");
|
||||
getInstance().userRoles = userRoles;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder removeRegistryLockPassword() {
|
||||
getInstance().registryLockPasswordHash = null;
|
||||
getInstance().registryLockPasswordSalt = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRegistryLockPassword(String registryLockPassword) {
|
||||
checkArgument(
|
||||
getInstance().hasAnyRegistryLockPermission(), "User has no registry lock permission");
|
||||
checkArgument(
|
||||
!getInstance().hasRegistryLockPassword(), "User already has a password, remove it first");
|
||||
checkArgument(
|
||||
!isNullOrEmpty(registryLockPassword), "Registry lock password was null or empty");
|
||||
byte[] salt = SALT_SUPPLIER.get();
|
||||
getInstance().registryLockPasswordSalt = base64().encode(salt);
|
||||
getInstance().registryLockPasswordHash = hashPassword(registryLockPassword, salt);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
// 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.model.console;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static com.google.common.io.BaseEncoding.base64;
|
||||
import static google.registry.model.registrar.Registrar.checkValidEmail;
|
||||
import static google.registry.util.PasswordUtils.SALT_SUPPLIER;
|
||||
import static google.registry.util.PasswordUtils.hashPassword;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.UpdateAutoTimestampEntity;
|
||||
import google.registry.util.PasswordUtils;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
/**
|
||||
* A console user, either a registry employee or a registrar partner.
|
||||
*
|
||||
* <p>This class deliberately does not include an {@link Id} so that any foreign-keyed fields can
|
||||
* refer to the proper parent entity's ID, whether we're storing this in the DB itself or as part of
|
||||
* another entity.
|
||||
*/
|
||||
@Access(AccessType.FIELD)
|
||||
@Embeddable
|
||||
@MappedSuperclass
|
||||
public class UserBase extends UpdateAutoTimestampEntity implements Buildable {
|
||||
|
||||
private static final long serialVersionUID = 6936728603828566721L;
|
||||
|
||||
/** Autogenerated unique ID of this user. */
|
||||
@Transient private Long id;
|
||||
|
||||
/** Email address of the user in question. */
|
||||
@Column(nullable = false)
|
||||
String emailAddress;
|
||||
|
||||
/** Optional external email address to use for registry lock confirmation emails. */
|
||||
@Column String registryLockEmailAddress;
|
||||
|
||||
/** Roles (which grant permissions) associated with this user. */
|
||||
@Column(nullable = false)
|
||||
UserRoles userRoles;
|
||||
|
||||
/**
|
||||
* A hashed password that exists iff this contact is registry-lock-enabled. The hash is a base64
|
||||
* encoded SHA256 string.
|
||||
*/
|
||||
String registryLockPasswordHash;
|
||||
|
||||
/** Randomly generated hash salt. */
|
||||
String registryLockPasswordSalt;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user ID.
|
||||
*
|
||||
* <p>This should only be used for restoring the user id of an object being loaded in a PostLoad
|
||||
* method (effectively, when it is still under construction by Hibernate). In all other cases, the
|
||||
* object should be regarded as immutable and changes should go through a Builder.
|
||||
*
|
||||
* <p>In addition to this special case use, this method must exist to satisfy Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getEmailAddress() {
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
public Optional<String> getRegistryLockEmailAddress() {
|
||||
return Optional.ofNullable(registryLockEmailAddress);
|
||||
}
|
||||
|
||||
public UserRoles getUserRoles() {
|
||||
return userRoles;
|
||||
}
|
||||
|
||||
public boolean hasRegistryLockPassword() {
|
||||
return !isNullOrEmpty(registryLockPasswordHash) && !isNullOrEmpty(registryLockPasswordSalt);
|
||||
}
|
||||
|
||||
public boolean verifyRegistryLockPassword(String registryLockPassword) {
|
||||
if (isNullOrEmpty(registryLockPassword)
|
||||
|| isNullOrEmpty(registryLockPasswordSalt)
|
||||
|| isNullOrEmpty(registryLockPasswordHash)) {
|
||||
return false;
|
||||
}
|
||||
return PasswordUtils.verifyPassword(
|
||||
registryLockPassword, registryLockPasswordHash, registryLockPasswordSalt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the user has the registry lock permission on any registrar or globally.
|
||||
*
|
||||
* <p>If so, they should be allowed to (re)set their registry lock password.
|
||||
*/
|
||||
public boolean hasAnyRegistryLockPermission() {
|
||||
if (userRoles == null) {
|
||||
return false;
|
||||
}
|
||||
if (userRoles.isAdmin() || userRoles.hasGlobalPermission(ConsolePermission.REGISTRY_LOCK)) {
|
||||
return true;
|
||||
}
|
||||
return userRoles.getRegistrarRoles().values().stream()
|
||||
.anyMatch(role -> role.hasPermission(ConsolePermission.REGISTRY_LOCK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<? extends UserBase, ?> asBuilder() {
|
||||
return new Builder<>(clone(this));
|
||||
}
|
||||
|
||||
/** Builder for constructing immutable {@link UserBase} objects. */
|
||||
public static class Builder<T extends UserBase, B extends Builder<T, B>>
|
||||
extends GenericBuilder<T, B> {
|
||||
|
||||
public Builder() {}
|
||||
|
||||
public Builder(T abstractUser) {
|
||||
super(abstractUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T build() {
|
||||
checkArgumentNotNull(getInstance().emailAddress, "Email address cannot be null");
|
||||
checkArgumentNotNull(getInstance().userRoles, "User roles cannot be null");
|
||||
return super.build();
|
||||
}
|
||||
|
||||
public B setEmailAddress(String emailAddress) {
|
||||
getInstance().emailAddress = checkValidEmail(emailAddress);
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setRegistryLockEmailAddress(@Nullable String registryLockEmailAddress) {
|
||||
getInstance().registryLockEmailAddress =
|
||||
registryLockEmailAddress == null ? null : checkValidEmail(registryLockEmailAddress);
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setUserRoles(UserRoles userRoles) {
|
||||
checkArgumentNotNull(userRoles, "User roles cannot be null");
|
||||
getInstance().userRoles = userRoles;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B removeRegistryLockPassword() {
|
||||
getInstance().registryLockPasswordHash = null;
|
||||
getInstance().registryLockPasswordSalt = null;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setRegistryLockPassword(String registryLockPassword) {
|
||||
checkArgument(
|
||||
getInstance().hasAnyRegistryLockPermission(), "User has no registry lock permission");
|
||||
checkArgument(
|
||||
!getInstance().hasRegistryLockPassword(), "User already has a password, remove it first");
|
||||
checkArgument(
|
||||
!isNullOrEmpty(registryLockPassword), "Registry lock password was null or empty");
|
||||
byte[] salt = SALT_SUPPLIER.get();
|
||||
getInstance().registryLockPasswordSalt = base64().encode(salt);
|
||||
getInstance().registryLockPasswordHash = hashPassword(registryLockPassword, salt);
|
||||
return thisCastToDerived();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@ import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EnumType;
|
||||
@@ -32,6 +34,7 @@ import javax.persistence.Enumerated;
|
||||
* <p>See <a href="https://go/nomulus-console-authz">go/nomulus-console-authz</a> for more
|
||||
* information.
|
||||
*/
|
||||
@Access(AccessType.FIELD)
|
||||
@Embeddable
|
||||
public class UserRoles extends ImmutableObject implements Buildable {
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
// 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.model.console;
|
||||
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import google.registry.persistence.VKey;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* A persisted history object representing an update to a User.
|
||||
*
|
||||
* <p>In addition to the generic history fields (time, URL, etc.) we also persist a copy of the
|
||||
* modified User object at this point in time.
|
||||
*/
|
||||
@Access(AccessType.FIELD)
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "historyActingUser"), @Index(columnList = "emailAddress")})
|
||||
public class UserUpdateHistory extends ConsoleUpdateHistory {
|
||||
|
||||
UserBase user;
|
||||
|
||||
// This field exists so that it's populated in the SQL table
|
||||
@Column(nullable = false, name = "userId")
|
||||
Long id;
|
||||
|
||||
public UserBase getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
user.setId(id);
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance for this entity. */
|
||||
@Override
|
||||
public VKey<UserUpdateHistory> createVKey() {
|
||||
return VKey.create(UserUpdateHistory.class, getRevisionId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
return new Builder(clone(this));
|
||||
}
|
||||
|
||||
/** Builder for the immutable UserUpdateHistory. */
|
||||
public static class Builder extends ConsoleUpdateHistory.Builder<UserUpdateHistory, Builder> {
|
||||
|
||||
public Builder() {}
|
||||
|
||||
public Builder(UserUpdateHistory instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserUpdateHistory build() {
|
||||
checkArgumentNotNull(getInstance().user, "User must be specified");
|
||||
return super.build();
|
||||
}
|
||||
|
||||
public Builder setUser(User user) {
|
||||
getInstance().user = user;
|
||||
getInstance().id = user.getId();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,8 @@ import org.joda.time.DateTime;
|
||||
@Index(columnList = "lordnPhase"),
|
||||
@Index(columnList = "billing_recurrence_id"),
|
||||
@Index(columnList = "transfer_billing_event_id"),
|
||||
@Index(columnList = "transfer_billing_recurrence_id")
|
||||
@Index(columnList = "transfer_billing_recurrence_id"),
|
||||
@Index(columnList = "transfer_billing_cancellation_id")
|
||||
})
|
||||
@WithVKey(String.class)
|
||||
@ExternalMessagingName("domain")
|
||||
|
||||
@@ -659,22 +659,17 @@ public class DomainBase extends EppResource
|
||||
contact.getType());
|
||||
contactsDiscovered.add(contact.getType());
|
||||
switch (contact.getType()) {
|
||||
case BILLING:
|
||||
billingContact = contact.getContactKey();
|
||||
break;
|
||||
case TECH:
|
||||
techContact = contact.getContactKey();
|
||||
break;
|
||||
case ADMIN:
|
||||
adminContact = contact.getContactKey();
|
||||
break;
|
||||
case REGISTRANT:
|
||||
case BILLING -> billingContact = contact.getContactKey();
|
||||
case TECH -> techContact = contact.getContactKey();
|
||||
case ADMIN -> adminContact = contact.getContactKey();
|
||||
case REGISTRANT -> {
|
||||
if (includeRegistrant) {
|
||||
registrantContact = contact.getContactKey();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown contact resource type: " + contact.getType());
|
||||
}
|
||||
default ->
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown contact resource type: " + contact.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import google.registry.model.UpdateAutoTimestampEntity;
|
||||
@@ -90,6 +91,7 @@ public final class RegistryLock extends UpdateAutoTimestampEntity implements Bui
|
||||
|
||||
// TODO (b/140568328): remove this when everything is in Cloud SQL and we can join on "domain"
|
||||
@Column(nullable = false)
|
||||
@Expose
|
||||
private String domainName;
|
||||
|
||||
/**
|
||||
@@ -100,7 +102,7 @@ public final class RegistryLock extends UpdateAutoTimestampEntity implements Bui
|
||||
private String registrarId;
|
||||
|
||||
/** The POC that performed the action, or null if it was a superuser. */
|
||||
private String registrarPocId;
|
||||
@Expose private String registrarPocId;
|
||||
|
||||
/** When the lock is first requested. */
|
||||
@AttributeOverrides({
|
||||
@@ -108,22 +110,23 @@ public final class RegistryLock extends UpdateAutoTimestampEntity implements Bui
|
||||
name = "creationTime",
|
||||
column = @Column(name = "lockRequestTime", nullable = false))
|
||||
})
|
||||
@Expose
|
||||
private final CreateAutoTimestamp lockRequestTime = CreateAutoTimestamp.create(null);
|
||||
|
||||
/** When the unlock is first requested. */
|
||||
private DateTime unlockRequestTime;
|
||||
@Expose private DateTime unlockRequestTime;
|
||||
|
||||
/**
|
||||
* When the user has verified the lock. If this field is null, it means the lock has not been
|
||||
* verified yet (and thus not been put into effect).
|
||||
*/
|
||||
private DateTime lockCompletionTime;
|
||||
@Expose private DateTime lockCompletionTime;
|
||||
|
||||
/**
|
||||
* When the user has verified the unlock of this lock. If this field is null, it means the unlock
|
||||
* action has not been verified yet (and has not been put into effect).
|
||||
*/
|
||||
private DateTime unlockCompletionTime;
|
||||
@Expose private DateTime unlockCompletionTime;
|
||||
|
||||
/** The user must provide the random verification code in order to complete the action. */
|
||||
@Column(nullable = false)
|
||||
@@ -134,6 +137,7 @@ public final class RegistryLock extends UpdateAutoTimestampEntity implements Bui
|
||||
* this case, the action was performed by a registry admin rather than a registrar.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
@Expose
|
||||
private boolean isSuperuser;
|
||||
|
||||
/** The lock that undoes this lock, if this lock has been unlocked and the domain locked again. */
|
||||
|
||||
@@ -103,7 +103,7 @@ public enum GracePeriodStatus implements EppEnum {
|
||||
/**
|
||||
* Maps from xmlName to {@link GracePeriodStatus}.
|
||||
*
|
||||
* If no match is found for xmlName, null is returned.
|
||||
* <p>If no match is found for xmlName, null is returned.
|
||||
*/
|
||||
@Nullable
|
||||
public static GracePeriodStatus fromXmlName(String xmlName) {
|
||||
|
||||
@@ -34,7 +34,7 @@ public class Result extends ImmutableObject {
|
||||
* [RFC5321]. EPP uses four decimal digits to describe the success or failure of each EPP command.
|
||||
* Each of the digits of the reply have special significance."
|
||||
*
|
||||
* "The first digit denotes command success or failure. The second digit denotes the response
|
||||
* <p>"The first digit denotes command success or failure. The second digit denotes the response
|
||||
* category, such as command syntax or security. The third and fourth digits provide explicit
|
||||
* response detail within each response category."
|
||||
*/
|
||||
|
||||
@@ -49,6 +49,7 @@ import javax.persistence.Table;
|
||||
@Index(columnList = "creationTime"),
|
||||
@Index(columnList = "deletionTime"),
|
||||
@Index(columnList = "currentSponsorRegistrarId"),
|
||||
@Index(columnList = "superordinateDomain")
|
||||
})
|
||||
@ExternalMessagingName("host")
|
||||
@WithVKey(String.class)
|
||||
|
||||
@@ -529,8 +529,7 @@ public abstract class PollMessage extends ImmutableObject
|
||||
// Set the identifier according to the TransferResponse type.
|
||||
if (instance.transferResponse instanceof ContactTransferResponse) {
|
||||
instance.contactId = ((ContactTransferResponse) instance.transferResponse).getContactId();
|
||||
} else if (instance.transferResponse instanceof DomainTransferResponse) {
|
||||
DomainTransferResponse response = (DomainTransferResponse) instance.transferResponse;
|
||||
} else if (instance.transferResponse instanceof DomainTransferResponse response) {
|
||||
instance.domainName = response.getDomainName();
|
||||
instance.extendedRegistrationExpirationTime =
|
||||
response.getExtendedRegistrationExpirationTime();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -14,35 +14,14 @@
|
||||
|
||||
package google.registry.model.registrar;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.io.BaseEncoding.base64;
|
||||
import static google.registry.model.registrar.Registrar.checkValidEmail;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy;
|
||||
import static google.registry.util.PasswordUtils.SALT_SUPPLIER;
|
||||
import static google.registry.util.PasswordUtils.hashPassword;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.JsonMapBuilder;
|
||||
import google.registry.model.Jsonifiable;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.registrar.RegistrarPoc.RegistrarPocId;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.util.PasswordUtils;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
@@ -60,258 +39,20 @@ import javax.persistence.Table;
|
||||
@Entity
|
||||
@Table(indexes = @Index(columnList = "loginEmailAddress", name = "registrarpoc_login_email_idx"))
|
||||
@IdClass(RegistrarPocId.class)
|
||||
public class RegistrarPoc extends ImmutableObject implements Jsonifiable, UnsafeSerializable {
|
||||
|
||||
/**
|
||||
* Registrar contacts types for partner communication tracking.
|
||||
*
|
||||
* <p><b>Note:</b> These types only matter to the registry. They are not meant to be used for
|
||||
* WHOIS or RDAP results.
|
||||
*/
|
||||
public enum Type {
|
||||
ABUSE("abuse", true),
|
||||
ADMIN("primary", true),
|
||||
BILLING("billing", true),
|
||||
LEGAL("legal", true),
|
||||
MARKETING("marketing", false),
|
||||
TECH("technical", true),
|
||||
WHOIS("whois-inquiry", true);
|
||||
|
||||
private final String displayName;
|
||||
|
||||
private final boolean required;
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
Type(String display, boolean required) {
|
||||
displayName = display;
|
||||
this.required = required;
|
||||
}
|
||||
}
|
||||
|
||||
/** The name of the contact. */
|
||||
@Expose String name;
|
||||
|
||||
/**
|
||||
* The contact email address of the contact.
|
||||
*
|
||||
* <p>This is different from the login email which is assgined to the regstrar and cannot be
|
||||
* changed.
|
||||
*/
|
||||
@Expose @Id String emailAddress;
|
||||
|
||||
@Expose @Id public String registrarId;
|
||||
|
||||
/** External email address of this contact used for registry lock confirmations. */
|
||||
String registryLockEmailAddress;
|
||||
|
||||
/** The voice number of the contact. */
|
||||
@Expose String phoneNumber;
|
||||
|
||||
/** The fax number of the contact. */
|
||||
@Expose String faxNumber;
|
||||
|
||||
/**
|
||||
* Multiple types are used to associate the registrar contact with various mailing groups. This
|
||||
* data is internal to the registry.
|
||||
*/
|
||||
@Expose Set<Type> types;
|
||||
|
||||
/** A GAIA email address that was assigned to the registrar for console login purpose. */
|
||||
String loginEmailAddress;
|
||||
|
||||
/**
|
||||
* Whether this contact is publicly visible in WHOIS registrar query results as an Admin contact.
|
||||
*/
|
||||
@Expose boolean visibleInWhoisAsAdmin = false;
|
||||
|
||||
/**
|
||||
* Whether this contact is publicly visible in WHOIS registrar query results as a Technical
|
||||
* contact.
|
||||
*/
|
||||
@Expose boolean visibleInWhoisAsTech = false;
|
||||
|
||||
/**
|
||||
* Whether this contact's phone number and email address is publicly visible in WHOIS domain query
|
||||
* results as registrar abuse contact info.
|
||||
*/
|
||||
@Expose boolean visibleInDomainWhoisAsAbuse = false;
|
||||
|
||||
/**
|
||||
* Whether the contact is allowed to set their registry lock password through the registrar
|
||||
* console. This will be set to false on contact creation and when the user sets a password.
|
||||
*/
|
||||
boolean allowedToSetRegistryLockPassword = false;
|
||||
|
||||
/**
|
||||
* A hashed password that exists iff this contact is registry-lock-enabled. The hash is a base64
|
||||
* encoded SHA256 string.
|
||||
*/
|
||||
String registryLockPasswordHash;
|
||||
|
||||
/** Randomly generated hash salt. */
|
||||
String registryLockPasswordSalt;
|
||||
|
||||
/**
|
||||
* Helper to update the contacts associated with a Registrar. This requires querying for the
|
||||
* existing contacts, deleting existing contacts that are not part of the given {@code contacts}
|
||||
* set, and then saving the given {@code contacts}.
|
||||
*
|
||||
* <p>IMPORTANT NOTE: If you call this method then it is your responsibility to also persist the
|
||||
* relevant Registrar entity with the {@link Registrar#contactsRequireSyncing} field set to true.
|
||||
*/
|
||||
public static void updateContacts(
|
||||
final Registrar registrar, final ImmutableSet<RegistrarPoc> contacts) {
|
||||
tm().transact(
|
||||
() -> {
|
||||
ImmutableSet<String> emailAddressesToKeep =
|
||||
contacts.stream().map(RegistrarPoc::getEmailAddress).collect(toImmutableSet());
|
||||
tm().query(
|
||||
"DELETE FROM RegistrarPoc WHERE registrarId = :registrarId AND "
|
||||
+ "emailAddress NOT IN :emailAddressesToKeep")
|
||||
.setParameter("registrarId", registrar.getRegistrarId())
|
||||
.setParameter("emailAddressesToKeep", emailAddressesToKeep)
|
||||
.executeUpdate();
|
||||
|
||||
tm().putAll(contacts);
|
||||
});
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@Access(AccessType.FIELD)
|
||||
public class RegistrarPoc extends RegistrarPocBase {
|
||||
|
||||
@Id
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Override
|
||||
public String getEmailAddress() {
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
public Optional<String> getRegistryLockEmailAddress() {
|
||||
return Optional.ofNullable(registryLockEmailAddress);
|
||||
}
|
||||
|
||||
public String getPhoneNumber() {
|
||||
return phoneNumber;
|
||||
}
|
||||
|
||||
public String getFaxNumber() {
|
||||
return faxNumber;
|
||||
}
|
||||
|
||||
public ImmutableSortedSet<Type> getTypes() {
|
||||
return nullToEmptyImmutableSortedCopy(types);
|
||||
}
|
||||
|
||||
public boolean getVisibleInWhoisAsAdmin() {
|
||||
return visibleInWhoisAsAdmin;
|
||||
}
|
||||
|
||||
public boolean getVisibleInWhoisAsTech() {
|
||||
return visibleInWhoisAsTech;
|
||||
}
|
||||
|
||||
public boolean getVisibleInDomainWhoisAsAbuse() {
|
||||
return visibleInDomainWhoisAsAbuse;
|
||||
}
|
||||
|
||||
public String getLoginEmailAddress() {
|
||||
return loginEmailAddress;
|
||||
}
|
||||
|
||||
public Builder asBuilder() {
|
||||
return new Builder(clone(this));
|
||||
}
|
||||
|
||||
public boolean isAllowedToSetRegistryLockPassword() {
|
||||
return allowedToSetRegistryLockPassword;
|
||||
}
|
||||
|
||||
public boolean isRegistryLockAllowed() {
|
||||
return !isNullOrEmpty(registryLockPasswordHash) && !isNullOrEmpty(registryLockPasswordSalt);
|
||||
}
|
||||
|
||||
public boolean verifyRegistryLockPassword(String registryLockPassword) {
|
||||
if (isNullOrEmpty(registryLockPassword)
|
||||
|| isNullOrEmpty(registryLockPasswordSalt)
|
||||
|| isNullOrEmpty(registryLockPasswordHash)) {
|
||||
return false;
|
||||
}
|
||||
return PasswordUtils.verifyPassword(
|
||||
registryLockPassword, registryLockPasswordHash, registryLockPasswordSalt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation that's human friendly.
|
||||
*
|
||||
* <p>The output will look something like this:
|
||||
*
|
||||
* <pre>{@code
|
||||
* Some Person
|
||||
* person@example.com
|
||||
* Tel: +1.2125650666
|
||||
* Types: [ADMIN, WHOIS]
|
||||
* Visible in WHOIS as Admin contact: Yes
|
||||
* Visible in WHOIS as Technical contact: No
|
||||
* Registrar-Console access: Yes
|
||||
* Login Email Address: person@registry.example
|
||||
* }</pre>
|
||||
*/
|
||||
public String toStringMultilinePlainText() {
|
||||
StringBuilder result = new StringBuilder(256);
|
||||
result.append(getName()).append('\n');
|
||||
result.append(getEmailAddress()).append('\n');
|
||||
if (phoneNumber != null) {
|
||||
result.append("Tel: ").append(getPhoneNumber()).append('\n');
|
||||
}
|
||||
if (faxNumber != null) {
|
||||
result.append("Fax: ").append(getFaxNumber()).append('\n');
|
||||
}
|
||||
result.append("Types: ").append(getTypes()).append('\n');
|
||||
result
|
||||
.append("Visible in registrar WHOIS query as Admin contact: ")
|
||||
.append(getVisibleInWhoisAsAdmin() ? "Yes" : "No")
|
||||
.append('\n');
|
||||
result
|
||||
.append("Visible in registrar WHOIS query as Technical contact: ")
|
||||
.append(getVisibleInWhoisAsTech() ? "Yes" : "No")
|
||||
.append('\n');
|
||||
result
|
||||
.append(
|
||||
"Phone number and email visible in domain WHOIS query as "
|
||||
+ "Registrar Abuse contact info: ")
|
||||
.append(getVisibleInDomainWhoisAsAbuse() ? "Yes" : "No")
|
||||
.append('\n');
|
||||
result
|
||||
.append("Registrar-Console access: ")
|
||||
.append(getLoginEmailAddress() != null ? "Yes" : "No")
|
||||
.append('\n');
|
||||
if (getLoginEmailAddress() != null) {
|
||||
result.append("Login Email Address: ").append(getLoginEmailAddress()).append('\n');
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> toJsonMap() {
|
||||
return new JsonMapBuilder()
|
||||
.put("name", name)
|
||||
.put("emailAddress", emailAddress)
|
||||
.put("registryLockEmailAddress", registryLockEmailAddress)
|
||||
.put("phoneNumber", phoneNumber)
|
||||
.put("faxNumber", faxNumber)
|
||||
.put("types", getTypes().stream().map(Object::toString).collect(joining(",")))
|
||||
.put("visibleInWhoisAsAdmin", visibleInWhoisAsAdmin)
|
||||
.put("visibleInWhoisAsTech", visibleInWhoisAsTech)
|
||||
.put("visibleInDomainWhoisAsAbuse", visibleInDomainWhoisAsAbuse)
|
||||
.put("allowedToSetRegistryLockPassword", allowedToSetRegistryLockPassword)
|
||||
.put("registryLockAllowed", isRegistryLockAllowed())
|
||||
.put("loginEmailAddress", loginEmailAddress)
|
||||
.build();
|
||||
@Id
|
||||
@Access(AccessType.PROPERTY)
|
||||
public String getRegistrarId() {
|
||||
return registrarId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -319,6 +60,11 @@ public class RegistrarPoc extends ImmutableObject implements Jsonifiable, Unsafe
|
||||
return VKey.create(RegistrarPoc.class, new RegistrarPocId(emailAddress, registrarId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
return new Builder(clone(this));
|
||||
}
|
||||
|
||||
/** Class to represent the composite primary key for {@link RegistrarPoc} entity. */
|
||||
@VisibleForTesting
|
||||
public static class RegistrarPocId extends ImmutableObject implements Serializable {
|
||||
@@ -336,112 +82,24 @@ public class RegistrarPoc extends ImmutableObject implements Jsonifiable, Unsafe
|
||||
this.emailAddress = emailAddress;
|
||||
this.registrarId = registrarId;
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getEmailAddress() {
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getRegistrarId() {
|
||||
return registrarId;
|
||||
}
|
||||
}
|
||||
|
||||
/** A builder for constructing a {@link RegistrarPoc}, since it is immutable. */
|
||||
public static class Builder extends Buildable.Builder<RegistrarPoc> {
|
||||
public static class Builder extends RegistrarPocBase.Builder<RegistrarPoc, Builder> {
|
||||
|
||||
public Builder() {}
|
||||
|
||||
private Builder(RegistrarPoc instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/** Build the registrar, nullifying empty fields. */
|
||||
@Override
|
||||
public RegistrarPoc build() {
|
||||
checkNotNull(getInstance().registrarId, "Registrar ID cannot be null");
|
||||
checkValidEmail(getInstance().emailAddress);
|
||||
// Check allowedToSetRegistryLockPassword here because if we want to allow the user to set
|
||||
// a registry lock password, we must also set up the correct registry lock email concurrently
|
||||
// or beforehand.
|
||||
if (getInstance().allowedToSetRegistryLockPassword) {
|
||||
checkArgument(
|
||||
!isNullOrEmpty(getInstance().registryLockEmailAddress),
|
||||
"Registry lock email must not be null if allowing registry lock access");
|
||||
}
|
||||
return cloneEmptyToNull(super.build());
|
||||
}
|
||||
|
||||
public Builder setName(String name) {
|
||||
getInstance().name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setEmailAddress(String emailAddress) {
|
||||
getInstance().emailAddress = emailAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRegistryLockEmailAddress(@Nullable String registryLockEmailAddress) {
|
||||
getInstance().registryLockEmailAddress = registryLockEmailAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPhoneNumber(String phoneNumber) {
|
||||
getInstance().phoneNumber = phoneNumber;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRegistrarId(String registrarId) {
|
||||
getInstance().registrarId = registrarId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRegistrar(Registrar registrar) {
|
||||
getInstance().registrarId = registrar.getRegistrarId();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFaxNumber(String faxNumber) {
|
||||
getInstance().faxNumber = faxNumber;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTypes(Iterable<Type> types) {
|
||||
getInstance().types = ImmutableSet.copyOf(types);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setVisibleInWhoisAsAdmin(boolean visible) {
|
||||
getInstance().visibleInWhoisAsAdmin = visible;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setVisibleInWhoisAsTech(boolean visible) {
|
||||
getInstance().visibleInWhoisAsTech = visible;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setVisibleInDomainWhoisAsAbuse(boolean visible) {
|
||||
getInstance().visibleInDomainWhoisAsAbuse = visible;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setLoginEmailAddress(String loginEmailAddress) {
|
||||
getInstance().loginEmailAddress = loginEmailAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAllowedToSetRegistryLockPassword(boolean allowedToSetRegistryLockPassword) {
|
||||
if (allowedToSetRegistryLockPassword) {
|
||||
getInstance().registryLockPasswordSalt = null;
|
||||
getInstance().registryLockPasswordHash = null;
|
||||
}
|
||||
getInstance().allowedToSetRegistryLockPassword = allowedToSetRegistryLockPassword;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRegistryLockPassword(String registryLockPassword) {
|
||||
checkArgument(
|
||||
getInstance().allowedToSetRegistryLockPassword,
|
||||
"Not allowed to set registry lock password for this contact");
|
||||
checkArgument(
|
||||
!isNullOrEmpty(registryLockPassword), "Registry lock password was null or empty");
|
||||
byte[] salt = SALT_SUPPLIER.get();
|
||||
getInstance().registryLockPasswordSalt = base64().encode(salt);
|
||||
getInstance().registryLockPasswordHash = hashPassword(registryLockPassword, salt);
|
||||
getInstance().allowedToSetRegistryLockPassword = false;
|
||||
return this;
|
||||
public Builder(RegistrarPoc registrarPoc) {
|
||||
super(registrarPoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,441 @@
|
||||
// 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.model.registrar;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.io.BaseEncoding.base64;
|
||||
import static google.registry.model.registrar.RegistrarBase.checkValidEmail;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy;
|
||||
import static google.registry.util.PasswordUtils.SALT_SUPPLIER;
|
||||
import static google.registry.util.PasswordUtils.hashPassword;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import google.registry.model.Buildable.GenericBuilder;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.JsonMapBuilder;
|
||||
import google.registry.model.Jsonifiable;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.util.PasswordUtils;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
/**
|
||||
* A contact for a Registrar. Note, equality, hashCode and comparable have been overridden to only
|
||||
* enable key equality.
|
||||
*
|
||||
* <p>IMPORTANT NOTE: Any time that you change, update, or delete RegistrarContact entities, you
|
||||
* *MUST* also modify the persisted Registrar entity with {@link Registrar#contactsRequireSyncing}
|
||||
* set to true.
|
||||
*
|
||||
* <p>This class deliberately does not include an {@link Id} so that any foreign-keyed fields can
|
||||
* refer to the proper parent entity's ID, whether we're storing this in the DB itself or as part of
|
||||
* another entity.
|
||||
*/
|
||||
@Access(AccessType.FIELD)
|
||||
@Embeddable
|
||||
@MappedSuperclass
|
||||
public class RegistrarPocBase extends ImmutableObject implements Jsonifiable, UnsafeSerializable {
|
||||
/**
|
||||
* Registrar contacts types for partner communication tracking.
|
||||
*
|
||||
* <p><b>Note:</b> These types only matter to the registry. They are not meant to be used for
|
||||
* WHOIS or RDAP results.
|
||||
*/
|
||||
public enum Type {
|
||||
ABUSE("abuse", true),
|
||||
ADMIN("primary", true),
|
||||
BILLING("billing", true),
|
||||
LEGAL("legal", true),
|
||||
MARKETING("marketing", false),
|
||||
TECH("technical", true),
|
||||
WHOIS("whois-inquiry", true);
|
||||
|
||||
private final String displayName;
|
||||
|
||||
private final boolean required;
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
Type(String display, boolean required) {
|
||||
displayName = display;
|
||||
this.required = required;
|
||||
}
|
||||
}
|
||||
|
||||
/** The name of the contact. */
|
||||
@Expose String name;
|
||||
|
||||
/**
|
||||
* The contact email address of the contact.
|
||||
*
|
||||
* <p>This is different from the login email which is assgined to the regstrar and cannot be
|
||||
* changed.
|
||||
*/
|
||||
@Expose @Transient String emailAddress;
|
||||
|
||||
@Expose @Transient public String registrarId;
|
||||
|
||||
/** External email address of this contact used for registry lock confirmations. */
|
||||
String registryLockEmailAddress;
|
||||
|
||||
/** The voice number of the contact. */
|
||||
@Expose String phoneNumber;
|
||||
|
||||
/** The fax number of the contact. */
|
||||
@Expose String faxNumber;
|
||||
|
||||
/**
|
||||
* Multiple types are used to associate the registrar contact with various mailing groups. This
|
||||
* data is internal to the registry.
|
||||
*/
|
||||
@Expose Set<Type> types;
|
||||
|
||||
/** A GAIA email address that was assigned to the registrar for console login purpose. */
|
||||
String loginEmailAddress;
|
||||
|
||||
/**
|
||||
* Whether this contact is publicly visible in WHOIS registrar query results as an Admin contact.
|
||||
*/
|
||||
@Expose boolean visibleInWhoisAsAdmin = false;
|
||||
|
||||
/**
|
||||
* Whether this contact is publicly visible in WHOIS registrar query results as a Technical
|
||||
* contact.
|
||||
*/
|
||||
@Expose boolean visibleInWhoisAsTech = false;
|
||||
|
||||
/**
|
||||
* Whether this contact's phone number and email address is publicly visible in WHOIS domain query
|
||||
* results as registrar abuse contact info.
|
||||
*/
|
||||
@Expose boolean visibleInDomainWhoisAsAbuse = false;
|
||||
|
||||
/**
|
||||
* Whether the contact is allowed to set their registry lock password through the registrar
|
||||
* console. This will be set to false on contact creation and when the user sets a password.
|
||||
*/
|
||||
boolean allowedToSetRegistryLockPassword = false;
|
||||
|
||||
/**
|
||||
* A hashed password that exists iff this contact is registry-lock-enabled. The hash is a base64
|
||||
* encoded SHA256 string.
|
||||
*/
|
||||
String registryLockPasswordHash;
|
||||
|
||||
/** Randomly generated hash salt. */
|
||||
String registryLockPasswordSalt;
|
||||
|
||||
/**
|
||||
* Helper to update the contacts associated with a Registrar. This requires querying for the
|
||||
* existing contacts, deleting existing contacts that are not part of the given {@code contacts}
|
||||
* set, and then saving the given {@code contacts}.
|
||||
*
|
||||
* <p>IMPORTANT NOTE: If you call this method then it is your responsibility to also persist the
|
||||
* relevant Registrar entity with the {@link Registrar#contactsRequireSyncing} field set to true.
|
||||
*/
|
||||
public static void updateContacts(
|
||||
final Registrar registrar, final ImmutableSet<RegistrarPoc> contacts) {
|
||||
tm().transact(
|
||||
() -> {
|
||||
ImmutableSet<String> emailAddressesToKeep =
|
||||
contacts.stream().map(RegistrarPoc::getEmailAddress).collect(toImmutableSet());
|
||||
tm().query(
|
||||
"DELETE FROM RegistrarPoc WHERE registrarId = :registrarId AND "
|
||||
+ "emailAddress NOT IN :emailAddressesToKeep")
|
||||
.setParameter("registrarId", registrar.getRegistrarId())
|
||||
.setParameter("emailAddressesToKeep", emailAddressesToKeep)
|
||||
.executeUpdate();
|
||||
|
||||
tm().putAll(contacts);
|
||||
});
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getEmailAddress() {
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
public Optional<String> getRegistryLockEmailAddress() {
|
||||
return Optional.ofNullable(registryLockEmailAddress);
|
||||
}
|
||||
|
||||
public String getPhoneNumber() {
|
||||
return phoneNumber;
|
||||
}
|
||||
|
||||
public String getFaxNumber() {
|
||||
return faxNumber;
|
||||
}
|
||||
|
||||
public ImmutableSortedSet<Type> getTypes() {
|
||||
return nullToEmptyImmutableSortedCopy(types);
|
||||
}
|
||||
|
||||
public boolean getVisibleInWhoisAsAdmin() {
|
||||
return visibleInWhoisAsAdmin;
|
||||
}
|
||||
|
||||
public boolean getVisibleInWhoisAsTech() {
|
||||
return visibleInWhoisAsTech;
|
||||
}
|
||||
|
||||
public boolean getVisibleInDomainWhoisAsAbuse() {
|
||||
return visibleInDomainWhoisAsAbuse;
|
||||
}
|
||||
|
||||
public String getLoginEmailAddress() {
|
||||
return loginEmailAddress;
|
||||
}
|
||||
|
||||
public Builder<? extends RegistrarPocBase, ?> asBuilder() {
|
||||
return new Builder<>(clone(this));
|
||||
}
|
||||
|
||||
public boolean isAllowedToSetRegistryLockPassword() {
|
||||
return allowedToSetRegistryLockPassword;
|
||||
}
|
||||
|
||||
public boolean isRegistryLockAllowed() {
|
||||
return !isNullOrEmpty(registryLockPasswordHash) && !isNullOrEmpty(registryLockPasswordSalt);
|
||||
}
|
||||
|
||||
public boolean verifyRegistryLockPassword(String registryLockPassword) {
|
||||
if (isNullOrEmpty(registryLockPassword)
|
||||
|| isNullOrEmpty(registryLockPasswordSalt)
|
||||
|| isNullOrEmpty(registryLockPasswordHash)) {
|
||||
return false;
|
||||
}
|
||||
return PasswordUtils.verifyPassword(
|
||||
registryLockPassword, registryLockPasswordHash, registryLockPasswordSalt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation that's human friendly.
|
||||
*
|
||||
* <p>The output will look something like this:
|
||||
*
|
||||
* <pre>{@code
|
||||
* Some Person
|
||||
* person@example.com
|
||||
* Tel: +1.2125650666
|
||||
* Types: [ADMIN, WHOIS]
|
||||
* Visible in WHOIS as Admin contact: Yes
|
||||
* Visible in WHOIS as Technical contact: No
|
||||
* Registrar-Console access: Yes
|
||||
* Login Email Address: person@registry.example
|
||||
* }</pre>
|
||||
*/
|
||||
public String toStringMultilinePlainText() {
|
||||
StringBuilder result = new StringBuilder(256);
|
||||
result.append(getName()).append('\n');
|
||||
result.append(getEmailAddress()).append('\n');
|
||||
if (phoneNumber != null) {
|
||||
result.append("Tel: ").append(getPhoneNumber()).append('\n');
|
||||
}
|
||||
if (faxNumber != null) {
|
||||
result.append("Fax: ").append(getFaxNumber()).append('\n');
|
||||
}
|
||||
result.append("Types: ").append(getTypes()).append('\n');
|
||||
result
|
||||
.append("Visible in registrar WHOIS query as Admin contact: ")
|
||||
.append(getVisibleInWhoisAsAdmin() ? "Yes" : "No")
|
||||
.append('\n');
|
||||
result
|
||||
.append("Visible in registrar WHOIS query as Technical contact: ")
|
||||
.append(getVisibleInWhoisAsTech() ? "Yes" : "No")
|
||||
.append('\n');
|
||||
result
|
||||
.append(
|
||||
"Phone number and email visible in domain WHOIS query as "
|
||||
+ "Registrar Abuse contact info: ")
|
||||
.append(getVisibleInDomainWhoisAsAbuse() ? "Yes" : "No")
|
||||
.append('\n');
|
||||
result
|
||||
.append("Registrar-Console access: ")
|
||||
.append(getLoginEmailAddress() != null ? "Yes" : "No")
|
||||
.append('\n');
|
||||
if (getLoginEmailAddress() != null) {
|
||||
result.append("Login Email Address: ").append(getLoginEmailAddress()).append('\n');
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> toJsonMap() {
|
||||
return new JsonMapBuilder()
|
||||
.put("name", name)
|
||||
.put("emailAddress", emailAddress)
|
||||
.put("registryLockEmailAddress", registryLockEmailAddress)
|
||||
.put("phoneNumber", phoneNumber)
|
||||
.put("faxNumber", faxNumber)
|
||||
.put("types", getTypes().stream().map(Object::toString).collect(joining(",")))
|
||||
.put("visibleInWhoisAsAdmin", visibleInWhoisAsAdmin)
|
||||
.put("visibleInWhoisAsTech", visibleInWhoisAsTech)
|
||||
.put("visibleInDomainWhoisAsAbuse", visibleInDomainWhoisAsAbuse)
|
||||
.put("allowedToSetRegistryLockPassword", allowedToSetRegistryLockPassword)
|
||||
.put("registryLockAllowed", isRegistryLockAllowed())
|
||||
.put("loginEmailAddress", loginEmailAddress)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* These methods set the email address and registrar ID
|
||||
*
|
||||
* <p>This should only be used for restoring the fields of an object being loaded in a PostLoad
|
||||
* method (effectively, when it is still under construction by Hibernate). In all other cases, the
|
||||
* object should be regarded as immutable and changes should go through a Builder.
|
||||
*
|
||||
* <p>In addition to this special case use, this method must exist to satisfy Hibernate.
|
||||
*/
|
||||
public void setEmailAddress(String emailAddress) {
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
public void setRegistrarId(String registrarId) {
|
||||
this.registrarId = registrarId;
|
||||
}
|
||||
|
||||
/** A builder for constructing a {@link RegistrarPoc}, since it is immutable. */
|
||||
public static class Builder<T extends RegistrarPocBase, B extends Builder<T, B>>
|
||||
extends GenericBuilder<T, B> {
|
||||
public Builder() {}
|
||||
|
||||
protected Builder(T instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/** Build the registrar, nullifying empty fields. */
|
||||
@Override
|
||||
public T build() {
|
||||
checkNotNull(getInstance().registrarId, "Registrar ID cannot be null");
|
||||
checkValidEmail(getInstance().emailAddress);
|
||||
// Check allowedToSetRegistryLockPassword here because if we want to allow the user to set
|
||||
// a registry lock password, we must also set up the correct registry lock email concurrently
|
||||
// or beforehand.
|
||||
if (getInstance().allowedToSetRegistryLockPassword) {
|
||||
checkArgument(
|
||||
!isNullOrEmpty(getInstance().registryLockEmailAddress),
|
||||
"Registry lock email must not be null if allowing registry lock access");
|
||||
}
|
||||
return cloneEmptyToNull(super.build());
|
||||
}
|
||||
|
||||
public B setName(String name) {
|
||||
getInstance().name = name;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setEmailAddress(String emailAddress) {
|
||||
getInstance().emailAddress = emailAddress;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setRegistryLockEmailAddress(@Nullable String registryLockEmailAddress) {
|
||||
getInstance().registryLockEmailAddress = registryLockEmailAddress;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setPhoneNumber(String phoneNumber) {
|
||||
getInstance().phoneNumber = phoneNumber;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setRegistrarId(String registrarId) {
|
||||
getInstance().registrarId = registrarId;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setRegistrar(Registrar registrar) {
|
||||
getInstance().registrarId = registrar.getRegistrarId();
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setFaxNumber(String faxNumber) {
|
||||
getInstance().faxNumber = faxNumber;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setTypes(Iterable<Type> types) {
|
||||
getInstance().types = ImmutableSet.copyOf(types);
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setVisibleInWhoisAsAdmin(boolean visible) {
|
||||
getInstance().visibleInWhoisAsAdmin = visible;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setVisibleInWhoisAsTech(boolean visible) {
|
||||
getInstance().visibleInWhoisAsTech = visible;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setVisibleInDomainWhoisAsAbuse(boolean visible) {
|
||||
getInstance().visibleInDomainWhoisAsAbuse = visible;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setLoginEmailAddress(String loginEmailAddress) {
|
||||
getInstance().loginEmailAddress = loginEmailAddress;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setAllowedToSetRegistryLockPassword(boolean allowedToSetRegistryLockPassword) {
|
||||
if (allowedToSetRegistryLockPassword) {
|
||||
getInstance().registryLockPasswordSalt = null;
|
||||
getInstance().registryLockPasswordHash = null;
|
||||
}
|
||||
getInstance().allowedToSetRegistryLockPassword = allowedToSetRegistryLockPassword;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setRegistryLockPassword(String registryLockPassword) {
|
||||
checkArgument(
|
||||
getInstance().allowedToSetRegistryLockPassword,
|
||||
"Not allowed to set registry lock password for this contact");
|
||||
checkArgument(
|
||||
!isNullOrEmpty(registryLockPassword), "Registry lock password was null or empty");
|
||||
byte[] salt = SALT_SUPPLIER.get();
|
||||
getInstance().registryLockPasswordSalt = base64().encode(salt);
|
||||
getInstance().registryLockPasswordHash = hashPassword(registryLockPassword, salt);
|
||||
getInstance().allowedToSetRegistryLockPassword = false;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -458,20 +458,6 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||
@JsonDeserialize(using = CurrencyDeserializer.class)
|
||||
CurrencyUnit currency = DEFAULT_CURRENCY;
|
||||
|
||||
// TODO(sarahbot@): Remove this field once all saved configuration files have this field removed
|
||||
/** The per-year billing cost for registering a new domain name. */
|
||||
@Deprecated
|
||||
@JsonIgnore
|
||||
@Type(type = JodaMoneyType.TYPE_NAME)
|
||||
@Columns(
|
||||
columns = {
|
||||
@Column(name = "create_billing_cost_amount"),
|
||||
@Column(name = "create_billing_cost_currency")
|
||||
})
|
||||
Money createBillingCost = DEFAULT_CREATE_BILLING_COST;
|
||||
|
||||
// TODO(sarahbot@): Rename this field to createBillingCost once the old createBillingCost has been
|
||||
// removed
|
||||
/** A property that transitions to different create billing costs at different times. */
|
||||
@Column(nullable = false)
|
||||
@JsonDeserialize(using = TimedTransitionPropertyMoneyDeserializer.class)
|
||||
@@ -682,19 +668,10 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||
* Use {@code PricingEngineProxy.getDomainCreateCost} instead of this to find the cost for a
|
||||
* domain create.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public Money getCreateBillingCost(DateTime now) {
|
||||
return createBillingCostTransitions.getValueAtTime(now);
|
||||
}
|
||||
|
||||
// This getter is still necessary for the Jackson deserialization in the ConfigureTldCommand
|
||||
// TODO(sarahbot@): Remove this getter once the deprecated createBillingCost field is removed from
|
||||
// the schema
|
||||
@Deprecated
|
||||
public Money getCreateBillingCost() {
|
||||
return createBillingCost;
|
||||
}
|
||||
|
||||
public ImmutableSortedMap<DateTime, Money> getCreateBillingCostTransitions() {
|
||||
return createBillingCostTransitions.toValueMap();
|
||||
}
|
||||
@@ -976,12 +953,6 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCreateBillingCost(Money amount) {
|
||||
checkArgument(amount.isPositiveOrZero(), "createBillingCost cannot be negative");
|
||||
getInstance().createBillingCost = amount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCreateBillingCostTransitions(
|
||||
ImmutableSortedMap<DateTime, Money> createCostsMap) {
|
||||
checkArgumentNotNull(createCostsMap, "Create billing costs map cannot be null");
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.model.tld.label;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.monitoring.metrics.EventMetric;
|
||||
@@ -43,16 +42,11 @@ class DomainLabelMetrics {
|
||||
UNCACHED_POSITIVE
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
abstract static class MetricsReservedListMatch {
|
||||
record MetricsReservedListMatch(String reservedListName, ReservationType reservationType) {
|
||||
static MetricsReservedListMatch create(
|
||||
String reservedListName, ReservationType reservationType) {
|
||||
return new AutoValue_DomainLabelMetrics_MetricsReservedListMatch(
|
||||
reservedListName, reservationType);
|
||||
return new MetricsReservedListMatch(reservedListName, reservationType);
|
||||
}
|
||||
|
||||
abstract String reservedListName();
|
||||
abstract ReservationType reservationType();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -236,14 +235,10 @@ public final class PremiumListDao {
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
abstract static class RevisionIdAndLabel {
|
||||
abstract long revisionId();
|
||||
|
||||
abstract String label();
|
||||
record RevisionIdAndLabel(long revisionId, String label) {
|
||||
|
||||
static RevisionIdAndLabel create(long revisionId, String label) {
|
||||
return new AutoValue_PremiumListDao_RevisionIdAndLabel(revisionId, label);
|
||||
return new RevisionIdAndLabel(revisionId, label);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,12 +67,13 @@ public enum ReservationType {
|
||||
return messageForCheck;
|
||||
}
|
||||
|
||||
private static final Ordering<ReservationType> ORDERING = new Ordering<ReservationType>() {
|
||||
@Override
|
||||
public int compare(ReservationType left, ReservationType right) {
|
||||
return Integer.compare(left.ordinal(), right.ordinal());
|
||||
}
|
||||
};
|
||||
private static final Ordering<ReservationType> ORDERING =
|
||||
new Ordering<>() {
|
||||
@Override
|
||||
public int compare(ReservationType left, ReservationType right) {
|
||||
return Integer.compare(left.ordinal(), right.ordinal());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the {@code ReservationType} with the highest severity, used when a label has multiple
|
||||
|
||||
@@ -60,17 +60,17 @@ public final class TmchCrl extends CrossTldSingleton {
|
||||
}
|
||||
|
||||
/** ASCII-armored X.509 certificate revocation list. */
|
||||
public final String getCrl() {
|
||||
public String getCrl() {
|
||||
return crl;
|
||||
}
|
||||
|
||||
/** Returns the URL that the CRL was downloaded from. */
|
||||
public final String getUrl() {
|
||||
public String getUrl() {
|
||||
return crl;
|
||||
}
|
||||
|
||||
/** Time we last updated the Database with a newer ICANN CRL. */
|
||||
public final DateTime getUpdated() {
|
||||
public DateTime getUpdated() {
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import google.registry.batch.BatchModule;
|
||||
import google.registry.bigquery.BigqueryModule;
|
||||
import google.registry.config.CloudTasksUtilsModule;
|
||||
import google.registry.config.CredentialModule;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryConfig.ConfigModule;
|
||||
import google.registry.dns.writer.VoidDnsWriterModule;
|
||||
import google.registry.export.DriveModule;
|
||||
@@ -96,6 +97,9 @@ interface RegistryComponent {
|
||||
|
||||
Lazy<MetricReporter> metricReporter();
|
||||
|
||||
@Config("projectId")
|
||||
String projectId();
|
||||
|
||||
@Module
|
||||
class RegistryModule {
|
||||
@Provides
|
||||
|
||||
@@ -14,17 +14,51 @@
|
||||
|
||||
package google.registry.module;
|
||||
|
||||
import static com.google.cloud.logging.TraceLoggingEnhancer.setCurrentTraceId;
|
||||
import static google.registry.util.RandomStringGenerator.insecureRandomStringGenerator;
|
||||
import static google.registry.util.StringGenerator.Alphabets.HEX_DIGITS_ONLY;
|
||||
|
||||
import com.google.monitoring.metrics.MetricReporter;
|
||||
import dagger.Lazy;
|
||||
import google.registry.request.RequestHandler;
|
||||
import google.registry.util.RandomStringGenerator;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/** Servlet that handles all requests. */
|
||||
public class RegistryServlet extends ServletBase {
|
||||
|
||||
// Length of a log trace_id, arbitrarily chosen.
|
||||
private static final int LOG_TRACE_ID_LENGTH = 32;
|
||||
// GCP log trace pattern. Fill in project_id and trace id
|
||||
private static final String LOG_TRACE_PATTERN = "projects/%s/traces/%s";
|
||||
private static final RandomStringGenerator LOG_TRACE_ID_GENERATOR =
|
||||
insecureRandomStringGenerator(HEX_DIGITS_ONLY);
|
||||
|
||||
private static final RegistryComponent component = DaggerRegistryComponent.create();
|
||||
private static final RequestHandler<RequestComponent> requestHandler = component.requestHandler();
|
||||
private static final Lazy<MetricReporter> metricReporter = component.metricReporter();
|
||||
|
||||
private final String projectId;
|
||||
|
||||
public RegistryServlet() {
|
||||
super(requestHandler, metricReporter);
|
||||
this.projectId = component.projectId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void service(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
|
||||
setCurrentTraceId(traceId());
|
||||
try {
|
||||
super.service(req, rsp);
|
||||
} finally {
|
||||
setCurrentTraceId(null);
|
||||
}
|
||||
}
|
||||
|
||||
String traceId() {
|
||||
return String.format(
|
||||
LOG_TRACE_PATTERN, projectId, LOG_TRACE_ID_GENERATOR.createString(LOG_TRACE_ID_LENGTH));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,9 @@ import google.registry.tools.server.ToolsServerModule;
|
||||
import google.registry.tools.server.VerifyOteAction;
|
||||
import google.registry.ui.server.console.ConsoleDomainGetAction;
|
||||
import google.registry.ui.server.console.ConsoleDomainListAction;
|
||||
import google.registry.ui.server.console.ConsoleDumDownloadAction;
|
||||
import google.registry.ui.server.console.ConsoleEppPasswordAction;
|
||||
import google.registry.ui.server.console.ConsoleRegistryLockAction;
|
||||
import google.registry.ui.server.console.ConsoleUserDataAction;
|
||||
import google.registry.ui.server.console.RegistrarsAction;
|
||||
import google.registry.ui.server.console.settings.ContactAction;
|
||||
@@ -185,10 +187,14 @@ interface RequestComponent {
|
||||
|
||||
ConsoleRegistrarCreatorAction consoleRegistrarCreatorAction();
|
||||
|
||||
ConsoleRegistryLockAction consoleRegistryLockAction();
|
||||
|
||||
ConsoleUiAction consoleUiAction();
|
||||
|
||||
ConsoleUserDataAction consoleUserDataAction();
|
||||
|
||||
ConsoleDumDownloadAction consoleDumDownloadAction();
|
||||
|
||||
ContactAction contactAction();
|
||||
|
||||
CopyDetailReportsAction copyDetailReportAction();
|
||||
|
||||
@@ -27,7 +27,9 @@ import google.registry.request.RequestModule;
|
||||
import google.registry.request.RequestScope;
|
||||
import google.registry.ui.server.console.ConsoleDomainGetAction;
|
||||
import google.registry.ui.server.console.ConsoleDomainListAction;
|
||||
import google.registry.ui.server.console.ConsoleDumDownloadAction;
|
||||
import google.registry.ui.server.console.ConsoleEppPasswordAction;
|
||||
import google.registry.ui.server.console.ConsoleRegistryLockAction;
|
||||
import google.registry.ui.server.console.ConsoleUserDataAction;
|
||||
import google.registry.ui.server.console.RegistrarsAction;
|
||||
import google.registry.ui.server.console.settings.ContactAction;
|
||||
@@ -63,10 +65,15 @@ public interface FrontendRequestComponent {
|
||||
|
||||
ConsoleOteSetupAction consoleOteSetupAction();
|
||||
ConsoleRegistrarCreatorAction consoleRegistrarCreatorAction();
|
||||
|
||||
ConsoleRegistryLockAction consoleRegistryLockAction();
|
||||
|
||||
ConsoleUiAction consoleUiAction();
|
||||
|
||||
ConsoleUserDataAction consoleUserDataAction();
|
||||
|
||||
ConsoleDumDownloadAction consoleDumDownloadAction();
|
||||
|
||||
ContactAction contactAction();
|
||||
|
||||
EppTlsAction eppTlsAction();
|
||||
|
||||
@@ -16,14 +16,18 @@ package google.registry.monitoring.whitebox;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.auto.value.AutoBuilder;
|
||||
import google.registry.util.Clock;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** A value class for recording attributes of a domain check metric. */
|
||||
@AutoValue
|
||||
public abstract class CheckApiMetric {
|
||||
/** A record for recording attributes of a domain check metric. */
|
||||
public record CheckApiMetric(
|
||||
DateTime startTimestamp,
|
||||
DateTime endTimestamp,
|
||||
Status status,
|
||||
Optional<Tier> tier,
|
||||
Optional<Availability> availability) {
|
||||
|
||||
/** Price tier of a domain name. */
|
||||
public enum Tier {
|
||||
@@ -77,24 +81,13 @@ public abstract class CheckApiMetric {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract DateTime startTimestamp();
|
||||
|
||||
public abstract DateTime endTimestamp();
|
||||
|
||||
public abstract Status status();
|
||||
|
||||
public abstract Optional<Tier> tier();
|
||||
|
||||
public abstract Optional<Availability> availability();
|
||||
|
||||
public static Builder builder(Clock clock) {
|
||||
return new AutoValue_CheckApiMetric.Builder().startTimestamp(clock.nowUtc()).setClock(clock);
|
||||
return new AutoBuilder_CheckApiMetric_Builder().startTimestamp(clock.nowUtc()).setClock(clock);
|
||||
}
|
||||
|
||||
CheckApiMetric() {}
|
||||
|
||||
/** Builder for {@link CheckApiMetric}. */
|
||||
@AutoValue.Builder
|
||||
@AutoBuilder
|
||||
public abstract static class Builder {
|
||||
|
||||
private Clock clock;
|
||||
|
||||
@@ -16,7 +16,7 @@ package google.registry.monitoring.whitebox;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.auto.value.AutoBuilder;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import google.registry.model.eppoutput.Result.Code;
|
||||
@@ -25,30 +25,23 @@ import google.registry.util.Clock;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** A value class for recording attributes of an EPP metric. */
|
||||
@AutoValue
|
||||
public abstract class EppMetric {
|
||||
/** A record for recording attributes of an EPP metric. */
|
||||
public record EppMetric(
|
||||
DateTime startTimestamp,
|
||||
DateTime endTimestamp,
|
||||
Optional<String> commandName,
|
||||
Optional<String> registrarId,
|
||||
Optional<String> tld,
|
||||
Optional<Code> status) {
|
||||
|
||||
public abstract DateTime getStartTimestamp();
|
||||
|
||||
public abstract DateTime getEndTimestamp();
|
||||
|
||||
public abstract Optional<String> getCommandName();
|
||||
|
||||
public abstract Optional<String> getRegistrarId();
|
||||
|
||||
public abstract Optional<String> getTld();
|
||||
|
||||
public abstract Optional<Code> getStatus();
|
||||
|
||||
/** Create an {@link EppMetric.Builder}. */
|
||||
/** Create an {@link Builder}. */
|
||||
public static Builder builder() {
|
||||
return new AutoValue_EppMetric.Builder();
|
||||
return new AutoBuilder_EppMetric_Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@link EppMetric.Builder} for a request context, with the given request ID and
|
||||
* with start and end timestamps taken from the given clock.
|
||||
* Create an {@link Builder} for a request context, with the given request ID and with start and
|
||||
* end timestamps taken from the given clock.
|
||||
*
|
||||
* <p>The start timestamp is recorded now, and the end timestamp at {@code build()}.
|
||||
*/
|
||||
@@ -58,8 +51,32 @@ public abstract class EppMetric {
|
||||
.setClock(clock);
|
||||
}
|
||||
|
||||
public DateTime getStartTimestamp() {
|
||||
return startTimestamp;
|
||||
}
|
||||
|
||||
public DateTime getEndTimestamp() {
|
||||
return endTimestamp;
|
||||
}
|
||||
|
||||
public Optional<String> getCommandName() {
|
||||
return commandName;
|
||||
}
|
||||
|
||||
public Optional<String> getRegistrarId() {
|
||||
return registrarId;
|
||||
}
|
||||
|
||||
public Optional<String> getTld() {
|
||||
return tld;
|
||||
}
|
||||
|
||||
public Optional<Code> getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/** A builder to create instances of {@link EppMetric}. */
|
||||
@AutoValue.Builder
|
||||
@AutoBuilder
|
||||
public abstract static class Builder {
|
||||
|
||||
/** Builder-only clock to support automatic recording of endTimestamp on {@link #build()}. */
|
||||
@@ -97,18 +114,14 @@ public abstract class EppMetric {
|
||||
*/
|
||||
public Builder setTlds(ImmutableSet<String> tlds) {
|
||||
switch (tlds.size()) {
|
||||
case 0:
|
||||
setTld(Optional.empty());
|
||||
break;
|
||||
case 1:
|
||||
case 0 -> setTld(Optional.empty());
|
||||
case 1 -> {
|
||||
String tld = Iterables.getOnlyElement(tlds);
|
||||
// Only record TLDs that actually exist, otherwise we can blow up cardinality by recording
|
||||
// an arbitrarily large number of strings.
|
||||
setTld(Optional.ofNullable(Tlds.getTlds().contains(tld) ? tld : "_invalid"));
|
||||
break;
|
||||
default:
|
||||
setTld("_various");
|
||||
break;
|
||||
}
|
||||
default -> setTld("_various");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ public class IntervalDescriptor extends AbstractTypeDescriptor<PGInterval>
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>(javaTypeDescriptor, this) {
|
||||
return new BasicBinder<>(javaTypeDescriptor, this) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
@@ -117,7 +117,7 @@ public class IntervalDescriptor extends AbstractTypeDescriptor<PGInterval>
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicExtractor<X>(javaTypeDescriptor, this) {
|
||||
return new BasicExtractor<>(javaTypeDescriptor, this) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap(rs.getObject(name), options);
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.persistence.converter;
|
||||
|
||||
import google.registry.model.registrar.RegistrarPoc.Type;
|
||||
import google.registry.model.registrar.RegistrarPocBase.Type;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Converter;
|
||||
|
||||
|
||||
+3
-4
@@ -115,7 +115,7 @@ public class StringCollectionDescriptor extends AbstractTypeDescriptor<StringCol
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>(javaTypeDescriptor, this) {
|
||||
return new BasicBinder<>(javaTypeDescriptor, this) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
@@ -123,8 +123,7 @@ public class StringCollectionDescriptor extends AbstractTypeDescriptor<StringCol
|
||||
st.setArray(index, null);
|
||||
return;
|
||||
}
|
||||
if (value instanceof StringCollection) {
|
||||
StringCollection stringCollection = (StringCollection) value;
|
||||
if (value instanceof StringCollection stringCollection) {
|
||||
if (stringCollection.getCollection() == null) {
|
||||
st.setArray(index, null);
|
||||
} else {
|
||||
@@ -154,7 +153,7 @@ public class StringCollectionDescriptor extends AbstractTypeDescriptor<StringCol
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicExtractor<X>(javaTypeDescriptor, this) {
|
||||
return new BasicExtractor<>(javaTypeDescriptor, this) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap(rs.getArray(name), options);
|
||||
|
||||
@@ -105,7 +105,7 @@ public class StringMapDescriptor extends AbstractTypeDescriptor<StringMap>
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>(javaTypeDescriptor, this) {
|
||||
return new BasicBinder<>(javaTypeDescriptor, this) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
@@ -136,7 +136,7 @@ public class StringMapDescriptor extends AbstractTypeDescriptor<StringMap>
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicExtractor<X>(javaTypeDescriptor, this) {
|
||||
return new BasicExtractor<>(javaTypeDescriptor, this) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap(rs.getObject(name), options);
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
package google.registry.persistence.transaction;
|
||||
|
||||
import autovalue.shaded.com.google.common.collect.ImmutableList;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.PersistenceException;
|
||||
@@ -78,8 +78,7 @@ public class DatabaseException extends PersistenceException {
|
||||
static String getSqlError(Throwable t) {
|
||||
ImmutableList.Builder<String> errMessageBuilder = new ImmutableList.Builder<>();
|
||||
do {
|
||||
if (t instanceof SQLException) {
|
||||
SQLException e = (SQLException) t;
|
||||
if (t instanceof SQLException e) {
|
||||
getSqlExceptionDetails(e).ifPresent(errMessageBuilder::add);
|
||||
}
|
||||
t = t.getCause();
|
||||
|
||||
+1
-9
@@ -544,15 +544,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
||||
return emf.getMetamodel().entity(clazz);
|
||||
}
|
||||
|
||||
private static class EntityId {
|
||||
private final String name;
|
||||
private final Object value;
|
||||
|
||||
private EntityId(String name, Object value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
private record EntityId(String name, Object value) {}
|
||||
|
||||
private static ImmutableSet<EntityId> getEntityIdsFromEntity(
|
||||
EntityType<?> entityType, Object entity) {
|
||||
|
||||
+3
-11
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.privileges.secretmanager;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.cloud.secretmanager.v1.SecretVersion;
|
||||
import com.google.common.collect.Streams;
|
||||
import java.util.Optional;
|
||||
@@ -116,18 +115,11 @@ public interface SecretManagerClient {
|
||||
void deleteSecret(String secretId);
|
||||
|
||||
/** Contains the {@link SecretVersion.State State} of an secret version. */
|
||||
@AutoValue
|
||||
abstract class SecretVersionState {
|
||||
record SecretVersionState(String secretId, String version, SecretVersion.State state) {
|
||||
|
||||
public abstract String secretId();
|
||||
|
||||
public abstract String version();
|
||||
|
||||
public abstract SecretVersion.State state();
|
||||
|
||||
public static SecretVersionState of(
|
||||
public static SecretVersionState create(
|
||||
String secretId, String version, SecretVersion.State state) {
|
||||
return new AutoValue_SecretManagerClient_SecretVersionState(secretId, version, state);
|
||||
return new SecretVersionState(secretId, version, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-7
@@ -94,7 +94,7 @@ public class SecretManagerClientImpl implements SecretManagerClient {
|
||||
|
||||
private static SecretVersionState toSecretVersionState(SecretVersion secretVersion) {
|
||||
SecretVersionName name = SecretVersionName.parse(secretVersion.getName());
|
||||
return SecretVersionState.of(
|
||||
return SecretVersionState.create(
|
||||
name.getSecret(), name.getSecretVersion(), secretVersion.getState());
|
||||
}
|
||||
|
||||
@@ -165,12 +165,9 @@ public class SecretManagerClientImpl implements SecretManagerClient {
|
||||
return retrier.callWithRetry(callable, SecretManagerClientImpl::isRetryableException);
|
||||
} catch (ApiException e) {
|
||||
switch (e.getStatusCode().getCode()) {
|
||||
case ALREADY_EXISTS:
|
||||
throw new SecretAlreadyExistsException(e);
|
||||
case NOT_FOUND:
|
||||
throw new NoSuchSecretResourceException(e);
|
||||
default:
|
||||
throw new SecretManagerException(e);
|
||||
case ALREADY_EXISTS -> throw new SecretAlreadyExistsException(e);
|
||||
case NOT_FOUND -> throw new NoSuchSecretResourceException(e);
|
||||
default -> throw new SecretManagerException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,8 @@
|
||||
|
||||
package google.registry.privileges.secretmanager;
|
||||
|
||||
import static avro.shaded.com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -24,32 +23,27 @@ import java.util.List;
|
||||
*
|
||||
* <p>User must take care not to include the {@link #SEPARATOR} in property values.
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class SqlCredential {
|
||||
public record SqlCredential(String login, String password) {
|
||||
|
||||
public static final Character SEPARATOR = ' ';
|
||||
|
||||
public abstract String login();
|
||||
|
||||
public abstract String password();
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
// Use Object.toString(), which does not show object data.
|
||||
return super.toString();
|
||||
public String toString() {
|
||||
// Use the Object.toString() implementation, which does not show the sensitive date in fields.
|
||||
return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode());
|
||||
}
|
||||
|
||||
public final String toFormattedString() {
|
||||
public String toFormattedString() {
|
||||
return String.format("%s%c%s", login(), SEPARATOR, password());
|
||||
}
|
||||
|
||||
public static SqlCredential fromFormattedString(String sqlCredential) {
|
||||
List<String> items = com.google.common.base.Splitter.on(SEPARATOR).splitToList(sqlCredential);
|
||||
checkState(items.size() == 2, "Invalid SqlCredential string.");
|
||||
return of(items.get(0), items.get(1));
|
||||
return create(items.get(0), items.get(1));
|
||||
}
|
||||
|
||||
public static SqlCredential of(String login, String password) {
|
||||
return new AutoValue_SqlCredential(login, password);
|
||||
public static SqlCredential create(String login, String password) {
|
||||
return new SqlCredential(login, password);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public class SqlCredentialStore {
|
||||
String credentialVersion =
|
||||
csmClient.addSecretVersion(
|
||||
credentialDataSecretId,
|
||||
SqlCredential.of(createDatabaseLoginName(user), password).toFormattedString());
|
||||
SqlCredential.create(createDatabaseLoginName(user), password).toFormattedString());
|
||||
return SecretVersionName.of(csmClient.getProject(), credentialDataSecretId, credentialVersion);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,18 +52,13 @@ import org.joda.time.DateTime;
|
||||
*
|
||||
* <p>This implementation is geared towards RDAP replies, and hence has RDAP-specific quirks.
|
||||
* Specifically:
|
||||
*
|
||||
* - Fields with empty arrays are not shown at all
|
||||
*
|
||||
* - VCards are a built-in special case (Not implemented yet)
|
||||
*
|
||||
* - DateTime conversion is specifically supported as if it were a primitive
|
||||
*
|
||||
* - Arrays are considered to be SETS rather than lists, meaning repeated values are removed and the
|
||||
* order isn't guaranteed
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* {@link JsonableElement}
|
||||
* -----------------------
|
||||
*
|
||||
@@ -324,8 +319,7 @@ abstract class AbstractJsonableObject implements Jsonable {
|
||||
|
||||
/** Converts an Object to a JsonElement. */
|
||||
private static JsonElement toJsonElement(String name, Member member, Object object) {
|
||||
if (object instanceof Jsonable) {
|
||||
Jsonable jsonable = (Jsonable) object;
|
||||
if (object instanceof Jsonable jsonable) {
|
||||
verifyAllowedJsonKeyName(name, member, jsonable.getClass());
|
||||
return jsonable.toJson();
|
||||
}
|
||||
@@ -414,8 +408,7 @@ abstract class AbstractJsonableObject implements Jsonable {
|
||||
object, "Member '%s' is null. If you want an optional member - use Optional", member);
|
||||
|
||||
// We ignore any Optional that are empty, as if they didn't exist at all
|
||||
if (object instanceof Optional) {
|
||||
Optional<?> optional = (Optional<?>) object;
|
||||
if (object instanceof Optional<?> optional) {
|
||||
if (optional.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -14,13 +14,16 @@
|
||||
|
||||
package google.registry.rdap;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.ImmutableObject;
|
||||
|
||||
/** Authorization information for RDAP data access. */
|
||||
@AutoValue
|
||||
public abstract class RdapAuthorization extends ImmutableObject {
|
||||
/**
|
||||
* Authorization information for RDAP data access.
|
||||
*
|
||||
* @param role The role to be used for access.
|
||||
* @param registrarIds The registrar client IDs for which access is granted (used only if the role
|
||||
* is REGISTRAR.
|
||||
*/
|
||||
public record RdapAuthorization(Role role, ImmutableSet<String> registrarIds) {
|
||||
|
||||
enum Role {
|
||||
ADMINISTRATOR,
|
||||
@@ -28,29 +31,20 @@ public abstract class RdapAuthorization extends ImmutableObject {
|
||||
PUBLIC
|
||||
}
|
||||
|
||||
/** The role to be used for access. */
|
||||
public abstract Role role();
|
||||
|
||||
/** The registrar client IDs for which access is granted (used only if the role is REGISTRAR. */
|
||||
public abstract ImmutableSet<String> registrarIds();
|
||||
|
||||
static RdapAuthorization create(Role role, String registrarId) {
|
||||
return new AutoValue_RdapAuthorization(role, ImmutableSet.of(registrarId));
|
||||
return create(role, ImmutableSet.of(registrarId));
|
||||
}
|
||||
|
||||
static RdapAuthorization create(Role role, ImmutableSet<String> clientIds) {
|
||||
return new AutoValue_RdapAuthorization(role, clientIds);
|
||||
return new RdapAuthorization(role, clientIds);
|
||||
}
|
||||
|
||||
boolean isAuthorizedForRegistrar(String registrarId) {
|
||||
switch (role()) {
|
||||
case ADMINISTRATOR:
|
||||
return true;
|
||||
case REGISTRAR:
|
||||
return registrarIds().contains(registrarId);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return switch (role()) {
|
||||
case ADMINISTRATOR -> true;
|
||||
case REGISTRAR -> registrarIds().contains(registrarId);
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
public static final RdapAuthorization PUBLIC_AUTHORIZATION =
|
||||
|
||||
@@ -79,7 +79,7 @@ public class RdapIcannStandardInformation {
|
||||
/**
|
||||
* Required by ICANN RDAP Profile section 1.4.9, as corrected by Gustavo Lozano of ICANN.
|
||||
*
|
||||
* Also mentioned in the RDAP Technical Implementation Guide 3.6.
|
||||
* <p>Also mentioned in the RDAP Technical Implementation Guide 3.6.
|
||||
*
|
||||
* @see <a href="http://mm.icann.org/pipermail/gtld-tech/2016-October/000822.html">Questions about
|
||||
* the ICANN RDAP Profile</a>
|
||||
@@ -95,7 +95,7 @@ public class RdapIcannStandardInformation {
|
||||
/**
|
||||
* Required by ICANN RDAP Profile section 1.4.8, as corrected by Gustavo Lozano of ICANN.
|
||||
*
|
||||
* Also mentioned in the RDAP Technical Implementation Guide 3.5.
|
||||
* <p>Also mentioned in the RDAP Technical Implementation Guide 3.5.
|
||||
*
|
||||
* @see <a href="http://mm.icann.org/pipermail/gtld-tech/2016-October/000822.html">Questions about
|
||||
* the ICANN RDAP Profile</a>
|
||||
|
||||
@@ -808,17 +808,12 @@ public class RdapJsonFormatter {
|
||||
|
||||
/** Converts a domain registry contact type into a role as defined by RFC 9083. */
|
||||
private static RdapEntity.Role convertContactTypeToRdapRole(DesignatedContact.Type contactType) {
|
||||
switch (contactType) {
|
||||
case REGISTRANT:
|
||||
return RdapEntity.Role.REGISTRANT;
|
||||
case TECH:
|
||||
return RdapEntity.Role.TECH;
|
||||
case BILLING:
|
||||
return RdapEntity.Role.BILLING;
|
||||
case ADMIN:
|
||||
return RdapEntity.Role.ADMIN;
|
||||
}
|
||||
throw new AssertionError();
|
||||
return switch (contactType) {
|
||||
case REGISTRANT -> RdapEntity.Role.REGISTRANT;
|
||||
case TECH -> RdapEntity.Role.TECH;
|
||||
case BILLING -> RdapEntity.Role.BILLING;
|
||||
case ADMIN -> RdapEntity.Role.ADMIN;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.rdap;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.auto.value.AutoBuilder;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.monitoring.metrics.DistributionFitter;
|
||||
@@ -102,10 +102,7 @@ public class RdapMetrics {
|
||||
static final IncrementableMetric requests =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newIncrementableMetric(
|
||||
"/rdap/requests",
|
||||
"Count of RDAP Requests",
|
||||
"count",
|
||||
LABEL_DESCRIPTORS_FOR_REQUESTS);
|
||||
"/rdap/requests", "Count of RDAP Requests", "count", LABEL_DESCRIPTORS_FOR_REQUESTS);
|
||||
|
||||
@VisibleForTesting
|
||||
static final IncrementableMetric responses =
|
||||
@@ -163,8 +160,7 @@ public class RdapMetrics {
|
||||
* ways of looking at the data, since cardinality constraints prevent us from saving all the
|
||||
* information in a single metric.
|
||||
*/
|
||||
public void updateMetrics(
|
||||
RdapMetricInformation rdapMetricInformation) {
|
||||
public void updateMetrics(RdapMetricInformation rdapMetricInformation) {
|
||||
requests.increment(
|
||||
rdapMetricInformation.endpointType().toString(),
|
||||
rdapMetricInformation.includeDeleted() ? "YES" : "NO",
|
||||
@@ -206,95 +202,76 @@ public class RdapMetrics {
|
||||
}
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
abstract static class RdapMetricInformation {
|
||||
/**
|
||||
* Information on RDAP metrics.
|
||||
*
|
||||
* @param endpointType The type of RDAP endpoint (domain, domains, nameserver, etc.).
|
||||
* @param searchType The search type (by domain name, by nameserver name, etc.).
|
||||
* @param wildcardType The type of wildcarding requested (prefix, suffix, etc.).
|
||||
* @param prefixLength The length of the prefix string before the wildcard, if any; any length
|
||||
* longer than MAX_RECORDED_PREFIX_LENGTH is limited to MAX_RECORDED_PREFIX_LENGTH when
|
||||
* recording the metric, to avoid cardinality problems.
|
||||
* @param includeDeleted Whether the search included deleted records.
|
||||
* @param registrarSpecified Whether the search requested a specific registrar.
|
||||
* @param role Type of authentication/authorization: public, admin or registrar.
|
||||
* @param requestMethod Http request method (GET, POST, HEAD, etc.).
|
||||
* @param statusCode Http status code.
|
||||
* @param incompletenessWarningType Incompleteness warning type (e.g. truncated).
|
||||
* @param numDomainsRetrieved Number of domains retrieved from the database; this might be more
|
||||
* than were actually returned in the response; absent if a search was not performed.
|
||||
* @param numHostsRetrieved Number of hosts retrieved from the database; this might be more than
|
||||
* were actually returned in the response; absent if a search was not performed.
|
||||
* @param numContactsRetrieved Number of contacts retrieved from the database; this might be more
|
||||
* than were actually returned in the response; absent if a search was not performed.
|
||||
*/
|
||||
record RdapMetricInformation(
|
||||
EndpointType endpointType,
|
||||
SearchType searchType,
|
||||
WildcardType wildcardType,
|
||||
int prefixLength,
|
||||
boolean includeDeleted,
|
||||
boolean registrarSpecified,
|
||||
RdapAuthorization.Role role,
|
||||
Action.Method requestMethod,
|
||||
int statusCode,
|
||||
IncompletenessWarningType incompletenessWarningType,
|
||||
Optional<Long> numDomainsRetrieved,
|
||||
Optional<Long> numHostsRetrieved,
|
||||
Optional<Long> numContactsRetrieved) {
|
||||
|
||||
/** The type of RDAP endpoint (domain, domains, nameserver, etc.). */
|
||||
abstract EndpointType endpointType();
|
||||
@AutoBuilder
|
||||
interface Builder {
|
||||
Builder setEndpointType(EndpointType endpointType);
|
||||
|
||||
/** The search type (by domain name, by nameserver name, etc.). */
|
||||
abstract SearchType searchType();
|
||||
Builder setSearchType(SearchType searchType);
|
||||
|
||||
/** The type of wildcarding requested (prefix, suffix, etc.). */
|
||||
abstract WildcardType wildcardType();
|
||||
Builder setWildcardType(WildcardType wildcardType);
|
||||
|
||||
/**
|
||||
* The length of the prefix string before the wildcard, if any; any length longer than
|
||||
* MAX_RECORDED_PREFIX_LENGTH is limited to MAX_RECORDED_PREFIX_LENGTH when recording the
|
||||
* metric, to avoid cardinality problems.
|
||||
*/
|
||||
abstract int prefixLength();
|
||||
Builder setPrefixLength(int prefixLength);
|
||||
|
||||
/** Whether the search included deleted records. */
|
||||
abstract boolean includeDeleted();
|
||||
Builder setIncludeDeleted(boolean includeDeleted);
|
||||
|
||||
/** Whether the search requested a specific registrar. */
|
||||
abstract boolean registrarSpecified();
|
||||
Builder setRegistrarSpecified(boolean registrarSpecified);
|
||||
|
||||
/** Type of authentication/authorization: public, admin or registrar. */
|
||||
abstract RdapAuthorization.Role role();
|
||||
Builder setRole(RdapAuthorization.Role role);
|
||||
|
||||
/** Http request method (GET, POST, HEAD, etc.). */
|
||||
abstract Action.Method requestMethod();
|
||||
Builder setRequestMethod(Action.Method requestMethod);
|
||||
|
||||
/** Http status code. */
|
||||
abstract int statusCode();
|
||||
Builder setStatusCode(int statusCode);
|
||||
|
||||
/** Incompleteness warning type (e.g. truncated). */
|
||||
abstract IncompletenessWarningType incompletenessWarningType();
|
||||
Builder setIncompletenessWarningType(IncompletenessWarningType incompletenessWarningType);
|
||||
|
||||
/**
|
||||
* Number of domains retrieved from the database; this might be more than were actually returned
|
||||
* in the response; absent if a search was not performed.
|
||||
*/
|
||||
abstract Optional<Long> numDomainsRetrieved();
|
||||
Builder setNumDomainsRetrieved(long numDomainsRetrieved);
|
||||
|
||||
/**
|
||||
* Number of hosts retrieved from the database; this might be more than were actually returned
|
||||
* in the response; absent if a search was not performed.
|
||||
*/
|
||||
abstract Optional<Long> numHostsRetrieved();
|
||||
Builder setNumHostsRetrieved(long numHostsRetrieved);
|
||||
|
||||
/**
|
||||
* Number of contacts retrieved from the database; this might be more than were actually
|
||||
* returned in the response; absent if a search was not performed.
|
||||
*/
|
||||
abstract Optional<Long> numContactsRetrieved();
|
||||
Builder setNumContactsRetrieved(long numContactRetrieved);
|
||||
|
||||
@AutoValue.Builder
|
||||
abstract static class Builder {
|
||||
abstract Builder setEndpointType(EndpointType endpointType);
|
||||
|
||||
abstract Builder setSearchType(SearchType searchType);
|
||||
|
||||
abstract Builder setWildcardType(WildcardType wildcardType);
|
||||
|
||||
abstract Builder setPrefixLength(int prefixLength);
|
||||
|
||||
abstract Builder setIncludeDeleted(boolean includeDeleted);
|
||||
|
||||
abstract Builder setRegistrarSpecified(boolean registrarSpecified);
|
||||
|
||||
abstract Builder setRole(RdapAuthorization.Role role);
|
||||
|
||||
abstract Builder setRequestMethod(Action.Method requestMethod);
|
||||
|
||||
abstract Builder setStatusCode(int statusCode);
|
||||
|
||||
abstract Builder setIncompletenessWarningType(
|
||||
IncompletenessWarningType incompletenessWarningType);
|
||||
|
||||
abstract Builder setNumDomainsRetrieved(long numDomainsRetrieved);
|
||||
|
||||
abstract Builder setNumHostsRetrieved(long numHostsRetrieved);
|
||||
|
||||
abstract Builder setNumContactsRetrieved(long numContactRetrieved);
|
||||
|
||||
abstract RdapMetricInformation build();
|
||||
RdapMetricInformation build();
|
||||
}
|
||||
|
||||
static Builder builder() {
|
||||
return new AutoValue_RdapMetrics_RdapMetricInformation.Builder()
|
||||
return new AutoBuilder_RdapMetrics_RdapMetricInformation_Builder()
|
||||
.setSearchType(SearchType.NONE)
|
||||
.setWildcardType(WildcardType.INVALID)
|
||||
.setPrefixLength(0)
|
||||
|
||||
@@ -47,7 +47,7 @@ final class RdapObjectClasses {
|
||||
/**
|
||||
* Temporary implementation of VCards.
|
||||
*
|
||||
* Will create a better implementation soon.
|
||||
* <p>Will create a better implementation soon.
|
||||
*/
|
||||
@RestrictJsonNames({})
|
||||
@AutoValue
|
||||
@@ -146,7 +146,7 @@ final class RdapObjectClasses {
|
||||
/**
|
||||
* An object that can be used to create a TopLevelReply.
|
||||
*
|
||||
* All Actions need to return an object of this type.
|
||||
* <p>All Actions need to return an object of this type.
|
||||
*/
|
||||
abstract static class ReplyPayloadBase extends AbstractJsonableObject {
|
||||
final BoilerplateType boilerplateType;
|
||||
@@ -173,15 +173,14 @@ final class RdapObjectClasses {
|
||||
@JsonableElement("notices[]") abstract Notice aTosNotice();
|
||||
|
||||
@JsonableElement("notices") ImmutableList<Notice> boilerplateNotices() {
|
||||
switch (aAreplyObject().boilerplateType) {
|
||||
case DOMAIN:
|
||||
return RdapIcannStandardInformation.domainBoilerplateNotices;
|
||||
case NAMESERVER:
|
||||
case ENTITY:
|
||||
return RdapIcannStandardInformation.nameserverAndEntityBoilerplateNotices;
|
||||
default: // things other than domains, nameservers and entities do not yet have boilerplate
|
||||
return ImmutableList.of();
|
||||
}
|
||||
return switch (aAreplyObject().boilerplateType) {
|
||||
case DOMAIN -> RdapIcannStandardInformation.domainBoilerplateNotices;
|
||||
case NAMESERVER, ENTITY ->
|
||||
RdapIcannStandardInformation.nameserverAndEntityBoilerplateNotices;
|
||||
default -> // things other than domains, nameservers and entities do not yet have
|
||||
// boilerplate
|
||||
ImmutableList.of();
|
||||
};
|
||||
}
|
||||
|
||||
static TopLevelReplyObject create(ReplyPayloadBase replyObject, Notice tosNotice) {
|
||||
|
||||
@@ -14,14 +14,23 @@
|
||||
|
||||
package google.registry.rdap;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.rdap.RdapSearchResults.IncompletenessWarningType;
|
||||
import java.util.List;
|
||||
|
||||
@AutoValue
|
||||
abstract class RdapResultSet<T extends EppResource> {
|
||||
/**
|
||||
* RDAP result set.
|
||||
*
|
||||
* @param resources List of EPP resources.
|
||||
* @param incompletenessWarningType Type of warning to display regarding possible incomplete data.
|
||||
* @param numResourcesRetrieved Number of resources retrieved from the database in the process of
|
||||
* assembling the data set.
|
||||
*/
|
||||
record RdapResultSet<T extends EppResource>(
|
||||
ImmutableList<T> resources,
|
||||
IncompletenessWarningType incompletenessWarningType,
|
||||
int numResourcesRetrieved) {
|
||||
|
||||
static <S extends EppResource> RdapResultSet<S> create(List<S> resources) {
|
||||
return create(resources, IncompletenessWarningType.COMPLETE, resources.size());
|
||||
@@ -31,16 +40,7 @@ abstract class RdapResultSet<T extends EppResource> {
|
||||
List<S> resources,
|
||||
IncompletenessWarningType incompletenessWarningType,
|
||||
int numResourcesRetrieved) {
|
||||
return new AutoValue_RdapResultSet<>(
|
||||
return new RdapResultSet<>(
|
||||
ImmutableList.copyOf(resources), incompletenessWarningType, numResourcesRetrieved);
|
||||
}
|
||||
|
||||
/** List of EPP resources. */
|
||||
abstract ImmutableList<T> resources();
|
||||
|
||||
/** Type of warning to display regarding possible incomplete data. */
|
||||
abstract IncompletenessWarningType incompletenessWarningType();
|
||||
|
||||
/** Number of resources retrieved from the database in the process of assembling the data set. */
|
||||
abstract int numResourcesRetrieved();
|
||||
}
|
||||
|
||||
@@ -14,22 +14,16 @@
|
||||
|
||||
package google.registry.rde;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/** Container of RDE resource marshalled by {@link RdeMarshaller}. */
|
||||
@AutoValue
|
||||
public abstract class DepositFragment implements Serializable {
|
||||
public record DepositFragment(RdeResourceType type, String xml, String error)
|
||||
implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -5241410684255467454L;
|
||||
|
||||
public abstract RdeResourceType type();
|
||||
public abstract String xml();
|
||||
public abstract String error();
|
||||
@Serial private static final long serialVersionUID = -5241410684255467454L;
|
||||
|
||||
public static DepositFragment create(RdeResourceType type, String xml, String error) {
|
||||
return new AutoValue_DepositFragment(type, xml, error);
|
||||
return new DepositFragment(type, xml, error);
|
||||
}
|
||||
|
||||
DepositFragment() {}
|
||||
}
|
||||
|
||||
@@ -14,17 +14,13 @@
|
||||
|
||||
package google.registry.rde;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import google.registry.model.common.Cursor.CursorType;
|
||||
import google.registry.model.rde.RdeMode;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -46,52 +42,46 @@ import org.joda.time.Duration;
|
||||
* arguments (see {@code RdePipeline#decodePendingDeposits}). The latter requires safe
|
||||
* deserialization because the data crosses credential boundaries (See {@code
|
||||
* SafeObjectInputStream}).
|
||||
*
|
||||
* @param manual True if deposits should be generated via manual operation, which does not update
|
||||
* the cursor, and saves the generated deposits in a special manual subdirectory tree.
|
||||
* @param tld TLD for which a deposit should be generated.
|
||||
* @param watermarkStr String representation of the watermark date for which a deposit should be
|
||||
* generated.
|
||||
* @param mode Which type of deposit to generate: full (RDE) or thin (BRDA).
|
||||
* @param cursor The cursor type to update (not used in manual operation).
|
||||
* @param intervalStr String representation of the amount of time to increment the cursor (not used
|
||||
* in manual operation).
|
||||
* @param directoryWithTrailingSlash Subdirectory of bucket/manual in which files should be placed,
|
||||
* including a trailing slash (used only in manual operation).
|
||||
* @param revision Revision number for generated files; if absent, use the next available in the
|
||||
* sequence (used only in manual operation).
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class PendingDeposit implements Serializable {
|
||||
public record PendingDeposit(
|
||||
boolean manual,
|
||||
String tld,
|
||||
String watermarkStr,
|
||||
RdeMode mode,
|
||||
@Nullable CursorType cursor,
|
||||
@Nullable String intervalStr,
|
||||
@Nullable String directoryWithTrailingSlash,
|
||||
@Nullable Integer revision)
|
||||
implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3141095605225904433L;
|
||||
public DateTime watermark() {
|
||||
return DateTime.parse(watermarkStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* True if deposits should be generated via manual operation, which does not update the cursor,
|
||||
* and saves the generated deposits in a special manual subdirectory tree.
|
||||
*/
|
||||
public abstract boolean manual();
|
||||
public Duration interval() {
|
||||
return intervalStr == null ? null : Duration.parse(intervalStr);
|
||||
}
|
||||
|
||||
/** TLD for which a deposit should be generated. */
|
||||
public abstract String tld();
|
||||
|
||||
/** Watermark date for which a deposit should be generated. */
|
||||
public abstract DateTime watermark();
|
||||
|
||||
/** Which type of deposit to generate: full (RDE) or thin (BRDA). */
|
||||
public abstract RdeMode mode();
|
||||
|
||||
/** The cursor type to update (not used in manual operation). */
|
||||
@Nullable
|
||||
public abstract CursorType cursor();
|
||||
|
||||
/** Amount of time to increment the cursor (not used in manual operation). */
|
||||
@Nullable
|
||||
public abstract Duration interval();
|
||||
|
||||
/**
|
||||
* Subdirectory of bucket/manual in which files should be placed, including a trailing slash (used
|
||||
* only in manual operation).
|
||||
*/
|
||||
@Nullable
|
||||
public abstract String directoryWithTrailingSlash();
|
||||
|
||||
/**
|
||||
* Revision number for generated files; if absent, use the next available in the sequence (used
|
||||
* only in manual operation).
|
||||
*/
|
||||
@Nullable
|
||||
public abstract Integer revision();
|
||||
@Serial private static final long serialVersionUID = 3141095605225904433L;
|
||||
|
||||
public static PendingDeposit create(
|
||||
String tld, DateTime watermark, RdeMode mode, CursorType cursor, Duration interval) {
|
||||
return new AutoValue_PendingDeposit(false, tld, watermark, mode, cursor, interval, null, null);
|
||||
return new PendingDeposit(
|
||||
false, tld, watermark.toString(), mode, cursor, interval.toString(), null, null);
|
||||
}
|
||||
|
||||
public static PendingDeposit createInManualOperation(
|
||||
@@ -100,58 +90,8 @@ public abstract class PendingDeposit implements Serializable {
|
||||
RdeMode mode,
|
||||
String directoryWithTrailingSlash,
|
||||
@Nullable Integer revision) {
|
||||
return new AutoValue_PendingDeposit(
|
||||
true, tld, watermark, mode, null, null, directoryWithTrailingSlash, revision);
|
||||
}
|
||||
|
||||
PendingDeposit() {}
|
||||
|
||||
/**
|
||||
* Specifies that {@link SerializedForm} be used for {@code SafeObjectInputStream}-compatible
|
||||
* custom-serialization of {@link AutoValue_PendingDeposit the AutoValue implementation class}.
|
||||
*
|
||||
* <p>This method is package-protected so that the AutoValue implementation class inherits this
|
||||
* behavior.
|
||||
*
|
||||
* <p>This method leverages {@link PendingDepositCoder} to serializes an instance. However, it is
|
||||
* not invoked in Beam pipelines.
|
||||
*/
|
||||
Object writeReplace() throws ObjectStreamException {
|
||||
return new SerializedForm(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy for custom-serialization of {@link PendingDeposit}. This is necessary because the actual
|
||||
* class to be (de)serialized is the generated AutoValue implementation. See also {@link
|
||||
* #writeReplace}.
|
||||
*
|
||||
* <p>This class leverages {@link PendingDepositCoder} to safely deserializes an instance.
|
||||
* However, it is not used in Beam pipelines.
|
||||
*/
|
||||
private static class SerializedForm implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3141095605225904433L;
|
||||
|
||||
private PendingDeposit value;
|
||||
|
||||
private SerializedForm(PendingDeposit value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream os) throws IOException {
|
||||
checkState(value != null, "Non-null value expected for serialization.");
|
||||
PendingDepositCoder.INSTANCE.encode(value, os);
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {
|
||||
checkState(value == null, "Non-null value unexpected for deserialization.");
|
||||
this.value = PendingDepositCoder.INSTANCE.decode(is);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return this.value;
|
||||
}
|
||||
return new PendingDeposit(
|
||||
true, tld, watermark.toString(), mode, null, null, directoryWithTrailingSlash, revision);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,32 +118,27 @@ public abstract class PendingDeposit implements Serializable {
|
||||
public void encode(PendingDeposit value, OutputStream outStream) throws IOException {
|
||||
BooleanCoder.of().encode(value.manual(), outStream);
|
||||
StringUtf8Coder.of().encode(value.tld(), outStream);
|
||||
StringUtf8Coder.of().encode(value.watermark().toString(), outStream);
|
||||
StringUtf8Coder.of().encode(value.watermarkStr(), outStream);
|
||||
StringUtf8Coder.of().encode(value.mode().name(), outStream);
|
||||
NullableCoder.of(StringUtf8Coder.of())
|
||||
.encode(
|
||||
Optional.ofNullable(value.cursor()).map(CursorType::name).orElse(null), outStream);
|
||||
NullableCoder.of(StringUtf8Coder.of())
|
||||
.encode(
|
||||
Optional.ofNullable(value.interval()).map(Duration::toString).orElse(null),
|
||||
outStream);
|
||||
NullableCoder.of(StringUtf8Coder.of()).encode(value.intervalStr(), outStream);
|
||||
NullableCoder.of(StringUtf8Coder.of()).encode(value.directoryWithTrailingSlash(), outStream);
|
||||
NullableCoder.of(VarIntCoder.of()).encode(value.revision(), outStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingDeposit decode(InputStream inStream) throws IOException {
|
||||
return new AutoValue_PendingDeposit(
|
||||
return new PendingDeposit(
|
||||
BooleanCoder.of().decode(inStream),
|
||||
StringUtf8Coder.of().decode(inStream),
|
||||
DateTime.parse(StringUtf8Coder.of().decode(inStream)),
|
||||
StringUtf8Coder.of().decode(inStream),
|
||||
RdeMode.valueOf(StringUtf8Coder.of().decode(inStream)),
|
||||
Optional.ofNullable(NullableCoder.of(StringUtf8Coder.of()).decode(inStream))
|
||||
.map(CursorType::valueOf)
|
||||
.orElse(null),
|
||||
Optional.ofNullable(NullableCoder.of(StringUtf8Coder.of()).decode(inStream))
|
||||
.map(Duration::parse)
|
||||
.orElse(null),
|
||||
NullableCoder.of(StringUtf8Coder.of()).decode(inStream),
|
||||
NullableCoder.of(StringUtf8Coder.of()).decode(inStream),
|
||||
NullableCoder.of(VarIntCoder.of()).decode(inStream));
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package google.registry.rde;
|
||||
import static google.registry.model.EppResourceUtils.loadAtPointInTime;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
@@ -71,8 +70,7 @@ public class RdeFragmenter {
|
||||
cache.put(WatermarkModePair.create(watermark, RdeMode.FULL), result);
|
||||
cache.put(WatermarkModePair.create(watermark, RdeMode.THIN), result);
|
||||
return result;
|
||||
} else if (resource instanceof Host) {
|
||||
Host host = (Host) resource;
|
||||
} else if (resource instanceof Host host) {
|
||||
result =
|
||||
Optional.of(
|
||||
host.isSubordinate()
|
||||
@@ -96,14 +94,10 @@ public class RdeFragmenter {
|
||||
}
|
||||
|
||||
/** Map key for {@link RdeFragmenter} cache. */
|
||||
@AutoValue
|
||||
abstract static class WatermarkModePair {
|
||||
abstract DateTime watermark();
|
||||
|
||||
abstract RdeMode mode();
|
||||
record WatermarkModePair(DateTime watermark, RdeMode mode) {
|
||||
|
||||
static WatermarkModePair create(DateTime watermark, RdeMode mode) {
|
||||
return new AutoValue_RdeFragmenter_WatermarkModePair(watermark, mode);
|
||||
return new WatermarkModePair(watermark, mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,9 @@ import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.State;
|
||||
import google.registry.model.registrar.RegistrarAddress;
|
||||
import google.registry.model.registrar.RegistrarBase;
|
||||
import google.registry.model.registrar.RegistrarBase.State;
|
||||
import google.registry.xjc.contact.XjcContactE164Type;
|
||||
import google.registry.xjc.rderegistrar.XjcRdeRegistrar;
|
||||
import google.registry.xjc.rderegistrar.XjcRdeRegistrarAddrType;
|
||||
@@ -40,7 +41,7 @@ final class RegistrarToXjcConverter {
|
||||
private static final String UNKNOWN_CC = "US";
|
||||
|
||||
/** A conversion map between internal Registrar states and external RDE states. */
|
||||
private static final ImmutableMap<Registrar.State, XjcRdeRegistrarStatusType>
|
||||
private static final ImmutableMap<RegistrarBase.State, XjcRdeRegistrarStatusType>
|
||||
REGISTRAR_STATUS_CONVERSIONS =
|
||||
ImmutableMap.of(
|
||||
State.ACTIVE, XjcRdeRegistrarStatusType.OK,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user