Compare commits

..
Author SHA1 Message Date
Ben McIlwainandGitHub 1f516e34b6 Add some shortcut flags to update allocation tokens command (#2321) 2024-02-15 23:25:14 +00:00
Ben McIlwainandGitHub 70942c87d1 Change !Optional.isPresent() to Optional.isEmpty() (#2325)
Also uses the new Optional.stream() in one class.

Thank you Java 17!
2024-02-15 17:55:09 +00:00
Lai JiangandGitHub 406059db72 Use standard JVM shutdown hook (#2323)
This removes a dependency on the App Engine SDK. It also looks like
(from the logs at least) that shutdown hooks registered the old  way stopped
working after the runtime is upgraded to Java 17.

Also removed some random leftover dependencies on the App Engine SKD
that are not needed any more.
2024-02-14 21:36:25 +00:00
sarahcaseybotandGitHub abc1a0ef3d Add java changes for createBillingCostTransitions (#2314)
* Add java changes for createBillingCostTransitions

* Add negative cost test

* Remove default value

* remove unused variable

* Add check that create cost and trnasitions map are the same

* inject clock, only use key set when checking for missing fields

* Add test for removing map
2024-02-09 17:08:51 +00:00
Weimin YuandGitHub 7b47ecb1f1 Add REGISTER_BSA allocation type (#2319)
* Add ALLOW_BSA allocation type

Add a new type to allow creation of domains blocked by BSA.
Except for the BSA semantics, the new type behaves exactly
like SINGLE_USE.

* Addressing reviews

* Addressing review
2024-02-08 21:45:13 +00:00
Ben McIlwainandGitHub 469d62703a Fix the test class name for UpdateRecurrenceCommand (#2320)
It looks like the command was renamed at some point to be shorter but then the test class itself was forgotten.
2024-02-08 19:34:18 +00:00
Lai JiangandGitHub 009fda67b7 Do not retry transactions inside Beam (#2318) 2024-02-05 18:40:56 +00:00
sarahcaseybotandGitHub e492936cec Add check for build_environment flag in updateReservedListCommand and updatePremiumListCommand (#2317)
* Add check for build_environment flag in updateReservedListCommand

* Do the same for premium list
2024-02-02 16:43:45 -05:00
Weimin YuandGitHub d1d59c1afd Add a reminder for BEAM at Java version declaration (#2316) 2024-02-02 12:05:10 -05:00
Weimin YuandGitHub 7b786eaf1f Update dataflow java runtime to 17 (#2315) 2024-02-01 15:37:21 -05:00
Pavlo TkachandGitHub 45c5d12743 Add angular signals and computed to the console (#2308) 2024-02-01 14:15:05 -05:00
sarahcaseybotandGitHub 73ab95bd9d Add Cloud Build sync job for reserved and premium lists (#2302)
* Change tld-update to db-object-updater

* rename sync_tlds.sh to sync_db_objects.sh

* Change to configured command name

* Change environment to sandbox explicitly for testing on alpha

* Add remaining object steps and change cloudbuild-tld-sync to cloudbuild-sync-db-objects

* Add build_environment flag

* Change order of command and directory

* Uncomment out reserved list part
2024-01-31 14:50:54 -05:00
Weimin YuandGitHub f85cf57e36 Reduce query batch size for BSA unavailables (#2313)
Query size is borderline too-large for the replica.

At 50000, about 2 out of 30 took more than 30 seconds and were retried.
Lower to 40000 and we will keep monitoring the executions.
2024-01-30 13:18:41 -05:00
Ben McIlwainandGitHub 5e36cf30c3 Don't override existing registrar email address when setting referral email (#2300)
The fallback should only apply on creates, not on updates, otherwise it can
override an existing value for the email address when only the referral email
should be what's updated.

This fixes a bug introduced back in commit in 0ead4f8d9d.

BUG= http://b/322026165
2024-01-30 18:31:54 +01:00
sarahcaseybotandGitHub 829be0777b Add a createBillingCostTransitions column to TLD (#2312) 2024-01-29 18:06:02 -05:00
Lai JiangandGitHub c0ac9bdba4 Compile to Java 17 bytecode (#2304)
Also fix a linter warning.
2024-01-25 18:29:07 -05:00
Weimin YuandGitHub 58ec0f826d Stop saving BSA empty refresh changes (#2307)
* Stop saving BSA empty refresh changes

We thought that as a way to verify the refresh job to be running, browsing
the GCS bucket with empty files is easier than quering the DB or go to GCP
logging dashboard, but there are too many of them to be useful.
2024-01-25 16:02:04 -05:00
Pavlo TkachandGitHub f9e0908022 Replace invoice email attachement with bucket link (#2299) 2024-01-25 14:08:08 -05:00
sarahcaseybotandGitHub b21e1a1935 Add required --build_environment flag to tld-sync Cloud Build job (#2306) 2024-01-25 12:27:05 -05:00
Lai JiangandGitHub 0112b3ae06 Make the formatting tasks work with Java 17 (take 2) (#2305)
We should not assume org.gradle.java.home to exist on kokoro or GCB.
2024-01-25 12:08:30 -05:00
Lai JiangandGitHub a4903c27b9 Make the formatting tasks work with Java 17 (#2301)
TESTED=ran gradle jIFA locally after intentionally mis-formatting a Java
file.
2024-01-24 17:15:13 -05:00
sarahcaseybotandGitHub 2166c28d6d Update to only include changes to check for production required tags (#2273) 2024-01-24 17:12:46 -05:00
Lai JiangandGitHub 891e7c0174 Make Kythe work with Java 17 (#2293)
TESTED=submitted a GCB job locally and it ran successfully.
2024-01-24 13:26:45 -05:00
Ben McIlwainandGitHub 64f5971275 Include a better error message to debug nomulus tool not working (#2275)
Failures to initialize the tool transaction manager seem to often be caused by
stale local credentials.
2024-01-24 13:08:33 -05:00
sarahcaseybotandGitHub 818944317f Add some updates to UpdateReservedListCommand to facilitate internal config presubmits and syncing (#2292)
* Add some updates to UpdateReservedListCommand to facilitate internal config presubmits and syncing

Added a dry-run tag for presubmit tests

Added early exit behavior when there are no new changes to the list

Added a new --build_environment tag to be used to indicate command runs from build tools. This tag was also added to UpdatePremiumListCommand. Once this new tag is deployed, and break glass behavior is added, these commands will be modified to prevent runs on the command line in the production environment unless the --build_environment or --break_glass flag is used.

* Fix capitalization

* Added in commented out production environment check for buildEnv flag
2024-01-23 17:32:33 -05:00
Weimin YuandGitHub ea96ed300f Drop the BsaDomainInUse table (#2298)
Already renamed to BsaUnlockableDomain table.
2024-01-23 17:07:35 -05:00
Weimin YuandGitHub 8415c8bbe4 Fix typo in BsaRefreshAction (#2297) 2024-01-22 16:03:35 -05:00
Lai JiangandGitHub dc48c257b5 Use Java 17 runtime on sandbox and production (#2296)
The blocking issue is fixed in
https://github.com/google/nomulus/pull/2224.

Java 8 support is being deprecated on 2024-01-31 and no further deployment is
possible afterwards without exception:

https://cloud.google.com/appengine/docs/legacy/standard/java/deprecations

We have been using Java 17 on alpha/crash/qa for several months and have
not oberved any other blocking issue other than possible missing email
attachements, which is being mitigated by including a link to the
attachments saved in GCS.
2024-01-22 15:21:17 -05:00
sarahcaseybotandGitHub 2bf3867532 Add an example tld YAML config file (#2295) 2024-01-22 13:32:36 -05:00
170 changed files with 8766 additions and 25452 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '11'
java-version: '17'
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
+38 -15
View File
@@ -211,6 +211,30 @@ allprojects {
options.fork = true
options.forkOptions.executable =
file("${System.env.JAVA_HOME}/bin/javac")
options.compilerArgs = ["--add-exports",
"jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED"]
options.forkOptions.jvmArgs = ["-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED"]
}
}
}
@@ -358,16 +382,11 @@ subprojects {
apply from: "${rootDir.path}/java_common.gradle"
if (!rootProject.enableCrossReferencing.toBoolean()) {
compileJava {
// TODO: Remove this once we migrate off of AppEngine.
options.release = 8
}
compileTestJava {
// TODO: Remove this once we migrate off of AppEngine.
options.release = 8
}
}
// When changing Java version here, be sure to update BEAM Java runtime:
// in core/build.gradle, search for `flex-template-base-image` and update
// the parameter value.
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
project.tasks.test.dependsOn runPresubmits
@@ -479,10 +498,14 @@ def createGetBuildSrcDirectDepsTask(outputFileName) {
rootProject.ext {
invokeJavaDiffFormatScript = { action ->
println("JAVA_HOME=${System.env.JAVA_HOME}")
println("PATH=${System.env.PATH}")
println(ext.execInBash("type java", "${rootDir}"))
println(ext.execInBash("java -version", "${rootDir}"))
def javaHome = project.findProperty('org.gradle.java.home')
def javaBin
if (javaHome != null) {
javaBin = "$javaHome/bin/java"
} else {
javaBin = ext.execInBash("which java", rootDir)
}
println("Running the formatting tool with $javaBin")
def scriptDir = rootDir.path.endsWith('buildSrc')
? "${rootDir}/../java-format"
: "${rootDir}/java-format"
@@ -493,7 +516,7 @@ rootProject.ext {
def pythonExe = getPythonExecutable()
return ext.execInBash(
"PYTHON=${pythonExe} ${formatDiffScript} ${action}", "${workingDir}")
"JAVA=${javaBin} PYTHON=${pythonExe} ${formatDiffScript} ${action}", "${workingDir}")
}
}
+1 -1
View File
@@ -87,7 +87,7 @@ PRESUBMITS = {
PresubmitCheck(
r".*Copyright 20\d{2} The Nomulus Authors\. All Rights Reserved\.",
("java", "js", "soy", "sql", "py", "sh", "gradle", "ts"), {
".git", "/build/", "/generated/", "/generated_tests/",
".git", "/build/", "/bin/generated-sources/", "/bin/generated-test-sources/",
"node_modules/", "LoggerConfig.java", "registrar_bin.",
"registrar_dbg.", "google-java-format-diff.py",
"nomulus.golden.sql", "soyutils_usegoog.js", "javascript/checks.js"
+2310 -15168
View File
File diff suppressed because it is too large Load Diff
+8 -6
View File
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ViewChild, effect } from '@angular/core';
import { RegistrarService } from './registrar/registrar.service';
import { UserDataService } from './shared/services/userData.service';
import { GlobalLoaderService } from './shared/services/globalLoader.service';
@@ -36,11 +36,13 @@ export class AppComponent implements AfterViewInit {
protected globalLoader: GlobalLoaderService,
protected router: Router
) {
registrarService.activeRegistrarIdChange.subscribe(() => {
this.renderRouter = false;
setTimeout(() => {
this.renderRouter = true;
}, 400);
effect(() => {
if (registrarService.registrarId()) {
this.renderRouter = false;
setTimeout(() => {
this.renderRouter = true;
}, 400);
}
});
}
@@ -52,7 +52,7 @@ export class DomainListService {
) {
return this.backendService
.getDomains(
this.registrarService.activeRegistrarId,
this.registrarService.registrarId(),
this.checkpointTime,
pageNumber,
resultsPerPage,
@@ -23,8 +23,10 @@ export class BillingWidgetComponent {
constructor(public registrarService: RegistrarService) {}
public get driveFolderUrl(): string {
if (this.registrarService?.registrar.driveFolderId) {
return `https://drive.google.com/drive/folders/${this.registrarService?.registrar.driveFolderId}`;
if (this.registrarService.registrar()?.driveFolderId) {
return `https://drive.google.com/drive/folders/${
this.registrarService.registrar()?.driveFolderId
}`;
}
return '';
}
@@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component } from '@angular/core';
import { Component, effect } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { RegistrarService } from './registrar.service';
@@ -24,22 +23,15 @@ import { RegistrarService } from './registrar.service';
styleUrls: ['./emptyRegistrar.component.scss'],
})
export class EmptyRegistrar {
private registrarIdChangeSubscription?: Subscription;
constructor(
private route: ActivatedRoute,
protected registrarService: RegistrarService,
private router: Router
) {
this.registrarIdChangeSubscription =
registrarService.activeRegistrarIdChange.subscribe((newRegistrarId) => {
if (newRegistrarId) {
this.router.navigate([this.route.snapshot.paramMap.get('nextUrl')]);
}
});
}
ngOnDestroy() {
this.registrarIdChangeSubscription?.unsubscribe();
effect(() => {
if (registrarService.registrarId()) {
this.router.navigate([this.route.snapshot.paramMap.get('nextUrl')]);
}
});
}
}
@@ -34,7 +34,7 @@ export class RegistrarGuard {
_: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Promise<boolean> | boolean {
if (this.registrarService.activeRegistrarId) {
if (this.registrarService.registrarId()) {
return true;
}
return this.router.navigate([
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { Observable, Subject, tap } from 'rxjs';
import { Injectable, computed, signal } from '@angular/core';
import { Observable, tap } from 'rxjs';
import { BackendService } from '../shared/services/backend.service';
import {
@@ -52,9 +52,11 @@ export interface Registrar {
providedIn: 'root',
})
export class RegistrarService implements GlobalLoader {
activeRegistrarId: string = '';
registrars: Registrar[] = [];
activeRegistrarIdChange: Subject<string> = new Subject<string>();
registrarId = signal<string>('');
registrars = signal<Registrar[]>([]);
registrar = computed<Registrar | undefined>(() =>
this.registrars().find((r) => r.registrarId === this.registrarId())
);
constructor(
private backend: BackendService,
@@ -67,22 +69,15 @@ export class RegistrarService implements GlobalLoader {
this.globalLoader.startGlobalLoader(this);
}
public get registrar(): Registrar {
return this.registrars.filter(
(r) => r.registrarId === this.activeRegistrarId
)[0];
}
public updateSelectedRegistrar(registrarId: string) {
this.activeRegistrarId = registrarId;
this.activeRegistrarIdChange.next(registrarId);
this.registrarId.set(registrarId);
}
public loadRegistrars(): Observable<Registrar[]> {
return this.backend.getRegistrars().pipe(
tap((registrars) => {
if (registrars) {
this.registrars = registrars;
this.registrars.set(registrars);
}
})
);
@@ -5,20 +5,20 @@
routerLinkActive="active"
*ngIf="isMobile; else desktop"
>
{{ registrarService.activeRegistrarId || "Select registrar" }}
{{ registrarService.registrarId() || "Select registrar" }}
<mat-icon>open_in_new</mat-icon>
</button>
<ng-template #desktop>
<mat-form-field class="mat-form-field-density-5" appearance="fill">
<mat-label>Registrar</mat-label>
<mat-select
[ngModel]="registrarService.activeRegistrarId"
[ngModel]="registrarService.registrarId()"
(selectionChange)="
registrarService.updateSelectedRegistrar($event.value)
"
>
<mat-option
*ngFor="let registrar of registrarService.registrars"
*ngFor="let registrar of registrarService.registrars()"
[value]="registrar.registrarId"
>
{{ registrar.registrarId }}
@@ -87,7 +87,7 @@ export class RegistrarComponent {
constructor(protected registrarService: RegistrarService) {
this.dataSource = new MatTableDataSource<Registrar>(
registrarService.registrars
registrarService.registrars()
);
}
@@ -1,41 +1,41 @@
<div *ngIf="loading" class="contact__loading">
@if (loading) {
<div class="contact__loading">
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</div>
<div *ngIf="!loading">
<div
class="contact__empty-contacts"
*ngIf="contactService.contacts.length === 0"
>
} @else {
<div>
@if (contactService.contacts().length === 0) {
<div class="contact__empty-contacts">
<mat-icon class="contact__empty-contacts-icon secondary-text"
>apps_outage</mat-icon
>
<h1>No contacts found</h1>
</div>
<div *ngFor="let group of groupedData">
<div class="contact__cards-wrapper" *ngIf="group.contacts.length">
<h3>{{ group.label }}s</h3>
<mat-divider></mat-divider>
<div class="contact__cards">
<mat-card class="contact__card" *ngFor="let contact of group.contacts">
<mat-card-title>{{ contact.name }}</mat-card-title>
<p *ngIf="contact.phoneNumber">{{ contact.phoneNumber }}</p>
<p *ngIf="contact.emailAddress">{{ contact.emailAddress }}</p>
<mat-card-actions class="contact__card-actions">
<button
mat-button
color="primary"
(click)="openDetails($event, contact)"
>
<mat-icon>edit</mat-icon>Edit
</button>
<button mat-button color="accent" (click)="deleteContact(contact)">
<mat-icon>delete</mat-icon>Delete
</button>
</mat-card-actions>
</mat-card>
</div>
} @else { @for (group of groupedContacts(); track group.emailAddress) {
<div class="contact__cards-wrapper">
<h3>{{ group.label }}s</h3>
<mat-divider></mat-divider>
<div class="contact__cards">
<mat-card class="contact__card" *ngFor="let contact of group.contacts">
<mat-card-title>{{ contact.name }}</mat-card-title>
<p *ngIf="contact.phoneNumber">{{ contact.phoneNumber }}</p>
<p *ngIf="contact.emailAddress">{{ contact.emailAddress }}</p>
<mat-card-actions class="contact__card-actions">
<button
mat-button
color="primary"
(click)="openDetails($event, contact)"
>
<mat-icon>edit</mat-icon>Edit
</button>
<button mat-button color="accent" (click)="deleteContact(contact)">
<mat-icon>delete</mat-icon>Delete
</button>
</mat-card-actions>
</mat-card>
</div>
</div>
} }
<div class="contact__actions">
<button mat-raised-button color="primary" (click)="openCreateNew($event)">
<mat-icon>add</mat-icon>Create a Contact
@@ -45,3 +45,4 @@
#contactDetailsWrapper
></app-dialog-bottom-sheet-wrapper>
</div>
}
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, ViewChild } from '@angular/core';
import { Component, ViewChild, computed } from '@angular/core';
import { Contact, ContactService } from './contact.service';
import { HttpErrorResponse } from '@angular/common/http';
import { MatSnackBar } from '@angular/material/snack-bar';
@@ -70,9 +70,9 @@ export class ContactDetailsDialogComponent implements DialogBottomSheetContent {
init(params: ContactDetailsParams) {
this.params = params;
this.contactIndex = this.contactService.contacts.findIndex(
(c) => c === params.data.contact
);
this.contactIndex = this.contactService
.contacts()
.findIndex((c) => c === params.data.contact);
this.contact = JSON.parse(JSON.stringify(params.data.contact));
}
@@ -115,6 +115,16 @@ export class ContactDetailsDialogComponent implements DialogBottomSheetContent {
})
export default class ContactComponent {
public static PATH = 'contact';
public groupedContacts = computed(() => {
return this.contactService.contacts().reduce((acc, contact) => {
contact.types.forEach((contactType) => {
acc
.find((group: GroupedContacts) => group.value === contactType)
?.contacts.push(contact);
});
return acc;
}, JSON.parse(JSON.stringify(contactTypes)));
});
@ViewChild('contactDetailsWrapper')
detailsComponentWrapper!: DialogBottomSheetWrapper;
@@ -131,17 +141,6 @@ export default class ContactComponent {
});
}
public get groupedData() {
return this.contactService.contacts?.reduce((acc, contact) => {
contact.types.forEach((type) => {
acc
.find((group: GroupedContacts) => group.value === type)
?.contacts.push(contact);
});
return acc;
}, JSON.parse(JSON.stringify(contactTypes)));
}
deleteContact(contact: Contact) {
if (confirm(`Please confirm contact ${contact.name} delete`)) {
this.contactService.deleteContact(contact).subscribe({
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { Injectable, signal } from '@angular/core';
import { Observable, tap } from 'rxjs';
import { RegistrarService } from 'src/app/registrar/registrar.service';
import { BackendService } from 'src/app/shared/services/backend.service';
@@ -33,7 +33,7 @@ export interface Contact {
providedIn: 'root',
})
export class ContactService {
contacts: Contact[] = [];
contacts = signal<Contact[]>([]);
constructor(
private backend: BackendService,
@@ -42,39 +42,37 @@ export class ContactService {
// TODO: Come up with a better handling for registrarId
fetchContacts(): Observable<Contact[]> {
return this.backend
.getContacts(this.registrarService.activeRegistrarId)
.pipe(
tap((contacts = []) => {
this.contacts = contacts;
})
);
return this.backend.getContacts(this.registrarService.registrarId()).pipe(
tap((contacts = []) => {
this.contacts.set(contacts);
})
);
}
saveContacts(contacts: Contact[]): Observable<Contact[]> {
return this.backend
.postContacts(this.registrarService.activeRegistrarId, contacts)
.postContacts(this.registrarService.registrarId(), contacts)
.pipe(
tap((_) => {
this.contacts = contacts;
this.contacts.set(contacts);
})
);
}
updateContact(index: number, contact: Contact) {
const newContacts = this.contacts.map((c, i) =>
const newContacts = this.contacts().map((c, i) =>
i === index ? contact : c
);
return this.saveContacts(newContacts);
}
addContact(contact: Contact) {
const newContacts = this.contacts.concat([contact]);
const newContacts = this.contacts().concat([contact]);
return this.saveContacts(newContacts);
}
deleteContact(contact: Contact) {
const newContacts = this.contacts.filter((c) => c !== contact);
const newContacts = this.contacts().filter((c) => c !== contact);
return this.saveContacts(newContacts);
}
}
@@ -40,7 +40,7 @@ export default class SecurityComponent {
private _snackBar: MatSnackBar,
public registrarService: RegistrarService
) {
this.dataSource = apiToUiConverter(this.registrarService.registrar);
this.dataSource = apiToUiConverter(this.registrarService.registrar());
}
enableEdit() {
@@ -76,6 +76,6 @@ export default class SecurityComponent {
}
resetDataSource() {
this.dataSource = apiToUiConverter(this.registrarService.registrar);
this.dataSource = apiToUiConverter(this.registrarService.registrar());
}
}
@@ -64,7 +64,7 @@ export class SecurityService {
saveChanges(newSecuritySettings: SecuritySettings) {
return this.backend
.postSecuritySettings(
this.registrarService.activeRegistrarId,
this.registrarService.registrarId(),
uiToApiConverter(newSecuritySettings)
)
.pipe(
+1 -1
View File
@@ -1,3 +1,3 @@
FROM gcr.io/distroless/java:debug
FROM gcr.io/distroless/java17-debian11:debug
ADD build/libs/nomulus.jar /nomulus.jar
ENTRYPOINT ["/usr/bin/java", "-jar", "/nomulus.jar"]
+1 -1
View File
@@ -776,7 +776,7 @@ if (environment == 'alpha') {
gs://${gcpProject}-deploy/live/beam/${metaDataBaseName} \
--image-gcr-path ${imageName}:live \
--sdk-language JAVA \
--flex-template-base-image JAVA11 \
--flex-template-base-image JAVA17 \
--metadata-file ${projectDir}/src/main/resources/${metaData} \
--jar ${uberJarName} \
--env FLEX_TEMPLATE_JAVA_MAIN_CLASS=${mainClass} \
@@ -207,7 +207,7 @@ public class CloudTasksUtils implements Serializable {
Service service,
Multimap<String, String> params,
Optional<Integer> jitterSeconds) {
if (!jitterSeconds.isPresent() || jitterSeconds.get() <= 0) {
if (jitterSeconds.isEmpty() || jitterSeconds.get() <= 0) {
return createTask(path, method, service, params);
}
return createTaskWithDelay(
@@ -171,7 +171,7 @@ public class DeleteExpiredDomainsAction implements Runnable {
tm().transact(
() -> {
Domain transDomain = tm().loadByKey(domain.createVKey());
if (!domain.getAutorenewEndTime().isPresent()
if (domain.getAutorenewEndTime().isEmpty()
|| domain.getAutorenewEndTime().get().isAfter(tm().getTransactionTime())) {
logger.atSevere().log(
"Failed to delete domain %s because of its autorenew end time: %s.",
@@ -151,7 +151,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
DateTime lastExpiringCertNotificationSentDate,
CertificateType certificateType,
Optional<String> certificate) {
if (!certificate.isPresent()
if (certificate.isEmpty()
|| !certificateChecker.shouldReceiveExpiringNotification(
lastExpiringCertNotificationSentDate, certificate.get())) {
return false;
@@ -163,7 +163,12 @@ public class InvoicingPipeline implements Serializable {
}
}
/** Saves the billing events to a single overall invoice CSV file. */
/**
* Saves the billing events to a single overall invoice CSV file. TextIO always produces the file
* of type text/plain, which we then update to desired text/csv before sending an email to billing
* team {@link google.registry.reporting.billing.BillingEmailUtils#emailOverallInvoice()
* emailOverallInvoice}
*/
static void saveInvoiceCsv(
PCollection<google.registry.beam.billing.BillingEvent> billingEvents,
InvoicingPipelineOptions options) {
@@ -209,10 +209,18 @@ public final class RegistryJpaIO {
@ProcessElement
public void processElement(OutputReceiver<T> outputReceiver) {
tm().transact(
// Note the use of no-retry transaction here. The results from the query are streamed to the
// output receiver inside the transaction, which cannot be rolled back in case of a retry,
// which in turn results in duplicate elements. If we try to pass the results to the output
// receiver outside the transaction, they have to be materialized into a list containing all
// the elements (without resorting to manual pagination) and greatly decrease the
// parallelism of the pipeline.
tm().transactNoRetry(
() -> {
query.stream().map(resultMapper::apply).forEach(outputReceiver::output);
});
return null;
},
null);
}
}
}
@@ -116,7 +116,7 @@ public class BsaDownloadAction implements Runnable {
return null;
}
Optional<DownloadSchedule> scheduleOptional = downloadScheduler.schedule();
if (!scheduleOptional.isPresent()) {
if (scheduleOptional.isEmpty()) {
logger.atInfo().log("Nothing to do.");
return null;
}
@@ -102,7 +102,7 @@ public class BsaRefreshAction implements Runnable {
return null;
}
Optional<RefreshSchedule> maybeSchedule = scheduler.schedule();
if (!maybeSchedule.isPresent()) {
if (maybeSchedule.isEmpty()) {
logger.atInfo().log("No completed downloads yet. Exiting.");
return null;
}
@@ -117,13 +117,12 @@ public class BsaRefreshAction implements Runnable {
case CHECK_FOR_CHANGES:
ImmutableList<UnblockableDomainChange> blockabilityChanges =
refresher.checkForBlockabilityChanges();
// Always write even if no change. Easier for manual inspection of GCS bucket.
gcsClient.writeRefreshChanges(schedule.jobName(), blockabilityChanges.stream());
if (blockabilityChanges.isEmpty()) {
logger.atInfo().log("No change to Unblockable domains found.");
schedule.updateJobStage(RefreshStage.DONE);
return null;
}
gcsClient.writeRefreshChanges(schedule.jobName(), blockabilityChanges.stream());
schedule.updateJobStage(RefreshStage.APPLY_CHANGES);
// Fall through
case APPLY_CHANGES:
@@ -162,7 +161,7 @@ public class BsaRefreshAction implements Runnable {
.filter(UnblockableDomainChange::isNewOrChange)
.map(UnblockableDomainChange::newValue));
if (report.isPresent()) {
gcsClient.logRemovedUnblockableDomainsReport(
gcsClient.logAddedUnblockableDomainsReport(
schedule.jobName(), LINE_SPLITTER.splitToStream(report.get()));
bsaReportSender.addUnblockableDomainsUpdates(report.get());
} else {
@@ -48,7 +48,8 @@ public final class BsaTransactions {
@CanIgnoreReturnValue
public static <T> T bsaQuery(Callable<T> work) {
verify(!isInTransaction(), "May only be used for top-level transactions.");
return replicaTm().transact(work, TRANSACTION_REPEATABLE_READ);
// TRANSACTION_REPEATABLE_READ is default on replica.
return replicaTm().transact(work);
}
private BsaTransactions() {}
@@ -80,7 +80,7 @@ public class UploadBsaUnavailableDomainsAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final int BATCH_SIZE = 50000;
private static final int BATCH_SIZE = 40000;
Clock clock;
@@ -52,7 +52,7 @@ public class RefreshScheduler {
}
// No previously completed refreshes. Need start time of a completed download as
// lower bound of refresh checks.
if (!mostRecentDownload.isPresent()) {
if (mostRecentDownload.isEmpty()) {
return Optional.empty();
}
@@ -721,6 +721,17 @@ public final class RegistryConfig {
return "gs://" + billingBucket;
}
/**
* Returns origin part of the URL of the billing invoice file
*
* @see google.registry.beam.billing.InvoicingPipeline
*/
@Provides
@Config("billingInvoiceOriginUrl")
public static String provideBillingInvoiceOriginUrl(RegistryConfigSettings config) {
return config.billing.billingInvoiceOriginUrl;
}
/**
* Returns whether or not we should publish invoices to partners automatically by default.
*
@@ -173,6 +173,7 @@ public class RegistryConfigSettings {
public List<String> invoiceEmailRecipients;
public String invoiceReplyToEmailAddress;
public String invoiceFilePrefix;
public String billingInvoiceOriginUrl;
}
/** Configuration for Registry Data Escrow (RDE). */
@@ -381,6 +381,7 @@ billing:
# Optional return address that overrides the default.
invoiceReplyToEmailAddress: null
invoiceFilePrefix: REG-INV
billingInvoiceOriginUrl: https://billing-origin-url/
rde:
# URL prefix of ICANN's server to upload RDE reports to. Nomulus adds /TLD/ID
@@ -0,0 +1,60 @@
# Example of a TLD configuration file. TLD configuration files are stored in
# the internal repository and synced regularly to the database using the
# release/cloudbuild-tld-sync.yaml job. The file can be created using the exact
# output from the getTldCommand of an existing TLD.
addGracePeriodLength: "PT432000S"
allowedFullyQualifiedHostNames: []
allowedRegistrantContactIds: []
anchorTenantAddGracePeriodLength: "PT2592000S"
autoRenewGracePeriodLength: "PT3888000S"
automaticTransferLength: "PT432000S"
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
createBillingCost:
currency: "USD"
amount: 8.00
creationTime: "2017-01-03T19:52:47.770Z"
currency: "USD"
defaultPromoTokens: []
dnsAPlusAaaaTtl: null
dnsDsTtl: null
dnsNsTtl: null
dnsPaused: true
dnsWriters:
- "VoidDnsWriter"
driveFolderId: null
eapFeeSchedule:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 0.00
escrowEnabled: false
idnTables: []
invoicingEnabled: false
lordnUsername: null
numDnsPublishLocks: 1
pendingDeleteLength: "PT432000S"
premiumListName: null
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
redemptionGracePeriodLength: "PT2592000S"
registryLockOrUnlockBillingCost:
currency: "USD"
amount: 0.00
renewBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 8.00
renewGracePeriodLength: "PT432000S"
reservedListNames: []
restoreBillingCost:
currency: "USD"
amount: 50.00
roidSuffix: "EXAMPLE"
serverStatusChangeBillingCost:
currency: "USD"
amount: 0.00
tldStateTransitions:
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
tldStr: "example"
tldType: "TEST"
tldUnicode: "example"
transferGracePeriodLength: "PT432000S"
@@ -128,7 +128,7 @@ public class CloudDnsWriter extends BaseDnsWriter {
// Return early if no DNS records should be published.
// desiredRecordsBuilder is populated with an empty set to indicate that all existing records
// should be deleted.
if (!domain.isPresent() || !domain.get().shouldPublishToDns()) {
if (domain.isEmpty() || !domain.get().shouldPublishToDns()) {
desiredRecords.put(absoluteDomainName, ImmutableSet.of());
return;
}
@@ -192,7 +192,7 @@ public class CloudDnsWriter extends BaseDnsWriter {
Optional<Host> host = loadByForeignKey(Host.class, hostName, clock.nowUtc());
// Return early if the host is deleted.
if (!host.isPresent()) {
if (host.isEmpty()) {
desiredRecords.put(absoluteHostName, ImmutableSet.of());
return;
}
@@ -247,7 +247,7 @@ public class CloudDnsWriter extends BaseDnsWriter {
Optional<InternetDomainName> tld = Tlds.findTldForName(host);
// Host not managed by our registry, no need to update DNS.
if (!tld.isPresent()) {
if (tld.isEmpty()) {
logger.atSevere().log("publishHost called for invalid host '%s'.", hostName);
return;
}
@@ -157,7 +157,7 @@ public class DnsUpdateWriter extends BaseDnsWriter {
Optional<InternetDomainName> tld = Tlds.findTldForName(host);
// host not managed by our registry, no need to update DNS.
if (!tld.isPresent()) {
if (tld.isEmpty()) {
return;
}
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java8</runtime>
<runtime>java17</runtime>
<service>backend</service>
<!--app-engine-apis>true</app-engine-apis-->
<threadsafe>true</threadsafe>
<app-engine-apis>true</app-engine-apis>
<sessions-enabled>true</sessions-enabled>
<instance-class>B4_1G</instance-class>
<basic-scaling>
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java8</runtime>
<runtime>java17</runtime>
<service>bsa</service>
<!--app-engine-apis>true</app-engine-apis-->
<threadsafe>true</threadsafe>
<app-engine-apis>true</app-engine-apis>
<sessions-enabled>true</sessions-enabled>
<instance-class>B4_1G</instance-class>
<basic-scaling>
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java8</runtime>
<runtime>java17</runtime>
<service>default</service>
<!--app-engine-apis>true</app-engine-apis-->
<threadsafe>true</threadsafe>
<app-engine-apis>true</app-engine-apis>
<sessions-enabled>true</sessions-enabled>
<instance-class>B4_1G</instance-class>
<manual-scaling>
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java8</runtime>
<runtime>java17</runtime>
<service>pubapi</service>
<!--app-engine-apis>true</app-engine-apis-->
<threadsafe>true</threadsafe>
<app-engine-apis>true</app-engine-apis>
<sessions-enabled>true</sessions-enabled>
<instance-class>B4_1G</instance-class>
<manual-scaling>
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java8</runtime>
<runtime>java17</runtime>
<service>tools</service>
<!--app-engine-apis>true</app-engine-apis-->
<threadsafe>true</threadsafe>
<app-engine-apis>true</app-engine-apis>
<sessions-enabled>true</sessions-enabled>
<instance-class>B4_1G</instance-class>
<basic-scaling>
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java8</runtime>
<runtime>java17</runtime>
<service>backend</service>
<!--app-engine-apis>true</app-engine-apis-->
<threadsafe>true</threadsafe>
<app-engine-apis>true</app-engine-apis>
<sessions-enabled>true</sessions-enabled>
<instance-class>B4</instance-class>
<basic-scaling>
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java8</runtime>
<runtime>java17</runtime>
<service>bsa</service>
<!--app-engine-apis>true</app-engine-apis-->
<threadsafe>true</threadsafe>
<app-engine-apis>true</app-engine-apis>
<sessions-enabled>true</sessions-enabled>
<instance-class>B4</instance-class>
<basic-scaling>
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java8</runtime>
<runtime>java17</runtime>
<service>default</service>
<!--app-engine-apis>true</app-engine-apis-->
<threadsafe>true</threadsafe>
<app-engine-apis>true</app-engine-apis>
<sessions-enabled>true</sessions-enabled>
<instance-class>B4_1G</instance-class>
<manual-scaling>
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java8</runtime>
<runtime>java17</runtime>
<service>pubapi</service>
<!--app-engine-apis>true</app-engine-apis-->
<threadsafe>true</threadsafe>
<app-engine-apis>true</app-engine-apis>
<sessions-enabled>true</sessions-enabled>
<instance-class>B4_1G</instance-class>
<manual-scaling>
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java8</runtime>
<runtime>java17</runtime>
<service>tools</service>
<!--app-engine-apis>true</app-engine-apis-->
<threadsafe>true</threadsafe>
<app-engine-apis>true</app-engine-apis>
<sessions-enabled>true</sessions-enabled>
<instance-class>B4</instance-class>
<basic-scaling>
@@ -115,7 +115,7 @@ public class ExportPremiumTermsAction implements Runnable {
"Skipping premium terms export for TLD %s because Drive folder isn't specified.", tldStr);
return Optional.of("Skipping export because no Drive folder is associated with this TLD");
}
if (!tld.getPremiumListName().isPresent()) {
if (tld.getPremiumListName().isEmpty()) {
logger.atInfo().log("No premium terms to export for TLD '%s'.", tldStr);
return Optional.of("No premium lists configured");
}
@@ -63,7 +63,7 @@ class SyncRegistrarsSheet {
boolean wereRegistrarsModified() {
Optional<Cursor> cursor =
tm().transact(() -> tm().loadByKeyIfPresent(Cursor.createGlobalVKey(SYNC_REGISTRAR_SHEET)));
DateTime lastUpdateTime = !cursor.isPresent() ? START_OF_TIME : cursor.get().getCursorTime();
DateTime lastUpdateTime = cursor.isEmpty() ? START_OF_TIME : cursor.get().getCursorTime();
for (Registrar registrar : Registrar.loadAllCached()) {
if (DateTimeUtils.isAtOrAfter(registrar.getLastUpdateTime(), lastUpdateTime)) {
return true;
@@ -112,11 +112,11 @@ public class SyncRegistrarsSheetAction implements Runnable {
@Override
public void run() {
final Optional<String> sheetId = Optional.ofNullable(idParam.orElse(idConfig.orElse(null)));
if (!sheetId.isPresent()) {
if (sheetId.isEmpty()) {
Result.MISSINGNO.send(response, null);
return;
}
if (!idParam.isPresent()) {
if (idParam.isEmpty()) {
if (!syncRegistrarsSheet.wereRegistrarsModified()) {
Result.NOTMODIFIED.send(response, null);
return;
@@ -122,7 +122,7 @@ public final class ResourceFlowUtils {
/** Check that the given AuthInfo is present for a resource being transferred. */
public static void verifyAuthInfoPresentForResourceTransfer(Optional<AuthInfo> authInfo)
throws EppException {
if (!authInfo.isPresent()) {
if (authInfo.isEmpty()) {
throw new MissingTransferRequestAuthInfoException();
}
}
@@ -160,7 +160,7 @@ public final class ResourceFlowUtils {
domain.getReferencedContacts().stream()
.filter(key -> key.getKey().equals(authRepoId))
.findFirst();
if (!foundContact.isPresent()) {
if (foundContact.isEmpty()) {
throw new BadAuthInfoForResourceException();
}
// Check the authInfo against the contact.
@@ -105,7 +105,7 @@ public class TlsCredentials implements TransportCredentials {
}
// In the rare unexpected case that the client inet address wasn't passed along at all, then
// by default deny access.
if (!clientInetAddr.isPresent()) {
if (clientInetAddr.isEmpty()) {
logger.atWarning().log(
"Authentication error: Missing IP address for registrar %s.", registrar.getRegistrarId());
throw new BadRegistrarIpAddressException(clientInetAddr);
@@ -129,8 +129,8 @@ public class TlsCredentials implements TransportCredentials {
@VisibleForTesting
void validateCertificateHash(Registrar registrar) throws AuthenticationErrorException {
if (!registrar.getClientCertificateHash().isPresent()
&& !registrar.getFailoverClientCertificateHash().isPresent()) {
if (registrar.getClientCertificateHash().isEmpty()
&& registrar.getFailoverClientCertificateHash().isEmpty()) {
if (requireSslCertificates) {
throw new RegistrarCertificateNotConfiguredException();
} else {
@@ -140,7 +140,7 @@ public class TlsCredentials implements TransportCredentials {
}
}
// Check that the request included the certificate hash
if (!clientCertificateHash.isPresent()) {
if (clientCertificateHash.isEmpty()) {
logger.atInfo().log(
"Request from registrar %s did not include X-SSL-Certificate.",
registrar.getRegistrarId());
@@ -75,7 +75,7 @@ public final class ContactTransferQueryFlow implements TransactionalFlow {
}
// Note that the authorization info on the command (if present) has already been verified. If
// it's present, then the other checks are unnecessary.
if (!authInfo.isPresent()
if (authInfo.isEmpty()
&& !registrarId.equals(contact.getTransferData().getGainingRegistrarId())
&& !registrarId.equals(contact.getTransferData().getLosingRegistrarId())) {
throw new NotAuthorizedToViewTransferException();
@@ -26,6 +26,7 @@ import static google.registry.flows.domain.DomainFlowUtils.checkHasBillingAccoun
import static google.registry.flows.domain.DomainFlowUtils.getReservationTypes;
import static google.registry.flows.domain.DomainFlowUtils.handleFeeRequest;
import static google.registry.flows.domain.DomainFlowUtils.isAnchorTenant;
import static google.registry.flows.domain.DomainFlowUtils.isRegisterBsaCreate;
import static google.registry.flows.domain.DomainFlowUtils.isReserved;
import static google.registry.flows.domain.DomainFlowUtils.isValidReservedCreate;
import static google.registry.flows.domain.DomainFlowUtils.validateDomainName;
@@ -218,7 +219,7 @@ public final class DomainCheckFlow implements TransactionalFlow {
domainCheckResults,
tldStates,
allocationToken);
boolean isAvailable = !message.isPresent();
boolean isAvailable = message.isEmpty();
checksBuilder.add(DomainCheck.create(isAvailable, domainName, message.orElse(null)));
if (isAvailable) {
availableDomains.add(domainName);
@@ -269,13 +270,13 @@ public final class DomainCheckFlow implements TransactionalFlow {
if (tokenResult.isPresent()) {
return tokenResult;
}
if (bsaBlockedDomains.contains(domainName)) {
// TODO(weiminyu): extract to a constant for here and CheckApiAction.
// Excerpt from BSA's custom message. Max len 32 chars by EPP XML schema.
return Optional.of("Blocked by a GlobalBlock service");
} else {
if (isRegisterBsaCreate(domainName, allocationToken)
|| !bsaBlockedDomains.contains(domainName)) {
return Optional.empty();
}
// TODO(weiminyu): extract to a constant for here and CheckApiAction.
// Excerpt from BSA's custom message. Max len 32 chars by EPP XML schema.
return Optional.of("Blocked by a GlobalBlock service");
}
/** Handle the fee check extension. */
@@ -288,7 +289,7 @@ public final class DomainCheckFlow implements TransactionalFlow {
throws EppException {
Optional<FeeCheckCommandExtension> feeCheckOpt =
eppInput.getSingleExtension(FeeCheckCommandExtension.class);
if (!feeCheckOpt.isPresent()) {
if (feeCheckOpt.isEmpty()) {
return ImmutableList.of(); // No fee checks were requested.
}
FeeCheckCommandExtension<?, ?> feeCheck = feeCheckOpt.get();
@@ -276,7 +276,7 @@ public final class DomainCreateFlow implements MutatingFlow {
now,
eppInput.getSingleExtension(AllocationTokenExtension.class));
boolean defaultTokenUsed = false;
if (!allocationToken.isPresent()) {
if (allocationToken.isEmpty()) {
allocationToken =
DomainFlowUtils.checkForDefaultToken(
tld, command.getDomainName(), CommandName.CREATE, registrarId, now);
@@ -330,7 +330,7 @@ public final class DomainCreateFlow implements MutatingFlow {
.verifySignedMarks(launchCreate.get().getSignedMarks(), domainLabel, now)
.getId();
}
verifyNotBlockedByBsa(domainLabel, tld, now);
verifyNotBlockedByBsa(domainName, tld, now, allocationToken);
flowCustomLogic.afterValidation(
DomainCreateFlowCustomLogic.AfterValidationParameters.newBuilder()
.setDomainName(domainName)
@@ -421,8 +421,7 @@ public final class DomainCreateFlow implements MutatingFlow {
createNameCollisionOneTimePollMessage(targetId, domainHistory, registrarId, now));
}
entitiesToSave.add(domain, domainHistory);
if (allocationToken.isPresent()
&& TokenType.SINGLE_USE.equals(allocationToken.get().getTokenType())) {
if (allocationToken.isPresent() && allocationToken.get().getTokenType().isOneTimeUse()) {
entitiesToSave.add(
allocationTokenFlowUtils.redeemToken(
allocationToken.get(), domainHistory.getHistoryEntryId()));
@@ -520,7 +519,7 @@ public final class DomainCreateFlow implements MutatingFlow {
if (behavior.equals(RegistrationBehavior.BYPASS_TLD_STATE)
|| behavior.equals(RegistrationBehavior.ANCHOR_TENANT)) {
// Non-trademarked names with the state check bypassed are always available
if (!claimsList.getClaimKey(domainLabel).isPresent()) {
if (claimsList.getClaimKey(domainLabel).isEmpty()) {
return;
}
if (!currentState.equals(START_DATE_SUNRISE)) {
@@ -27,6 +27,7 @@ import static com.google.common.collect.Sets.intersection;
import static com.google.common.collect.Sets.union;
import static google.registry.bsa.persistence.BsaLabelUtils.isLabelBlocked;
import static google.registry.model.domain.Domain.MAX_REGISTRATION_YEARS;
import static google.registry.model.domain.token.AllocationToken.TokenType.REGISTER_BSA;
import static google.registry.model.tld.Tld.TldState.GENERAL_AVAILABILITY;
import static google.registry.model.tld.Tld.TldState.PREDELEGATION;
import static google.registry.model.tld.Tld.TldState.QUIET_PERIOD;
@@ -214,7 +215,7 @@ public class DomainFlowUtils {
throw new DomainNameExistsAsTldException();
}
Optional<InternetDomainName> tldParsed = findTldForName(domainName);
if (!tldParsed.isPresent()) {
if (tldParsed.isEmpty()) {
throw new TldDoesNotExistException(domainName.parent().toString());
}
if (domainName.parts().size() != tldParsed.get().parts().size() + 1) {
@@ -255,7 +256,7 @@ public class DomainFlowUtils {
Optional<String> idnTableName =
IDN_LABEL_VALIDATOR.findValidIdnTableForTld(
domainName.parts().get(0), domainName.parent().toString());
if (!idnTableName.isPresent()) {
if (idnTableName.isEmpty()) {
throw new InvalidIdnDomainLabelException();
}
return idnTableName.get();
@@ -265,9 +266,14 @@ public class DomainFlowUtils {
* Verifies that the {@code domainLabel} is not blocked by any BSA block label for the given
* {@code tld} at the specified time.
*/
public static void verifyNotBlockedByBsa(String domainLabel, Tld tld, DateTime now)
public static void verifyNotBlockedByBsa(
InternetDomainName domainName,
Tld tld,
DateTime now,
Optional<AllocationToken> allocationToken)
throws DomainLabelBlockedByBsaException {
if (isBlockedByBsa(domainLabel, tld, now)) {
if (!isRegisterBsaCreate(domainName, allocationToken)
&& isBlockedByBsa(domainName.parts().get(0), tld, now)) {
throw new DomainLabelBlockedByBsaException();
}
}
@@ -311,6 +317,15 @@ public class DomainFlowUtils {
&& token.get().getDomainName().get().equals(domainName.toString());
}
/** Returns whether a given domain create request may bypass the BSA block check. */
public static boolean isRegisterBsaCreate(
InternetDomainName domainName, Optional<AllocationToken> token) {
return token.isPresent()
&& token.get().getTokenType().equals(REGISTER_BSA)
&& token.get().getDomainName().isPresent()
&& token.get().getDomainName().get().equals(domainName.toString());
}
/** 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)) {
@@ -353,7 +368,7 @@ public class DomainFlowUtils {
}
ImmutableList<DomainDsData> invalidDigestTypes =
dsData.stream()
.filter(ds -> !DigestType.fromWireValue(ds.getDigestType()).isPresent())
.filter(ds -> DigestType.fromWireValue(ds.getDigestType()).isEmpty())
.collect(toImmutableList());
if (!invalidDigestTypes.isEmpty()) {
throw new InvalidDsRecordException(
@@ -801,7 +816,7 @@ public class DomainFlowUtils {
FeesAndCredits feesAndCredits,
boolean defaultTokenUsed)
throws EppException {
if (feesAndCredits.hasAnyPremiumFees() && !feeCommand.isPresent()) {
if (feesAndCredits.hasAnyPremiumFees() && feeCommand.isEmpty()) {
throw new FeesRequiredForPremiumNameException();
}
validateFeesAckedIfPresent(feeCommand, feesAndCredits, defaultTokenUsed);
@@ -822,7 +837,7 @@ public class DomainFlowUtils {
// Check for the case where a fee command extension was required but not provided.
// This only happens when the total fees are non-zero and include custom fees requiring the
// extension.
if (!feeCommand.isPresent()) {
if (feeCommand.isEmpty()) {
if (!feesAndCredits.getEapCost().isZero()) {
throw new FeesRequiredDuringEarlyAccessProgramException(feesAndCredits.getEapCost());
}
@@ -1034,7 +1049,7 @@ public class DomainFlowUtils {
/** Validate the secDNS extension, if present. */
static Optional<SecDnsCreateExtension> validateSecDnsExtension(
Optional<SecDnsCreateExtension> secDnsCreate) throws EppException {
if (!secDnsCreate.isPresent()) {
if (secDnsCreate.isEmpty()) {
return Optional.empty();
}
if (secDnsCreate.get().getDsData() == null) {
@@ -73,7 +73,6 @@ import google.registry.model.domain.fee.FeeTransformResponseExtension;
import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationToken.TokenType;
import google.registry.model.domain.token.AllocationTokenExtension;
import google.registry.model.eppcommon.AuthInfo;
import google.registry.model.eppcommon.StatusValue;
@@ -183,7 +182,7 @@ public final class DomainRenewFlow implements MutatingFlow {
CommandName.RENEW,
eppInput.getSingleExtension(AllocationTokenExtension.class));
boolean defaultTokenUsed = false;
if (!allocationToken.isPresent()) {
if (allocationToken.isEmpty()) {
allocationToken =
DomainFlowUtils.checkForDefaultToken(
tld, existingDomain.getDomainName(), CommandName.RENEW, registrarId, now);
@@ -258,8 +257,7 @@ public final class DomainRenewFlow implements MutatingFlow {
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
entitiesToSave.add(
newDomain, domainHistory, explicitRenewEvent, newAutorenewEvent, newAutorenewPollMessage);
if (allocationToken.isPresent()
&& TokenType.SINGLE_USE.equals(allocationToken.get().getTokenType())) {
if (allocationToken.isPresent() && allocationToken.get().getTokenType().isOneTimeUse()) {
entitiesToSave.add(
allocationTokenFlowUtils.redeemToken(
allocationToken.get(), domainHistory.getHistoryEntryId()));
@@ -81,7 +81,7 @@ public final class DomainTransferQueryFlow implements TransactionalFlow {
}
// Note that the authorization info on the command (if present) has already been verified. If
// it's present, then the other checks are unnecessary.
if (!authInfo.isPresent()
if (authInfo.isEmpty()
&& !registrarId.equals(transferData.getGainingRegistrarId())
&& !registrarId.equals(transferData.getLosingRegistrarId())) {
throw new NotAuthorizedToViewTransferException();
@@ -201,7 +201,7 @@ public final class DomainTransferRequestFlow implements MutatingFlow {
Optional<FeesAndCredits> feesAndCredits;
if (period.getValue() == 0) {
feesAndCredits = Optional.empty();
} else if (!existingDomain.getCurrentBulkToken().isPresent()) {
} else if (existingDomain.getCurrentBulkToken().isEmpty()) {
feesAndCredits =
Optional.of(pricingLogic.getTransferPrice(tld, targetId, now, existingBillingRecurrence));
} else {
@@ -36,7 +36,6 @@ import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName
import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationToken.TokenBehavior;
import google.registry.model.domain.token.AllocationToken.TokenStatus;
import google.registry.model.domain.token.AllocationToken.TokenType;
import google.registry.model.domain.token.AllocationTokenExtension;
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
import google.registry.model.tld.Tld;
@@ -105,8 +104,7 @@ public class AllocationTokenFlowUtils {
/** Redeems a SINGLE_USE {@link AllocationToken}, returning the redeemed copy. */
public AllocationToken redeemToken(AllocationToken token, HistoryEntryId redemptionHistoryId) {
checkArgument(
TokenType.SINGLE_USE.equals(token.getTokenType()),
"Only SINGLE_USE tokens can be marked as redeemed");
token.getTokenType().isOneTimeUse(), "Only SINGLE_USE tokens can be marked as redeemed");
return token.asBuilder().setRedemptionHistoryId(redemptionHistoryId).build();
}
@@ -184,7 +182,7 @@ public class AllocationTokenFlowUtils {
maybeTokenEntity =
tm().transact(() -> tm().loadByKeyIfPresent(VKey.create(AllocationToken.class, token)));
if (!maybeTokenEntity.isPresent()) {
if (maybeTokenEntity.isEmpty()) {
throw new InvalidAllocationTokenException();
}
if (maybeTokenEntity.get().isRedeemed()) {
@@ -201,7 +199,7 @@ public class AllocationTokenFlowUtils {
DateTime now,
Optional<AllocationTokenExtension> extension)
throws EppException {
if (!extension.isPresent()) {
if (extension.isEmpty()) {
return Optional.empty();
}
AllocationToken tokenEntity = loadToken(extension.get().getAllocationToken());
@@ -224,7 +222,7 @@ public class AllocationTokenFlowUtils {
CommandName commandName,
Optional<AllocationTokenExtension> extension)
throws EppException {
if (!extension.isPresent()) {
if (extension.isEmpty()) {
return Optional.empty();
}
AllocationToken tokenEntity = loadToken(extension.get().getAllocationToken());
@@ -256,7 +254,7 @@ public class AllocationTokenFlowUtils {
public static Domain maybeApplyBulkPricingRemovalToken(
Domain domain, Optional<AllocationToken> allocationToken) {
if (!allocationToken.isPresent()
if (allocationToken.isEmpty()
|| !TokenBehavior.REMOVE_BULK_PRICING.equals(allocationToken.get().getTokenBehavior())) {
return domain;
}
@@ -81,7 +81,7 @@ public class HostFlowUtils {
public static Optional<Domain> lookupSuperordinateDomain(
InternetDomainName hostName, DateTime now) throws EppException {
Optional<InternetDomainName> tld = findTldForName(hostName);
if (!tld.isPresent()) {
if (tld.isEmpty()) {
// This is an host on a TLD we don't run, therefore obviously external, so we are done.
return Optional.empty();
}
@@ -91,7 +91,7 @@ public class HostFlowUtils {
.skip(hostName.parts().size() - (tld.get().parts().size() + 1))
.collect(joining("."));
Optional<Domain> superordinateDomain = loadByForeignKey(Domain.class, domainName, now);
if (!superordinateDomain.isPresent() || !isActive(superordinateDomain.get(), now)) {
if (superordinateDomain.isEmpty() || !isActive(superordinateDomain.get(), now)) {
throw new SuperordinateDomainDoesNotExistException(domainName);
}
return superordinateDomain;
@@ -148,23 +148,25 @@ public class FlowPicker {
* <p>This provider must be tried before {@link #RESOURCE_CRUD_FLOW_PROVIDER}. Otherwise, the
* regular domain update flow will match first.
*/
private static final FlowProvider DOMAIN_RESTORE_FLOW_PROVIDER = new FlowProvider() {
@Override
Class<? extends Flow> get(
EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) {
if (!(resourceCommand instanceof DomainCommand.Update)) {
return null;
}
Optional<RgpUpdateExtension> rgpUpdateExtension =
eppInput.getSingleExtension(RgpUpdateExtension.class);
if (!rgpUpdateExtension.isPresent()) {
return null;
}
// Restore command with an op of "report" is not currently supported.
return (rgpUpdateExtension.get().getRestoreCommand().getRestoreOp() == RestoreOp.REQUEST)
? DomainRestoreRequestFlow.class
: UnimplementedRestoreFlow.class;
}};
private static final FlowProvider DOMAIN_RESTORE_FLOW_PROVIDER =
new FlowProvider() {
@Override
Class<? extends Flow> get(
EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) {
if (!(resourceCommand instanceof DomainCommand.Update)) {
return null;
}
Optional<RgpUpdateExtension> rgpUpdateExtension =
eppInput.getSingleExtension(RgpUpdateExtension.class);
if (rgpUpdateExtension.isEmpty()) {
return null;
}
// Restore command with an op of "report" is not currently supported.
return (rgpUpdateExtension.get().getRestoreCommand().getRestoreOp() == RestoreOp.REQUEST)
? DomainRestoreRequestFlow.class
: UnimplementedRestoreFlow.class;
}
};
/**
* The claims check flow is keyed on the type of the {@link ResourceCommand} and on having the
@@ -180,7 +182,7 @@ public class FlowPicker {
}
Optional<LaunchCheckExtension> launchCheck =
eppInput.getSingleExtension(LaunchCheckExtension.class);
if (!launchCheck.isPresent()
if (launchCheck.isEmpty()
|| CheckType.AVAILABILITY.equals(launchCheck.get().getCheckType())) {
// We don't distinguish between registry phases for "avail", so don't bother checking
// phase.
@@ -86,7 +86,7 @@ public final class PollAckFlow implements MutatingFlow {
// it as if it doesn't exist yet. Same for if the message ID year isn't the same as the actual
// poll message's event time (that means they're passing in an old already-acked ID).
Optional<PollMessage> maybePollMessage = tm().loadByKeyIfPresent(pollMessageKey);
if (!maybePollMessage.isPresent()
if (maybePollMessage.isEmpty()
|| !isBeforeOrAt(maybePollMessage.get().getEventTime(), now)
|| !makePollMessageExternalId(maybePollMessage.get()).equals(messageId)) {
throw new MessageDoesNotExistException(messageId);
@@ -66,7 +66,7 @@ public final class PollRequestFlow implements TransactionalFlow {
// Return the oldest message from the queue.
DateTime now = tm().getTransactionTime();
Optional<PollMessage> maybePollMessage = getFirstPollMessage(registrarId, now);
if (!maybePollMessage.isPresent()) {
if (maybePollMessage.isEmpty()) {
return responseBuilder.setResultFromCode(SUCCESS_WITH_NO_MESSAGES).build();
}
PollMessage pollMessage = maybePollMessage.get();
@@ -123,7 +123,7 @@ public class LoginFlow implements MutatingFlow {
serviceExtensionUrisBuilder.add(uri);
}
Optional<Registrar> registrar = Registrar.loadByRegistrarIdCached(login.getClientId());
if (!registrar.isPresent()) {
if (registrar.isEmpty()) {
throw new BadRegistrarIdException(login.getClientId());
}
@@ -155,7 +155,7 @@ public class LoginFlow implements MutatingFlow {
});
// Load fresh from database (bypassing the cache) to ensure we don't save stale data.
Optional<Registrar> freshRegistrar = Registrar.loadByRegistrarId(login.getClientId());
if (!freshRegistrar.isPresent()) {
if (freshRegistrar.isEmpty()) {
throw new BadRegistrarIdException(login.getClientId());
}
tm().put(freshRegistrar.get().asBuilder().setPassword(newPassword).build());
@@ -118,6 +118,14 @@ public class GcsUtils implements Serializable {
storage().delete(blobId);
}
/** Update file content type on existing GCS file */
public void updateContentType(BlobId blobId, String contentType) throws StorageException {
if (existsAndNotEmpty(blobId)) {
Blob blob = storage().get(blobId);
blob.toBuilder().setContentType(contentType).build().update();
}
}
/**
* Returns a list of all object names within a bucket for a given prefix.
*
@@ -539,7 +539,7 @@ public class DomainBase extends EppResource
for (GracePeriod gracePeriod : almostBuilt.getGracePeriods()) {
if (isBeforeOrAt(gracePeriod.getExpirationTime(), now)) {
builder.removeGracePeriod(gracePeriod);
if (!newLastEppUpdateTime.isPresent()
if (newLastEppUpdateTime.isEmpty()
|| isBeforeOrAt(newLastEppUpdateTime.get(), gracePeriod.getExpirationTime())) {
newLastEppUpdateTime = Optional.of(gracePeriod.getExpirationTime());
}
@@ -219,7 +219,7 @@ public final class RegistryLock extends UpdateAutoTimestampEntity implements Bui
/** Returns true iff the lock was requested &gt;= 1 hour ago and has not been verified. */
public boolean isLockRequestExpired(DateTime now) {
return !getLockCompletionTime().isPresent()
return getLockCompletionTime().isEmpty()
&& isBeforeOrAt(getLockRequestTime(), now.minusHours(1));
}
@@ -227,7 +227,7 @@ public final class RegistryLock extends UpdateAutoTimestampEntity implements Bui
public boolean isUnlockRequestExpired(DateTime now) {
Optional<DateTime> unlockRequestTimestamp = getUnlockRequestTime();
return unlockRequestTimestamp.isPresent()
&& !getUnlockCompletionTime().isPresent()
&& getUnlockCompletionTime().isEmpty()
&& isBeforeOrAt(unlockRequestTimestamp.get(), now.minusHours(1));
}
@@ -22,6 +22,7 @@ import static google.registry.model.domain.token.AllocationToken.TokenStatus.CAN
import static google.registry.model.domain.token.AllocationToken.TokenStatus.ENDED;
import static google.registry.model.domain.token.AllocationToken.TokenStatus.NOT_STARTED;
import static google.registry.model.domain.token.AllocationToken.TokenStatus.VALID;
import static google.registry.model.domain.token.AllocationToken.TokenType.REGISTER_BSA;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.forceEmptyToNull;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
@@ -120,18 +121,37 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
/** Type of the token that indicates how and where it should be used. */
public enum TokenType {
/** Token used for bulk pricing */
BULK_PRICING,
BULK_PRICING(/* isOneTimeUse= */ false),
/** Token saved on a TLD to use if no other token is passed from the client */
DEFAULT_PROMO,
DEFAULT_PROMO(/* isOneTimeUse= */ false),
/** This is the old name for what is now BULK_PRICING. */
// TODO(sarahbot@): Remove this type once all tokens of this type have been scrubbed from the
// database
@Deprecated
PACKAGE,
PACKAGE(/* isOneTimeUse= */ false),
/** Invalid after use */
SINGLE_USE,
SINGLE_USE(/* isOneTimeUse= */ true),
/** Do not expire after use */
UNLIMITED_USE,
UNLIMITED_USE(/* isOneTimeUse= */ false),
/**
* Allows bypassing the BSA check during domain creation, otherwise has the same semantics as
* {@link #SINGLE_USE}.
*
* <p>This token applies to a single domain only. If the domain is not blocked by BSA at the
* redemption time this token is processed like {@code SINGLE_USE}, as mentioned above.
*/
REGISTER_BSA(/* isOneTimeUse= */ true);
private final boolean isOneTimeUse;
private TokenType(boolean isOneTimeUse) {
this.isOneTimeUse = isOneTimeUse;
}
/** Returns true if token should be invalidated after use. */
public boolean isOneTimeUse() {
return this.isOneTimeUse;
}
}
/**
@@ -361,12 +381,11 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
|| !getInstance().discountPremiums,
"Bulk tokens cannot discount premium names");
checkArgument(
getInstance().domainName == null || TokenType.SINGLE_USE.equals(getInstance().tokenType),
"Domain name can only be specified for SINGLE_USE tokens");
getInstance().domainName == null || getInstance().tokenType.isOneTimeUse(),
"Domain name can only be specified for SINGLE_USE or REGISTER_BSA tokens");
checkArgument(
getInstance().redemptionHistoryId == null
|| TokenType.SINGLE_USE.equals(getInstance().tokenType),
"Redemption history entry can only be specified for SINGLE_USE tokens");
getInstance().redemptionHistoryId == null || getInstance().tokenType.isOneTimeUse(),
"Redemption history entry can only be specified for SINGLE_USE or REGISTER_BSA tokens");
checkArgument(
getInstance().tokenType != TokenType.BULK_PRICING
|| (getInstance().allowedClientIds != null
@@ -378,6 +397,10 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
checkArgument(
getInstance().discountFraction > 0 || getInstance().discountYears == 1,
"Discount years can only be specified along with a discount fraction");
if (getInstance().getTokenType().equals(REGISTER_BSA)) {
checkArgumentNotNull(
getInstance().domainName, "REGISTER_BSA tokens must be tied to a domain");
}
if (getInstance().registrationBehavior.equals(RegistrationBehavior.ANCHOR_TENANT)) {
checkArgumentNotNull(
getInstance().domainName, "ANCHOR_TENANT tokens must be tied to a domain");
@@ -46,7 +46,7 @@ public class ServerSecret extends CrossTldSingleton {
// Make sure we're in a transaction and attempt to load any existing secret, then
// create it if it's absent.
Optional<ServerSecret> secret = tm().loadSingleton(ServerSecret.class);
if (!secret.isPresent()) {
if (secret.isEmpty()) {
secret = Optional.of(create(UUID.randomUUID()));
tm().insert(secret.get());
}
@@ -74,6 +74,7 @@ import google.registry.tldconfig.idn.IdnTableEnum;
import google.registry.util.Idn;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
@@ -458,6 +459,8 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
@JsonDeserialize(using = CurrencyDeserializer.class)
CurrencyUnit currency = DEFAULT_CURRENCY;
// TODO(sarahbot@): Remove this field and make createBillingCostTransitions not-null once all TLDs
// are populated with a create cost transition map
/** The per-year billing cost for registering a new domain name. */
@Type(type = JodaMoneyType.TYPE_NAME)
@Columns(
@@ -467,6 +470,12 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
})
Money createBillingCost = DEFAULT_CREATE_BILLING_COST;
// TODO(sarahbot@): Make this field not null and add a default value once field is populated on
// all existing TLDs
/** A property that transitions to different create billing costs at different times. */
@JsonDeserialize(using = TimedTransitionPropertyMoneyDeserializer.class)
TimedTransitionProperty<Money> createBillingCostTransitions;
/** The one-time billing cost for restoring a domain name from the redemption grace period. */
@Type(type = JodaMoneyType.TYPE_NAME)
@Columns(
@@ -676,6 +685,13 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
return createBillingCost;
}
public ImmutableSortedMap<DateTime, Money> getCreateBillingCostTransitions() {
return Objects.requireNonNullElseGet(
createBillingCostTransitions,
() -> TimedTransitionProperty.withInitialValue(getCreateBillingCost()))
.toValueMap();
}
/**
* Returns the add-on cost of a domain restore (the flat tld-wide fee charged in addition to one
* year of renewal for that name).
@@ -959,6 +975,17 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
return this;
}
public Builder setCreateBillingCostTransitions(
ImmutableSortedMap<DateTime, Money> createCostsMap) {
checkArgumentNotNull(createCostsMap, "Create billing costs map cannot be null");
checkArgument(
createCostsMap.values().stream().allMatch(Money::isPositiveOrZero),
"Create billing cost cannot be negative");
getInstance().createBillingCostTransitions =
TimedTransitionProperty.fromValueMap(createCostsMap);
return this;
}
public Builder setReservedListsByName(Set<String> reservedListNames) {
// TODO(b/309175133): forbid if enrolled with BSA
checkArgument(reservedListNames != null, "reservedListNames must not be null");
@@ -1131,6 +1158,10 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
// here to catch cases where we loaded an invalid TimedTransitionProperty from the database
// and cloned it into a new builder, to block re-building a Tld in an invalid state.
instance.tldStateTransitions.checkValidity();
// TODO(sarahbot@): Remove null check when createBillingCostTransitions field is made not-null
if (instance.createBillingCostTransitions != null) {
instance.createBillingCostTransitions.checkValidity();
}
instance.renewBillingCostTransitions.checkValidity();
instance.eapFeeSchedule.checkValidity();
// All costs must be in the expected currency.
@@ -115,7 +115,7 @@ public final class PremiumListDao {
*/
public static Optional<Money> getPremiumPrice(String premiumListName, String label) {
Optional<PremiumList> maybeLoadedList = getLatestRevision(premiumListName);
if (!maybeLoadedList.isPresent()) {
if (maybeLoadedList.isEmpty()) {
return Optional.empty();
}
PremiumList loadedList = maybeLoadedList.get();
@@ -14,7 +14,6 @@
package google.registry.module;
import com.google.appengine.api.LifecycleManager;
import com.google.common.flogger.FluentLogger;
import com.google.monitoring.metrics.MetricReporter;
import dagger.Lazy;
@@ -46,25 +45,26 @@ public class ServletBase extends HttpServlet {
public void init() {
Security.addProvider(new BouncyCastleProvider());
// If metric reporter failed to instantiate for any reason (bad keyring, bad json credential,
// etc), we log the error but keep the main thread running. Also the shutdown hook will only be
// registered if metric reporter starts up correctly.
// If the metric reporter failed to instantiate for any reason (bad keyring, bad json
// credential, etc.), we log the error but keep the main thread running. Also, the shutdown hook
// will only be registered if the metric reporter starts up correctly.
try {
metricReporter.get().startAsync().awaitRunning(java.time.Duration.ofSeconds(10));
logger.atInfo().log("Started up MetricReporter.");
LifecycleManager.getInstance()
.setShutdownHook(
() -> {
try {
metricReporter
.get()
.stopAsync()
.awaitTerminated(java.time.Duration.ofSeconds(10));
logger.atInfo().log("Shut down MetricReporter.");
} catch (TimeoutException e) {
logger.atSevere().withCause(e).log("Failed to stop MetricReporter.");
}
});
Runtime.getRuntime()
.addShutdownHook(
new Thread(
() -> {
try {
metricReporter
.get()
.stopAsync()
.awaitTerminated(java.time.Duration.ofSeconds(10));
logger.atInfo().log("Shut down MetricReporter.");
} catch (TimeoutException e) {
logger.atSevere().withCause(e).log("Failed to stop MetricReporter.");
}
}));
} catch (Exception e) {
logger.atSevere().withCause(e).log("Failed to initialize MetricReporter.");
}
@@ -203,6 +203,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
return transact(work, null);
}
@Override
public <T> T transactNoRetry(
Callable<T> work, @Nullable TransactionIsolationLevel isolationLevel) {
if (inTransaction()) {
@@ -63,6 +63,18 @@ public interface TransactionManager {
*/
<T> T transact(Callable<T> work, TransactionIsolationLevel isolationLevel);
/**
* Executes the work in a transaction at the given {@link TransactionIsolationLevel} and returns
* the result, without retrying upon retryable exceptions.
*
* <p>This method should only be used when the transaction contains side effects that are not
* rolled back by the transaction manager, for example in {@link
* google.registry.beam.common.RegistryJpaIO} where the results from a query are streamed to the
* next transformation inside a transaction, as the result stream has to materialize to a list
* outside a transaction and doing so would greatly affect the parallelism of the pipeline.
*/
<T> T transactNoRetry(Callable<T> work, TransactionIsolationLevel isolationLevel);
/**
* Executes the work in a (potentially wrapped) transaction and returns the result.
*
@@ -387,7 +387,7 @@ abstract class AbstractJsonableObject implements Jsonable {
*/
static void verifyAllowedJsonKeyName(String name, @Nullable Member member, Class<?> clazz) {
Optional<ImmutableSet<String>> allowedFieldNames = getNameRestriction(clazz);
if (!allowedFieldNames.isPresent()) {
if (allowedFieldNames.isEmpty()) {
return;
}
checkState(
@@ -416,7 +416,7 @@ abstract class AbstractJsonableObject implements Jsonable {
// We ignore any Optional that are empty, as if they didn't exist at all
if (object instanceof Optional) {
Optional<?> optional = (Optional<?>) object;
if (!optional.isPresent()) {
if (optional.isEmpty()) {
return;
}
object = optional.get();
@@ -64,7 +64,7 @@ public class RdapDomainAction extends RdapActionBase {
Domain.class,
pathSearchString,
shouldIncludeDeleted() ? START_OF_TIME : rdapJsonFormatter.getRequestTime());
if (!domain.isPresent() || !isAuthorized(domain.get())) {
if (domain.isEmpty() || !isAuthorized(domain.get())) {
// RFC7480 5.3 - if the server wishes to respond that it doesn't have data satisfying the
// query, it MUST reply with 404 response code.
//
@@ -342,7 +342,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
Host.class,
partialStringQuery.getInitialString(),
shouldIncludeDeleted() ? START_OF_TIME : getRequestTime());
return (!host.isPresent()
return (host.isEmpty()
|| !desiredRegistrar.get().equals(host.get().getPersistedCurrentSponsorRegistrarId()))
? ImmutableList.of()
: ImmutableList.of(host.get().createVKey());
@@ -121,7 +121,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
// Check the subtype.
Subtype subtype;
if (!subtypeParam.isPresent() || subtypeParam.get().equalsIgnoreCase("all")) {
if (subtypeParam.isEmpty() || subtypeParam.get().equalsIgnoreCase("all")) {
subtype = Subtype.ALL;
} else if (subtypeParam.get().equalsIgnoreCase("contacts")) {
subtype = Subtype.CONTACTS;
@@ -133,7 +133,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
CursorType cursorType;
Optional<String> cursorQueryString;
if (!cursorString.isPresent()) {
if (cursorString.isEmpty()) {
cursorType = CursorType.NONE;
cursorQueryString = Optional.empty();
} else {
@@ -101,7 +101,7 @@ public final class RdapModule {
@Provides
static RdapAuthorization provideRdapAuthorization(
AuthResult authResult, AuthenticatedRegistrarAccessor registrarAccessor) {
if (!authResult.userAuthInfo().isPresent()) {
if (authResult.userAuthInfo().isEmpty()) {
return RdapAuthorization.PUBLIC_AUTHORIZATION;
}
UserAuthInfo userAuthInfo = authResult.userAuthInfo().get();
@@ -66,7 +66,7 @@ public class RdapNameserverAction extends RdapActionBase {
Host.class,
pathSearchString,
shouldIncludeDeleted() ? START_OF_TIME : getRequestTime());
if (!host.isPresent() || !isAuthorized(host.get())) {
if (host.isEmpty() || !isAuthorized(host.get())) {
// RFC7480 5.3 - if the server wishes to respond that it doesn't have data satisfying the
// query, it MUST reply with 404 response code.
//
@@ -175,7 +175,7 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
RdapSearchPattern partialStringQuery) {
Optional<Domain> domain =
loadByForeignKeyCached(Domain.class, partialStringQuery.getSuffix(), getRequestTime());
if (!domain.isPresent()) {
if (domain.isEmpty()) {
// Don't allow wildcards with suffixes which are not domains we manage. That would risk a
// table scan in many easily foreseeable cases. The user might ask for ns*.zombo.com,
// forcing us to query for all hosts beginning with ns, then filter for those ending in
@@ -121,7 +121,7 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
*/
protected boolean shouldBeVisible(EppResource eppResource) {
return isAuthorized(eppResource)
&& (!registrarParam.isPresent()
&& (registrarParam.isEmpty()
|| registrarParam.get().equals(eppResource.getPersistedCurrentSponsorRegistrarId()));
}
@@ -135,7 +135,7 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
*/
protected boolean shouldBeVisible(Registrar registrar) {
return isAuthorized(registrar)
&& (!registrarParam.isPresent() || registrarParam.get().equals(registrar.getRegistrarId()));
&& (registrarParam.isEmpty() || registrarParam.get().equals(registrar.getRegistrarId()));
}
/**
@@ -99,7 +99,7 @@ public final class RdeReportAction implements Runnable, EscrowTask {
RdeRevision.getCurrentRevision(tld, watermark, FULL)
.orElseThrow(
() -> new IllegalStateException("RdeRevision was not set on generated deposit"));
if (!prefix.isPresent()) {
if (prefix.isEmpty()) {
prefix = Optional.of(findMostRecentPrefixForWatermark(watermark, bucket, tld, gcsUtils));
}
String name = prefix.get() + RdeNamingUtils.makeRydeFilename(tld, watermark, FULL, 1, revision);
@@ -23,7 +23,6 @@ import static google.registry.util.DomainNameUtils.canonicalizeHostname;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.api.client.http.HttpMethods;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.config.RegistryConfig.Config;
@@ -107,7 +106,7 @@ public class RdeReporter {
}
/**
* Unmarshals IIRDEA XML result object from {@link HTTPResponse} payload.
* Unmarshall IIRDEA XML result object from HTTP response payload.
*
* @see <a
* href="http://tools.ietf.org/html/draft-lozano-icann-registry-interfaces-05#section-4.1">
@@ -352,7 +352,7 @@ public final class RdeStagingAction implements Runnable {
}
private ImmutableSetMultimap<String, PendingDeposit> getManualPendingDeposits() {
if (!directory.isPresent()) {
if (directory.isEmpty()) {
throw new BadRequestException("Directory parameter required in manual operation");
}
if (directory.get().startsWith("/")) {
@@ -138,7 +138,7 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
public void runWithLock(final DateTime watermark) throws Exception {
// If a prefix is not provided,try to determine the prefix. This should only happen when the RDE
// upload cron job runs to catch up any un-retried (i. e. expected) RDE failures.
if (!prefix.isPresent()) {
if (prefix.isEmpty()) {
prefix = Optional.of(findMostRecentPrefixForWatermark(watermark, bucket, tld, gcsUtils));
}
logger.atInfo().log("Verifying readiness to upload the RDE deposit.");
@@ -161,7 +161,7 @@ final class RydeEncryption {
.filter(ciphertext -> ciphertext.getKeyID() == privateKey.getKeyID())
.findAny();
// If we can't find one with our key ID, then we can't decrypt the file!
if (!cyphertext.isPresent()) {
if (cyphertext.isEmpty()) {
String keyIds =
PgpUtils.stream(ciphertextList, PGPPublicKeyEncryptedData.class)
.map(ciphertext -> Long.toHexString(ciphertext.getKeyID()))
@@ -15,20 +15,17 @@
package google.registry.reporting.billing;
import static com.google.common.base.Throwables.getRootCause;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.StorageException;
import com.google.common.collect.ImmutableList;
import com.google.common.io.CharStreams;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.config.RegistryConfig.Config;
import google.registry.gcs.GcsUtils;
import google.registry.groups.GmailClient;
import google.registry.reporting.billing.BillingModule.InvoiceDirectoryPrefix;
import google.registry.util.EmailMessage;
import google.registry.util.EmailMessage.Attachment;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Optional;
import javax.inject.Inject;
import javax.mail.internet.InternetAddress;
@@ -37,6 +34,7 @@ import org.joda.time.YearMonth;
/** Utility functions for sending emails involving monthly invoices. */
public class BillingEmailUtils {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final GmailClient gmailClient;
private final YearMonth yearMonth;
private final InternetAddress outgoingEmailAddress;
@@ -46,6 +44,7 @@ public class BillingEmailUtils {
private final String billingBucket;
private final String invoiceFilePrefix;
private final String invoiceDirectoryPrefix;
private final String billingInvoiceOriginUrl;
private final GcsUtils gcsUtils;
@Inject
@@ -58,6 +57,7 @@ public class BillingEmailUtils {
@Config("invoiceReplyToEmailAddress") Optional<InternetAddress> replyToEmailAddress,
@Config("billingBucket") String billingBucket,
@Config("invoiceFilePrefix") String invoiceFilePrefix,
@Config("billingInvoiceOriginUrl") String billingInvoiceOriginUrl,
@InvoiceDirectoryPrefix String invoiceDirectoryPrefix,
GcsUtils gcsUtils) {
this.gmailClient = gmailClient;
@@ -69,31 +69,36 @@ public class BillingEmailUtils {
this.billingBucket = billingBucket;
this.invoiceFilePrefix = invoiceFilePrefix;
this.invoiceDirectoryPrefix = invoiceDirectoryPrefix;
this.billingInvoiceOriginUrl = billingInvoiceOriginUrl;
this.gcsUtils = gcsUtils;
}
/** Sends an e-mail to all expected recipients with an attached overall invoice from GCS. */
void emailOverallInvoice() {
public void emailOverallInvoice() {
try {
String invoiceFile = String.format("%s-%s.csv", invoiceFilePrefix, yearMonth);
String fileUrl = billingInvoiceOriginUrl + invoiceDirectoryPrefix + invoiceFile;
BlobId invoiceFilename = BlobId.of(billingBucket, invoiceDirectoryPrefix + invoiceFile);
try (InputStream in = gcsUtils.openInputStream(invoiceFilename)) {
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setSubject(String.format("Domain Registry invoice data %s", yearMonth))
.setBody(
String.format("Attached is the %s invoice for the domain registry.", yearMonth))
.setFrom(outgoingEmailAddress)
.setRecipients(invoiceEmailRecipients)
.setReplyToEmailAddress(replyToEmailAddress)
.setAttachment(
Attachment.newBuilder()
.setContent(CharStreams.toString(new InputStreamReader(in, UTF_8)))
.setContentType(MediaType.CSV_UTF_8)
.setFilename(invoiceFile)
.build())
.build());
try {
gcsUtils.updateContentType(invoiceFilename, "text/csv");
} catch (StorageException e) {
// We want to continue with email anyway, it just will be less convenient for billing team
// to process the file.
logger.atWarning().withCause(e).log("Failed to update invoice file type");
}
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setSubject(String.format("Domain Registry invoice data %s", yearMonth))
.setBody(
String.format(
"<p>Use the following link to download %s invoice for the domain registry -"
+ " <a href=\"%s\">invoice</a>.</p>",
yearMonth, fileUrl))
.setFrom(outgoingEmailAddress)
.setRecipients(invoiceEmailRecipients)
.setReplyToEmailAddress(replyToEmailAddress)
.setContentType(MediaType.HTML_UTF_8)
.build());
} catch (Throwable e) {
// Strip one layer, because callWithRetry wraps in a RuntimeException
sendAlertEmail(
@@ -104,7 +104,7 @@ public final class CopyDetailReportsAction implements Runnable {
// TODO(larryruili): Determine a safer way of enforcing this.
String registrarId = Iterables.get(Splitter.on('_').split(detailReportName), 3);
Optional<Registrar> registrar = Registrar.loadByRegistrarId(registrarId);
if (!registrar.isPresent()) {
if (registrar.isEmpty()) {
logger.atWarning().log(
"Registrar %s not found in database for file '%s'.", registrar, detailReportName);
continue;
@@ -132,7 +132,7 @@ public class RequestHandler<C> {
}
String path = req.getRequestURI();
Optional<Route> route = router.route(path);
if (!route.isPresent()) {
if (route.isEmpty()) {
logger.atInfo().log("No action found for: %s", path);
rsp.sendError(SC_NOT_FOUND);
return;
@@ -144,7 +144,7 @@ public class RequestHandler<C> {
}
Optional<AuthResult> authResult =
requestAuthenticator.authorize(route.get().action().auth().authSettings(), req);
if (!authResult.isPresent()) {
if (authResult.isEmpty()) {
rsp.sendError(SC_FORBIDDEN, "Not authorized");
return;
}
@@ -262,7 +262,7 @@ public class AuthenticatedRegistrarAccessor {
Lazy<GroupsConnection> lazyGroupsConnection,
String userEmail,
Optional<String> gSuiteSupportGroupEmailAddress) {
if (!gSuiteSupportGroupEmailAddress.isPresent()) {
if (gSuiteSupportGroupEmailAddress.isEmpty()) {
return false;
}
try {
@@ -282,7 +282,7 @@ public class AuthenticatedRegistrarAccessor {
AuthResult authResult,
Optional<String> gSuiteSupportGroupEmailAddress,
Lazy<GroupsConnection> lazyGroupsConnection) {
if (!authResult.userAuthInfo().isPresent()) {
if (authResult.userAuthInfo().isEmpty()) {
return false;
}
@@ -300,7 +300,7 @@ public class AuthenticatedRegistrarAccessor {
/** Returns a map of registrar IDs to roles for all registrars that the user has access to. */
private static ImmutableSetMultimap<String, Role> createRoleMap(
AuthResult authResult, boolean isAdmin, String registryAdminRegistrarId) {
if (!authResult.userAuthInfo().isPresent()) {
if (authResult.userAuthInfo().isEmpty()) {
return ImmutableSetMultimap.of();
}
ImmutableSetMultimap.Builder<String, Role> builder = new ImmutableSetMultimap.Builder<>();
@@ -24,8 +24,8 @@ import com.google.common.collect.ImmutableSortedSet;
import com.google.common.flogger.FluentLogger;
import com.google.common.util.concurrent.UncheckedExecutionException;
import google.registry.model.server.Lock;
import google.registry.util.AppEngineTimeLimiter;
import google.registry.util.Clock;
import google.registry.util.TimeLimiter;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
@@ -82,7 +82,7 @@ public class LockHandlerImpl implements LockHandler {
DateTime startTime = clock.nowUtc();
String sanitizedTld = Strings.emptyToNull(tld);
try {
return AppEngineTimeLimiter.create()
return TimeLimiter.create()
.callWithTimeout(
new LockingCallable(callable, lockAcquirer, sanitizedTld, leaseLength, lockNames),
leaseLength.minus(LOCK_TIMEOUT_FUDGE).getMillis(),
@@ -147,7 +147,7 @@ public class LockHandlerImpl implements LockHandler {
try {
for (String lockName : lockNames) {
Optional<Lock> lock = lockAcquirer.acquireLock(lockName, tld, leaseLength);
if (!lock.isPresent()) {
if (lock.isEmpty()) {
logger.atInfo().log("Couldn't acquire lock named: %s for TLD %s.", lockName, tld);
return false;
}
@@ -1,41 +0,0 @@
// Copyright 2018 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.tools;
import com.google.api.services.appengine.v1.Appengine;
import dagger.Module;
import dagger.Provides;
import google.registry.config.CredentialModule.LocalCredential;
import google.registry.config.RegistryConfig.Config;
import google.registry.util.GoogleCredentialsBundle;
import javax.inject.Singleton;
/** Module providing the instance of {@link Appengine} to access App Engine Admin Api. */
@Module
public abstract class AppEngineAdminApiModule {
@Provides
@Singleton
public static Appengine provideAppengine(
@LocalCredential GoogleCredentialsBundle credentialsBundle,
@Config("projectId") String projectId) {
return new Appengine.Builder(
credentialsBundle.getHttpTransport(),
credentialsBundle.getJsonFactory(),
credentialsBundle.getHttpRequestInitializer())
.setApplicationName(projectId)
.build();
}
}
@@ -14,6 +14,7 @@
package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.model.tld.Tld.Builder.ROID_SUFFIX_PATTERN;
import static google.registry.model.tld.Tlds.getTlds;
import static google.registry.util.ListNamingUtils.convertFilePathToName;
@@ -28,10 +29,12 @@ import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import com.google.common.flogger.FluentLogger;
import google.registry.model.common.TimedTransitionProperty;
import google.registry.model.tld.Tld;
import google.registry.model.tld.label.PremiumList;
import google.registry.model.tld.label.PremiumListDao;
import google.registry.tools.params.PathParameter;
import google.registry.util.Clock;
import google.registry.util.Idn;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@@ -40,9 +43,11 @@ import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.inject.Inject;
import javax.inject.Named;
import org.joda.money.CurrencyUnit;
@@ -90,6 +95,8 @@ public class ConfigureTldCommand extends MutatingCommand {
@Inject ObjectMapper mapper;
@Inject Clock clock;
@Inject
@Named("dnsWriterNames")
Set<String> validDnsWriterNames;
@@ -105,11 +112,20 @@ public class ConfigureTldCommand extends MutatingCommand {
@Override
protected void init() throws Exception {
if (RegistryToolEnvironment.get().equals(RegistryToolEnvironment.PRODUCTION)) {
checkArgument(
buildEnv || breakGlass != null,
"Either the --break_glass or --build_environment flag must be used when"
+ " running the configure_tld command on Production");
}
String name = convertFilePathToName(inputFile);
Map<String, Object> tldData = new Yaml().load(Files.newBufferedReader(inputFile));
checkName(name, tldData);
checkForMissingFields(tldData);
Tld oldTld = getTlds().contains(name) ? Tld.get(name) : null;
checkForMissingFields(
Stream.concat(tldData.keySet().stream(), Stream.of("createBillingCostTransitions"))
.collect(toImmutableSet()));
Tld newTld = mapper.readValue(inputFile.toFile(), Tld.class);
if (oldTld != null) {
oldTldInBreakGlass = oldTld.getBreakglassMode();
@@ -140,6 +156,14 @@ public class ConfigureTldCommand extends MutatingCommand {
checkPremiumList(newTld);
checkDnsWriters(newTld);
checkCurrency(newTld);
// TODO(sarahbot@): Remove this once the createBillingCost field is removed
checkArgument(
Objects.equals(
TimedTransitionProperty.fromValueMap(newTld.getCreateBillingCostTransitions())
.getValueAtTime(clock.nowUtc()),
newTld.getCreateBillingCost()),
"The createBillingCostTransitions map must have the same current cost as the"
+ " createBillingCost field");
// bsaEnrollStartTime only exists in DB. Need to carry it over to the updated copy. See Tld.java
// for more information.
Optional<DateTime> bsaEnrollTime =
@@ -192,7 +216,7 @@ public class ConfigureTldCommand extends MutatingCommand {
ROID_SUFFIX_PATTERN.pattern());
}
private void checkForMissingFields(Map<String, Object> tldData) {
private void checkForMissingFields(ImmutableSet<String> keySet) {
Set<String> tldFields =
Arrays.stream(Tld.class.getDeclaredFields())
.filter(field -> !Modifier.isStatic(field.getModifiers()))
@@ -201,7 +225,7 @@ public class ConfigureTldCommand extends MutatingCommand {
.collect(Collectors.toSet());
Set<String> missingFields = new HashSet<>();
for (String field : tldFields) {
if (!tldData.containsKey(field)) {
if (!keySet.contains(field)) {
missingFields.add(field);
}
}
@@ -213,7 +237,7 @@ public class ConfigureTldCommand extends MutatingCommand {
private void checkPremiumList(Tld newTld) {
Optional<String> premiumListName = newTld.getPremiumListName();
if (!premiumListName.isPresent()) {
if (premiumListName.isEmpty()) {
return;
}
Optional<PremiumList> premiumList = PremiumListDao.getLatestRevision(premiumListName.get());
@@ -31,7 +31,7 @@ public final class CreateBulkPricingPackageCommand extends CreateOrUpdateBulkPri
@Override
BulkPricingPackage getOldBulkPricingPackage(String tokenString) {
checkArgument(
!BulkPricingPackage.loadByTokenString(tokenString).isPresent(),
BulkPricingPackage.loadByTokenString(tokenString).isEmpty(),
"BulkPricingPackage with token %s already exists",
tokenString);
return null;
@@ -292,8 +292,8 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
}
if (!isNullOrEmpty(email)) {
builder.setEmailAddress(email);
} else if (!isNullOrEmpty(
icannReferralEmail)) { // fall back to ICANN referral email if present
} else if (!isNullOrEmpty(icannReferralEmail) && oldRegistrar == null) {
// On creates, fall back to ICANN referral email (if present).
builder.setEmailAddress(icannReferralEmail);
}
if (url != null) {
@@ -47,7 +47,7 @@ public class CreatePremiumListCommand extends CreateOrUpdatePremiumListCommand {
currency = CurrencyUnit.of(currencyUnit);
name = Strings.isNullOrEmpty(name) ? convertFilePathToName(inputFile) : name;
checkArgument(
!PremiumListDao.getLatestRevision(name).isPresent(),
PremiumListDao.getLatestRevision(name).isEmpty(),
"A premium list already exists by this name");
if (!override) {
assertTldExists(
@@ -81,9 +81,7 @@ final class CreateRegistrarCommand extends CreateOrUpdateRegistrarCommand
clientId);
}
checkState(
!Registrar.loadByRegistrarId(clientId).isPresent(),
"Registrar %s already exists",
clientId);
Registrar.loadByRegistrarId(clientId).isEmpty(), "Registrar %s already exists", clientId);
List<Registrar> collisions =
Streams.stream(Registrar.loadAll())
.filter(registrar -> normalizeRegistrarId(registrar.getRegistrarId()).equals(clientId))
@@ -47,8 +47,7 @@ final class CreateReservedListCommand extends CreateOrUpdateReservedListCommand
@Override
protected String prompt() throws Exception {
name = Strings.isNullOrEmpty(name) ? convertFilePathToName(input) : name;
checkArgument(
!ReservedList.get(name).isPresent(), "A reserved list already exists by this name");
checkArgument(ReservedList.get(name).isEmpty(), "A reserved list already exists by this name");
if (!override) {
validateListName(name);
}
@@ -28,8 +28,7 @@ public class CreateUserCommand extends CreateOrUpdateUserCommand {
@Nullable
@Override
User getExistingUser(String email) {
checkArgument(
!UserDao.loadUser(email).isPresent(), "A user with email %s already exists", email);
checkArgument(UserDao.loadUser(email).isEmpty(), "A user with email %s already exists", email);
return null;
}
}
@@ -18,7 +18,6 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Iterables.partition;
import static com.google.common.collect.Streams.stream;
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.beust.jcommander.Parameter;
@@ -77,8 +76,8 @@ final class DeleteAllocationTokensCommand extends UpdateOrDeleteAllocationTokens
// since the query ran. This also filters out per-domain tokens if they're not to be deleted.
ImmutableSet<VKey<AllocationToken>> tokensToDelete =
tm().loadByKeys(batch).values().stream()
.filter(t -> withDomains || !t.getDomainName().isPresent())
.filter(t -> SINGLE_USE.equals(t.getTokenType()))
.filter(t -> withDomains || t.getDomainName().isEmpty())
.filter(t -> t.getTokenType().isOneTimeUse())
.filter(t -> !t.isRedeemed())
.map(AllocationToken::createVKey)
.collect(toImmutableSet());

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