mirror of
https://github.com/google/nomulus
synced 2026-06-09 16:33:02 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fa721e82ff | |||
| d4faa77ee4 | |||
| 96d3d88c2f | |||
| 213e06f02e | |||
| d5445dd049 | |||
| af5adcb0ba | |||
| ca238a8578 | |||
| 1a8f133d54 | |||
| 233ee09efe | |||
| 35ff768176 | |||
| c4e5bc913e | |||
| 0241937dee | |||
| 68b46735cd | |||
| bfeaf4a23e | |||
| 5f9f157494 | |||
| c23eed6ec4 | |||
| 04a4431d6a | |||
| d9c5d71f40 | |||
| 75f09c2fdf | |||
| 74f0a8dd7b | |||
| 092e3dca47 | |||
| b8a6ac72dd |
@@ -6,13 +6,13 @@ com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,test
|
||||
com.github.ben-manes.caffeine:caffeine:3.1.8=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.auto.value:auto-value-annotations:1.10.4=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.11.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.auto:auto-common:1.2.1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
|
||||
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.26.1=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.28.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle
|
||||
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
@@ -24,13 +24,13 @@ com.google.guava:failureaccess:1.0.2=compileClasspath,deploy_jar,runtimeClasspat
|
||||
com.google.guava:guava-parent:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.guava:guava:31.0.1-jre=checkstyle
|
||||
com.google.guava:guava:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.guava:guava:33.2.1-jre=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.guava:guava:33.2.1-android=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle,compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.j2objc:j2objc-annotations:1.3=checkstyle
|
||||
com.google.j2objc:j2objc-annotations:3.0.0=compileClasspath,testCompileClasspath,testingCompileClasspath
|
||||
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.truth:truth:1.4.2=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.truth:truth:1.4.3=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.puppycrawl.tools:checkstyle:9.3=checkstyle
|
||||
commons-beanutils:commons-beanutils:1.9.4=checkstyle
|
||||
commons-collections:commons-collections:3.2.2=checkstyle
|
||||
@@ -54,6 +54,7 @@ org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
|
||||
org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
|
||||
org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
|
||||
org.javassist:javassist:3.28.0-GA=checkstyle
|
||||
org.jspecify:jspecify:0.3.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
@@ -62,7 +63,8 @@ org.junit:junit-bom:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-commons:9.6=jacocoAnt
|
||||
org.ow2.asm:asm-tree:9.6=jacocoAnt
|
||||
org.ow2.asm:asm:9.6=compileClasspath,deploy_jar,jacocoAnt,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
org.ow2.asm:asm:9.6=jacocoAnt
|
||||
org.ow2.asm:asm:9.7=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
org.reflections:reflections:0.10.2=checkstyle
|
||||
empty=testingCompile,testingRuntime,testingRuntimeClasspath
|
||||
|
||||
@@ -26,6 +26,7 @@ import { SettingsComponent } from './settings/settings.component';
|
||||
import UsersComponent from './settings/users/users.component';
|
||||
import WhoisComponent from './settings/whois/whois.component';
|
||||
import { SupportComponent } from './support/support.component';
|
||||
import { RegistryLockVerifyComponent } from './lock/registryLockVerify.component';
|
||||
|
||||
export interface RouteWithIcon extends Route {
|
||||
iconName?: string;
|
||||
@@ -33,6 +34,10 @@ export interface RouteWithIcon extends Route {
|
||||
|
||||
export const routes: RouteWithIcon[] = [
|
||||
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
||||
{
|
||||
path: RegistryLockVerifyComponent.PATH,
|
||||
component: RegistryLockVerifyComponent,
|
||||
},
|
||||
{ path: 'registrars', component: RegistrarComponent },
|
||||
{
|
||||
path: 'home',
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<div class="console-app mat-typography">
|
||||
<app-header (toggleNavOpen)="toggleSidenav()"></app-header>
|
||||
<div class="console-app__global-spinner">
|
||||
<mat-progress-bar
|
||||
mode="indeterminate"
|
||||
*ngIf="globalLoader.isLoading"
|
||||
></mat-progress-bar>
|
||||
</div>
|
||||
<mat-sidenav-container class="console-app__container">
|
||||
<mat-sidenav
|
||||
[mode]="breakpointObserver.isMobileView() ? 'over' : 'side'"
|
||||
@@ -10,9 +16,6 @@
|
||||
<app-navigation />
|
||||
</mat-sidenav>
|
||||
<mat-sidenav-content class="console-app__content-wrapper">
|
||||
<div *ngIf="globalLoader.isLoading" class="console-app__global-spinner">
|
||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||
</div>
|
||||
<div class="console-app__content">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
padding: 0 16px;
|
||||
}
|
||||
&__global-spinner {
|
||||
margin-bottom: 2rem;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import { provideHttpClient } from '@angular/common/http';
|
||||
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
|
||||
import { BillingInfoComponent } from './billingInfo/billingInfo.component';
|
||||
import { DomainListComponent } from './domains/domainList.component';
|
||||
import { RegistryLockComponent } from './domains/registryLock.component';
|
||||
import { HeaderComponent } from './header/header.component';
|
||||
import { HomeComponent } from './home/home.component';
|
||||
import { NavigationComponent } from './navigation/navigation.component';
|
||||
@@ -46,12 +47,14 @@ import WhoisEditComponent from './settings/whois/whoisEdit.component';
|
||||
import { NotificationsComponent } from './shared/components/notifications/notifications.component';
|
||||
import { SelectedRegistrarWrapper } from './shared/components/selectedRegistrarWrapper/selectedRegistrarWrapper.component';
|
||||
import { LocationBackDirective } from './shared/directives/locationBack.directive';
|
||||
import { UserLevelVisibility } from './shared/directives/userLevelVisiblity.directive';
|
||||
import { BreakPointObserverService } from './shared/services/breakPoint.service';
|
||||
import { GlobalLoaderService } from './shared/services/globalLoader.service';
|
||||
import { UserDataService } from './shared/services/userData.service';
|
||||
import { SnackBarModule } from './snackbar.module';
|
||||
import { SupportComponent } from './support/support.component';
|
||||
import { TldsComponent } from './tlds/tlds.component';
|
||||
import { RegistryLockVerifyComponent } from './lock/registryLockVerify.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -63,12 +66,15 @@ import { TldsComponent } from './tlds/tlds.component';
|
||||
HeaderComponent,
|
||||
HomeComponent,
|
||||
LocationBackDirective,
|
||||
UserLevelVisibility,
|
||||
NavigationComponent,
|
||||
NewRegistrarComponent,
|
||||
NotificationsComponent,
|
||||
RegistrarComponent,
|
||||
RegistrarDetailsComponent,
|
||||
RegistryLockComponent,
|
||||
RegistrarSelectorComponent,
|
||||
RegistryLockVerifyComponent,
|
||||
ResourcesComponent,
|
||||
SecurityComponent,
|
||||
SecurityEditComponent,
|
||||
|
||||
@@ -2,6 +2,17 @@
|
||||
<div class="console-app-domains">
|
||||
<h1 class="mat-headline-4">Domains</h1>
|
||||
|
||||
<div
|
||||
class="console-app-domains__actions-wrapper"
|
||||
[hidden]="!domainListService.activeActionComponent"
|
||||
>
|
||||
<ng-container
|
||||
v-if="domainListService.activeActionComponent"
|
||||
*ngComponentOutlet="domainListService.activeActionComponent"
|
||||
>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
@if (!isLoading && totalResults == 0) {
|
||||
<div class="console-app__empty-domains">
|
||||
<h1>
|
||||
@@ -12,83 +23,127 @@
|
||||
<h1>No domains found</h1>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="console-app__domains-table-parent">
|
||||
@if (isLoading) {
|
||||
<div class="console-app__domains-spinner">
|
||||
<mat-spinner />
|
||||
<mat-menu #actions="matMenu">
|
||||
<ng-template matMenuContent let-domainName="domainName">
|
||||
<button mat-menu-item (click)="openRegistryLock(domainName)">
|
||||
<mat-icon>key</mat-icon>
|
||||
<span>Registry Lock</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</mat-menu>
|
||||
<div
|
||||
class="console-app__domains-table-parent"
|
||||
[hidden]="domainListService.activeActionComponent"
|
||||
>
|
||||
<div class="console-app__scrollable-wrapper">
|
||||
<div class="console-app__scrollable">
|
||||
@if (isLoading) {
|
||||
<div class="console-app__domains-spinner">
|
||||
<mat-spinner />
|
||||
</div>
|
||||
}
|
||||
<a
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
href="/console-api/dum-download?registrarId={{
|
||||
registrarService.registrarId()
|
||||
}}"
|
||||
class="console-app-domains__download"
|
||||
>
|
||||
<mat-icon>download</mat-icon>
|
||||
Download domains (.csv)
|
||||
</a>
|
||||
|
||||
<mat-form-field class="console-app__domains-filter">
|
||||
<mat-label>Filter</mat-label>
|
||||
<input
|
||||
type="search"
|
||||
matInput
|
||||
[(ngModel)]="searchTerm"
|
||||
(ngModelChange)="sendInput()"
|
||||
#input
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-table
|
||||
[dataSource]="dataSource"
|
||||
class="mat-elevation-z0"
|
||||
class="console-app__domains-table"
|
||||
>
|
||||
<ng-container matColumnDef="domainName">
|
||||
<mat-header-cell *matHeaderCellDef>Domain Name</mat-header-cell>
|
||||
<mat-cell *matCellDef="let element">{{
|
||||
element.domainName
|
||||
}}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="creationTime">
|
||||
<mat-header-cell *matHeaderCellDef>Creation Time</mat-header-cell>
|
||||
<mat-cell *matCellDef="let element">
|
||||
{{ element.creationTime.creationTime }}
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="registrationExpirationTime">
|
||||
<mat-header-cell *matHeaderCellDef
|
||||
>Expiration Time</mat-header-cell
|
||||
>
|
||||
<mat-cell *matCellDef="let element">
|
||||
{{ element.registrationExpirationTime }}
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="statuses">
|
||||
<mat-header-cell *matHeaderCellDef>Statuses</mat-header-cell>
|
||||
<mat-cell *matCellDef="let element">{{
|
||||
element.statuses
|
||||
}}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="registryLock">
|
||||
<mat-header-cell *matHeaderCellDef
|
||||
>Registry-Locked</mat-header-cell
|
||||
>
|
||||
<mat-cell *matCellDef="let element">{{
|
||||
isDomainLocked(element.domainName)
|
||||
}}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<mat-header-cell *matHeaderCellDef>Actions</mat-header-cell>
|
||||
<mat-cell *matCellDef="let element">
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="actions"
|
||||
[matMenuTriggerData]="{ domainName: element.domainName }"
|
||||
aria-label="Domain actions"
|
||||
>
|
||||
<mat-icon>more_horiz</mat-icon>
|
||||
</button>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row
|
||||
*matHeaderRowDef="displayedColumns"
|
||||
></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
|
||||
|
||||
<!-- Row shown when there is no matching data. -->
|
||||
<mat-row *matNoDataRow>
|
||||
<mat-cell colspan="6">No domains found</mat-cell>
|
||||
</mat-row>
|
||||
</mat-table>
|
||||
<mat-paginator
|
||||
[length]="totalResults"
|
||||
[pageIndex]="pageNumber"
|
||||
[pageSize]="resultsPerPage"
|
||||
[pageSizeOptions]="[10, 25, 50, 100, 500]"
|
||||
(page)="onPageChange($event)"
|
||||
aria-label="Select page of domain results"
|
||||
showFirstLastButtons
|
||||
></mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
} @else {
|
||||
<a
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
href="/console-api/dum-download?registrarId={{
|
||||
registrarService.registrarId()
|
||||
}}"
|
||||
class="console-app-domains__download"
|
||||
>
|
||||
<mat-icon>download</mat-icon>
|
||||
Download domains (.csv)
|
||||
</a>
|
||||
<mat-form-field class="console-app__domains-filter">
|
||||
<mat-label>Filter</mat-label>
|
||||
<input
|
||||
type="search"
|
||||
matInput
|
||||
[(ngModel)]="searchTerm"
|
||||
(ngModelChange)="sendInput()"
|
||||
[disabled]="isLoading"
|
||||
#input
|
||||
/>
|
||||
</mat-form-field>
|
||||
}
|
||||
<mat-table
|
||||
[dataSource]="dataSource"
|
||||
class="mat-elevation-z0"
|
||||
class="console-app__domains-table"
|
||||
>
|
||||
<ng-container matColumnDef="domainName">
|
||||
<mat-header-cell *matHeaderCellDef>Domain Name</mat-header-cell>
|
||||
<mat-cell *matCellDef="let element">{{
|
||||
element.domainName
|
||||
}}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="creationTime">
|
||||
<mat-header-cell *matHeaderCellDef>Creation Time</mat-header-cell>
|
||||
<mat-cell *matCellDef="let element">
|
||||
{{ element.creationTime.creationTime }}
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="registrationExpirationTime">
|
||||
<mat-header-cell *matHeaderCellDef>Expiration Time</mat-header-cell>
|
||||
<mat-cell *matCellDef="let element">
|
||||
{{ element.registrationExpirationTime }}
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="statuses">
|
||||
<mat-header-cell *matHeaderCellDef>Statuses</mat-header-cell>
|
||||
<mat-cell *matCellDef="let element">{{ element.statuses }}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
|
||||
|
||||
<!-- Row shown when there is no matching data. -->
|
||||
<mat-row *matNoDataRow>
|
||||
<mat-cell colspan="4">No domains found</mat-cell>
|
||||
</mat-row>
|
||||
</mat-table>
|
||||
<mat-paginator
|
||||
[length]="totalResults"
|
||||
[pageIndex]="pageNumber"
|
||||
[pageSize]="resultsPerPage"
|
||||
[pageSizeOptions]="[10, 25, 50, 100, 500]"
|
||||
(page)="onPageChange($event)"
|
||||
aria-label="Select page of domain results"
|
||||
showFirstLastButtons
|
||||
></mat-paginator>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -18,11 +18,6 @@
|
||||
right: 0;
|
||||
}
|
||||
|
||||
&__domains {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
&__domains-filter {
|
||||
min-width: $min-width !important;
|
||||
width: 100%;
|
||||
@@ -30,12 +25,17 @@
|
||||
|
||||
&__domains-table-parent {
|
||||
position: relative;
|
||||
width: fit-content;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
&__domains-table {
|
||||
min-width: $min-width !important;
|
||||
.mat-column-actions {
|
||||
max-width: 100px;
|
||||
}
|
||||
.mat-column-registryLock {
|
||||
max-width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
&__domains-spinner {
|
||||
@@ -46,6 +46,7 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.mat-mdc-paginator {
|
||||
|
||||
@@ -19,14 +19,14 @@ import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { Subject, debounceTime } from 'rxjs';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { BackendService } from '../shared/services/backend.service';
|
||||
import { Domain, DomainListService } from './domainList.service';
|
||||
import { RegistryLockComponent } from './registryLock.component';
|
||||
import { RegistryLockService } from './registryLock.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-domain-list',
|
||||
templateUrl: './domainList.component.html',
|
||||
styleUrls: ['./domainList.component.scss'],
|
||||
providers: [DomainListService],
|
||||
})
|
||||
export class DomainListComponent {
|
||||
public static PATH = 'domain-list';
|
||||
@@ -37,6 +37,8 @@ export class DomainListComponent {
|
||||
'creationTime',
|
||||
'registrationExpirationTime',
|
||||
'statuses',
|
||||
'registryLock',
|
||||
'actions',
|
||||
];
|
||||
|
||||
dataSource: MatTableDataSource<Domain> = new MatTableDataSource();
|
||||
@@ -52,15 +54,16 @@ export class DomainListComponent {
|
||||
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
|
||||
|
||||
constructor(
|
||||
private backendService: BackendService,
|
||||
private domainListService: DomainListService,
|
||||
protected domainListService: DomainListService,
|
||||
protected registrarService: RegistrarService,
|
||||
protected registryLockService: RegistryLockService,
|
||||
private _snackBar: MatSnackBar
|
||||
) {
|
||||
effect(() => {
|
||||
this.pageNumber = 0;
|
||||
this.totalResults = 0;
|
||||
if (this.registrarService.registrarId()) {
|
||||
this.loadLocks();
|
||||
this.reloadData();
|
||||
}
|
||||
});
|
||||
@@ -80,6 +83,25 @@ export class DomainListComponent {
|
||||
this.searchTermSubject.complete();
|
||||
}
|
||||
|
||||
openRegistryLock(domainName: string) {
|
||||
this.domainListService.selectedDomain = domainName;
|
||||
this.domainListService.activeActionComponent = RegistryLockComponent;
|
||||
}
|
||||
|
||||
loadLocks() {
|
||||
this.registryLockService.retrieveLocks().subscribe({
|
||||
error: (err: HttpErrorResponse) => {
|
||||
this._snackBar.open(err.message);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
isDomainLocked(domainName: string) {
|
||||
return this.registryLockService.domainsLocks.some(
|
||||
(d) => d.domainName === domainName
|
||||
);
|
||||
}
|
||||
|
||||
reloadData() {
|
||||
this.isLoading = true;
|
||||
this.domainListService
|
||||
@@ -95,7 +117,7 @@ export class DomainListComponent {
|
||||
this.isLoading = false;
|
||||
},
|
||||
next: (domainListResult) => {
|
||||
this.dataSource.data = (domainListResult || {}).domains;
|
||||
this.dataSource.data = this.domainListService.domainsList;
|
||||
this.totalResults = (domainListResult || {}).totalResults || 0;
|
||||
this.isLoading = false;
|
||||
},
|
||||
|
||||
@@ -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, Type } from '@angular/core';
|
||||
import { tap } from 'rxjs';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { BackendService } from '../shared/services/backend.service';
|
||||
@@ -35,9 +35,14 @@ export interface DomainListResult {
|
||||
totalResults: number;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class DomainListService {
|
||||
checkpointTime?: string;
|
||||
selectedDomain?: string;
|
||||
public activeActionComponent: Type<any> | null = null;
|
||||
public domainsList: Domain[] = [];
|
||||
|
||||
constructor(
|
||||
private backendService: BackendService,
|
||||
@@ -62,6 +67,7 @@ export class DomainListService {
|
||||
.pipe(
|
||||
tap((domainListResult: DomainListResult) => {
|
||||
this.checkpointTime = domainListResult?.checkpointTime;
|
||||
this.domainsList = domainListResult?.domains;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
<div class="console-app__registry-lock">
|
||||
<p>
|
||||
<button
|
||||
mat-icon-button
|
||||
aria-label="Back to domains list"
|
||||
(click)="goBack()"
|
||||
>
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
</button>
|
||||
</p>
|
||||
|
||||
@if(!registrarService.registrar()?.registryLockAllowed) {
|
||||
<h1>
|
||||
Sorry, your registrar hasn't enrolled in registry lock yet. To do so, please
|
||||
contact {{ userDataService.userData()?.supportEmail }}.
|
||||
</h1>
|
||||
} @else if (isLocked()) {
|
||||
<h1>Unlock the domain {{ domainListService.selectedDomain }}</h1>
|
||||
<form (ngSubmit)="save(false)" [formGroup]="unlockDomain">
|
||||
<p>
|
||||
<mat-label for="password">Password: </mat-label>
|
||||
<mat-form-field name="password" appearance="outline">
|
||||
<input matInput type="text" formControlName="password" required />
|
||||
</mat-form-field>
|
||||
</p>
|
||||
<p>
|
||||
<mat-label for="relockTime"
|
||||
>Automatically re-lock the domain after:</mat-label
|
||||
>
|
||||
<mat-radio-group
|
||||
name="relockTime"
|
||||
formControlName="relockTime"
|
||||
aria-label="Automatically relock option"
|
||||
>
|
||||
@for (option of relockOptions; track option.name) {
|
||||
<mat-radio-button [value]="option.duration">{{
|
||||
option.name
|
||||
}}</mat-radio-button>
|
||||
}
|
||||
</mat-radio-group>
|
||||
</p>
|
||||
|
||||
<div class="console-app__registry-lock-notification">
|
||||
<mat-icon>priority_high</mat-icon>Confirmation email will be sent to your
|
||||
email address to confirm the unlock
|
||||
</div>
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
type="submit"
|
||||
[disabled]="!unlockDomain.valid"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</form>
|
||||
} @else {
|
||||
<h1>Lock the domain {{ domainListService.selectedDomain }}</h1>
|
||||
<form (ngSubmit)="save(true)" [formGroup]="lockDomain">
|
||||
<p>
|
||||
<mat-label for="password">Password: </mat-label>
|
||||
<mat-form-field name="password" appearance="outline">
|
||||
<input matInput type="text" formControlName="password" required />
|
||||
</mat-form-field>
|
||||
</p>
|
||||
|
||||
<div class="console-app__registry-lock-notification">
|
||||
<mat-icon>priority_high</mat-icon>The lock will not take effect until you
|
||||
click the confirmation link that will be emailed to you. When it takes
|
||||
effect, you will be billed the standard server status change billing cost.
|
||||
</div>
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
type="submit"
|
||||
[disabled]="!lockDomain.valid"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</form>
|
||||
}
|
||||
</div>
|
||||
@@ -0,0 +1,20 @@
|
||||
.console-app {
|
||||
&__registry-lock {
|
||||
mat-label {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
p {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
}
|
||||
&__registry-lock-notification {
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
background-color: var(--light-highlight);
|
||||
margin-bottom: 20px;
|
||||
width: max-content;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { Component, computed } from '@angular/core';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { UserDataService } from '../shared/services/userData.service';
|
||||
import { DomainListService } from './domainList.service';
|
||||
import { RegistryLockService } from './registryLock.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-registry-lock',
|
||||
templateUrl: './registryLock.component.html',
|
||||
styleUrls: ['./registryLock.component.scss'],
|
||||
})
|
||||
export class RegistryLockComponent {
|
||||
readonly isLocked = computed(() =>
|
||||
this.registryLockService.domainsLocks.some(
|
||||
(dl) => dl.domainName === this.domainListService.selectedDomain
|
||||
)
|
||||
);
|
||||
|
||||
relockOptions = [
|
||||
{ name: '1 hour', duration: 3600000 },
|
||||
{ name: '6 hours', duration: 21600000 },
|
||||
{ name: '24 hours', duration: 86400000 },
|
||||
{ name: 'Never', duration: undefined },
|
||||
];
|
||||
|
||||
lockDomain = new FormGroup({
|
||||
password: new FormControl(''),
|
||||
});
|
||||
|
||||
unlockDomain = new FormGroup({
|
||||
password: new FormControl(''),
|
||||
relockTime: new FormControl(undefined),
|
||||
});
|
||||
|
||||
constructor(
|
||||
protected registrarService: RegistrarService,
|
||||
protected domainListService: DomainListService,
|
||||
protected registryLockService: RegistryLockService,
|
||||
protected userDataService: UserDataService,
|
||||
private _snackBar: MatSnackBar
|
||||
) {}
|
||||
|
||||
goBack() {
|
||||
this.domainListService.selectedDomain = undefined;
|
||||
this.domainListService.activeActionComponent = null;
|
||||
}
|
||||
|
||||
save(isLock: boolean) {
|
||||
let request;
|
||||
if (!isLock) {
|
||||
request = this.registryLockService.registryLockDomain(
|
||||
this.domainListService.selectedDomain || '',
|
||||
this.unlockDomain.value.password || '',
|
||||
this.unlockDomain.value.relockTime || undefined,
|
||||
isLock
|
||||
);
|
||||
} else {
|
||||
request = this.registryLockService.registryLockDomain(
|
||||
this.domainListService.selectedDomain || '',
|
||||
this.lockDomain.value.password || '',
|
||||
undefined,
|
||||
isLock
|
||||
);
|
||||
}
|
||||
|
||||
request.subscribe({
|
||||
complete: () => {
|
||||
this.goBack();
|
||||
},
|
||||
error: (err: HttpErrorResponse) => {
|
||||
this._snackBar.open(err.error);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { tap } from 'rxjs';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { BackendService } from '../shared/services/backend.service';
|
||||
|
||||
export interface DomainLocksResult {
|
||||
domainName: string;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class RegistryLockService {
|
||||
public domainsLocks: DomainLocksResult[] = [];
|
||||
|
||||
constructor(
|
||||
private backendService: BackendService,
|
||||
private registrarService: RegistrarService
|
||||
) {}
|
||||
|
||||
retrieveLocks() {
|
||||
return this.backendService
|
||||
.getLocks(this.registrarService.registrarId())
|
||||
.pipe(
|
||||
tap((domainLocksResult) => {
|
||||
this.domainsLocks = domainLocksResult;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
registryLockDomain(
|
||||
domainName: string,
|
||||
password: string,
|
||||
relockDurationMillis: number | undefined,
|
||||
isLock: boolean
|
||||
) {
|
||||
return this.backendService.registryLockDomain(
|
||||
domainName,
|
||||
password,
|
||||
relockDurationMillis,
|
||||
this.registrarService.registrarId(),
|
||||
isLock
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,11 @@
|
||||
&__logo {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
margin-left: -10px;
|
||||
margin-left: -15px;
|
||||
}
|
||||
&__menu-btn {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
}
|
||||
&__header {
|
||||
@@ -32,9 +32,6 @@
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
}
|
||||
|
||||
&-user-icon {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,10 @@
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
|
||||
<mat-card appearance="outlined">
|
||||
<mat-card
|
||||
appearance="outlined"
|
||||
[elementId]="getElementIdForRegistrarsBlock()"
|
||||
>
|
||||
<mat-card-content>
|
||||
<h3>
|
||||
<mat-icon class="secondary-text">account_circle</mat-icon>
|
||||
|
||||
@@ -18,6 +18,7 @@ import { DomainListComponent } from '../domains/domainList.component';
|
||||
import { RegistrarComponent } from '../registrar/registrarsTable.component';
|
||||
import SecurityComponent from '../settings/security/security.component';
|
||||
import { SettingsComponent } from '../settings/settings.component';
|
||||
import { RESTRICTED_ELEMENTS } from '../shared/directives/userLevelVisiblity.directive';
|
||||
import { BreakPointObserverService } from '../shared/services/breakPoint.service';
|
||||
|
||||
@Component({
|
||||
@@ -30,6 +31,9 @@ export class HomeComponent {
|
||||
protected breakPointObserverService: BreakPointObserverService,
|
||||
private router: Router
|
||||
) {}
|
||||
getElementIdForRegistrarsBlock() {
|
||||
return RESTRICTED_ELEMENTS.REGISTRAR_ELEMENT;
|
||||
}
|
||||
viewRegistrars() {
|
||||
this.router.navigate([RegistrarComponent.PATH], {
|
||||
queryParamsHandling: 'merge',
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
@if (isLoading) {
|
||||
<div class="console-app__registry-lock-verify-spinner">
|
||||
<mat-spinner />
|
||||
</div>
|
||||
} @else if (domainName) {
|
||||
<h1 class="mat-headline-4">Success!</h1>
|
||||
<div class="console-app__registry-lock-content">
|
||||
<div class="console-app__registry-lock-subhead">
|
||||
The domain {{ domainName }} has been successfully {{ action }}ed.
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a
|
||||
class="text-l"
|
||||
routerLink="{{ DOMAIN_LIST_COMPONENT_PATH }}"
|
||||
[queryParams]="{ registrarId: this.registrarService.registrarId() }"
|
||||
>Return to the list of domains</a
|
||||
>
|
||||
</div>
|
||||
} @else {
|
||||
<h1 class="mat-headline-4">Failure</h1>
|
||||
<div class="console-app__registry-lock-content">
|
||||
<div class="console-app__registry-lock-subhead">
|
||||
An error occurred: {{ errorMessage }}.<br /><br />Please double-check the
|
||||
verification code and try again.
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
.console-app__registry-lock {
|
||||
&-content {
|
||||
margin-top: 30px;
|
||||
}
|
||||
&-subhead {
|
||||
font-size: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||
import { RegistryLockVerifyService } from './registryLockVerify.service';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { take } from 'rxjs';
|
||||
import { DomainListComponent } from '../domains/domainList.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-registry-lock-verify',
|
||||
templateUrl: './registryLockVerify.component.html',
|
||||
styleUrls: ['./registryLockVerify.component.scss'],
|
||||
providers: [RegistryLockVerifyService],
|
||||
})
|
||||
export class RegistryLockVerifyComponent {
|
||||
public static PATH = 'registry-lock-verify';
|
||||
|
||||
readonly DOMAIN_LIST_COMPONENT_PATH = `/${DomainListComponent.PATH}`;
|
||||
|
||||
isLoading = true;
|
||||
domainName?: string;
|
||||
action?: string;
|
||||
errorMessage?: string;
|
||||
|
||||
constructor(
|
||||
protected registrarService: RegistrarService,
|
||||
protected registryLockVerifyService: RegistryLockVerifyService,
|
||||
private route: ActivatedRoute
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.queryParamMap.pipe(take(1)).subscribe((params: ParamMap) => {
|
||||
this.registryLockVerifyService
|
||||
.verifyRequest(params.get('lockVerificationCode') || '')
|
||||
.subscribe({
|
||||
error: (err: HttpErrorResponse) => {
|
||||
this.isLoading = false;
|
||||
this.errorMessage = err.error;
|
||||
},
|
||||
next: (verificationResponse) => {
|
||||
this.domainName = verificationResponse.domainName;
|
||||
this.action = verificationResponse.action;
|
||||
this.registrarService.registrarId.set(
|
||||
verificationResponse.registrarId
|
||||
);
|
||||
this.isLoading = false;
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BackendService } from '../shared/services/backend.service';
|
||||
|
||||
export interface RegistryLockVerificationResponse {
|
||||
action: string;
|
||||
domainName: string;
|
||||
registrarId: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class RegistryLockVerifyService {
|
||||
constructor(private backendService: BackendService) {}
|
||||
|
||||
verifyRequest(lockVerificationCode: string) {
|
||||
return this.backendService.verifyRegistryLockRequest(lockVerificationCode);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
matTreeNodeToggle
|
||||
(click)="onClick(node)"
|
||||
[class.active]="router.url.includes(node.path)"
|
||||
[elementId]="getElementId(node)"
|
||||
>
|
||||
<mat-icon class="console-app__nav-icon" *ngIf="node.iconName">
|
||||
{{ node.iconName }}
|
||||
|
||||
@@ -44,10 +44,10 @@ $expand-icon-size: 26px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--light-highlight);
|
||||
border-radius: 0 25px 25px 0;
|
||||
border-radius: 0 15px 15px 0;
|
||||
}
|
||||
&.active {
|
||||
border-radius: 0 25px 25px 0;
|
||||
border-radius: 0 15px 15px 0;
|
||||
background-color: var(--lightest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import { MatTreeNestedDataSource } from '@angular/material/tree';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { RouteWithIcon, routes } from '../app-routing.module';
|
||||
import { RESTRICTED_ELEMENTS } from '../shared/directives/userLevelVisiblity.directive';
|
||||
|
||||
interface NavMenuNode extends RouteWithIcon {
|
||||
parentRoute?: RouteWithIcon;
|
||||
@@ -37,6 +38,7 @@ export class NavigationComponent {
|
||||
treeControl = new NestedTreeControl<RouteWithIcon>((node) => node.children);
|
||||
dataSource = new MatTreeNestedDataSource<RouteWithIcon>();
|
||||
private subscription!: Subscription;
|
||||
|
||||
hasChild = (_: number, node: RouteWithIcon) =>
|
||||
!!node.children && node.children.length > 0;
|
||||
|
||||
@@ -56,6 +58,12 @@ export class NavigationComponent {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
|
||||
getElementId(node: RouteWithIcon) {
|
||||
return node.path === 'registrars'
|
||||
? RESTRICTED_ELEMENTS.REGISTRAR_ELEMENT
|
||||
: null;
|
||||
}
|
||||
|
||||
syncExpandedNavigationWithRoute(url: string) {
|
||||
const maybeComponentWithChildren = this.dataSource.data.find((menuNode) => {
|
||||
return (
|
||||
|
||||
@@ -142,7 +142,7 @@ JPY=billing-id-for-yen"
|
||||
<mat-label>State/Region: </mat-label>
|
||||
<input
|
||||
matInput
|
||||
[required]="false"
|
||||
[required]="true"
|
||||
[(ngModel)]="newRegistrar.localizedAddress.state"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="console-app__registrar">
|
||||
<mat-form-field class="example-full-width" appearance="outline">
|
||||
<mat-form-field class="field-small" appearance="outline">
|
||||
<mat-label>Registrar</mat-label>
|
||||
<input
|
||||
type="text"
|
||||
|
||||
@@ -14,41 +14,50 @@
|
||||
Add new registrar
|
||||
</button>
|
||||
</div>
|
||||
<mat-form-field class="console-app__registrars-filter">
|
||||
<mat-label>Search</mat-label>
|
||||
<input
|
||||
matInput
|
||||
(keyup)="applyFilter($event)"
|
||||
placeholder="..."
|
||||
type="search"
|
||||
/>
|
||||
<mat-icon matPrefix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
<mat-table
|
||||
[dataSource]="dataSource"
|
||||
class="mat-elevation-z0"
|
||||
class="console-app__registrars-table"
|
||||
matSort
|
||||
>
|
||||
<ng-container
|
||||
*ngFor="let column of columns"
|
||||
[matColumnDef]="column.columnDef"
|
||||
>
|
||||
<mat-header-cell *matHeaderCellDef> {{ column.header }} </mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" [innerHTML]="column.cell(row)"></mat-cell>
|
||||
</ng-container>
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row
|
||||
*matRowDef="let row; columns: displayedColumns"
|
||||
(click)="openDetails(row.registrarId)"
|
||||
></mat-row>
|
||||
</mat-table>
|
||||
<div class="console-app__scrollable-wrapper">
|
||||
<div class="console-app__scrollable">
|
||||
<mat-form-field class="console-app__registrars-filter">
|
||||
<mat-label>Search</mat-label>
|
||||
<input
|
||||
matInput
|
||||
(keyup)="applyFilter($event)"
|
||||
placeholder="..."
|
||||
type="search"
|
||||
/>
|
||||
<mat-icon matPrefix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
<mat-table
|
||||
[dataSource]="dataSource"
|
||||
class="mat-elevation-z0"
|
||||
class="console-app__registrars-table"
|
||||
matSort
|
||||
>
|
||||
<ng-container
|
||||
*ngFor="let column of columns"
|
||||
[matColumnDef]="column.columnDef"
|
||||
>
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
{{ column.header }}
|
||||
</mat-header-cell>
|
||||
<mat-cell
|
||||
*matCellDef="let row"
|
||||
[innerHTML]="column.cell(row)"
|
||||
></mat-cell>
|
||||
</ng-container>
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row
|
||||
*matRowDef="let row; columns: displayedColumns"
|
||||
(click)="openDetails(row.registrarId)"
|
||||
></mat-row>
|
||||
</mat-table>
|
||||
|
||||
<mat-paginator
|
||||
class="mat-elevation-z0"
|
||||
[pageSizeOptions]="[5, 10, 20]"
|
||||
showFirstLastButtons
|
||||
></mat-paginator>
|
||||
<mat-paginator
|
||||
class="mat-elevation-z0"
|
||||
[pageSizeOptions]="[5, 10, 20]"
|
||||
showFirstLastButtons
|
||||
></mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
.console-app {
|
||||
$min-width: 756px;
|
||||
|
||||
&__registrars {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
&__registrars-filter {
|
||||
min-width: $min-width !important;
|
||||
width: 100%;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="console-app__resources-subhead">Technical resources</div>
|
||||
<a
|
||||
class="text-l"
|
||||
href="{{ userDataService.userData.technicalDocsUrl }}"
|
||||
href="{{ userDataService.userData()?.technicalDocsUrl }}"
|
||||
target="_blank"
|
||||
>View onboarding FAQs, TLD information, and technical documentation on
|
||||
Google Drive</a
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Directive, ElementRef, Input, effect } from '@angular/core';
|
||||
import { UserDataService } from '../services/userData.service';
|
||||
|
||||
export enum RESTRICTED_ELEMENTS {
|
||||
REGISTRAR_ELEMENT,
|
||||
}
|
||||
|
||||
export const DISABLED_ELEMENTS_PER_ROLE = {
|
||||
NONE: [RESTRICTED_ELEMENTS.REGISTRAR_ELEMENT],
|
||||
};
|
||||
|
||||
@Directive({
|
||||
selector: '[elementId]',
|
||||
})
|
||||
export class UserLevelVisibility {
|
||||
@Input() elementId!: RESTRICTED_ELEMENTS | null;
|
||||
|
||||
constructor(
|
||||
private userDataService: UserDataService,
|
||||
private el: ElementRef
|
||||
) {
|
||||
effect(this.processElement.bind(this));
|
||||
}
|
||||
|
||||
processElement() {
|
||||
const globalRole = this.userDataService?.userData()?.globalRole || 'NONE';
|
||||
if (this.elementId === null) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
// @ts-ignore
|
||||
(DISABLED_ELEMENTS_PER_ROLE[globalRole] || []).includes(this.elementId)
|
||||
) {
|
||||
this.el.nativeElement.style.display = 'none';
|
||||
} else {
|
||||
this.el.nativeElement.style.display = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@ import { Injectable } from '@angular/core';
|
||||
import { Observable, catchError, of, throwError } from 'rxjs';
|
||||
|
||||
import { DomainListResult } from 'src/app/domains/domainList.service';
|
||||
import { DomainLocksResult } from 'src/app/domains/registryLock.service';
|
||||
import { RegistryLockVerificationResponse } from 'src/app/lock/registryLockVerify.service';
|
||||
import {
|
||||
Registrar,
|
||||
SecuritySettingsBackendModel,
|
||||
@@ -169,4 +171,38 @@ export class BackendService {
|
||||
whoisRegistrarFields
|
||||
);
|
||||
}
|
||||
|
||||
registryLockDomain(
|
||||
domainName: string,
|
||||
password: string | undefined,
|
||||
relockDurationMillis: number | undefined,
|
||||
registrarId: string,
|
||||
isLock: boolean
|
||||
) {
|
||||
return this.http.post(
|
||||
`/console-api/registry-lock?registrarId=${registrarId}`,
|
||||
{
|
||||
domainName,
|
||||
password,
|
||||
isLock,
|
||||
relockDurationMillis,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
getLocks(registrarId: string): Observable<DomainLocksResult[]> {
|
||||
return this.http
|
||||
.get<DomainLocksResult[]>(
|
||||
`/console-api/registry-lock?registrarId=${registrarId}`
|
||||
)
|
||||
.pipe(catchError((err) => this.errorCatcher<DomainLocksResult[]>(err)));
|
||||
}
|
||||
|
||||
verifyRegistryLockRequest(
|
||||
lockVerificationCode: string
|
||||
): Observable<RegistryLockVerificationResponse> {
|
||||
return this.http.get<RegistryLockVerificationResponse>(
|
||||
`/console-api/registry-lock-verify?lockVerificationCode=${lockVerificationCode}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { Observable, tap } from 'rxjs';
|
||||
import { BackendService } from './backend.service';
|
||||
@@ -33,7 +33,7 @@ export interface UserData {
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class UserDataService implements GlobalLoader {
|
||||
public userData!: UserData;
|
||||
userData = signal<UserData | undefined>(undefined);
|
||||
constructor(
|
||||
private backend: BackendService,
|
||||
protected globalLoader: GlobalLoaderService,
|
||||
@@ -48,7 +48,7 @@ export class UserDataService implements GlobalLoader {
|
||||
getUserData(): Observable<UserData> {
|
||||
return this.backend.getUserData().pipe(
|
||||
tap((userData: UserData) => {
|
||||
this.userData = userData;
|
||||
this.userData.set(userData);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
For general purpose questions once you are integrated with our registry
|
||||
system. If the issue is urgent, please put "Urgent" in the email title.
|
||||
</p>
|
||||
<a class="text-l" href="mailto:{{ userDataService.userData.supportEmail }}">{{
|
||||
userDataService.userData.supportEmail
|
||||
}}</a>
|
||||
<a
|
||||
class="text-l"
|
||||
href="mailto:{{ userDataService.userData()?.supportEmail }}"
|
||||
>{{ userDataService.userData()?.supportEmail }}</a
|
||||
>
|
||||
<p class="secondary-text">
|
||||
Note: You may receive occasional service announcements via
|
||||
registrar-announcement@google.com. You will not be able to reply to
|
||||
@@ -29,13 +31,13 @@
|
||||
<p class="text-l">For general support inquiries 24/7:</p>
|
||||
<a
|
||||
class="text-l"
|
||||
href="tel:{{ userDataService.userData.supportPhoneNumber }}"
|
||||
>{{ userDataService.userData.supportPhoneNumber }}</a
|
||||
href="tel:{{ userDataService.userData()?.supportPhoneNumber }}"
|
||||
>{{ userDataService.userData()?.supportPhoneNumber }}</a
|
||||
>
|
||||
@if (userDataService.userData.passcode) {
|
||||
@if (userDataService.userData()?.passcode) {
|
||||
<p class="text-l">Your telephone passcode:</p>
|
||||
<p class="text-l console-app__support-passcode">
|
||||
{{ userDataService.userData.passcode }}
|
||||
{{ userDataService.userData()?.passcode }}
|
||||
</p>
|
||||
<p class="secondary-text">
|
||||
Note: Please be ready with your account name and telephone passcode when
|
||||
|
||||
@@ -70,4 +70,11 @@ body {
|
||||
.mat-mdc-list-item-unscoped-content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&__scrollable {
|
||||
overflow-x: auto;
|
||||
&-wrapper {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@use "sass:map";
|
||||
@use "sass:math";
|
||||
@use "@angular/material" as mat;
|
||||
@use "@material/textfield";
|
||||
|
||||
$secondary-color: #80868b;
|
||||
$border-color: #dadce0;
|
||||
@@ -131,13 +132,7 @@ $theme: mat.define-theme(
|
||||
html {
|
||||
@include mat.all-component-themes($theme);
|
||||
@include mat.typography-hierarchy($typographyConfig);
|
||||
@include mat.form-field-theme(
|
||||
mat.define-theme(
|
||||
(
|
||||
density: (
|
||||
scale: -3,
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
.field-small {
|
||||
@include mat.form-field-density(-3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,6 +217,7 @@ dependencies {
|
||||
implementation deps['org.bouncycastle:bcpg-jdk18on']
|
||||
implementation deps['org.bouncycastle:bcpkix-jdk18on']
|
||||
implementation deps['org.bouncycastle:bcprov-jdk18on']
|
||||
implementation deps['com.fasterxml.jackson.dataformat:jackson-dataformat-yaml']
|
||||
testImplementation deps['com.fasterxml.jackson.core:jackson-databind']
|
||||
implementation deps['org.hibernate:hibernate-core']
|
||||
implementation deps['org.hibernate:hibernate-hikaricp']
|
||||
|
||||
+151
-151
@@ -8,22 +8,14 @@ args4j:args4j:2.0.26=css
|
||||
args4j:args4j:2.33=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
cglib:cglib-nodep:2.2=css
|
||||
com.charleskorn.kaml:kaml:0.20.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.17.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.17.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.17.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.17.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.17.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.17.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.17.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml:classmate:1.5.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.github.ben-manes.caffeine:caffeine:3.1.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -45,70 +37,70 @@ com.google.api-client:google-api-client-java6:2.1.4=compileClasspath,deploy_jar,
|
||||
com.google.api-client:google-api-client-servlet:2.6.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client:2.6.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.32.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.39.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.176.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.176.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.109.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.13.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.40.1-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.5.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.177.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.177.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.39.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.111.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.13.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.32.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.39.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.39.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.176.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.176.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-datastore-v1:0.110.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-firestore-v1:3.20.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:1.64.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.39.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.109.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.13.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-executor-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.40.1-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.5.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.177.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.177.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.39.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.39.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-datastore-v1:0.110.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-firestore-v1:3.21.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.111.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.13.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-executor-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.32.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.39.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.134.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.134.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.39.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.34.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:api-common:2.31.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-grpc:2.48.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:2.48.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.48.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev20240509-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20240423-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.40.1-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.136.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.136.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:api-common:2.33.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-grpc:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev20240618-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20240623-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20240310-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20240430-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dns:v1-rev20240419-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-drive:v3-rev20240521-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20240624-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dns:v1-rev20240531-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-drive:v3-rev20240628-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-gmail:v1-rev20240520-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev20210624-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev20220614-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-healthcare:v1-rev20240130-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-iam:v2-rev20240314-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-iam:v2-rev20240530-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-iamcredentials:v1-rev20211203-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-monitoring:v3-rev20240519-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-monitoring:v3-rev20240616-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-pubsub:v1-rev20220904-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sheets:v4-rev20240514-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sqladmin:v1beta4-rev20240324-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240311-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240319-2.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sqladmin:v1beta4-rev20240622-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240319-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240621-2.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.service:auto-service-annotations:1.0.1=errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.auto.service:auto-service-annotations:1.1.1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.service:auto-service:1.1.1=annotationProcessor
|
||||
com.google.auto.value:auto-value-annotations:1.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.10.4=compileClasspath,nonprodCompileClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.11.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.auto.value:auto-value:1.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value:1.11.0=annotationProcessor,testAnnotationProcessor
|
||||
@@ -117,34 +109,33 @@ com.google.closure-stylesheets:closure-stylesheets:1.5.0=css
|
||||
com.google.cloud.bigdataoss:gcsio:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigdataoss:util:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigtable:bigtable-client-core-config:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.datastore:datastore-v1-proto-client:2.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:jdbc-socket-factory-core:1.18.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:postgres-socket-factory:1.18.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigquerystorage:3.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable-stats:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.36.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.38.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.datastore:datastore-v1-proto-client:2.19.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.opentelemetry:detector-resources-support:0.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:jdbc-socket-factory-core:1.19.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:postgres-socket-factory:1.19.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigquerystorage:3.5.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable:2.39.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.38.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.40.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.38.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.36.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.38.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-firestore:3.20.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-monitoring:1.82.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
com.google.cloud:google-cloud-monitoring:3.39.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-nio:0.127.18=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsub:1.127.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsublite:1.13.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-spanner:6.62.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.40.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.38.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.40.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-firestore:3.21.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-monitoring:3.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-nio:0.127.20=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsub:1.129.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsublite:1.13.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-spanner:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.32.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.39.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.40.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:grpc-gcp:1.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.20.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.21.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.findbugs:jsr305:3.0.1=css
|
||||
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.gson:gson:2.10.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.gson:gson:2.11.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.gson:gson:2.7=css,soy
|
||||
com.google.common.html.types:types:1.0.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.dagger:dagger-compiler:2.51.1=annotationProcessor,testAnnotationProcessor
|
||||
@@ -153,7 +144,7 @@ com.google.dagger:dagger:2.51.1=annotationProcessor,compileClasspath,deploy_jar,
|
||||
com.google.devtools.ksp:symbol-processing-api:1.9.20-1.0.14=annotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.27.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle,soy
|
||||
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
@@ -174,15 +165,16 @@ com.google.guava:guava:20.0=css
|
||||
com.google.guava:guava:31.0.1-jre=checkstyle,soy
|
||||
com.google.guava:guava:32.1.1-jre=errorprone,nonprodAnnotationProcessor
|
||||
com.google.guava:guava:33.0.0-jre=annotationProcessor,testAnnotationProcessor
|
||||
com.google.guava:guava:33.2.0-android=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.guava:guava:33.2.1-android=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.guava:guava:33.2.1-jre=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.gwt:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.44.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.44.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.44.2=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-gson:1.44.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.44.2=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-protobuf:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client:1.44.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -210,7 +202,7 @@ com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,nonprodA
|
||||
com.google.protobuf:protobuf-java:3.25.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.re2j:re2j:1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.template:soy:2021-02-01=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.truth:truth:1.4.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.truth:truth:1.4.3=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.googlecode.json-simple:json-simple:1.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.ibm.icu:icu4j:57.1=soy
|
||||
com.ibm.icu:icu4j:73.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -248,6 +240,7 @@ com.zaxxer:HikariCP:5.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,no
|
||||
commons-beanutils:commons-beanutils:1.9.4=checkstyle
|
||||
commons-codec:commons-codec:1.17.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-collections:commons-collections:3.2.2=checkstyle
|
||||
commons-dbutils:commons-dbutils:1.8.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-io:commons-io:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-logging:commons-logging:1.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
dnsjava:dnsjava:3.5.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -306,8 +299,14 @@ io.opencensus:opencensus-exporter-stats-stackdriver:0.31.0=compileClasspath,depl
|
||||
io.opencensus:opencensus-impl-core:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-impl:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-proto:0.2.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-api:1.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-context:1.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-api-incubator:1.37.0-alpha=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-api:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-context:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-common:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-logs:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-metrics:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-trace:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.outfoxx:swiftpoet:1.3.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.perfmark:perfmark-api:0.27.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
jakarta-regexp:jakarta-regexp:1.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -316,7 +315,7 @@ jakarta.inject:jakarta.inject-api:1.0.5=compileClasspath,deploy_jar,nonprodCompi
|
||||
jakarta.inject:jakarta.inject-api:2.0.1=soy
|
||||
jakarta.mail:jakarta.mail-api:2.1.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
jakarta.servlet:jakarta.servlet-api:6.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
jakarta.servlet:jakarta.servlet-api:6.1.0-M2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
jakarta.servlet:jakarta.servlet-api:6.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=jaxb
|
||||
javacc:javacc:4.1=css
|
||||
javax.activation:javax.activation-api:1.2.0=compileClasspath,deploy_jar,jaxb,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -340,46 +339,45 @@ net.ltgt.gradle.incap:incap:0.2=annotationProcessor,testAnnotationProcessor
|
||||
net.sf.saxon:Saxon-HE:10.6=checkstyle
|
||||
org.antlr:antlr4-runtime:4.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.antlr:antlr4-runtime:4.9.3=checkstyle
|
||||
org.apache.arrow:arrow-format:15.0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.arrow:arrow-memory-core:15.0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.arrow:arrow-vector:15.0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.arrow:arrow-format:15.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.arrow:arrow-memory-core:15.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.arrow:arrow-vector:15.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.avro:avro:1.11.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-fn-execution:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-job-management:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-pipeline:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-fn-execution:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-job-management:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-pipeline:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-construction-java:2.54.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-java:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-direct-java:2.56.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-java-fn-execution:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-core:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-expansion-service:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-arrow:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-avro:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-java:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-direct-java:2.57.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-java-fn-execution:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-core:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-expansion-service:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-arrow:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-avro:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-fn-execution:2.54.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-harness:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-transform-service-launcher:2.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-harness:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-transform-service-launcher:2.57.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-grpc-1_60_1:0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-guava-32_1_2-jre:0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-compress:1.24.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-compress:1.26.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-csv:1.11.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-exec:1.3=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-lang3:3.14.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-lang3:3.9=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
org.apache.commons:commons-lang3:3.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-text:1.12.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.ftpserver:ftplet-api:1.2.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.ftpserver:ftpserver-core:1.2.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpcore:4.4.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.mina:mina-core:2.1.6=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-common:2.12.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-core:2.12.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-scp:2.12.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-sftp:2.12.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.tomcat:tomcat-annotations-api:11.0.0-M20=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-common:2.13.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-core:2.13.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-scp:2.13.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-sftp:2.13.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.tomcat:tomcat-annotations-api:11.0.0-M22=testCompileClasspath,testRuntimeClasspath
|
||||
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
|
||||
org.bouncycastle:bcpg-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpkix-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -391,7 +389,7 @@ org.checkerframework:checker-compat-qual:2.5.6=deploy_jar,nonprodRuntimeClasspat
|
||||
org.checkerframework:checker-qual:3.12.0=checkstyle,soy
|
||||
org.checkerframework:checker-qual:3.33.0=errorprone,nonprodAnnotationProcessor
|
||||
org.checkerframework:checker-qual:3.41.0=annotationProcessor,testAnnotationProcessor
|
||||
org.checkerframework:checker-qual:3.42.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-qual:3.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.23=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.conscrypt:conscrypt-openjdk-uber:2.5.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.easymock:easymock:3.0=css
|
||||
@@ -399,18 +397,18 @@ org.eclipse.angus:angus-activation:2.0.2=deploy_jar,nonprodRuntimeClasspath,runt
|
||||
org.eclipse.angus:jakarta.mail:2.0.3=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.eclipse.collections:eclipse-collections-api:11.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.collections:eclipse-collections:11.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.0.10=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.0.10=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-ee:12.0.10=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-http:12.0.10=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-io:12.0.10=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-security:12.0.10=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-server:12.0.10=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-session:12.0.10=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util:12.0.10=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-xml:12.0.10=testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-core:10.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-database-postgresql:10.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.0.11=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.0.11=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-ee:12.0.11=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-http:12.0.11=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-io:12.0.11=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-security:12.0.11=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-server:12.0.11=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-session:12.0.11=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util:12.0.11=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-xml:12.0.11=testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-core:10.15.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-database-postgresql:10.15.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:jaxb-runtime:2.3.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:txw2:2.3.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.gwtproject:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -449,11 +447,12 @@ org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.0.1=deploy_jar,nonprodRun
|
||||
org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.jetbrains:annotations:13.0=annotationProcessor,testAnnotationProcessor
|
||||
org.jetbrains:annotations:17.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jline:jline:3.26.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jline:jline:3.26.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.joda:joda-money:1.0.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.json:json:20160212=soy
|
||||
org.json:json:20240303=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jsoup:jsoup:1.17.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jsoup:jsoup:1.18.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jspecify:jspecify:0.3.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.junit-pioneer:junit-pioneer:2.2.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.11.0-M2=testCompileClasspath,testRuntimeClasspath
|
||||
@@ -486,9 +485,10 @@ org.ow2.asm:asm-util:7.0=soy
|
||||
org.ow2.asm:asm-util:9.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm:7.0=soy
|
||||
org.ow2.asm:asm:9.2=compileClasspath,nonprodCompileClasspath
|
||||
org.ow2.asm:asm:9.6=deploy_jar,jacocoAnt,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm:9.6=jacocoAnt
|
||||
org.ow2.asm:asm:9.7=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
org.postgresql:postgresql:42.7.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.postgresql:postgresql:42.7.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.reflections:reflections:0.10.2=checkstyle
|
||||
org.rnorth.duct-tape:duct-tape:1.0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-api:3.141.59=testCompileClasspath,testRuntimeClasspath
|
||||
@@ -504,7 +504,7 @@ org.seleniumhq.selenium:selenium-support:3.141.59=testCompileClasspath,testRunti
|
||||
org.slf4j:jcl-over-slf4j:1.7.32=testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:jul-to-slf4j:1.7.30=testRuntimeClasspath
|
||||
org.slf4j:slf4j-api:2.0.13=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:slf4j-jdk14:2.0.12=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:slf4j-jdk14:2.0.13=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.snakeyaml:snakeyaml-engine:2.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.testcontainers:database-commons:1.19.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:jdbc:1.19.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -517,13 +517,13 @@ org.w3c.css:sac:1.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodR
|
||||
org.webjars.npm:viz.js-graphviz-java:2.1.3=testRuntimeClasspath
|
||||
org.xerial.snappy:snappy-java:1.1.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.yaml:snakeyaml:2.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-api:16.21.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-diagram:16.21.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-loader:16.21.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-postgresql:16.21.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-text:16.21.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-tools:16.21.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-utility:16.21.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler:16.21.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-api:16.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-diagram:16.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-loader:16.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-postgresql:16.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-text:16.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-tools:16.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-utility:16.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler:16.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
xerces:xmlParserAPIs:2.6.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
empty=devtool,nomulus_test
|
||||
|
||||
@@ -64,7 +64,7 @@ import org.joda.time.Duration;
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class DeleteProberDataAction implements Runnable {
|
||||
|
||||
// TODO(b/323026070): Add email alert on failure of this action
|
||||
// TODO(b/346390641): Add email alert on failure of this action
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,7 @@ import google.registry.request.Action.Method;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@@ -74,8 +75,15 @@ public class ResaveEntityAction implements Runnable {
|
||||
"Re-saving entity %s which was enqueued at %s.", resourceKey, requestedTime);
|
||||
tm().transact(
|
||||
() -> {
|
||||
EppResource entity = tm().loadByKey(VKey.createEppVKeyFromString(resourceKey));
|
||||
tm().put(entity.cloneProjectedAtTime(tm().getTransactionTime()));
|
||||
Optional<EppResource> entity =
|
||||
tm().loadByKeyIfPresent(VKey.createEppVKeyFromString(resourceKey));
|
||||
if (entity.isEmpty()) {
|
||||
logger.atSevere().log(
|
||||
"Could not re-save entity %s because it does not exist; failing permanently.",
|
||||
resourceKey);
|
||||
return;
|
||||
}
|
||||
tm().put(entity.get().cloneProjectedAtTime(tm().getTransactionTime()));
|
||||
if (!resaveTimes.isEmpty()) {
|
||||
asyncTaskEnqueuer.enqueueAsyncResave(
|
||||
VKey.createEppVKeyFromString(resourceKey), requestedTime, resaveTimes);
|
||||
|
||||
@@ -1780,6 +1780,19 @@ public final class RegistryConfig {
|
||||
return CONFIG_SETTINGS.get().registryPolicy.sunriseDomainCreateDiscount;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of registrars for which we include a promotional price on domain checks if configured.
|
||||
*
|
||||
* <p>In these cases, when a default promotion is running for the domain+registrar combination in
|
||||
* question (a DEFAULT_PROMO token is set on the TLD), the standard non-promotional price will be
|
||||
* returned for that domain as the standard create price. We will then add an additional fee check
|
||||
* response with the actual promotional price and a "STANDARD PROMOTION" class.
|
||||
*/
|
||||
public static ImmutableSet<String> getTieredPricingPromotionRegistrarIds() {
|
||||
return ImmutableSet.copyOf(
|
||||
CONFIG_SETTINGS.get().registryPolicy.tieredPricingPromotionRegistrarIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Memoizes loading of the {@link RegistryConfigSettings} POJO.
|
||||
*
|
||||
@@ -1790,8 +1803,6 @@ public final class RegistryConfig {
|
||||
public static final Supplier<RegistryConfigSettings> CONFIG_SETTINGS =
|
||||
memoize(RegistryConfig::getConfigSettings);
|
||||
|
||||
|
||||
|
||||
private static InternetAddress parseEmailAddress(String email) {
|
||||
try {
|
||||
return new InternetAddress(email);
|
||||
|
||||
@@ -113,6 +113,7 @@ public class RegistryConfigSettings {
|
||||
public List<String> spec11WebResources;
|
||||
public boolean requireSslCertificates;
|
||||
public double sunriseDomainCreateDiscount;
|
||||
public Set<String> tieredPricingPromotionRegistrarIds;
|
||||
}
|
||||
|
||||
/** Configuration for Hibernate. */
|
||||
|
||||
@@ -201,6 +201,15 @@ registryPolicy:
|
||||
# will be free.
|
||||
sunriseDomainCreateDiscount: 0.15
|
||||
|
||||
# List of registrars participating in tiered pricing promotions that require
|
||||
# non-standard responses to EPP domain:check and domain:create commands.
|
||||
# When a promotion is active, we will set an additional STANDARD PROMOTION
|
||||
# fee check response on any domain checks that corresponds to the actual
|
||||
# promotional price (the regular response will be the non-promotional price).
|
||||
# In addition, we will return the non-promotional (i.e. incorrect) price on
|
||||
# domain create requests.
|
||||
tieredPricingPromotionRegistrarIds: []
|
||||
|
||||
hibernate:
|
||||
# If set to false, calls to tm().transact() cannot be nested. If set to true,
|
||||
# nested calls to tm().transact() are allowed, as long as they do not specify
|
||||
|
||||
@@ -9,6 +9,8 @@ registryPolicy:
|
||||
reservedTermsExportDisclaimer: |
|
||||
Disclaimer line 1.
|
||||
Line 2 is this 1.
|
||||
tieredPricingPromotionRegistrarIds:
|
||||
- NewRegistrar
|
||||
|
||||
caching:
|
||||
singletonCacheRefreshSeconds: 0
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
|
||||
@@ -70,6 +71,7 @@ import google.registry.model.domain.DomainCommand.Check;
|
||||
import google.registry.model.domain.fee.FeeCheckCommandExtension;
|
||||
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
|
||||
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
|
||||
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem;
|
||||
import google.registry.model.domain.fee06.FeeCheckCommandExtensionV06;
|
||||
import google.registry.model.domain.launch.LaunchCheckExtension;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
@@ -129,6 +131,9 @@ import org.joda.time.DateTime;
|
||||
@ReportingSpec(ActivityReportField.DOMAIN_CHECK)
|
||||
public final class DomainCheckFlow implements TransactionalFlow {
|
||||
|
||||
private static final String STANDARD_FEE_RESPONSE_CLASS = "STANDARD";
|
||||
private static final String STANDARD_PROMOTION_FEE_RESPONSE_CLASS = "STANDARD PROMOTION";
|
||||
|
||||
@Inject ResourceCommand resourceCommand;
|
||||
@Inject ExtensionManager extensionManager;
|
||||
@Inject EppInput eppInput;
|
||||
@@ -300,6 +305,8 @@ public final class DomainCheckFlow implements TransactionalFlow {
|
||||
loadDomainsForChecks(feeCheck, domainNames, existingDomains);
|
||||
ImmutableMap<String, BillingRecurrence> recurrences = loadRecurrencesForDomains(domainObjs);
|
||||
|
||||
boolean shouldUseTieredPricingPromotion =
|
||||
RegistryConfig.getTieredPricingPromotionRegistrarIds().contains(registrarId);
|
||||
for (FeeCheckCommandExtensionItem feeCheckItem : feeCheck.getItems()) {
|
||||
for (String domainName : getDomainNamesToCheckForFee(feeCheckItem, domainNames.keySet())) {
|
||||
Optional<AllocationToken> defaultToken =
|
||||
@@ -332,6 +339,44 @@ public final class DomainCheckFlow implements TransactionalFlow {
|
||||
allocationToken.isPresent() ? allocationToken : defaultToken,
|
||||
availableDomains.contains(domainName),
|
||||
recurrences.getOrDefault(domainName, null));
|
||||
// In the case of a registrar that is running a tiered pricing promotion, we issue two
|
||||
// responses for the CREATE fee check command: one (the default response) with the
|
||||
// non-promotional price, and one (an extra STANDARD PROMO response) with the actual
|
||||
// promotional price.
|
||||
if (defaultToken.isPresent()
|
||||
&& shouldUseTieredPricingPromotion
|
||||
&& feeCheckItem
|
||||
.getCommandName()
|
||||
.equals(FeeQueryCommandExtensionItem.CommandName.CREATE)) {
|
||||
// First, set the promotional (real) price under the STANDARD PROMO class
|
||||
builder
|
||||
.setClass(STANDARD_PROMOTION_FEE_RESPONSE_CLASS)
|
||||
.setCommand(
|
||||
FeeQueryCommandExtensionItem.CommandName.CUSTOM,
|
||||
feeCheckItem.getPhase(),
|
||||
feeCheckItem.getSubphase());
|
||||
|
||||
// Next, get the non-promotional price and set it as the standard response to the CREATE
|
||||
// fee check command
|
||||
FeeCheckResponseExtensionItem.Builder<?> nonPromotionalBuilder =
|
||||
feeCheckItem.createResponseBuilder();
|
||||
handleFeeRequest(
|
||||
feeCheckItem,
|
||||
nonPromotionalBuilder,
|
||||
domainNames.get(domainName),
|
||||
domain,
|
||||
feeCheck.getCurrency(),
|
||||
now,
|
||||
pricingLogic,
|
||||
allocationToken,
|
||||
availableDomains.contains(domainName),
|
||||
recurrences.getOrDefault(domainName, null));
|
||||
responseItems.add(
|
||||
nonPromotionalBuilder
|
||||
.setClass(STANDARD_FEE_RESPONSE_CLASS)
|
||||
.setDomainNameIfSupported(domainName)
|
||||
.build());
|
||||
}
|
||||
responseItems.add(builder.setDomainNameIfSupported(domainName).build());
|
||||
} catch (AllocationTokenInvalidForPremiumNameException
|
||||
| AllocationTokenNotValidForCommandException
|
||||
|
||||
@@ -59,6 +59,7 @@ import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.CommandUseErrorException;
|
||||
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
|
||||
@@ -265,7 +266,6 @@ public final class DomainCreateFlow implements MutatingFlow {
|
||||
validateLaunchCreateNotice(launchCreate.get().getNotice(), domainLabel, isSuperuser, now);
|
||||
}
|
||||
boolean isSunriseCreate = hasSignedMarks && (tldState == START_DATE_SUNRISE);
|
||||
// TODO(sarahbot@): Add check for valid EPP actions on the token
|
||||
Optional<AllocationToken> allocationToken =
|
||||
allocationTokenFlowUtils.verifyAllocationTokenCreateIfPresent(
|
||||
command,
|
||||
@@ -438,11 +438,22 @@ public final class DomainCreateFlow implements MutatingFlow {
|
||||
.build());
|
||||
persistEntityChanges(entityChanges);
|
||||
|
||||
// If the registrar is participating in tiered pricing promos, return the standard price in the
|
||||
// response (even if the actual charged price is less)
|
||||
boolean shouldShowDefaultPrice =
|
||||
defaultTokenUsed
|
||||
&& RegistryConfig.getTieredPricingPromotionRegistrarIds().contains(registrarId);
|
||||
FeesAndCredits responseFeesAndCredits =
|
||||
shouldShowDefaultPrice
|
||||
? pricingLogic.getCreatePrice(
|
||||
tld, targetId, now, years, isAnchorTenant, isSunriseCreate, Optional.empty())
|
||||
: feesAndCredits;
|
||||
|
||||
BeforeResponseReturnData responseData =
|
||||
flowCustomLogic.beforeResponse(
|
||||
BeforeResponseParameters.newBuilder()
|
||||
.setResData(DomainCreateData.create(targetId, now, registrationExpirationTime))
|
||||
.setResponseExtensions(createResponseExtensions(feeCreate, feesAndCredits))
|
||||
.setResponseExtensions(createResponseExtensions(feeCreate, responseFeesAndCredits))
|
||||
.build());
|
||||
return responseBuilder
|
||||
.setResData(responseData.resData())
|
||||
|
||||
@@ -24,6 +24,8 @@ import static com.google.common.collect.Sets.difference;
|
||||
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.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_OPTIONAL;
|
||||
import static google.registry.model.common.FeatureFlag.isActiveNow;
|
||||
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;
|
||||
@@ -481,10 +483,14 @@ public class DomainFlowUtils {
|
||||
}
|
||||
}
|
||||
|
||||
static void validateRequiredContactsPresent(
|
||||
static void validateRequiredContactsPresentIfRequiredForDataset(
|
||||
Optional<VKey<Contact>> registrant, Set<DesignatedContact> contacts)
|
||||
throws RequiredParameterMissingException {
|
||||
// TODO: Check minimum reg data set migration schedule here and don't throw when any are empty.
|
||||
// TODO(b/353347632): Change this flag check to a registry config check.
|
||||
if (isActiveNow(MINIMUM_DATASET_CONTACTS_OPTIONAL)) {
|
||||
// Contacts are not required once we have begun the migration to the minimum dataset
|
||||
return;
|
||||
}
|
||||
if (registrant.isEmpty()) {
|
||||
throw new MissingRegistrantException();
|
||||
}
|
||||
@@ -1041,7 +1047,8 @@ public class DomainFlowUtils {
|
||||
String tldStr = tld.getTldStr();
|
||||
validateRegistrantAllowedOnTld(tldStr, command.getRegistrantContactId());
|
||||
validateNoDuplicateContacts(command.getContacts());
|
||||
validateRequiredContactsPresent(command.getRegistrant(), command.getContacts());
|
||||
validateRequiredContactsPresentIfRequiredForDataset(
|
||||
command.getRegistrant(), command.getContacts());
|
||||
ImmutableSet<String> hostNames = command.getNameserverHostNames();
|
||||
validateNameserversCountForTld(tldStr, domainName, hostNames.size());
|
||||
validateNameserversAllowedOnTld(tldStr, hostNames);
|
||||
|
||||
@@ -38,9 +38,11 @@ import static google.registry.flows.domain.DomainFlowUtils.validateNameserversAl
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateNameserversCountForTld;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateRegistrantAllowedOnTld;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresent;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresentIfRequiredForDataset;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNotProhibited;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_OPTIONAL;
|
||||
import static google.registry.model.common.FeatureFlag.isActiveNow;
|
||||
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_UPDATE;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
@@ -66,6 +68,7 @@ import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTl
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.billing.BillingBase.Reason;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainCommand.Update;
|
||||
@@ -87,6 +90,7 @@ import google.registry.model.poll.PendingActionNotificationResponse.DomainPendin
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.model.tld.Tld;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
@@ -248,7 +252,6 @@ public final class DomainUpdateFlow implements MutatingFlow {
|
||||
checkSameValuesNotAddedAndRemoved(add.getContacts(), remove.getContacts());
|
||||
checkSameValuesNotAddedAndRemoved(add.getStatusValues(), remove.getStatusValues());
|
||||
Change change = command.getInnerChange();
|
||||
validateRegistrantIsntBeingRemoved(change);
|
||||
Optional<SecDnsUpdateExtension> secDnsUpdate =
|
||||
eppInput.getSingleExtension(SecDnsUpdateExtension.class);
|
||||
|
||||
@@ -278,7 +281,7 @@ public final class DomainUpdateFlow implements MutatingFlow {
|
||||
.removeStatusValues(remove.getStatusValues())
|
||||
.removeContacts(remove.getContacts())
|
||||
.addContacts(add.getContacts())
|
||||
.setRegistrant(change.getRegistrant().or(domain::getRegistrant))
|
||||
.setRegistrant(determineUpdatedRegistrant(change, domain))
|
||||
.setAuthInfo(firstNonNull(change.getAuthInfo(), domain.getAuthInfo()));
|
||||
|
||||
if (!add.getNameservers().isEmpty()) {
|
||||
@@ -300,13 +303,19 @@ public final class DomainUpdateFlow implements MutatingFlow {
|
||||
return domainBuilder.build();
|
||||
}
|
||||
|
||||
private static void validateRegistrantIsntBeingRemoved(Change change) throws EppException {
|
||||
// TODO(mcilwain): Make this check the minimum registration data set migration schedule
|
||||
// and not require presence of a registrant in later stages.
|
||||
private Optional<VKey<Contact>> determineUpdatedRegistrant(Change change, Domain domain)
|
||||
throws EppException {
|
||||
// During phase 1 of minimum dataset transition, allow registrant to be removed
|
||||
if (change.getRegistrantContactId().isPresent()
|
||||
&& change.getRegistrantContactId().get().isEmpty()) {
|
||||
throw new MissingRegistrantException();
|
||||
// TODO(b/353347632): Change this flag check to a registry config check.
|
||||
if (isActiveNow(MINIMUM_DATASET_CONTACTS_OPTIONAL)) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
throw new MissingRegistrantException();
|
||||
}
|
||||
}
|
||||
return change.getRegistrant().or(domain::getRegistrant);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -317,7 +326,8 @@ public final class DomainUpdateFlow implements MutatingFlow {
|
||||
* cause Domain update failure.
|
||||
*/
|
||||
private static void validateNewState(Domain newDomain) throws EppException {
|
||||
validateRequiredContactsPresent(newDomain.getRegistrant(), newDomain.getContacts());
|
||||
validateRequiredContactsPresentIfRequiredForDataset(
|
||||
newDomain.getRegistrant(), newDomain.getContacts());
|
||||
validateDsData(newDomain.getDsData());
|
||||
validateNameserversCountForTld(
|
||||
newDomain.getTld(),
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import google.registry.model.common.FeatureFlag.FeatureStatus;
|
||||
import google.registry.model.common.TimedTransitionProperty;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.tld.Tld.TldState;
|
||||
@@ -363,6 +364,33 @@ public class EntityYamlUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/** A custom JSON deserializer for a {@link TimedTransitionProperty} of {@link FeatureStatus}. */
|
||||
public static class TimedTransitionPropertyFeatureStatusDeserializer
|
||||
extends StdDeserializer<TimedTransitionProperty<FeatureStatus>> {
|
||||
|
||||
public TimedTransitionPropertyFeatureStatusDeserializer() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public TimedTransitionPropertyFeatureStatusDeserializer(
|
||||
Class<TimedTransitionProperty<FeatureStatus>> t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimedTransitionProperty<FeatureStatus> deserialize(
|
||||
JsonParser jp, DeserializationContext context) throws IOException {
|
||||
SortedMap<String, String> valueMap = jp.readValueAs(SortedMap.class);
|
||||
return TimedTransitionProperty.fromValueMap(
|
||||
valueMap.keySet().stream()
|
||||
.collect(
|
||||
toImmutableSortedMap(
|
||||
natural(),
|
||||
DateTime::parse,
|
||||
key -> FeatureStatus.valueOf(valueMap.get(key)))));
|
||||
}
|
||||
}
|
||||
|
||||
/** A custom JSON deserializer for a {@link CreateAutoTimestamp}. */
|
||||
public static class CreateAutoTimestampDeserializer extends StdDeserializer<CreateAutoTimestamp> {
|
||||
|
||||
|
||||
@@ -14,29 +14,35 @@
|
||||
|
||||
package google.registry.model.common;
|
||||
|
||||
import static com.google.api.client.util.Preconditions.checkState;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.config.RegistryConfig.getSingletonCacheRefreshDuration;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.ACTIVE;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Maps;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.CacheUtils;
|
||||
import google.registry.model.EntityYamlUtils.TimedTransitionPropertyFeatureStatusDeserializer;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@@ -54,60 +60,76 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
|
||||
INACTIVE
|
||||
}
|
||||
|
||||
public enum FeatureName {
|
||||
TEST_FEATURE,
|
||||
MINIMUM_DATASET_CONTACTS_OPTIONAL,
|
||||
MINIMUM_DATASET_CONTACTS_PROHIBITED
|
||||
}
|
||||
|
||||
/** The name of the flag/feature. */
|
||||
@Id String featureName;
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Id
|
||||
FeatureName featureName;
|
||||
|
||||
/** A map of times for each {@link FeatureStatus} the FeatureFlag should hold. */
|
||||
@Column(nullable = false)
|
||||
@JsonDeserialize(using = TimedTransitionPropertyFeatureStatusDeserializer.class)
|
||||
TimedTransitionProperty<FeatureStatus> status =
|
||||
TimedTransitionProperty.withInitialValue(FeatureStatus.INACTIVE);
|
||||
|
||||
public static FeatureFlag get(String featureName) {
|
||||
FeatureFlag maybeFeatureFlag = CACHE.get(featureName);
|
||||
if (maybeFeatureFlag == null) {
|
||||
throw new FeatureFlagNotFoundException(featureName);
|
||||
} else {
|
||||
return maybeFeatureFlag;
|
||||
}
|
||||
public static Optional<FeatureFlag> getUncached(FeatureName featureName) {
|
||||
return tm().transact(() -> tm().loadByKeyIfPresent(createVKey(featureName)));
|
||||
}
|
||||
|
||||
public static ImmutableSet<FeatureFlag> get(Set<String> featureNames) {
|
||||
Map<String, FeatureFlag> featureFlags = CACHE.getAll(featureNames);
|
||||
ImmutableSet<String> missingFlags =
|
||||
Sets.difference(featureNames, featureFlags.keySet()).immutableCopy();
|
||||
public static ImmutableList<FeatureFlag> getAllUncached() {
|
||||
return tm().transact(() -> tm().loadAllOf(FeatureFlag.class));
|
||||
}
|
||||
|
||||
public static FeatureFlag get(FeatureName featureName) {
|
||||
Optional<FeatureFlag> maybeFeatureFlag = CACHE.get(featureName);
|
||||
return maybeFeatureFlag.orElseThrow(() -> new FeatureFlagNotFoundException(featureName));
|
||||
}
|
||||
|
||||
public static ImmutableSet<FeatureFlag> getAll(Set<FeatureName> featureNames) {
|
||||
Map<FeatureName, Optional<FeatureFlag>> featureFlags = CACHE.getAll(featureNames);
|
||||
ImmutableSet<FeatureName> missingFlags =
|
||||
featureFlags.entrySet().stream()
|
||||
.filter(e -> e.getValue().isEmpty())
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(toImmutableSet());
|
||||
if (missingFlags.isEmpty()) {
|
||||
return featureFlags.values().stream().collect(toImmutableSet());
|
||||
return featureFlags.values().stream().map(Optional::get).collect(toImmutableSet());
|
||||
} else {
|
||||
throw new FeatureFlagNotFoundException(missingFlags);
|
||||
}
|
||||
}
|
||||
|
||||
/** A cache that loads the {@link FeatureFlag} for a given featureName. */
|
||||
private static final LoadingCache<String, FeatureFlag> CACHE =
|
||||
private static final LoadingCache<FeatureName, Optional<FeatureFlag>> CACHE =
|
||||
CacheUtils.newCacheBuilder(getSingletonCacheRefreshDuration())
|
||||
.build(
|
||||
new CacheLoader<>() {
|
||||
@Override
|
||||
public FeatureFlag load(final String featureName) {
|
||||
return tm().reTransact(() -> tm().loadByKeyIfPresent(createVKey(featureName)))
|
||||
.orElse(null);
|
||||
public Optional<FeatureFlag> load(final FeatureName featureName) {
|
||||
return tm().reTransact(() -> tm().loadByKeyIfPresent(createVKey(featureName)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends String, ? extends FeatureFlag> loadAll(
|
||||
Set<? extends String> featureFlagNames) {
|
||||
ImmutableMap<String, VKey<FeatureFlag>> keysMap =
|
||||
public Map<? extends FeatureName, ? extends Optional<FeatureFlag>> loadAll(
|
||||
Set<? extends FeatureName> featureFlagNames) {
|
||||
ImmutableMap<FeatureName, VKey<FeatureFlag>> keysMap =
|
||||
featureFlagNames.stream()
|
||||
.collect(
|
||||
toImmutableMap(featureName -> featureName, FeatureFlag::createVKey));
|
||||
Map<VKey<? extends FeatureFlag>, FeatureFlag> entities =
|
||||
tm().reTransact(() -> tm().loadByKeysIfPresent(keysMap.values()));
|
||||
return entities.values().stream()
|
||||
.collect(toImmutableMap(flag -> flag.featureName, flag -> flag));
|
||||
return Maps.toMap(
|
||||
featureFlagNames,
|
||||
name -> Optional.ofNullable(entities.get(createVKey(name))));
|
||||
}
|
||||
});
|
||||
|
||||
public static VKey<FeatureFlag> createVKey(String featureName) {
|
||||
public static VKey<FeatureFlag> createVKey(FeatureName featureName) {
|
||||
return VKey.create(FeatureFlag.class, featureName);
|
||||
}
|
||||
|
||||
@@ -116,10 +138,11 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
|
||||
return createVKey(featureName);
|
||||
}
|
||||
|
||||
public String getFeatureName() {
|
||||
public FeatureName getFeatureName() {
|
||||
return featureName;
|
||||
}
|
||||
|
||||
@JsonProperty("status")
|
||||
public TimedTransitionProperty<FeatureStatus> getStatusMap() {
|
||||
return status;
|
||||
}
|
||||
@@ -128,6 +151,17 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
|
||||
return status.getValueAtTime(time);
|
||||
}
|
||||
|
||||
/** Returns if the FeatureFlag with the given FeatureName is active now. */
|
||||
public static boolean isActiveNow(FeatureName featureName) {
|
||||
tm().assertInTransaction();
|
||||
return isActiveAt(featureName, tm().getTransactionTime());
|
||||
}
|
||||
|
||||
/** Returns if the FeatureFlag with the given FeatureName is active at a given time. */
|
||||
public static boolean isActiveAt(FeatureName featureName, DateTime dateTime) {
|
||||
return FeatureFlag.get(featureName).getStatus(dateTime).equals(ACTIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureFlag.Builder asBuilder() {
|
||||
return new FeatureFlag.Builder(clone(this));
|
||||
@@ -144,20 +178,17 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
|
||||
|
||||
@Override
|
||||
public FeatureFlag build() {
|
||||
checkArgument(
|
||||
!Strings.isNullOrEmpty(getInstance().featureName),
|
||||
"Feature name must not be null or empty");
|
||||
getInstance().status.checkValidity();
|
||||
checkArgument(getInstance().featureName != null, "FeatureName cannot be null");
|
||||
return super.build();
|
||||
}
|
||||
|
||||
public Builder setFeatureName(String featureName) {
|
||||
checkState(getInstance().featureName == null, "Feature name can only be set once");
|
||||
public Builder setFeatureName(FeatureName featureName) {
|
||||
getInstance().featureName = featureName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setStatus(ImmutableSortedMap<DateTime, FeatureStatus> statusMap) {
|
||||
public Builder setStatusMap(ImmutableSortedMap<DateTime, FeatureStatus> statusMap) {
|
||||
getInstance().status = TimedTransitionProperty.fromValueMap(statusMap);
|
||||
return this;
|
||||
}
|
||||
@@ -166,11 +197,11 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
|
||||
/** Exception to throw when no FeatureFlag entity is found for given FeatureName string(s). */
|
||||
public static class FeatureFlagNotFoundException extends RuntimeException {
|
||||
|
||||
FeatureFlagNotFoundException(ImmutableSet<String> featureNames) {
|
||||
FeatureFlagNotFoundException(ImmutableSet<FeatureName> featureNames) {
|
||||
super("No feature flag object(s) found for " + Joiner.on(", ").join(featureNames));
|
||||
}
|
||||
|
||||
FeatureFlagNotFoundException(String featureName) {
|
||||
public FeatureFlagNotFoundException(FeatureName featureName) {
|
||||
this(ImmutableSet.of(featureName));
|
||||
}
|
||||
}
|
||||
|
||||
+16
-8
@@ -34,19 +34,26 @@ public abstract class FeeQueryCommandExtensionItem extends ImmutableObject {
|
||||
|
||||
/** The name of a command that might have an associated fee. */
|
||||
public enum CommandName {
|
||||
UNKNOWN(false),
|
||||
CREATE(false),
|
||||
RENEW(true),
|
||||
TRANSFER(true),
|
||||
RESTORE(true),
|
||||
UPDATE(false);
|
||||
UNKNOWN(false, false),
|
||||
CREATE(false, true),
|
||||
RENEW(true, true),
|
||||
TRANSFER(true, true),
|
||||
RESTORE(true, true),
|
||||
UPDATE(false, true),
|
||||
/**
|
||||
* We don't accept CUSTOM commands in requests but may issue them in responses. A CUSTOM command
|
||||
* name is permitted in general per RFC 8748 section 3.1.
|
||||
*/
|
||||
CUSTOM(false, false);
|
||||
|
||||
private final boolean loadDomainForCheck;
|
||||
private final boolean acceptableInputAction;
|
||||
|
||||
public static CommandName parseKnownCommand(String string) {
|
||||
try {
|
||||
CommandName command = valueOf(string);
|
||||
checkArgument(!command.equals(UNKNOWN));
|
||||
checkArgument(
|
||||
command.acceptableInputAction, "Command %s is not an acceptable input action", string);
|
||||
return command;
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(
|
||||
@@ -55,8 +62,9 @@ public abstract class FeeQueryCommandExtensionItem extends ImmutableObject {
|
||||
}
|
||||
}
|
||||
|
||||
CommandName(boolean loadDomainForCheck) {
|
||||
CommandName(boolean loadDomainForCheck, boolean acceptableInputAction) {
|
||||
this.loadDomainForCheck = loadDomainForCheck;
|
||||
this.acceptableInputAction = acceptableInputAction;
|
||||
}
|
||||
|
||||
public boolean shouldLoadDomainForCheck() {
|
||||
|
||||
@@ -50,6 +50,7 @@ import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithVKey;
|
||||
import google.registry.persistence.converter.JodaMoneyType;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@@ -63,6 +64,9 @@ import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import org.hibernate.annotations.Columns;
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** An entity representing an allocation token. */
|
||||
@@ -135,7 +139,7 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
|
||||
/** Token saved on a TLD to use if no other token is passed from the client */
|
||||
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
|
||||
// TODO(b/261763205): Remove this type once all tokens of this type have been scrubbed from the
|
||||
// database
|
||||
@Deprecated
|
||||
PACKAGE(/* isOneTimeUse= */ false),
|
||||
@@ -236,6 +240,12 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
|
||||
@Column(name = "renewalPriceBehavior", nullable = false)
|
||||
RenewalPriceBehavior renewalPriceBehavior = RenewalPriceBehavior.DEFAULT;
|
||||
|
||||
/** The price used for renewals iff the renewalPriceBehavior is SPECIFIED. */
|
||||
@Nullable
|
||||
@Type(type = JodaMoneyType.TYPE_NAME)
|
||||
@Columns(columns = {@Column(name = "renewalPriceAmount"), @Column(name = "renewalPriceCurrency")})
|
||||
Money renewalPrice;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false)
|
||||
RegistrationBehavior registrationBehavior = RegistrationBehavior.DEFAULT;
|
||||
@@ -310,6 +320,10 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
|
||||
return renewalPriceBehavior;
|
||||
}
|
||||
|
||||
public Optional<Money> getRenewalPrice() {
|
||||
return Optional.ofNullable(renewalPrice);
|
||||
}
|
||||
|
||||
public RegistrationBehavior getRegistrationBehavior() {
|
||||
return registrationBehavior;
|
||||
}
|
||||
@@ -377,29 +391,12 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
|
||||
public AllocationToken build() {
|
||||
checkArgumentNotNull(getInstance().tokenType, "Token type must be specified");
|
||||
checkArgument(!Strings.isNullOrEmpty(getInstance().token), "Token must not be null or empty");
|
||||
checkArgument(
|
||||
!getInstance().tokenType.equals(TokenType.BULK_PRICING)
|
||||
|| getInstance().renewalPriceBehavior.equals(RenewalPriceBehavior.SPECIFIED),
|
||||
"Bulk tokens must have renewalPriceBehavior set to SPECIFIED");
|
||||
checkArgument(
|
||||
!getInstance().tokenType.equals(TokenType.BULK_PRICING)
|
||||
|| ImmutableSet.of(CommandName.CREATE).equals(getInstance().allowedEppActions),
|
||||
"Bulk tokens may only be valid for CREATE actions");
|
||||
checkArgument(
|
||||
!getInstance().tokenType.equals(TokenType.BULK_PRICING)
|
||||
|| !getInstance().discountPremiums,
|
||||
"Bulk tokens cannot discount premium names");
|
||||
checkArgument(
|
||||
getInstance().domainName == null || getInstance().tokenType.isOneTimeUse(),
|
||||
"Domain name can only be specified for SINGLE_USE or REGISTER_BSA tokens");
|
||||
checkArgument(
|
||||
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
|
||||
&& getInstance().allowedClientIds.size() == 1),
|
||||
"BULK_PRICING tokens must have exactly one allowed client registrar");
|
||||
checkArgument(
|
||||
getInstance().discountFraction > 0 || !getInstance().discountPremiums,
|
||||
"Discount premiums can only be specified along with a discount fraction");
|
||||
@@ -425,6 +422,33 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
|
||||
|| getInstance().allowedEppActions.contains(CommandName.CREATE),
|
||||
"NONPREMIUM_CREATE tokens must allow for CREATE actions");
|
||||
}
|
||||
|
||||
checkArgument(
|
||||
getInstance().renewalPriceBehavior.equals(RenewalPriceBehavior.SPECIFIED)
|
||||
== (getInstance().renewalPrice != null),
|
||||
"renewalPrice must be specified iff renewalPriceBehavior is SPECIFIED");
|
||||
|
||||
if (getInstance().tokenType.equals(TokenType.BULK_PRICING)) {
|
||||
checkArgument(
|
||||
getInstance().discountFraction == 1.0,
|
||||
"BULK_PRICING tokens must have a discountFraction of 1.0");
|
||||
checkArgument(
|
||||
!getInstance().shouldDiscountPremiums(),
|
||||
"BULK_PRICING tokens cannot discount premium names");
|
||||
checkArgument(
|
||||
getInstance().renewalPriceBehavior.equals(RenewalPriceBehavior.SPECIFIED),
|
||||
"BULK_PRICING tokens must have renewalPriceBehavior set to SPECIFIED");
|
||||
checkArgument(
|
||||
getInstance().renewalPrice.getAmount().intValue() == 0,
|
||||
"BULK_PRICING tokens must have a renewal price of 0");
|
||||
checkArgument(
|
||||
ImmutableSet.of(CommandName.CREATE).equals(getInstance().allowedEppActions),
|
||||
"BULK_PRICING tokens may only be valid for CREATE actions");
|
||||
checkArgument(
|
||||
getInstance().allowedClientIds != null && getInstance().allowedClientIds.size() == 1,
|
||||
"BULK_PRICING tokens must have exactly one allowed client registrar");
|
||||
}
|
||||
|
||||
if (getInstance().domainName != null) {
|
||||
try {
|
||||
DomainFlowUtils.validateDomainName(getInstance().domainName);
|
||||
@@ -521,6 +545,11 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRenewalPrice(Money renewalPrice) {
|
||||
getInstance().renewalPrice = renewalPrice;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRegistrationBehavior(RegistrationBehavior registrationBehavior) {
|
||||
getInstance().registrationBehavior = registrationBehavior;
|
||||
return this;
|
||||
|
||||
@@ -25,8 +25,6 @@ import javax.persistence.AccessType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* A contact for a Registrar. Note, equality, hashCode and comparable have been overridden to only
|
||||
@@ -37,7 +35,6 @@ import javax.persistence.Table;
|
||||
* set to true.
|
||||
*/
|
||||
@Entity
|
||||
@Table(indexes = @Index(columnList = "loginEmailAddress", name = "registrarpoc_login_email_idx"))
|
||||
@IdClass(RegistrarPocId.class)
|
||||
@Access(AccessType.FIELD)
|
||||
public class RegistrarPoc extends RegistrarPocBase {
|
||||
|
||||
@@ -98,12 +98,7 @@ public class RegistrarPocBase extends ImmutableObject implements Jsonifiable, Un
|
||||
/** The name of the contact. */
|
||||
@Expose String name;
|
||||
|
||||
/**
|
||||
* The contact email address of the contact.
|
||||
*
|
||||
* <p>This is different from the login email which is assgined to the regstrar and cannot be
|
||||
* changed.
|
||||
*/
|
||||
/** The contact email address of the contact. */
|
||||
@Expose @Transient String emailAddress;
|
||||
|
||||
@Expose @Transient public String registrarId;
|
||||
@@ -123,9 +118,6 @@ public class RegistrarPocBase extends ImmutableObject implements Jsonifiable, Un
|
||||
*/
|
||||
@Expose Set<Type> types;
|
||||
|
||||
/** A GAIA email address that was assigned to the registrar for console login purpose. */
|
||||
String loginEmailAddress;
|
||||
|
||||
/**
|
||||
* Whether this contact is publicly visible in WHOIS registrar query results as an Admin contact.
|
||||
*/
|
||||
@@ -219,10 +211,6 @@ public class RegistrarPocBase extends ImmutableObject implements Jsonifiable, Un
|
||||
return visibleInDomainWhoisAsAbuse;
|
||||
}
|
||||
|
||||
public String getLoginEmailAddress() {
|
||||
return loginEmailAddress;
|
||||
}
|
||||
|
||||
public Builder<? extends RegistrarPocBase, ?> asBuilder() {
|
||||
return new Builder<>(clone(this));
|
||||
}
|
||||
@@ -286,13 +274,6 @@ public class RegistrarPocBase extends ImmutableObject implements Jsonifiable, Un
|
||||
+ "Registrar Abuse contact info: ")
|
||||
.append(getVisibleInDomainWhoisAsAbuse() ? "Yes" : "No")
|
||||
.append('\n');
|
||||
result
|
||||
.append("Registrar-Console access: ")
|
||||
.append(getLoginEmailAddress() != null ? "Yes" : "No")
|
||||
.append('\n');
|
||||
if (getLoginEmailAddress() != null) {
|
||||
result.append("Login Email Address: ").append(getLoginEmailAddress()).append('\n');
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@@ -310,7 +291,6 @@ public class RegistrarPocBase extends ImmutableObject implements Jsonifiable, Un
|
||||
.put("visibleInDomainWhoisAsAbuse", visibleInDomainWhoisAsAbuse)
|
||||
.put("allowedToSetRegistryLockPassword", allowedToSetRegistryLockPassword)
|
||||
.put("registryLockAllowed", isRegistryLockAllowed())
|
||||
.put("loginEmailAddress", loginEmailAddress)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -411,11 +391,6 @@ public class RegistrarPocBase extends ImmutableObject implements Jsonifiable, Un
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setLoginEmailAddress(String loginEmailAddress) {
|
||||
getInstance().loginEmailAddress = loginEmailAddress;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setAllowedToSetRegistryLockPassword(boolean allowedToSetRegistryLockPassword) {
|
||||
if (allowedToSetRegistryLockPassword) {
|
||||
getInstance().registryLockPasswordSalt = null;
|
||||
|
||||
@@ -41,9 +41,9 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Range;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.CacheUtils;
|
||||
@@ -192,21 +192,19 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||
|
||||
/** Returns the TLD for a given TLD, throwing if none exists. */
|
||||
public static Tld get(String tld) {
|
||||
Tld maybeTld = CACHE.get(tld);
|
||||
if (maybeTld == null) {
|
||||
throw new TldNotFoundException(tld);
|
||||
} else {
|
||||
return maybeTld;
|
||||
}
|
||||
return CACHE.get(tld).orElseThrow(() -> new TldNotFoundException(tld));
|
||||
}
|
||||
|
||||
/** Returns the TLD entities for the given TLD strings, throwing if any don't exist. */
|
||||
public static ImmutableSet<Tld> get(Set<String> tlds) {
|
||||
Map<String, Tld> registries = CACHE.getAll(tlds);
|
||||
Map<String, Optional<Tld>> registries = CACHE.getAll(tlds);
|
||||
ImmutableSet<String> missingRegistries =
|
||||
Sets.difference(tlds, registries.keySet()).immutableCopy();
|
||||
registries.entrySet().stream()
|
||||
.filter(e -> e.getValue().isEmpty())
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(toImmutableSet());
|
||||
if (missingRegistries.isEmpty()) {
|
||||
return registries.values().stream().collect(toImmutableSet());
|
||||
return registries.values().stream().map(Optional::get).collect(toImmutableSet());
|
||||
} else {
|
||||
throw new TldNotFoundException(missingRegistries);
|
||||
}
|
||||
@@ -224,24 +222,24 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||
}
|
||||
|
||||
/** A cache that loads the {@link Tld} for a given tld. */
|
||||
private static final LoadingCache<String, Tld> CACHE =
|
||||
private static final LoadingCache<String, Optional<Tld>> CACHE =
|
||||
CacheUtils.newCacheBuilder(getSingletonCacheRefreshDuration())
|
||||
.build(
|
||||
new CacheLoader<>() {
|
||||
@Override
|
||||
public Tld load(final String tld) {
|
||||
return tm().reTransact(() -> tm().loadByKeyIfPresent(createVKey(tld)))
|
||||
.orElse(null);
|
||||
public Optional<Tld> load(final String tld) {
|
||||
return tm().reTransact(() -> tm().loadByKeyIfPresent(createVKey(tld)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends String, ? extends Tld> loadAll(Set<? extends String> tlds) {
|
||||
public Map<? extends String, ? extends Optional<Tld>> loadAll(
|
||||
Set<? extends String> tlds) {
|
||||
ImmutableMap<String, VKey<Tld>> keysMap =
|
||||
tlds.stream().collect(toImmutableMap(tld -> tld, Tld::createVKey));
|
||||
Map<VKey<? extends Tld>, Tld> entities =
|
||||
tm().reTransact(() -> tm().loadByKeysIfPresent(keysMap.values()));
|
||||
return entities.values().stream()
|
||||
.collect(toImmutableMap(tld -> tld.tldStr, tld -> tld));
|
||||
return Maps.toMap(
|
||||
tlds, tld -> Optional.ofNullable(entities.get(createVKey(tld))));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ import google.registry.ui.server.console.ConsoleDomainListAction;
|
||||
import google.registry.ui.server.console.ConsoleDumDownloadAction;
|
||||
import google.registry.ui.server.console.ConsoleEppPasswordAction;
|
||||
import google.registry.ui.server.console.ConsoleRegistryLockAction;
|
||||
import google.registry.ui.server.console.ConsoleRegistryLockVerifyAction;
|
||||
import google.registry.ui.server.console.ConsoleUpdateRegistrarAction;
|
||||
import google.registry.ui.server.console.ConsoleUserDataAction;
|
||||
import google.registry.ui.server.console.RegistrarsAction;
|
||||
@@ -191,6 +192,8 @@ interface RequestComponent {
|
||||
|
||||
ConsoleRegistryLockAction consoleRegistryLockAction();
|
||||
|
||||
ConsoleRegistryLockVerifyAction consoleRegistryLockVerifyAction();
|
||||
|
||||
ConsoleUiAction consoleUiAction();
|
||||
|
||||
ConsoleUpdateRegistrarAction consoleUpdateRegistrarAction();
|
||||
|
||||
@@ -30,6 +30,7 @@ import google.registry.ui.server.console.ConsoleDomainListAction;
|
||||
import google.registry.ui.server.console.ConsoleDumDownloadAction;
|
||||
import google.registry.ui.server.console.ConsoleEppPasswordAction;
|
||||
import google.registry.ui.server.console.ConsoleRegistryLockAction;
|
||||
import google.registry.ui.server.console.ConsoleRegistryLockVerifyAction;
|
||||
import google.registry.ui.server.console.ConsoleUpdateRegistrarAction;
|
||||
import google.registry.ui.server.console.ConsoleUserDataAction;
|
||||
import google.registry.ui.server.console.RegistrarsAction;
|
||||
@@ -69,6 +70,8 @@ public interface FrontendRequestComponent {
|
||||
|
||||
ConsoleRegistryLockAction consoleRegistryLockAction();
|
||||
|
||||
ConsoleRegistryLockVerifyAction consoleRegistryLockVerifyAction();
|
||||
|
||||
ConsoleUiAction consoleUiAction();
|
||||
|
||||
ConsoleUpdateRegistrarAction consoleUpdateRegistrarAction();
|
||||
|
||||
@@ -76,7 +76,7 @@ public class RdapEntityAction extends RdapActionBase {
|
||||
// they are global, and might have different roles for different domains.
|
||||
if (contact.isPresent() && isAuthorized(contact.get())) {
|
||||
return rdapJsonFormatter.createRdapContactEntity(
|
||||
contact, ImmutableSet.of(), OutputDataType.FULL);
|
||||
contact.get(), ImmutableSet.of(), OutputDataType.FULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -461,7 +461,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
.entitySearchResultsBuilder()
|
||||
.add(
|
||||
rdapJsonFormatter.createRdapContactEntity(
|
||||
Optional.of(contact), ImmutableSet.of(), outputDataType));
|
||||
contact, ImmutableSet.of(), outputDataType));
|
||||
newCursor =
|
||||
Optional.of(
|
||||
CONTACT_CURSOR_PREFIX
|
||||
|
||||
@@ -75,7 +75,6 @@ import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@@ -251,16 +250,6 @@ public class RdapJsonFormatter {
|
||||
private static final Ordering<DesignatedContact> DESIGNATED_CONTACT_ORDERING =
|
||||
Ordering.natural().onResultOf(DesignatedContact::getType);
|
||||
|
||||
/**
|
||||
* The list of RDAP contact roles that are required to be present on each domain.
|
||||
*
|
||||
* <p>Per RDAP Response Profile 2.7.3, A domain MUST have the REGISTRANT, ADMIN, TECH roles and
|
||||
* MAY have others. We also have the BILLING role in our system but it isn't required and is only
|
||||
* listed if actually present.
|
||||
*/
|
||||
private static final ImmutableSet<Role> REQUIRED_CONTACT_ROLES =
|
||||
ImmutableSet.of(Role.REGISTRANT, Role.ADMIN, Role.TECH);
|
||||
|
||||
/** Creates the TOS notice that is added to every reply. */
|
||||
Notice createTosNotice() {
|
||||
String linkValue = makeRdapServletRelativeUrl("help", RdapHelpAction.TOS_PATH);
|
||||
@@ -403,7 +392,6 @@ public class RdapJsonFormatter {
|
||||
|
||||
// Convert the contact entities to RDAP output contacts (this also converts the contact types
|
||||
// to RDAP roles).
|
||||
Set<RdapContactEntity> rdapContacts = new LinkedHashSet<>();
|
||||
for (VKey<Contact> contactKey : contactsToRoles.keySet()) {
|
||||
Set<Role> roles =
|
||||
contactsToRoles.get(contactKey).stream()
|
||||
@@ -412,22 +400,13 @@ public class RdapJsonFormatter {
|
||||
if (roles.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
rdapContacts.add(
|
||||
createRdapContactEntity(
|
||||
Optional.ofNullable(loadedContacts.get(contactKey)), roles, OutputDataType.INTERNAL));
|
||||
builder
|
||||
.entitiesBuilder()
|
||||
.add(
|
||||
createRdapContactEntity(
|
||||
loadedContacts.get(contactKey), roles, OutputDataType.INTERNAL));
|
||||
}
|
||||
|
||||
// Loop through all required contact roles and fill in placeholder REDACTED info for any
|
||||
// required ones that are missing, i.e. because of minimum registration data set.
|
||||
for (Role role : REQUIRED_CONTACT_ROLES) {
|
||||
if (rdapContacts.stream().noneMatch(c -> c.roles().contains(role))) {
|
||||
rdapContacts.add(
|
||||
createRdapContactEntity(
|
||||
Optional.empty(), ImmutableSet.of(role), OutputDataType.INTERNAL));
|
||||
}
|
||||
}
|
||||
builder.entitiesBuilder().addAll(rdapContacts);
|
||||
|
||||
// Add the nameservers to the data; the load was kicked off above for efficiency.
|
||||
// RDAP Response Profile 2.9: we MUST have the nameservers
|
||||
for (Host host : HOST_RESOURCE_ORDERING.immutableSortedCopy(loadedHosts)) {
|
||||
@@ -537,28 +516,20 @@ public class RdapJsonFormatter {
|
||||
* @param outputDataType whether to generate full or summary data
|
||||
*/
|
||||
RdapContactEntity createRdapContactEntity(
|
||||
Optional<Contact> contact, Iterable<RdapEntity.Role> roles, OutputDataType outputDataType) {
|
||||
Contact contact, Iterable<RdapEntity.Role> roles, OutputDataType outputDataType) {
|
||||
RdapContactEntity.Builder contactBuilder = RdapContactEntity.builder();
|
||||
|
||||
// RDAP Response Profile 2.7.1, 2.7.3 - we MUST have the contacts. 2.7.4 discusses censoring of
|
||||
// fields we don't want to show (as opposed to not having contacts at all) because of GDPR etc.
|
||||
//
|
||||
// 2.8 allows for unredacted output for authorized people.
|
||||
// TODO(mcilwain): Once the RDAP profile is fully updated for minimum registration data set,
|
||||
// we will want to not include non-existent contacts at all, rather than
|
||||
// pretending they exist and just showing REDACTED info. This is especially
|
||||
// important for authorized flows, where you wouldn't expect to see redaction
|
||||
// (although no one actually has access to authorized flows yet).
|
||||
boolean isAuthorized =
|
||||
contact.isPresent()
|
||||
&& rdapAuthorization.isAuthorizedForRegistrar(
|
||||
contact.get().getCurrentSponsorRegistrarId());
|
||||
rdapAuthorization.isAuthorizedForRegistrar(contact.getCurrentSponsorRegistrarId());
|
||||
|
||||
VcardArray.Builder vcardBuilder = VcardArray.builder();
|
||||
|
||||
if (isAuthorized) {
|
||||
fillRdapContactEntityWhenAuthorized(
|
||||
contactBuilder, vcardBuilder, contact.get(), outputDataType);
|
||||
fillRdapContactEntityWhenAuthorized(contactBuilder, vcardBuilder, contact, outputDataType);
|
||||
} else {
|
||||
// GTLD Registration Data Temp Spec 17may18, Appendix A, 2.3, 2.4 and RDAP Response Profile
|
||||
// 2.7.4.1, 2.7.4.2 - the following fields must be redacted:
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.common.FeatureFlag.FeatureName;
|
||||
import google.registry.model.common.FeatureFlag.FeatureStatus;
|
||||
import google.registry.tools.params.TransitionListParameter.FeatureStatusTransitions;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Command for creating and updating {@link FeatureFlag} objects. */
|
||||
@Parameters(separators = " =", commandDescription = "Create or update a feature flag.")
|
||||
public class ConfigureFeatureFlagCommand extends MutatingCommand {
|
||||
|
||||
@Parameter(description = "Feature flag name(s) to create or update", required = true)
|
||||
private List<FeatureName> mainParameters;
|
||||
|
||||
@Parameter(
|
||||
names = "--status_map",
|
||||
converter = FeatureStatusTransitions.class,
|
||||
validateWith = FeatureStatusTransitions.class,
|
||||
description =
|
||||
"Comma-delimited list of feature status transitions effective on specific dates, of the"
|
||||
+ " form <time>=<status>[,<time>=<status>]* where each status represents the status"
|
||||
+ " of the feature flag.",
|
||||
required = true)
|
||||
private ImmutableSortedMap<DateTime, FeatureStatus> featureStatusTransitions;
|
||||
|
||||
@Override
|
||||
protected void init() throws Exception {
|
||||
for (FeatureName name : mainParameters) {
|
||||
Optional<FeatureFlag> oldFlag = FeatureFlag.getUncached(name);
|
||||
FeatureFlag.Builder newFlagBuilder =
|
||||
new FeatureFlag().asBuilder().setFeatureName(name).setStatusMap(featureStatusTransitions);
|
||||
stageEntityChange(oldFlag.orElse(null), newFlagBuilder.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -111,8 +111,8 @@ abstract class CreateOrUpdateBulkPricingPackageCommand extends MutatingCommand {
|
||||
if (clearLastNotificationSent()) {
|
||||
builder.setLastNotificationSent(null);
|
||||
}
|
||||
BulkPricingPackage newBUlkPricingPackage = builder.build();
|
||||
stageEntityChange(oldBulkPricingPackage, newBUlkPricingPackage);
|
||||
BulkPricingPackage newBulkPricingPackage = builder.build();
|
||||
stageEntityChange(oldBulkPricingPackage, newBulkPricingPackage);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ public final class DomainLockUtils {
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new IllegalArgumentException(
|
||||
String.format("Invalid verification code %s", verificationCode)));
|
||||
String.format("Invalid verification code \"%s\"", verificationCode)));
|
||||
}
|
||||
|
||||
private void applyLockStatuses(RegistryLock lock, DateTime lockTime, boolean isAdmin) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.beust.jcommander.internal.Nullable;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
@@ -62,6 +63,7 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Command to generate and persist {@link AllocationToken}s. */
|
||||
@@ -158,10 +160,16 @@ class GenerateAllocationTokensCommand implements Command {
|
||||
"The type of renewal price behavior, either DEFAULT (default), NONPREMIUM, or SPECIFIED."
|
||||
+ " This indicates how a domain should be charged for renewal. By default, a domain"
|
||||
+ " will be renewed at the renewal price from the pricing engine. If the renewal"
|
||||
+ " price behavior is set to SPECIFIED, it means that the renewal cost will be the"
|
||||
+ " same as the domain's calculated create price.")
|
||||
+ " price behavior is set to SPECIFIED, it means that the renewal cost will be equal"
|
||||
+ " to the provided renewal price.")
|
||||
private RenewalPriceBehavior renewalPriceBehavior = DEFAULT;
|
||||
|
||||
@Parameter(
|
||||
names = {"--renewal_price"},
|
||||
description = "The renewal price amount iff the renewal price behavior is SPECIFIED.")
|
||||
@Nullable
|
||||
private Money renewalPrice;
|
||||
|
||||
@Parameter(
|
||||
names = {"--registration_behavior"},
|
||||
description =
|
||||
@@ -228,6 +236,7 @@ class GenerateAllocationTokensCommand implements Command {
|
||||
Optional.ofNullable(discountYears).ifPresent(token::setDiscountYears);
|
||||
Optional.ofNullable(tokenStatusTransitions)
|
||||
.ifPresent(token::setTokenStatusTransitions);
|
||||
Optional.ofNullable(renewalPrice).ifPresent(token::setRenewalPrice);
|
||||
Optional.ofNullable(domainNames)
|
||||
.ifPresent(d -> token.setDomainName(d.removeFirst()));
|
||||
return token.build();
|
||||
@@ -284,7 +293,7 @@ class GenerateAllocationTokensCommand implements Command {
|
||||
// tokens should only be scheduled to end with a brief time period before the status
|
||||
// transition occurs so that no new domains are registered using that token between when the
|
||||
// status is scheduled and when the transition occurs.
|
||||
// TODO(@sarahbot): Create a cleaner way to handle ending bulk pricing packages once we
|
||||
// TODO(b/261763205): Create a cleaner way to handle ending bulk pricing packages once we
|
||||
// actually have customers using them
|
||||
boolean hasEnding =
|
||||
tokenStatusTransitions.containsValue(TokenStatus.ENDED)
|
||||
@@ -295,6 +304,10 @@ class GenerateAllocationTokensCommand implements Command {
|
||||
+ " map");
|
||||
}
|
||||
|
||||
checkArgument(
|
||||
renewalPriceBehavior.equals(RenewalPriceBehavior.SPECIFIED) == (renewalPrice != null),
|
||||
"renewal_price must be specified iff renewal_price_behavior is SPECIFIED");
|
||||
|
||||
if (tokenStrings != null) {
|
||||
verifyTokenStringsDoNotExist();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.common.FeatureFlag.FeatureFlagNotFoundException;
|
||||
import google.registry.model.common.FeatureFlag.FeatureName;
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Command to show a {@link FeatureFlag}. */
|
||||
@Parameters(separators = " =", commandDescription = "Show FeatureFlag record(s)")
|
||||
public class GetFeatureFlagCommand implements Command {
|
||||
|
||||
@Parameter(description = "Feature flag(s) to show", required = true)
|
||||
private List<FeatureName> mainParameters;
|
||||
|
||||
@Inject ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
// Don't use try-with-resources to manage standard output streams, closing the stream will
|
||||
// cause subsequent output to standard output or standard error to be lost
|
||||
// See: https://errorprone.info/bugpattern/ClosingStandardOutputStreams
|
||||
PrintStream printStream = new PrintStream(System.out, false, UTF_8);
|
||||
for (FeatureName featureFlag : mainParameters) {
|
||||
Optional<FeatureFlag> maybeFeatureFlag = FeatureFlag.getUncached(featureFlag);
|
||||
if (maybeFeatureFlag.isEmpty()) {
|
||||
throw new FeatureFlagNotFoundException(featureFlag);
|
||||
}
|
||||
printStream.println(objectMapper.writeValueAsString(maybeFeatureFlag.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import java.io.PrintStream;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Command to list all {@link google.registry.model.common.FeatureFlag} objects. */
|
||||
@Parameters(separators = " =", commandDescription = "List all feature flags.")
|
||||
public class ListFeatureFlagsCommand implements Command {
|
||||
|
||||
@Inject ObjectMapper mapper;
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
// Don't use try-with-resources to manage standard output streams, closing the stream will
|
||||
// cause subsequent output to standard output or standard error to be lost
|
||||
// See: https://errorprone.info/bugpattern/ClosingStandardOutputStreams
|
||||
PrintStream printStream = new PrintStream(System.out, false, UTF_8);
|
||||
ImmutableList<FeatureFlag> featureFlags = FeatureFlag.getAllUncached();
|
||||
for (FeatureFlag featureFlag : featureFlags) {
|
||||
printStream.println(mapper.writeValueAsString(featureFlag));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,6 @@ import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -87,12 +86,6 @@ final class RegistrarPocCommand extends MutatingCommand {
|
||||
+ " and will be used as the console login email, if --login_email is not specified.")
|
||||
String email;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
names = "--login_email",
|
||||
description = "Console login email address. If not specified, --email will be used.")
|
||||
String loginEmail;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
names = "--registry_lock_email",
|
||||
@@ -115,13 +108,6 @@ final class RegistrarPocCommand extends MutatingCommand {
|
||||
validateWith = OptionalPhoneNumberParameter.class)
|
||||
private Optional<String> fax;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
names = "--allow_console_access",
|
||||
description = "Enable or disable access to the registrar console for this contact.",
|
||||
arity = 1)
|
||||
Boolean allowConsoleAccess;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
names = "--visible_in_whois_as_admin",
|
||||
@@ -173,7 +159,7 @@ final class RegistrarPocCommand extends MutatingCommand {
|
||||
protected void init() throws Exception {
|
||||
checkArgument(mainParameters.size() == 1,
|
||||
"Must specify exactly one client identifier: %s", ImmutableList.copyOf(mainParameters));
|
||||
String clientId = mainParameters.get(0);
|
||||
String clientId = mainParameters.getFirst();
|
||||
Registrar registrar =
|
||||
checkArgumentPresent(
|
||||
Registrar.loadByRegistrarId(clientId), "Registrar %s not found", clientId);
|
||||
@@ -261,9 +247,6 @@ final class RegistrarPocCommand extends MutatingCommand {
|
||||
}
|
||||
builder.setTypes(nullToEmpty(contactTypes));
|
||||
|
||||
if (Objects.equals(allowConsoleAccess, Boolean.TRUE)) {
|
||||
builder.setLoginEmailAddress(loginEmail == null ? email : loginEmail);
|
||||
}
|
||||
if (visibleInWhoisAsAdmin != null) {
|
||||
builder.setVisibleInWhoisAsAdmin(visibleInWhoisAsAdmin);
|
||||
}
|
||||
@@ -308,13 +291,6 @@ final class RegistrarPocCommand extends MutatingCommand {
|
||||
if (visibleInDomainWhoisAsAbuse != null) {
|
||||
builder.setVisibleInDomainWhoisAsAbuse(visibleInDomainWhoisAsAbuse);
|
||||
}
|
||||
if (allowConsoleAccess != null) {
|
||||
if (allowConsoleAccess.equals(Boolean.TRUE)) {
|
||||
builder.setLoginEmailAddress(loginEmail == null ? email : loginEmail);
|
||||
} else {
|
||||
builder.setLoginEmailAddress(null);
|
||||
}
|
||||
}
|
||||
if (allowedToSetRegistryLockPassword != null) {
|
||||
builder.setAllowedToSetRegistryLockPassword(allowedToSetRegistryLockPassword);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ public final class RegistryTool {
|
||||
.put("canonicalize_labels", CanonicalizeLabelsCommand.class)
|
||||
.put("check_domain", CheckDomainCommand.class)
|
||||
.put("check_domain_claims", CheckDomainClaimsCommand.class)
|
||||
.put("configure_feature_flag", ConfigureFeatureFlagCommand.class)
|
||||
.put("configure_tld", ConfigureTldCommand.class)
|
||||
.put("convert_idn", ConvertIdnCommand.class)
|
||||
.put("count_domains", CountDomainsCommand.class)
|
||||
@@ -71,6 +72,7 @@ public final class RegistryTool {
|
||||
.put("get_claims_list", GetClaimsListCommand.class)
|
||||
.put("get_contact", GetContactCommand.class)
|
||||
.put("get_domain", GetDomainCommand.class)
|
||||
.put("get_feature_flag", GetFeatureFlagCommand.class)
|
||||
.put("get_history_entries", GetHistoryEntriesCommand.class)
|
||||
.put("get_host", GetHostCommand.class)
|
||||
.put("get_keyring_secret", GetKeyringSecretCommand.class)
|
||||
@@ -85,6 +87,7 @@ public final class RegistryTool {
|
||||
.put("hash_certificate", HashCertificateCommand.class)
|
||||
.put("list_cursors", ListCursorsCommand.class)
|
||||
.put("list_domains", ListDomainsCommand.class)
|
||||
.put("list_feature_flags", ListFeatureFlagsCommand.class)
|
||||
.put("list_hosts", ListHostsCommand.class)
|
||||
.put("list_premium_lists", ListPremiumListsCommand.class)
|
||||
.put("list_registrars", ListRegistrarsCommand.class)
|
||||
|
||||
@@ -119,6 +119,8 @@ interface RegistryToolComponent {
|
||||
|
||||
void inject(GetDomainCommand command);
|
||||
|
||||
void inject(GetFeatureFlagCommand command);
|
||||
|
||||
void inject(GetHostCommand command);
|
||||
|
||||
void inject(GetKeyringSecretCommand command);
|
||||
@@ -131,6 +133,8 @@ interface RegistryToolComponent {
|
||||
|
||||
void inject(ListCursorsCommand command);
|
||||
|
||||
void inject(ListFeatureFlagsCommand command);
|
||||
|
||||
void inject(LockDomainCommand command);
|
||||
|
||||
void inject(LoginCommand command);
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Command to update existing {@link AllocationToken}s. */
|
||||
@@ -110,11 +111,17 @@ final class UpdateAllocationTokensCommand extends UpdateOrDeleteAllocationTokens
|
||||
"The type of renewal price behavior, either DEFAULT (default), NONPREMIUM, or SPECIFIED."
|
||||
+ " This indicates how a domain should be charged for renewal. By default, a domain"
|
||||
+ " will be renewed at the renewal price from the pricing engine. If the renewal"
|
||||
+ " price behavior is set to SPECIFIED, it means that the renewal cost will be the"
|
||||
+ " same as the domain's calculated create price.")
|
||||
+ " price behavior is set to SPECIFIED, it means that the renewal cost will be equal"
|
||||
+ " to the provided renewal price.")
|
||||
@Nullable
|
||||
private RenewalPriceBehavior renewalPriceBehavior;
|
||||
|
||||
@Parameter(
|
||||
names = {"--renewal_price"},
|
||||
description = "The renewal price amount iff the renewal price behavior is SPECIFIED.")
|
||||
@Nullable
|
||||
private Money renewalPrice;
|
||||
|
||||
@Parameter(
|
||||
names = {"--registration_behavior"},
|
||||
description =
|
||||
@@ -189,17 +196,22 @@ final class UpdateAllocationTokensCommand extends UpdateOrDeleteAllocationTokens
|
||||
.ifPresent(tlds -> builder.setAllowedTlds(ImmutableSet.copyOf(tlds)));
|
||||
Optional.ofNullable(allowedEppActions)
|
||||
.ifPresent(
|
||||
eppActions -> {
|
||||
builder.setAllowedEppActions(
|
||||
eppActions.stream()
|
||||
.map(CommandName::parseKnownCommand)
|
||||
.collect(toImmutableSet()));
|
||||
});
|
||||
eppActions ->
|
||||
builder.setAllowedEppActions(
|
||||
eppActions.stream()
|
||||
.map(CommandName::parseKnownCommand)
|
||||
.collect(toImmutableSet())));
|
||||
Optional.ofNullable(discountFraction).ifPresent(builder::setDiscountFraction);
|
||||
Optional.ofNullable(discountPremiums).ifPresent(builder::setDiscountPremiums);
|
||||
Optional.ofNullable(discountYears).ifPresent(builder::setDiscountYears);
|
||||
Optional.ofNullable(tokenStatusTransitions).ifPresent(builder::setTokenStatusTransitions);
|
||||
|
||||
if (renewalPriceBehavior != null
|
||||
&& renewalPriceBehavior != original.getRenewalPriceBehavior()) {
|
||||
builder.setRenewalPrice(null);
|
||||
}
|
||||
Optional.ofNullable(renewalPriceBehavior).ifPresent(builder::setRenewalPriceBehavior);
|
||||
Optional.ofNullable(renewalPrice).ifPresent(builder::setRenewalPrice);
|
||||
Optional.ofNullable(registrationBehavior).ifPresent(builder::setRegistrationBehavior);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Ordering;
|
||||
import google.registry.model.common.FeatureFlag.FeatureStatus;
|
||||
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||
import google.registry.model.tld.Tld.TldState;
|
||||
import org.joda.money.Money;
|
||||
@@ -72,4 +73,12 @@ public abstract class TransitionListParameter<V> extends KeyValueMapParameter<Da
|
||||
return TokenStatus.valueOf(value);
|
||||
}
|
||||
}
|
||||
|
||||
/** Converter-validator for feature status transitions. */
|
||||
public static class FeatureStatusTransitions extends TransitionListParameter<FeatureStatus> {
|
||||
@Override
|
||||
protected FeatureStatus parseValue(String value) {
|
||||
return FeatureStatus.valueOf(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,9 +193,6 @@ public final class RegistrarFormFields {
|
||||
public static final FormField<String, String> CONTACT_FAX_NUMBER_FIELD =
|
||||
FormFields.PHONE_NUMBER.asBuilderNamed("faxNumber").build();
|
||||
|
||||
public static final FormField<String, String> CONTACT_LOGIN_EMAIL_ADDRESS_FIELD =
|
||||
FormFields.NAME.asBuilderNamed("loginEmailAddress").build();
|
||||
|
||||
public static final FormField<Object, Boolean> CONTACT_ALLOWED_TO_SET_REGISTRY_LOCK_PASSWORD =
|
||||
FormField.named("allowedToSetRegistryLockPassword", Object.class)
|
||||
.transform(Boolean.class, b -> Boolean.valueOf(Objects.toString(b)))
|
||||
@@ -384,8 +381,6 @@ public final class RegistrarFormFields {
|
||||
builder.setPhoneNumber(CONTACT_PHONE_NUMBER_FIELD.extractUntyped(args).orElse(null));
|
||||
builder.setFaxNumber(CONTACT_FAX_NUMBER_FIELD.extractUntyped(args).orElse(null));
|
||||
builder.setTypes(CONTACT_TYPES.extractUntyped(args).orElse(ImmutableSet.of()));
|
||||
builder.setLoginEmailAddress(
|
||||
CONTACT_LOGIN_EMAIL_ADDRESS_FIELD.extractUntyped(args).orElse(null));
|
||||
// The parser is inconsistent with whether it retrieves boolean values as strings or booleans.
|
||||
// As a result, use a potentially-redundant converter that can deal with both.
|
||||
builder.setAllowedToSetRegistryLockPassword(
|
||||
|
||||
@@ -29,10 +29,12 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.batch.CloudTasksUtils;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.export.sheet.SyncRegistrarsSheetAction;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.model.registrar.RegistrarPocBase;
|
||||
@@ -62,6 +64,10 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
|
||||
@Inject CloudTasksUtils cloudTasksUtils;
|
||||
|
||||
@Inject
|
||||
@RegistryConfig.Config("registryAdminClientId")
|
||||
String registryAdminClientId;
|
||||
|
||||
public ConsoleApiAction(ConsoleApiParams consoleApiParams) {
|
||||
this.consoleApiParams = consoleApiParams;
|
||||
}
|
||||
@@ -77,8 +83,12 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
|
||||
// This allows us to enable console to a selected cohort of users with release
|
||||
// We can ignore it in tests
|
||||
if (RegistryEnvironment.get() != RegistryEnvironment.UNITTEST
|
||||
&& GlobalRole.NONE.equals(user.getUserRoles().getGlobalRole())) {
|
||||
UserRoles userRoles = user.getUserRoles();
|
||||
boolean hasGlobalOrTestingRole =
|
||||
!GlobalRole.NONE.equals(userRoles.getGlobalRole())
|
||||
|| userRoles.hasPermission(
|
||||
registryAdminClientId, ConsolePermission.VIEW_REGISTRAR_DETAILS);
|
||||
if (RegistryEnvironment.get() != RegistryEnvironment.UNITTEST && !hasGlobalOrTestingRole) {
|
||||
try {
|
||||
consoleApiParams.response().sendRedirect(ConsoleUiAction.PATH);
|
||||
return;
|
||||
@@ -161,7 +171,7 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
|
||||
Map<String, Object> registrarDiffMap = registrar.toDiffableFieldMap();
|
||||
Stream.of("passwordHash", "salt") // fields to remove from final diff
|
||||
.forEach(fieldToBeRemoved -> registrarDiffMap.remove(fieldToBeRemoved));
|
||||
.forEach(registrarDiffMap::remove);
|
||||
|
||||
// Use LinkedHashMap here to preserve ordering; null values mean we can't use ImmutableMap.
|
||||
LinkedHashMap<String, Object> result = new LinkedHashMap<>(registrarDiffMap);
|
||||
|
||||
@@ -115,6 +115,7 @@ public class ConsoleDomainListAction extends ConsoleApiAction {
|
||||
.setFirstResult(numResultsToSkip)
|
||||
.setMaxResults(resultsPerPage)
|
||||
.getResultList();
|
||||
|
||||
consoleApiParams
|
||||
.response()
|
||||
.setPayload(gson.toJson(new DomainListResult(domains, checkpoint, actualTotalResults)));
|
||||
|
||||
+22
-21
@@ -19,16 +19,13 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.request.RequestParameters.extractBooleanParameter;
|
||||
import static google.registry.request.RequestParameters.extractOptionalLongParameter;
|
||||
import static google.registry.request.RequestParameters.extractOptionalParameter;
|
||||
import static google.registry.request.RequestParameters.extractRequiredParameter;
|
||||
import static google.registry.ui.server.registrar.RegistryLockPostAction.VERIFICATION_EMAIL_TEMPLATE;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.domain.DomainFlowUtils;
|
||||
import google.registry.groups.GmailClient;
|
||||
@@ -46,11 +43,9 @@ import google.registry.ui.server.registrar.ConsoleApiParams;
|
||||
import google.registry.util.EmailMessage;
|
||||
import jakarta.mail.internet.AddressException;
|
||||
import jakarta.mail.internet.InternetAddress;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
@@ -71,6 +66,7 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
private final DomainLockUtils domainLockUtils;
|
||||
private final GmailClient gmailClient;
|
||||
private final Gson gson;
|
||||
private final Optional<ConsoleRegistryLockPostInput> optionalPostInput;
|
||||
private final String registrarId;
|
||||
|
||||
@Inject
|
||||
@@ -79,11 +75,14 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
DomainLockUtils domainLockUtils,
|
||||
GmailClient gmailClient,
|
||||
Gson gson,
|
||||
@Parameter("consoleRegistryLockPostInput")
|
||||
Optional<ConsoleRegistryLockPostInput> optionalPostInput,
|
||||
@Parameter("registrarId") String registrarId) {
|
||||
super(consoleApiParams);
|
||||
this.domainLockUtils = domainLockUtils;
|
||||
this.gmailClient = gmailClient;
|
||||
this.gson = gson;
|
||||
this.optionalPostInput = optionalPostInput;
|
||||
this.registrarId = registrarId;
|
||||
}
|
||||
|
||||
@@ -96,7 +95,6 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
|
||||
@Override
|
||||
protected void postHandler(User user) {
|
||||
HttpServletRequest req = consoleApiParams.request();
|
||||
Response response = consoleApiParams.response();
|
||||
// User must have the proper permission on the registrar
|
||||
checkPermission(user, registrarId, ConsolePermission.REGISTRY_LOCK);
|
||||
@@ -109,10 +107,12 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
registrarId);
|
||||
|
||||
// Retrieve and validate the necessary params
|
||||
String domainName = extractRequiredParameter(req, "domainName");
|
||||
boolean isLock = extractBooleanParameter(req, "isLock");
|
||||
Optional<String> maybePassword = extractOptionalParameter(req, "password");
|
||||
Optional<Long> relockDurationMillis = extractOptionalLongParameter(req, "relockDurationMillis");
|
||||
ConsoleRegistryLockPostInput postInput =
|
||||
optionalPostInput.orElseThrow(() -> new IllegalArgumentException("No POST input provided"));
|
||||
String domainName = postInput.domainName();
|
||||
boolean isLock = postInput.isLock();
|
||||
Optional<String> maybePassword = Optional.ofNullable(postInput.password());
|
||||
Optional<Long> relockDurationMillis = Optional.ofNullable(postInput.relockDurationMillis());
|
||||
|
||||
try {
|
||||
DomainFlowUtils.validateDomainName(domainName);
|
||||
@@ -153,14 +153,9 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
private void sendVerificationEmail(RegistryLock lock, String userEmail, boolean isLock) {
|
||||
try {
|
||||
String url =
|
||||
new URIBuilder()
|
||||
.setScheme("https")
|
||||
.setHost(consoleApiParams.request().getServerName())
|
||||
// TODO: replace this with the PATH in ConsoleRegistryLockVerifyAction once it exists
|
||||
.setPath("/console-api/registry-lock-verify")
|
||||
.setParameter("lockVerificationCode", lock.getVerificationCode())
|
||||
.build()
|
||||
.toString();
|
||||
String.format(
|
||||
"https://%s/console/#/registry-lock-verify?lockVerificationCode=%s",
|
||||
consoleApiParams.request().getServerName(), lock.getVerificationCode());
|
||||
String body = String.format(VERIFICATION_EMAIL_TEMPLATE, lock.getDomainName(), url);
|
||||
ImmutableList<InternetAddress> recipients =
|
||||
ImmutableList.of(new InternetAddress(userEmail, true));
|
||||
@@ -171,7 +166,7 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
.setSubject(String.format("Registry %s verification", action))
|
||||
.setRecipients(recipients)
|
||||
.build());
|
||||
} catch (AddressException | URISyntaxException e) {
|
||||
} catch (AddressException e) {
|
||||
throw new RuntimeException(e); // caught above -- this is so we can run in a transaction
|
||||
}
|
||||
}
|
||||
@@ -183,4 +178,10 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
.filter(lock -> !lock.isLockRequestExpired(tm().getTransactionTime()))
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
|
||||
public record ConsoleRegistryLockPostInput(
|
||||
@Expose String domainName,
|
||||
@Expose boolean isLock,
|
||||
@Expose @Nullable String password,
|
||||
@Expose @Nullable Long relockDurationMillis) {}
|
||||
}
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.ui.server.console;
|
||||
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.domain.RegistryLock;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.tools.DomainLockUtils;
|
||||
import google.registry.ui.server.registrar.ConsoleApiParams;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Handler for verifying registry lock requests, a form of 2FA. */
|
||||
@Action(
|
||||
service = Action.Service.DEFAULT,
|
||||
path = ConsoleRegistryLockVerifyAction.PATH,
|
||||
method = {GET},
|
||||
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
||||
public class ConsoleRegistryLockVerifyAction extends ConsoleApiAction {
|
||||
|
||||
static final String PATH = "/console-api/registry-lock-verify";
|
||||
|
||||
private final DomainLockUtils domainLockUtils;
|
||||
private final Gson gson;
|
||||
private final String lockVerificationCode;
|
||||
|
||||
@Inject
|
||||
public ConsoleRegistryLockVerifyAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
DomainLockUtils domainLockUtils,
|
||||
Gson gson,
|
||||
@Parameter("lockVerificationCode") String lockVerificationCode) {
|
||||
super(consoleApiParams);
|
||||
this.domainLockUtils = domainLockUtils;
|
||||
this.gson = gson;
|
||||
this.lockVerificationCode = lockVerificationCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getHandler(User user) {
|
||||
RegistryLock lock =
|
||||
domainLockUtils.verifyVerificationCode(lockVerificationCode, user.getUserRoles().isAdmin());
|
||||
RegistryLockAction action =
|
||||
lock.getLockCompletionTime().isPresent()
|
||||
? RegistryLockAction.UNLOCKED
|
||||
: RegistryLockAction.LOCKED;
|
||||
RegistryLockVerificationResponse lockResponse =
|
||||
new RegistryLockVerificationResponse(
|
||||
Ascii.toLowerCase(action.toString()), lock.getDomainName(), lock.getRegistrarId());
|
||||
consoleApiParams.response().setPayload(gson.toJson(lockResponse));
|
||||
consoleApiParams.response().setStatus(HttpServletResponse.SC_OK);
|
||||
}
|
||||
|
||||
private enum RegistryLockAction {
|
||||
LOCKED,
|
||||
UNLOCKED
|
||||
}
|
||||
|
||||
private record RegistryLockVerificationResponse(
|
||||
@Expose String action, @Expose String domainName, @Expose String registrarId) {}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ package google.registry.ui.server.console;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
@@ -23,6 +24,7 @@ import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
@@ -36,6 +38,8 @@ import google.registry.request.Parameter;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.ui.server.registrar.ConsoleApiParams;
|
||||
import google.registry.util.StringGenerator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
@@ -50,6 +54,11 @@ public class RegistrarsAction extends ConsoleApiAction {
|
||||
private static final int PASSCODE_LENGTH = 5;
|
||||
private static final ImmutableList<RegistrarBase.Type> allowedRegistrarTypes =
|
||||
ImmutableList.of(Registrar.Type.REAL, RegistrarBase.Type.OTE);
|
||||
private static final String SQL_TEMPLATE =
|
||||
"""
|
||||
SELECT * FROM "Registrar"
|
||||
WHERE registrar_id in :registrarIds
|
||||
""";
|
||||
static final String PATH = "/console-api/registrars";
|
||||
private final Gson gson;
|
||||
private final Optional<Registrar> registrar;
|
||||
@@ -72,18 +81,34 @@ public class RegistrarsAction extends ConsoleApiAction {
|
||||
|
||||
@Override
|
||||
protected void getHandler(User user) {
|
||||
if (!user.getUserRoles().hasGlobalPermission(ConsolePermission.VIEW_REGISTRARS)) {
|
||||
if (user.getUserRoles().hasGlobalPermission(ConsolePermission.VIEW_REGISTRARS)) {
|
||||
ImmutableList<Registrar> registrars =
|
||||
Streams.stream(Registrar.loadAll())
|
||||
.filter(r -> allowedRegistrarTypes.contains(r.getType()))
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
consoleApiParams.response().setPayload(gson.toJson(registrars));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
} else if (user.getUserRoles().getRegistrarRoles().values().stream()
|
||||
.anyMatch(role -> role.hasPermission(ConsolePermission.VIEW_REGISTRAR_DETAILS))) {
|
||||
ImmutableSet<String> accessibleRegistrarIds =
|
||||
user.getUserRoles().getRegistrarRoles().entrySet().stream()
|
||||
.filter(e -> e.getValue().hasPermission(ConsolePermission.VIEW_REGISTRAR_DETAILS))
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(toImmutableSet());
|
||||
|
||||
List<Registrar> registrars =
|
||||
tm().transact(
|
||||
() ->
|
||||
tm().getEntityManager()
|
||||
.createNativeQuery(SQL_TEMPLATE, Registrar.class)
|
||||
.setParameter("registrarIds", accessibleRegistrarIds)
|
||||
.getResultList());
|
||||
|
||||
consoleApiParams.response().setPayload(gson.toJson(registrars));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
} else {
|
||||
consoleApiParams.response().setStatus(SC_FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
|
||||
ImmutableList<Registrar> registrars =
|
||||
Streams.stream(Registrar.loadAll())
|
||||
.filter(r -> allowedRegistrarTypes.contains(r.getType()))
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
|
||||
consoleApiParams.response().setPayload(gson.toJson(registrars));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -139,7 +164,6 @@ public class RegistrarsAction extends ConsoleApiAction {
|
||||
.setRegistrar(registrar)
|
||||
.setName(registrarParam.getEmailAddress())
|
||||
.setEmailAddress(registrarParam.getEmailAddress())
|
||||
.setLoginEmailAddress(registrarParam.getEmailAddress())
|
||||
.build();
|
||||
|
||||
tm().transact(
|
||||
@@ -151,4 +175,5 @@ public class RegistrarsAction extends ConsoleApiAction {
|
||||
tm().putAll(registrar, contact);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import google.registry.request.auth.AuthResult;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
import google.registry.ui.server.SendEmailUtils;
|
||||
import google.registry.ui.server.console.ConsoleEppPasswordAction.EppPasswordData;
|
||||
import google.registry.ui.server.console.ConsoleRegistryLockAction.ConsoleRegistryLockPostInput;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -242,4 +243,11 @@ public final class RegistrarConsoleModule {
|
||||
Gson gson, @OptionalJsonPayload Optional<JsonElement> payload) {
|
||||
return payload.map(s -> gson.fromJson(s, EppPasswordData.class));
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter("consoleRegistryLockPostInput")
|
||||
public static Optional<ConsoleRegistryLockPostInput> provideRegistryLockPostInput(
|
||||
Gson gson, @OptionalJsonPayload Optional<JsonElement> payload) {
|
||||
return payload.map(e -> gson.fromJson(e, ConsoleRegistryLockPostInput.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static google.registry.testing.DatabaseHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistEppResource;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.testing.LogsSubject.assertAboutLogs;
|
||||
import static org.joda.money.CurrencyUnit.USD;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -111,8 +112,9 @@ public class CheckBulkComplianceActionTest {
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(CurrencyUnit.USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setDiscountFraction(1)
|
||||
.setDiscountFraction(1.0)
|
||||
.build());
|
||||
bulkPricingPackage =
|
||||
new BulkPricingPackage.Builder()
|
||||
@@ -206,8 +208,9 @@ public class CheckBulkComplianceActionTest {
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setDiscountFraction(1)
|
||||
.setDiscountFraction(1.0)
|
||||
.build());
|
||||
BulkPricingPackage bulkPricingPackage2 =
|
||||
new BulkPricingPackage.Builder()
|
||||
@@ -263,8 +266,9 @@ public class CheckBulkComplianceActionTest {
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setDiscountFraction(1)
|
||||
.setDiscountFraction(1.0)
|
||||
.build());
|
||||
BulkPricingPackage packagePromotion2 =
|
||||
new BulkPricingPackage.Builder()
|
||||
@@ -338,8 +342,9 @@ public class CheckBulkComplianceActionTest {
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setDiscountFraction(1)
|
||||
.setDiscountFraction(1.0)
|
||||
.build());
|
||||
BulkPricingPackage bulkPricingPackage2 =
|
||||
new BulkPricingPackage.Builder()
|
||||
@@ -404,8 +409,9 @@ public class CheckBulkComplianceActionTest {
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setDiscountFraction(1)
|
||||
.setDiscountFraction(1.0)
|
||||
.build());
|
||||
BulkPricingPackage bulkPricingPackage2 =
|
||||
new BulkPricingPackage.Builder()
|
||||
|
||||
@@ -20,6 +20,7 @@ import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.loadByEntity;
|
||||
import static google.registry.testing.DatabaseHelper.newDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistDomainWithDependentResources;
|
||||
import static google.registry.testing.DatabaseHelper.persistDomainWithPendingTransfer;
|
||||
@@ -39,7 +40,6 @@ import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationT
|
||||
import google.registry.request.Response;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -107,7 +107,7 @@ public class ResaveEntityActionTest {
|
||||
|
||||
@Test
|
||||
void test_domainPendingDeletion_isResavedAndReenqueued() {
|
||||
Domain newDomain = DatabaseHelper.newDomain("domain.tld");
|
||||
Domain newDomain = newDomain("domain.tld");
|
||||
Domain domain =
|
||||
persistResource(
|
||||
newDomain
|
||||
@@ -144,4 +144,16 @@ public class ResaveEntityActionTest {
|
||||
.param(PARAM_REQUESTED_TIME, requestedTime.toString())
|
||||
.scheduleTime(clock.nowUtc().plus(standardDays(5))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_queuedTaskForNonExistentDomain_failsPermanently() {
|
||||
DateTime requestedTime = clock.nowUtc();
|
||||
// It should complete its run without throwing an exception (that would cause a retry) ...
|
||||
runAction(
|
||||
newDomain("nonexistent.tld").createVKey().stringify(),
|
||||
requestedTime,
|
||||
ImmutableSortedSet.of(requestedTime.plusDays(5)));
|
||||
// ... and it shouldn't enqueue the subsequent re-save 5 days later.
|
||||
cloudTasksHelper.assertNoTasksEnqueued(QUEUE_ASYNC_ACTIONS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,6 @@ public class SyncRegistrarsSheetTest {
|
||||
// distinction to make sure we're not relying on it. Sigh.
|
||||
.setVisibleInWhoisAsAdmin(false)
|
||||
.setVisibleInWhoisAsTech(true)
|
||||
.setLoginEmailAddress("john.doe@example.tld")
|
||||
.build(),
|
||||
new RegistrarPoc.Builder()
|
||||
.setRegistrar(registrar)
|
||||
@@ -191,7 +190,7 @@ public class SyncRegistrarsSheetTest {
|
||||
ImmutableList<ImmutableMap<String, String>> rows = getOnlyElement(rowsCaptor.getAllValues());
|
||||
assertThat(rows).hasSize(2);
|
||||
|
||||
ImmutableMap<String, String> row = rows.get(0);
|
||||
ImmutableMap<String, String> row = rows.getFirst();
|
||||
assertThat(row).containsEntry("registrarId", "aaaregistrar");
|
||||
assertThat(row).containsEntry("registrarName", "AAA Registrar Inc.");
|
||||
assertThat(row).containsEntry("state", "SUSPENDED");
|
||||
@@ -208,7 +207,6 @@ public class SyncRegistrarsSheetTest {
|
||||
Visible in registrar WHOIS query as Technical contact: No
|
||||
Phone number and email visible in domain WHOIS query as Registrar Abuse contact\
|
||||
info: No
|
||||
Registrar-Console access: No
|
||||
|
||||
John Doe
|
||||
john.doe@example.tld
|
||||
@@ -219,8 +217,6 @@ public class SyncRegistrarsSheetTest {
|
||||
Visible in registrar WHOIS query as Technical contact: Yes
|
||||
Phone number and email visible in domain WHOIS query as Registrar Abuse contact\
|
||||
info: No
|
||||
Registrar-Console access: Yes
|
||||
Login Email Address: john.doe@example.tld
|
||||
""");
|
||||
assertThat(row)
|
||||
.containsEntry(
|
||||
@@ -233,7 +229,6 @@ public class SyncRegistrarsSheetTest {
|
||||
Visible in registrar WHOIS query as Technical contact: No
|
||||
Phone number and email visible in domain WHOIS query as Registrar Abuse contact\
|
||||
info: No
|
||||
Registrar-Console access: No
|
||||
""");
|
||||
assertThat(row).containsEntry("marketingContacts", "");
|
||||
assertThat(row).containsEntry("abuseContacts", "");
|
||||
@@ -251,7 +246,6 @@ public class SyncRegistrarsSheetTest {
|
||||
Visible in registrar WHOIS query as Technical contact: No
|
||||
Phone number and email visible in domain WHOIS query as Registrar Abuse contact\
|
||||
info: No
|
||||
Registrar-Console access: No
|
||||
""");
|
||||
assertThat(row).containsEntry("contactsMarkedAsWhoisAdmin", "");
|
||||
assertThat(row)
|
||||
@@ -267,8 +261,6 @@ public class SyncRegistrarsSheetTest {
|
||||
Visible in registrar WHOIS query as Technical contact: Yes
|
||||
Phone number and email visible in domain WHOIS query as Registrar Abuse contact\
|
||||
info: No
|
||||
Registrar-Console access: Yes
|
||||
Login Email Address: john.doe@example.tld
|
||||
""");
|
||||
assertThat(row).containsEntry("emailAddress", "nowhere@example.org");
|
||||
assertThat(row).containsEntry(
|
||||
|
||||
@@ -16,6 +16,8 @@ package google.registry.flows;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_OPTIONAL;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.INACTIVE;
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS_AND_CLOSE;
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
|
||||
@@ -40,6 +42,7 @@ import com.google.re2j.Matcher;
|
||||
import com.google.re2j.Pattern;
|
||||
import google.registry.model.billing.BillingBase.Reason;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.reporting.HistoryEntry.Type;
|
||||
@@ -73,6 +76,12 @@ class EppLifecycleDomainTest extends EppTestCase {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
persistResource(
|
||||
new FeatureFlag()
|
||||
.asBuilder()
|
||||
.setFeatureName(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.setStatusMap(ImmutableSortedMap.of(START_OF_TIME, INACTIVE))
|
||||
.build());
|
||||
createTlds("example", "tld");
|
||||
}
|
||||
|
||||
|
||||
@@ -16,13 +16,19 @@ package google.registry.flows;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_OPTIONAL;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.INACTIVE;
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.createTlds;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.testing.EppMetricSubject.assertThat;
|
||||
import static google.registry.testing.HostSubject.assertAboutHosts;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
@@ -88,6 +94,12 @@ class EppLifecycleHostTest extends EppTestCase {
|
||||
|
||||
@Test
|
||||
void testRenamingHostToExistingHost_fails() throws Exception {
|
||||
persistResource(
|
||||
new FeatureFlag()
|
||||
.asBuilder()
|
||||
.setFeatureName(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.setStatusMap(ImmutableSortedMap.of(START_OF_TIME, INACTIVE))
|
||||
.build());
|
||||
createTld("example");
|
||||
assertThatLoginSucceeds("NewRegistrar", "foo-BAR2");
|
||||
// Create the fakesite domain.
|
||||
@@ -138,6 +150,12 @@ class EppLifecycleHostTest extends EppTestCase {
|
||||
|
||||
@Test
|
||||
void testSuccess_multipartTldsWithSharedSuffixes() throws Exception {
|
||||
persistResource(
|
||||
new FeatureFlag()
|
||||
.asBuilder()
|
||||
.setFeatureName(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.setStatusMap(ImmutableSortedMap.of(START_OF_TIME, INACTIVE))
|
||||
.build());
|
||||
createTlds("bar.foo.tld", "foo.tld", "tld");
|
||||
|
||||
assertThatLoginSucceeds("NewRegistrar", "foo-BAR2");
|
||||
|
||||
@@ -17,18 +17,24 @@ package google.registry.flows;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.EppResourceUtils.loadAtPointInTime;
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_OPTIONAL;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.INACTIVE;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.loadAllOf;
|
||||
import static google.registry.testing.DatabaseHelper.loadByEntity;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveHost;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.joda.time.Duration.standardDays;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import google.registry.flows.EppTestComponent.FakesAndMocksModule;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.monitoring.whitebox.EppMetric;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
@@ -54,6 +60,12 @@ class EppPointInTimeTest {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
persistResource(
|
||||
new FeatureFlag()
|
||||
.asBuilder()
|
||||
.setFeatureName(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.setStatusMap(ImmutableSortedMap.of(START_OF_TIME, INACTIVE))
|
||||
.build());
|
||||
createTld("tld");
|
||||
}
|
||||
|
||||
|
||||
@@ -918,24 +918,6 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
|
||||
runFlowAssertResponse(loadFile("domain_check_fee_response_v06.xml"));
|
||||
}
|
||||
|
||||
private void setUpDefaultToken() {
|
||||
AllocationToken defaultToken =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setDiscountFraction(0.5)
|
||||
.build());
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFeeExtension_defaultToken_v06() throws Exception {
|
||||
setUpDefaultToken();
|
||||
@@ -1782,24 +1764,6 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
private void runEapFeeCheckTest(String inputFile, String outputFile) throws Exception {
|
||||
clock.setTo(DateTime.parse("2010-01-01T10:00:00Z"));
|
||||
persistActiveDomain("example1.tld");
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setEapFeeSchedule(
|
||||
new ImmutableSortedMap.Builder<DateTime, Money>(Ordering.natural())
|
||||
.put(START_OF_TIME, Money.of(USD, 0))
|
||||
.put(clock.nowUtc().minusDays(1), Money.of(USD, 100))
|
||||
.put(clock.nowUtc().plusDays(1), Money.of(USD, 50))
|
||||
.put(clock.nowUtc().plusDays(2), Money.of(USD, 0))
|
||||
.build())
|
||||
.build());
|
||||
setEppInput(inputFile, ImmutableMap.of("CURRENCY", "USD"));
|
||||
runFlowAssertResponse(loadFile(outputFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_eapFeeCheck_v06() throws Exception {
|
||||
runEapFeeCheckTest("domain_check_fee_v06.xml", "domain_check_eap_fee_response_v06.xml");
|
||||
@@ -1836,6 +1800,43 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
|
||||
assertTldsFieldLogged("com", "net", "org");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTieredPricingPromoResponse() throws Exception {
|
||||
sessionMetadata.setRegistrarId("NewRegistrar");
|
||||
setUpDefaultToken("NewRegistrar");
|
||||
persistActiveDomain("example1.tld");
|
||||
setEppInput("domain_check_fee_v12.xml");
|
||||
runFlowAssertResponse(loadFile("domain_check_tiered_promotion_fee_response_v12.xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTieredPricingPromo_registrarNotIncluded_standardResponse() throws Exception {
|
||||
setUpDefaultToken("NewRegistrar");
|
||||
persistActiveDomain("example1.tld");
|
||||
setEppInput("domain_check_fee_v12.xml");
|
||||
runFlowAssertResponse(loadFile("domain_check_fee_response_v12.xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTieredPricingPromo_registrarIncluded_noTokenActive() throws Exception {
|
||||
sessionMetadata.setRegistrarId("NewRegistrar");
|
||||
persistActiveDomain("example1.tld");
|
||||
|
||||
persistResource(
|
||||
setUpDefaultToken("NewRegistrar")
|
||||
.asBuilder()
|
||||
.setTokenStatusTransitions(
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
TokenStatus.NOT_STARTED,
|
||||
clock.nowUtc().plusDays(1),
|
||||
TokenStatus.VALID))
|
||||
.build());
|
||||
|
||||
setEppInput("domain_check_fee_v12.xml");
|
||||
runFlowAssertResponse(loadFile("domain_check_fee_response_v12.xml"));
|
||||
}
|
||||
|
||||
private Domain persistPendingDeleteDomain(String domainName) {
|
||||
Domain existingDomain =
|
||||
persistResource(
|
||||
@@ -1867,4 +1868,45 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
|
||||
return persistResource(
|
||||
existingDomain.asBuilder().setAutorenewBillingEvent(renewEvent.createVKey()).build());
|
||||
}
|
||||
|
||||
private void runEapFeeCheckTest(String inputFile, String outputFile) throws Exception {
|
||||
clock.setTo(DateTime.parse("2010-01-01T10:00:00Z"));
|
||||
persistActiveDomain("example1.tld");
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setEapFeeSchedule(
|
||||
new ImmutableSortedMap.Builder<DateTime, Money>(Ordering.natural())
|
||||
.put(START_OF_TIME, Money.of(USD, 0))
|
||||
.put(clock.nowUtc().minusDays(1), Money.of(USD, 100))
|
||||
.put(clock.nowUtc().plusDays(1), Money.of(USD, 50))
|
||||
.put(clock.nowUtc().plusDays(2), Money.of(USD, 0))
|
||||
.build())
|
||||
.build());
|
||||
setEppInput(inputFile, ImmutableMap.of("CURRENCY", "USD"));
|
||||
runFlowAssertResponse(loadFile(outputFile));
|
||||
}
|
||||
|
||||
private AllocationToken setUpDefaultToken() {
|
||||
return setUpDefaultToken("TheRegistrar");
|
||||
}
|
||||
|
||||
private AllocationToken setUpDefaultToken(String registrarId) {
|
||||
AllocationToken defaultToken =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of(registrarId))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setDiscountFraction(0.5)
|
||||
.build());
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
|
||||
.build());
|
||||
return defaultToken;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@ import static google.registry.model.billing.BillingBase.Flag.SUNRISE;
|
||||
import static google.registry.model.billing.BillingBase.RenewalPriceBehavior.DEFAULT;
|
||||
import static google.registry.model.billing.BillingBase.RenewalPriceBehavior.NONPREMIUM;
|
||||
import static google.registry.model.billing.BillingBase.RenewalPriceBehavior.SPECIFIED;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_OPTIONAL;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.ACTIVE;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.INACTIVE;
|
||||
import static google.registry.model.domain.fee.Fee.FEE_EXTENSION_URIS;
|
||||
import static google.registry.model.domain.token.AllocationToken.TokenType.BULK_PRICING;
|
||||
import static google.registry.model.domain.token.AllocationToken.TokenType.DEFAULT_PROMO;
|
||||
@@ -48,6 +51,7 @@ import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.createTlds;
|
||||
import static google.registry.testing.DatabaseHelper.deleteTld;
|
||||
import static google.registry.testing.DatabaseHelper.getHistoryEntries;
|
||||
import static google.registry.testing.DatabaseHelper.loadAllOf;
|
||||
import static google.registry.testing.DatabaseHelper.loadRegistrar;
|
||||
import static google.registry.testing.DatabaseHelper.newContact;
|
||||
import static google.registry.testing.DatabaseHelper.newHost;
|
||||
@@ -155,6 +159,7 @@ import google.registry.model.billing.BillingBase.Reason;
|
||||
import google.registry.model.billing.BillingBase.RenewalPriceBehavior;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingRecurrence;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
@@ -223,7 +228,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
|
||||
DomainCreateFlowTest() {
|
||||
setEppInput("domain_create.xml", ImmutableMap.of("DOMAIN", "example.tld"));
|
||||
clock.setTo(DateTime.parse("1999-04-03T22:00:00.0Z").minus(Duration.millis(1)));
|
||||
clock.setTo(DateTime.parse("1999-04-03T22:00:00.0Z").minus(Duration.millis(2)));
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
@@ -249,6 +254,12 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
"badcrash,NAME_COLLISION"),
|
||||
persistReservedList("global-list", "resdom,FULLY_BLOCKED"))
|
||||
.build());
|
||||
persistResource(
|
||||
new FeatureFlag()
|
||||
.asBuilder()
|
||||
.setFeatureName(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.setStatusMap(ImmutableSortedMap.of(START_OF_TIME, INACTIVE))
|
||||
.build());
|
||||
persistClaimsList(ImmutableMap.of("example-one", CLAIMS_KEY, "test-validate", CLAIMS_KEY));
|
||||
}
|
||||
|
||||
@@ -1099,19 +1110,10 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
|
||||
@Test
|
||||
void testSuccess_wrongFeeAmountTooHigh_defaultToken_v06() throws Exception {
|
||||
AllocationToken defaultToken =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setDiscountFraction(0.5)
|
||||
.build());
|
||||
setupDefaultTokenWithDiscount();
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
|
||||
.setCreateBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 8)))
|
||||
.build());
|
||||
// Expects fee of $24
|
||||
@@ -1126,19 +1128,10 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
|
||||
@Test
|
||||
void testFailure_wrongFeeAmountTooLow_defaultToken_v06() throws Exception {
|
||||
AllocationToken defaultToken =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setDiscountFraction(0.5)
|
||||
.build());
|
||||
setupDefaultTokenWithDiscount();
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
|
||||
.setCreateBillingCostTransitions(
|
||||
ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 100)))
|
||||
.build());
|
||||
@@ -1165,19 +1158,10 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
|
||||
@Test
|
||||
void testSuccess_wrongFeeAmountTooHigh_defaultToken_v11() throws Exception {
|
||||
AllocationToken defaultToken =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setDiscountFraction(0.5)
|
||||
.build());
|
||||
setupDefaultTokenWithDiscount();
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
|
||||
.setCreateBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 8)))
|
||||
.build());
|
||||
// Expects fee of $24
|
||||
@@ -1192,19 +1176,10 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
|
||||
@Test
|
||||
void testFailure_wrongFeeAmountTooLow_defaultToken_v11() throws Exception {
|
||||
AllocationToken defaultToken =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setDiscountFraction(0.5)
|
||||
.build());
|
||||
setupDefaultTokenWithDiscount();
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
|
||||
.setCreateBillingCostTransitions(
|
||||
ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 100)))
|
||||
.build());
|
||||
@@ -1231,19 +1206,10 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
|
||||
@Test
|
||||
void testSuccess_wrongFeeAmountTooHigh_defaultToken_v12() throws Exception {
|
||||
AllocationToken defaultToken =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setDiscountFraction(0.5)
|
||||
.build());
|
||||
setupDefaultTokenWithDiscount();
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
|
||||
.setCreateBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 8)))
|
||||
.build());
|
||||
// Expects fee of $24
|
||||
@@ -1258,19 +1224,10 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
|
||||
@Test
|
||||
void testFailure_wrongFeeAmountTooLow_defaultToken_v12() throws Exception {
|
||||
AllocationToken defaultToken =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setDiscountFraction(0.5)
|
||||
.build());
|
||||
setupDefaultTokenWithDiscount();
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
|
||||
.setCreateBillingCostTransitions(
|
||||
ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 100)))
|
||||
.build());
|
||||
@@ -1371,6 +1328,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setDomainName("resdom.tld")
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.build());
|
||||
// Despite the domain being FULLY_BLOCKED, the non-superuser create succeeds the domain is also
|
||||
// RESERVED_FOR_SPECIFIC_USE and the correct allocation token is passed.
|
||||
@@ -1835,28 +1793,8 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
@Test
|
||||
void testSuccess_usesDefaultToken() throws Exception {
|
||||
persistContactsAndHosts();
|
||||
AllocationToken defaultToken1 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("aaaaa")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
AllocationToken defaultToken2 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(
|
||||
ImmutableList.of(defaultToken1.createVKey(), defaultToken2.createVKey()))
|
||||
.build());
|
||||
setupDefaultToken("aaaaa", 0, "NewRegistrar");
|
||||
setupDefaultTokenWithDiscount();
|
||||
runTest_defaultToken("bbbbb");
|
||||
}
|
||||
|
||||
@@ -1869,28 +1807,8 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
.setTokenType(UNLIMITED_USE)
|
||||
.setDiscountFraction(0.5)
|
||||
.build());
|
||||
AllocationToken defaultToken1 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("aaaaa")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
AllocationToken defaultToken2 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(
|
||||
ImmutableList.of(defaultToken1.createVKey(), defaultToken2.createVKey()))
|
||||
.build());
|
||||
setupDefaultToken("aaaaa", 0, "NewRegistrar");
|
||||
setupDefaultTokenWithDiscount();
|
||||
clock.advanceOneMilli();
|
||||
setEppInput(
|
||||
"domain_create_allocationtoken.xml",
|
||||
@@ -1907,178 +1825,49 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
@Test
|
||||
void testSuccess_noValidDefaultToken() throws Exception {
|
||||
persistContactsAndHosts();
|
||||
AllocationToken defaultToken1 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("aaaaa")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
AllocationToken defaultToken2 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("OtherRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(
|
||||
ImmutableList.of(defaultToken1.createVKey(), defaultToken2.createVKey()))
|
||||
.build());
|
||||
setupDefaultToken("aaaaa", 0, "NewRegistrar");
|
||||
setupDefaultToken("bbbbb", 0, "OtherRegistrar");
|
||||
doSuccessfulTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_onlyUseFirstValidDefaultToken() throws Exception {
|
||||
persistContactsAndHosts();
|
||||
AllocationToken defaultToken1 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("aaaaa")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
AllocationToken defaultToken2 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(
|
||||
ImmutableList.of(defaultToken1.createVKey(), defaultToken2.createVKey()))
|
||||
.build());
|
||||
setupDefaultToken("aaaaa", 0, "TheRegistrar");
|
||||
setupDefaultTokenWithDiscount();
|
||||
runTest_defaultToken("aaaaa");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_registryHasDeletedDefaultToken() throws Exception {
|
||||
persistContactsAndHosts();
|
||||
AllocationToken defaultToken1 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("aaaaa")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
AllocationToken defaultToken2 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(
|
||||
ImmutableList.of(defaultToken1.createVKey(), defaultToken2.createVKey()))
|
||||
.build());
|
||||
AllocationToken defaultToken1 = setupDefaultToken("aaaaa", 0, "NewRegistrar");
|
||||
setupDefaultTokenWithDiscount();
|
||||
DatabaseHelper.deleteResource(defaultToken1);
|
||||
runTest_defaultToken("bbbbb");
|
||||
assertThat(runTest_defaultToken("bbbbb").getCost()).isEqualTo(Money.of(USD, 17.50));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_defaultTokenAppliesCorrectPrice() throws Exception {
|
||||
persistContactsAndHosts();
|
||||
AllocationToken defaultToken1 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("aaaaa")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
AllocationToken defaultToken2 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setDiscountFraction(0.5)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(
|
||||
ImmutableList.of(defaultToken1.createVKey(), defaultToken2.createVKey()))
|
||||
.build());
|
||||
BillingEvent billingEvent = runTest_defaultToken("bbbbb");
|
||||
assertThat(billingEvent.getCost()).isEqualTo(Money.of(USD, BigDecimal.valueOf(17.5)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_skipsOverMissingDefaultToken() throws Exception {
|
||||
persistContactsAndHosts();
|
||||
AllocationToken defaultToken1 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("aaaaa")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
AllocationToken defaultToken2 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setDiscountFraction(0.5)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(
|
||||
ImmutableList.of(defaultToken1.createVKey(), defaultToken2.createVKey()))
|
||||
.build());
|
||||
DatabaseHelper.deleteResource(defaultToken1);
|
||||
BillingEvent billingEvent = runTest_defaultToken("bbbbb");
|
||||
assertThat(billingEvent.getCost()).isEqualTo(Money.of(USD, BigDecimal.valueOf(17.5)));
|
||||
setupDefaultToken("aaaaa", 0, "NewRegistrar");
|
||||
setupDefaultTokenWithDiscount();
|
||||
assertThat(runTest_defaultToken("bbbbb").getCost())
|
||||
.isEqualTo(Money.of(USD, BigDecimal.valueOf(17.5)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_skipsOverExpiredDefaultToken() throws Exception {
|
||||
persistContactsAndHosts();
|
||||
AllocationToken defaultToken1 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("aaaaa")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.build());
|
||||
AllocationToken defaultToken2 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("bbbbb")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setDiscountFraction(0.5)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setTokenStatusTransitions(
|
||||
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
|
||||
.put(clock.nowUtc().minusDays(2), TokenStatus.VALID)
|
||||
.put(clock.nowUtc().minusDays(1), TokenStatus.ENDED)
|
||||
.build())
|
||||
.build());
|
||||
persistResource(
|
||||
Tld.get("tld")
|
||||
setupDefaultTokenWithDiscount()
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(
|
||||
ImmutableList.of(defaultToken1.createVKey(), defaultToken2.createVKey()))
|
||||
.setTokenStatusTransitions(
|
||||
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
|
||||
.put(clock.nowUtc().minusDays(2), TokenStatus.VALID)
|
||||
.put(clock.nowUtc().minusDays(1), TokenStatus.ENDED)
|
||||
.build())
|
||||
.build());
|
||||
doSuccessfulTest();
|
||||
}
|
||||
@@ -2087,20 +1876,10 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
void testSuccess_doesNotApplyNonPremiumDefaultTokenToPremiumName() throws Exception {
|
||||
persistContactsAndHosts();
|
||||
createTld("example");
|
||||
AllocationToken defaultToken1 =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("aaaaa")
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("example"))
|
||||
.setDiscountFraction(0.5)
|
||||
.setDiscountPremiums(false)
|
||||
.build());
|
||||
persistResource(
|
||||
Tld.get("example")
|
||||
setupDefaultTokenWithDiscount()
|
||||
.asBuilder()
|
||||
.setDefaultPromoTokens(ImmutableList.of(defaultToken1.createVKey()))
|
||||
.setAllowedTlds(ImmutableSet.of("example"))
|
||||
.build());
|
||||
setEppInput("domain_create_premium.xml");
|
||||
runFlowAssertResponse(
|
||||
@@ -2110,7 +1889,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
assertSuccessfulCreate("example", ImmutableSet.of());
|
||||
}
|
||||
|
||||
BillingEvent runTest_defaultToken(String token) throws Exception {
|
||||
private BillingEvent runTest_defaultToken(String token) throws Exception {
|
||||
setEppInput("domain_create.xml", ImmutableMap.of("DOMAIN", "example.tld"));
|
||||
runFlowAssertResponse(
|
||||
loadFile(
|
||||
@@ -2384,6 +2163,20 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_minimumDatasetPhase1_missingRegistrant() throws Exception {
|
||||
persistResource(
|
||||
FeatureFlag.get(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.asBuilder()
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, clock.nowUtc().minusDays(5), ACTIVE))
|
||||
.build());
|
||||
setEppInput("domain_create_missing_registrant.xml");
|
||||
persistContactsAndHosts();
|
||||
runFlowAssertResponse(
|
||||
loadFile("domain_create_response.xml", ImmutableMap.of("DOMAIN", "example.tld")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_missingAdmin() {
|
||||
setEppInput("domain_create_missing_admin.xml");
|
||||
@@ -2392,6 +2185,20 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_minimumDatasetPhase1_missingAdmin() throws Exception {
|
||||
persistResource(
|
||||
FeatureFlag.get(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.asBuilder()
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, clock.nowUtc().minusDays(5), ACTIVE))
|
||||
.build());
|
||||
setEppInput("domain_create_missing_admin.xml");
|
||||
persistContactsAndHosts();
|
||||
runFlowAssertResponse(
|
||||
loadFile("domain_create_response.xml", ImmutableMap.of("DOMAIN", "example.tld")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_missingTech() {
|
||||
setEppInput("domain_create_missing_tech.xml");
|
||||
@@ -2400,6 +2207,20 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_minimumDatasetPhase1_missingTech() throws Exception {
|
||||
persistResource(
|
||||
FeatureFlag.get(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.asBuilder()
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, clock.nowUtc().minusDays(5), ACTIVE))
|
||||
.build());
|
||||
setEppInput("domain_create_missing_tech.xml");
|
||||
persistContactsAndHosts();
|
||||
runFlowAssertResponse(
|
||||
loadFile("domain_create_response.xml", ImmutableMap.of("DOMAIN", "example.tld")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_missingNonRegistrantContacts() {
|
||||
setEppInput("domain_create_missing_non_registrant_contacts.xml");
|
||||
@@ -2408,6 +2229,20 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_minimumDatasetPhase1_missingNonRegistrantContacts() throws Exception {
|
||||
persistResource(
|
||||
FeatureFlag.get(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.asBuilder()
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, clock.nowUtc().minusDays(5), ACTIVE))
|
||||
.build());
|
||||
setEppInput("domain_create_missing_non_registrant_contacts.xml");
|
||||
persistContactsAndHosts();
|
||||
runFlowAssertResponse(
|
||||
loadFile("domain_create_response.xml", ImmutableMap.of("DOMAIN", "example.tld")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_badIdn() {
|
||||
createTld("xn--q9jyb4c");
|
||||
@@ -3413,6 +3248,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.build());
|
||||
assertThat(
|
||||
DomainCreateFlow.getRenewalPriceInfo(
|
||||
@@ -3439,6 +3275,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.build())),
|
||||
new FeesAndCredits.Builder()
|
||||
.setCurrency(USD)
|
||||
@@ -3891,10 +3728,12 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.build());
|
||||
persistContactsAndHosts();
|
||||
setEppInput(
|
||||
@@ -3919,10 +3758,12 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.build());
|
||||
persistContactsAndHosts();
|
||||
setEppInput(
|
||||
@@ -3935,4 +3776,96 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
.isEqualTo(
|
||||
"The bulk token abc123 cannot be used to register names for longer than 1 year.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTieredPricingPromoResponse() throws Exception {
|
||||
sessionMetadata.setRegistrarId("NewRegistrar");
|
||||
setupDefaultTokenWithDiscount("NewRegistrar");
|
||||
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.12", "CURRENCY", "USD"));
|
||||
persistContactsAndHosts();
|
||||
|
||||
// Fee in the result should be 24 (create cost of 13 plus renew cost of 11) even though the
|
||||
// actual cost is lower (due to the tiered pricing promo)
|
||||
runFlowAssertResponse(
|
||||
loadFile(
|
||||
"domain_create_response_fee.xml",
|
||||
ImmutableMap.of("FEE_VERSION", "0.12", "FEE", "24.00")));
|
||||
// Expected cost is half off the create cost (13/2 == 6.50) plus one full-cost renew (11)
|
||||
assertThat(Iterables.getOnlyElement(loadAllOf(BillingEvent.class)).getCost())
|
||||
.isEqualTo(Money.of(USD, 17.50));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTieredPricingPromo_registrarNotIncluded_standardResponse() throws Exception {
|
||||
setupDefaultTokenWithDiscount("NewRegistrar");
|
||||
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.12", "CURRENCY", "USD"));
|
||||
persistContactsAndHosts();
|
||||
|
||||
// For a registrar not included in the tiered pricing promo, costs should be 24
|
||||
runFlowAssertResponse(
|
||||
loadFile(
|
||||
"domain_create_response_fee.xml",
|
||||
ImmutableMap.of("FEE_VERSION", "0.12", "FEE", "24.00")));
|
||||
assertThat(Iterables.getOnlyElement(loadAllOf(BillingEvent.class)).getCost())
|
||||
.isEqualTo(Money.of(USD, 24));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTieredPricingPromo_registrarIncluded_noTokenActive() throws Exception {
|
||||
sessionMetadata.setRegistrarId("NewRegistrar");
|
||||
persistActiveDomain("example1.tld");
|
||||
|
||||
persistResource(
|
||||
setupDefaultTokenWithDiscount("NewRegistrar")
|
||||
.asBuilder()
|
||||
.setTokenStatusTransitions(
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
TokenStatus.NOT_STARTED,
|
||||
clock.nowUtc().plusDays(1),
|
||||
TokenStatus.VALID))
|
||||
.build());
|
||||
|
||||
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.12", "CURRENCY", "USD"));
|
||||
persistContactsAndHosts();
|
||||
|
||||
// The token hasn't started yet, so the cost should be create (13) plus renew (11)
|
||||
runFlowAssertResponse(
|
||||
loadFile(
|
||||
"domain_create_response_fee.xml",
|
||||
ImmutableMap.of("FEE_VERSION", "0.12", "FEE", "24.00")));
|
||||
assertThat(Iterables.getOnlyElement(loadAllOf(BillingEvent.class)).getCost())
|
||||
.isEqualTo(Money.of(USD, 24));
|
||||
}
|
||||
|
||||
private AllocationToken setupDefaultTokenWithDiscount() {
|
||||
return setupDefaultTokenWithDiscount("TheRegistrar");
|
||||
}
|
||||
|
||||
private AllocationToken setupDefaultTokenWithDiscount(String registrarId) {
|
||||
return setupDefaultToken("bbbbb", 0.5, registrarId);
|
||||
}
|
||||
|
||||
private AllocationToken setupDefaultToken(
|
||||
String token, double discountFraction, String registrarId) {
|
||||
AllocationToken allocationToken =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken(token)
|
||||
.setTokenType(DEFAULT_PROMO)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of(registrarId))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setDiscountFraction(discountFraction)
|
||||
.build());
|
||||
Tld tld = Tld.get("tld");
|
||||
persistResource(
|
||||
tld.asBuilder()
|
||||
.setDefaultPromoTokens(
|
||||
ImmutableList.<VKey<AllocationToken>>builder()
|
||||
.addAll(tld.getDefaultPromoTokens())
|
||||
.add(allocationToken.createVKey())
|
||||
.build())
|
||||
.build());
|
||||
return allocationToken;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1118,8 +1118,9 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setDiscountFraction(1)
|
||||
.setDiscountFraction(1.0)
|
||||
.build());
|
||||
domain = domain.asBuilder().setCurrentBulkToken(token.createVKey()).build();
|
||||
persistResource(domain);
|
||||
@@ -1139,8 +1140,9 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setDiscountFraction(1)
|
||||
.setDiscountFraction(1.0)
|
||||
.build());
|
||||
domain = domain.asBuilder().setCurrentBulkToken(token.createVKey()).build();
|
||||
persistResource(domain);
|
||||
@@ -1172,8 +1174,9 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setDiscountFraction(1)
|
||||
.setDiscountFraction(1.0)
|
||||
.build());
|
||||
domain = domain.asBuilder().setCurrentBulkToken(token.createVKey()).build();
|
||||
persistResource(domain);
|
||||
|
||||
@@ -1257,9 +1257,11 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.build());
|
||||
persistDomain();
|
||||
@@ -1290,9 +1292,11 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.build());
|
||||
persistDomain();
|
||||
@@ -1327,9 +1331,11 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.build());
|
||||
persistDomain(SPECIFIED, Money.of(USD, 2));
|
||||
@@ -1357,9 +1363,11 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.build());
|
||||
persistDomain(SPECIFIED, Money.of(USD, 2));
|
||||
|
||||
@@ -388,7 +388,9 @@ class DomainTransferApproveFlowTest
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.build());
|
||||
@@ -417,7 +419,9 @@ class DomainTransferApproveFlowTest
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.build());
|
||||
|
||||
@@ -1339,7 +1339,9 @@ class DomainTransferRequestFlowTest
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.build());
|
||||
@@ -1398,7 +1400,9 @@ class DomainTransferRequestFlowTest
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.build());
|
||||
@@ -1456,7 +1460,9 @@ class DomainTransferRequestFlowTest
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.build());
|
||||
|
||||
@@ -19,6 +19,9 @@ import static com.google.common.collect.Sets.union;
|
||||
import static com.google.common.io.BaseEncoding.base16;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_OPTIONAL;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.ACTIVE;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.INACTIVE;
|
||||
import static google.registry.model.eppcommon.StatusValue.CLIENT_DELETE_PROHIBITED;
|
||||
import static google.registry.model.eppcommon.StatusValue.CLIENT_HOLD;
|
||||
import static google.registry.model.eppcommon.StatusValue.CLIENT_RENEW_PROHIBITED;
|
||||
@@ -96,6 +99,7 @@ import google.registry.flows.exceptions.ResourceStatusProhibitsOperationExceptio
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.billing.BillingBase.Reason;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.DesignatedContact.Type;
|
||||
@@ -140,6 +144,12 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
|
||||
createTld("tld");
|
||||
// Note that "domain_update.xml" tests adding and removing the same contact type.
|
||||
setEppInput("domain_update.xml");
|
||||
persistResource(
|
||||
new FeatureFlag()
|
||||
.asBuilder()
|
||||
.setFeatureName(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.setStatusMap(ImmutableSortedMap.of(START_OF_TIME, INACTIVE))
|
||||
.build());
|
||||
}
|
||||
|
||||
private void persistReferencedEntities() {
|
||||
@@ -289,6 +299,21 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_minimumDatasetPhase1_emptyRegistrant() throws Exception {
|
||||
persistResource(
|
||||
FeatureFlag.get(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.asBuilder()
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, clock.nowUtc().minusDays(5), ACTIVE))
|
||||
.build());
|
||||
setEppInput("domain_update_empty_registrant.xml");
|
||||
persistReferencedEntities();
|
||||
persistDomain();
|
||||
runFlowAssertResponse(loadFile("generic_success_response.xml"));
|
||||
assertThat(reloadResourceByForeignKey().getRegistrant()).isEmpty();
|
||||
}
|
||||
|
||||
private void modifyDomainToHave13Nameservers() throws Exception {
|
||||
ImmutableSet.Builder<VKey<Host>> nameservers = new ImmutableSet.Builder<>();
|
||||
for (int i = 1; i < 15; i++) {
|
||||
@@ -1478,6 +1503,27 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_minimumDatasetPhase1_removeAdmin() throws Exception {
|
||||
persistResource(
|
||||
FeatureFlag.get(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.asBuilder()
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, clock.nowUtc().minusDays(5), ACTIVE))
|
||||
.build());
|
||||
setEppInput("domain_update_remove_admin.xml");
|
||||
persistReferencedEntities();
|
||||
persistResource(
|
||||
DatabaseHelper.newDomain(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
.setContacts(
|
||||
ImmutableSet.of(
|
||||
DesignatedContact.create(Type.ADMIN, sh8013Contact.createVKey()),
|
||||
DesignatedContact.create(Type.TECH, sh8013Contact.createVKey())))
|
||||
.build());
|
||||
runFlowAssertResponse(loadFile("generic_success_response.xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_removeTech() throws Exception {
|
||||
setEppInput("domain_update_remove_tech.xml");
|
||||
@@ -1494,6 +1540,27 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_minimumDatasetPhase1_removeTech() throws Exception {
|
||||
persistResource(
|
||||
FeatureFlag.get(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.asBuilder()
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, clock.nowUtc().minusDays(5), ACTIVE))
|
||||
.build());
|
||||
setEppInput("domain_update_remove_tech.xml");
|
||||
persistReferencedEntities();
|
||||
persistResource(
|
||||
DatabaseHelper.newDomain(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
.setContacts(
|
||||
ImmutableSet.of(
|
||||
DesignatedContact.create(Type.ADMIN, sh8013Contact.createVKey()),
|
||||
DesignatedContact.create(Type.TECH, sh8013Contact.createVKey())))
|
||||
.build());
|
||||
runFlowAssertResponse(loadFile("generic_success_response.xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_addPendingDeleteContact() throws Exception {
|
||||
persistReferencedEntities();
|
||||
|
||||
@@ -15,8 +15,12 @@
|
||||
package google.registry.model.common;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_OPTIONAL;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_PROHIBITED;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.TEST_FEATURE;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.ACTIVE;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.INACTIVE;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.testing.DatabaseHelper.loadByEntity;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
@@ -42,8 +46,8 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
void testSuccess_persistence() {
|
||||
FeatureFlag featureFlag =
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName("testFlag")
|
||||
.setStatus(
|
||||
.setFeatureName(TEST_FEATURE)
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
@@ -58,15 +62,15 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
void testSuccess_getSingleFlag() {
|
||||
FeatureFlag featureFlag =
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName("testFlag")
|
||||
.setStatus(
|
||||
.setFeatureName(TEST_FEATURE)
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
.build())
|
||||
.build();
|
||||
persistResource(featureFlag);
|
||||
assertThat(FeatureFlag.get("testFlag")).isEqualTo(featureFlag);
|
||||
assertThat(FeatureFlag.get(TEST_FEATURE)).isEqualTo(featureFlag);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -74,8 +78,8 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
FeatureFlag featureFlag1 =
|
||||
persistResource(
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName("testFlag1")
|
||||
.setStatus(
|
||||
.setFeatureName(TEST_FEATURE)
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
@@ -84,8 +88,8 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
FeatureFlag featureFlag2 =
|
||||
persistResource(
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName("testFlag2")
|
||||
.setStatus(
|
||||
.setFeatureName(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(3), INACTIVE)
|
||||
@@ -94,14 +98,18 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
FeatureFlag featureFlag3 =
|
||||
persistResource(
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName("testFlag3")
|
||||
.setStatus(
|
||||
.setFeatureName(MINIMUM_DATASET_CONTACTS_PROHIBITED)
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.build())
|
||||
.build());
|
||||
ImmutableSet<FeatureFlag> featureFlags =
|
||||
FeatureFlag.get(ImmutableSet.of("testFlag1", "testFlag2", "testFlag3"));
|
||||
FeatureFlag.getAll(
|
||||
ImmutableSet.of(
|
||||
TEST_FEATURE,
|
||||
MINIMUM_DATASET_CONTACTS_OPTIONAL,
|
||||
MINIMUM_DATASET_CONTACTS_PROHIBITED));
|
||||
assertThat(featureFlags.size()).isEqualTo(3);
|
||||
assertThat(featureFlags).containsExactly(featureFlag1, featureFlag2, featureFlag3);
|
||||
}
|
||||
@@ -110,8 +118,8 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
void testFailure_getMultipleFlagsOneMissing() {
|
||||
persistResource(
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName("testFlag1")
|
||||
.setStatus(
|
||||
.setFeatureName(TEST_FEATURE)
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
@@ -119,8 +127,8 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
.build());
|
||||
persistResource(
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName("testFlag2")
|
||||
.setStatus(
|
||||
.setFeatureName(MINIMUM_DATASET_CONTACTS_OPTIONAL)
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(3), INACTIVE)
|
||||
@@ -129,74 +137,48 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
FeatureFlagNotFoundException thrown =
|
||||
assertThrows(
|
||||
FeatureFlagNotFoundException.class,
|
||||
() -> FeatureFlag.get(ImmutableSet.of("missingFlag", "testFlag1", "testFlag2")));
|
||||
() ->
|
||||
FeatureFlag.getAll(
|
||||
ImmutableSet.of(
|
||||
TEST_FEATURE,
|
||||
MINIMUM_DATASET_CONTACTS_OPTIONAL,
|
||||
MINIMUM_DATASET_CONTACTS_PROHIBITED)));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("No feature flag object(s) found for missingFlag");
|
||||
.isEqualTo("No feature flag object(s) found for MINIMUM_DATASET_CONTACTS_PROHIBITED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_featureFlagNotPresent() {
|
||||
FeatureFlagNotFoundException thrown =
|
||||
assertThrows(FeatureFlagNotFoundException.class, () -> FeatureFlag.get("fakeFlag"));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("No feature flag object(s) found for fakeFlag");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_resetFeatureName() {
|
||||
FeatureFlag featureFlag =
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName("testFlag")
|
||||
.setStatus(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
.build())
|
||||
.build();
|
||||
IllegalStateException thrown =
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> featureFlag.asBuilder().setFeatureName("differentName"));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Feature name can only be set once");
|
||||
assertThrows(FeatureFlagNotFoundException.class, () -> FeatureFlag.get(TEST_FEATURE));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("No feature flag object(s) found for TEST_FEATURE");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_nullFeatureName() {
|
||||
FeatureFlag.Builder featureFlagBuilder =
|
||||
new FeatureFlag.Builder()
|
||||
.setStatus(
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
.build());
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(IllegalArgumentException.class, () -> featureFlagBuilder.build());
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Feature name must not be null or empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_emptyFeatureName() {
|
||||
FeatureFlag.Builder featureFlagBuilder =
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName("")
|
||||
.setStatus(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
.build());
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(IllegalArgumentException.class, () -> featureFlagBuilder.build());
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Feature name must not be null or empty");
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("FeatureName cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_invalidStatusMap() {
|
||||
FeatureFlag.Builder featureFlagBuilder = new FeatureFlag.Builder().setFeatureName("testFlag");
|
||||
FeatureFlag.Builder featureFlagBuilder = new FeatureFlag.Builder().setFeatureName(TEST_FEATURE);
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
featureFlagBuilder.setStatus(
|
||||
featureFlagBuilder.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
.build()));
|
||||
@@ -204,4 +186,21 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Must provide transition entry for the start of time (Unix Epoch)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_isActiveNow() {
|
||||
fakeClock.setTo(DateTime.parse("2010-10-17TZ"));
|
||||
persistResource(
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName(TEST_FEATURE)
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(fakeClock.nowUtc().plusWeeks(8), ACTIVE)
|
||||
.build())
|
||||
.build());
|
||||
assertThat(tm().transact(() -> FeatureFlag.isActiveNow(TEST_FEATURE))).isFalse();
|
||||
fakeClock.setTo(DateTime.parse("2011-10-17TZ"));
|
||||
assertThat(tm().transact(() -> FeatureFlag.isActiveNow(TEST_FEATURE))).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ import google.registry.testing.FakeClock;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -134,10 +136,12 @@ public class DomainSqlTest {
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123Unlimited")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.setAllowedTlds(ImmutableSet.of("dev", "app"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(CurrencyUnit.USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setTokenStatusTransitions(
|
||||
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||
|
||||
@@ -842,7 +842,9 @@ public class DomainTest {
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.build());
|
||||
@@ -904,7 +906,9 @@ public class DomainTest {
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.build());
|
||||
@@ -1074,7 +1078,9 @@ public class DomainTest {
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.build();
|
||||
@@ -1092,7 +1098,9 @@ public class DomainTest {
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.setRenewalPrice(Money.of(USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.build());
|
||||
|
||||
@@ -43,6 +43,8 @@ import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||
import google.registry.model.domain.token.AllocationToken.TokenType;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -158,15 +160,16 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
void testSetRenewalBehavior_assertsRenewalBehaviorIsNotDefault() {
|
||||
assertThat(
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.build())
|
||||
.getRenewalPriceBehavior())
|
||||
.isEqualTo(RenewalPriceBehavior.SPECIFIED);
|
||||
AllocationToken token =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(CurrencyUnit.USD, 5))
|
||||
.build());
|
||||
assertThat(token.getRenewalPriceBehavior()).isEqualTo(RenewalPriceBehavior.SPECIFIED);
|
||||
assertThat(token.getRenewalPrice()).hasValue(Money.of(CurrencyUnit.USD, 5));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -181,7 +184,11 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
AllocationToken loadedToken = loadByEntity(token);
|
||||
assertThat(token).isEqualTo(loadedToken);
|
||||
persistResource(
|
||||
loadedToken.asBuilder().setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED).build());
|
||||
loadedToken
|
||||
.asBuilder()
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(CurrencyUnit.USD, 5))
|
||||
.build());
|
||||
assertThat(loadByEntity(token).getRenewalPriceBehavior())
|
||||
.isEqualTo(RenewalPriceBehavior.SPECIFIED);
|
||||
}
|
||||
@@ -218,17 +225,50 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFail_bulkTokenNotSpecifiedRenewalBehavior() {
|
||||
void testFail_bulkTokenInvalidRenewalBehavior() {
|
||||
assertThat(
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(TokenType.BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.DEFAULT)
|
||||
.build()))
|
||||
.hasMessageThat()
|
||||
.isEqualTo("BULK_PRICING tokens must have renewalPriceBehavior set to SPECIFIED");
|
||||
|
||||
assertThat(
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(TokenType.BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(CurrencyUnit.USD, 5))
|
||||
.build()))
|
||||
.hasMessageThat()
|
||||
.isEqualTo("BULK_PRICING tokens must have a renewal price of 0");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_bulkTokenDiscountFraction() {
|
||||
AllocationToken.Builder builder =
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(TokenType.BULK_PRICING)
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.DEFAULT);
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(CurrencyUnit.USD, 0));
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, builder::build);
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Bulk tokens must have renewalPriceBehavior set to SPECIFIED");
|
||||
.isEqualTo("BULK_PRICING tokens must have a discountFraction of 1.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -237,12 +277,14 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(TokenType.BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE, CommandName.RESTORE))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED);
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(CurrencyUnit.USD, 0));
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, builder::build);
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Bulk tokens may only be valid for CREATE actions");
|
||||
.isEqualTo("BULK_PRICING tokens may only be valid for CREATE actions");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -263,11 +305,13 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(TokenType.BULK_PRICING)
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED);
|
||||
.setDiscountFraction(1.0)
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(CurrencyUnit.USD, 0));
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, builder::build);
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Bulk tokens may only be valid for CREATE actions");
|
||||
.isEqualTo("BULK_PRICING tokens may only be valid for CREATE actions");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -276,11 +320,15 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(TokenType.BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(CurrencyUnit.USD, 0))
|
||||
.setDiscountPremiums(true);
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, builder::build);
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Bulk tokens cannot discount premium names");
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("BULK_PRICING tokens cannot discount premium names");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -338,8 +386,10 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
new AllocationToken.Builder()
|
||||
.setToken("foobar")
|
||||
.setTokenType(BULK_PRICING)
|
||||
.setDiscountFraction(1.0)
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(CurrencyUnit.USD, 0))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("foo", "bar"));
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, builder::build);
|
||||
assertThat(thrown)
|
||||
@@ -536,6 +586,32 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
.isEqualTo("Discount years can only be specified along with a discount fraction");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuild_specifiedTokenInvalidBehavior() {
|
||||
assertThat(
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.build()))
|
||||
.hasMessageThat()
|
||||
.isEqualTo("renewalPrice must be specified iff renewalPriceBehavior is SPECIFIED");
|
||||
assertThat(
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setRenewalPrice(Money.of(CurrencyUnit.USD, 10))
|
||||
.build()))
|
||||
.hasMessageThat()
|
||||
.isEqualTo("renewalPrice must be specified iff renewalPriceBehavior is SPECIFIED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuild_registrationBehaviors() {
|
||||
createTld("tld");
|
||||
|
||||
@@ -55,8 +55,9 @@ public class BulkPricingPackageTest extends EntityTestCase {
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setRenewalPrice(Money.of(CurrencyUnit.USD, 0))
|
||||
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
|
||||
.setDiscountFraction(1)
|
||||
.setDiscountFraction(1.0)
|
||||
.build());
|
||||
|
||||
BulkPricingPackage bulkPricingPackage =
|
||||
@@ -84,7 +85,7 @@ public class BulkPricingPackageTest extends EntityTestCase {
|
||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setDiscountFraction(1)
|
||||
.setDiscountFraction(1.0)
|
||||
.build());
|
||||
|
||||
IllegalArgumentException thrown =
|
||||
|
||||
-2
@@ -426,7 +426,6 @@ public abstract class JpaTransactionManagerExtension
|
||||
.setEmailAddress("johndoe@theregistrar.com")
|
||||
.setPhoneNumber("+1.1234567890")
|
||||
.setTypes(ImmutableSet.of(RegistrarPocBase.Type.ADMIN))
|
||||
.setLoginEmailAddress("johndoe@theregistrar.com")
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -438,7 +437,6 @@ public abstract class JpaTransactionManagerExtension
|
||||
.setRegistryLockEmailAddress("Marla.Singer.RegistryLock@crr.com")
|
||||
.setPhoneNumber("+1.2128675309")
|
||||
.setTypes(ImmutableSet.of(RegistrarPocBase.Type.TECH))
|
||||
.setLoginEmailAddress("Marla.Singer@crr.com")
|
||||
.setAllowedToSetRegistryLockPassword(true)
|
||||
.setRegistryLockPassword("hi")
|
||||
.build();
|
||||
|
||||
@@ -276,27 +276,23 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidDomain_notLoggedIn_noContacts() {
|
||||
assertProperResponseForCatLol("cat.lol", "rdap_domain_no_contacts_with_remark.json");
|
||||
void testValidDomain_notLoggedIn_redactsAllContactInfo() {
|
||||
assertProperResponseForCatLol("cat.lol", "rdap_domain_redacted_contacts_with_remark.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidDomain_notLoggedIn_contactsShowRedacted_evenWhenRegistrantDoesntExist() {
|
||||
// Even though the registrant is empty on this domain, it still shows a full set of REDACTED
|
||||
// fields through RDAP.
|
||||
void testValidDomain_notLoggedIn_showsNoRegistrant_whenRegistrantDoesntExist() {
|
||||
persistResource(
|
||||
loadByForeignKey(Domain.class, "cat.lol", clock.nowUtc())
|
||||
.get()
|
||||
.asBuilder()
|
||||
.setRegistrant(Optional.empty())
|
||||
.build());
|
||||
assertProperResponseForCatLol("cat.lol", "rdap_domain_no_contacts_with_remark.json");
|
||||
assertProperResponseForCatLol("cat.lol", "rdap_domain_no_registrant_with_remark.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidDomain_notLoggedIn_contactsShowRedacted_whenNoContactsExist() {
|
||||
// Even though the domain has no contacts, it still shows a full set of REDACTED fields through
|
||||
// RDAP.
|
||||
void testValidDomain_notLoggedIn_containsNoContactEntities_whenNoContactsExist() {
|
||||
persistResource(
|
||||
loadByForeignKey(Domain.class, "cat.lol", clock.nowUtc())
|
||||
.get()
|
||||
@@ -308,24 +304,38 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidDomain_loggedInAsOtherRegistrar_noContacts() {
|
||||
void testValidDomain_loggedIn_containsNoContactEntities_whenNoContactsExist() {
|
||||
login("evilregistrar");
|
||||
persistResource(
|
||||
loadByForeignKey(Domain.class, "cat.lol", clock.nowUtc())
|
||||
.get()
|
||||
.asBuilder()
|
||||
.setRegistrant(Optional.empty())
|
||||
.setContacts(ImmutableSet.of())
|
||||
.build());
|
||||
assertProperResponseForCatLol("cat.lol", "rdap_domain_no_contacts_exist_with_remark.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidDomain_loggedInAsOtherRegistrar_redactsAllContactInfo() {
|
||||
login("idnregistrar");
|
||||
assertProperResponseForCatLol("cat.lol", "rdap_domain_no_contacts_with_remark.json");
|
||||
assertProperResponseForCatLol("cat.lol", "rdap_domain_redacted_contacts_with_remark.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpperCase_ignored() {
|
||||
assertProperResponseForCatLol("CaT.lOl", "rdap_domain_no_contacts_with_remark.json");
|
||||
assertProperResponseForCatLol("CaT.lOl", "rdap_domain_redacted_contacts_with_remark.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTrailingDot_ignored() {
|
||||
assertProperResponseForCatLol("cat.lol.", "rdap_domain_no_contacts_with_remark.json");
|
||||
assertProperResponseForCatLol("cat.lol.", "rdap_domain_redacted_contacts_with_remark.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testQueryParameter_ignored() {
|
||||
assertProperResponseForCatLol("cat.lol?key=value", "rdap_domain_no_contacts_with_remark.json");
|
||||
assertProperResponseForCatLol(
|
||||
"cat.lol?key=value", "rdap_domain_redacted_contacts_with_remark.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -750,7 +750,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
||||
void testDomainMatch_found_loggedInAsOtherRegistrar() {
|
||||
login("otherregistrar");
|
||||
runSuccessfulTestWithCatLol(
|
||||
RequestType.NAME, "cat.lol", "rdap_domain_no_contacts_with_remark.json");
|
||||
RequestType.NAME, "cat.lol", "rdap_domain_redacted_contacts_with_remark.json");
|
||||
verifyMetrics(SearchType.BY_DOMAIN_NAME, Optional.of(1L));
|
||||
}
|
||||
|
||||
@@ -782,7 +782,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
||||
.addRegistrar("St. John Chrysostom")
|
||||
.addNameserver("ns1.cat.lol", "8-ROID")
|
||||
.addNameserver("ns2.external.tld", "1F-ROID")
|
||||
.load("rdap_domain_no_contacts_with_remark.json"));
|
||||
.load("rdap_domain_redacted_contacts_with_remark.json"));
|
||||
verifyMetrics(SearchType.BY_DOMAIN_NAME, Optional.of(1L));
|
||||
}
|
||||
|
||||
@@ -826,7 +826,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
||||
.addRegistrar("1.test")
|
||||
.addNameserver("ns1.cat.1.test", "35-ROID")
|
||||
.addNameserver("ns2.cat.2.test", "37-ROID")
|
||||
.load("rdap_domain_no_contacts_with_remark.json"));
|
||||
.load("rdap_domain_redacted_contacts_with_remark.json"));
|
||||
verifyMetrics(SearchType.BY_DOMAIN_NAME, Optional.of(1L));
|
||||
}
|
||||
|
||||
@@ -840,7 +840,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
||||
.addRegistrar("1.test")
|
||||
.addNameserver("ns1.cat.1.test", "35-ROID")
|
||||
.addNameserver("ns2.cat.2.test", "37-ROID")
|
||||
.load("rdap_domain_no_contacts_with_remark.json"));
|
||||
.load("rdap_domain_redacted_contacts_with_remark.json"));
|
||||
verifyMetrics(SearchType.BY_DOMAIN_NAME, Optional.of(1L));
|
||||
}
|
||||
|
||||
@@ -1378,7 +1378,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
||||
.addRegistrar("1.test")
|
||||
.addNameserver("ns1.cat.1.test", "35-ROID")
|
||||
.addNameserver("ns2.cat.2.test", "37-ROID")
|
||||
.load("rdap_domain_no_contacts_with_remark.json"));
|
||||
.load("rdap_domain_redacted_contacts_with_remark.json"));
|
||||
verifyMetrics(SearchType.BY_NAMESERVER_NAME, 1, 1);
|
||||
}
|
||||
|
||||
@@ -1392,7 +1392,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
||||
.addRegistrar("1.test")
|
||||
.addNameserver("ns1.cat.1.test", "35-ROID")
|
||||
.addNameserver("ns2.cat.2.test", "37-ROID")
|
||||
.load("rdap_domain_no_contacts_with_remark.json"));
|
||||
.load("rdap_domain_redacted_contacts_with_remark.json"));
|
||||
verifyMetrics(SearchType.BY_NAMESERVER_NAME, 1, 1);
|
||||
}
|
||||
|
||||
@@ -1675,7 +1675,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
||||
runSuccessfulTestWithCatLol(
|
||||
RequestType.NS_IP,
|
||||
"bad:f00d:cafe:0:0:0:15:beef",
|
||||
"rdap_domain_no_contacts_with_remark.json");
|
||||
"rdap_domain_redacted_contacts_with_remark.json");
|
||||
verifyMetrics(SearchType.BY_NAMESERVER_ADDRESS, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ import google.registry.rdap.RdapObjectClasses.ReplyPayloadBase;
|
||||
import google.registry.rdap.RdapObjectClasses.TopLevelReplyObject;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FullFieldsTestEntityHelper;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -373,7 +372,7 @@ class RdapJsonFormatterTest {
|
||||
.that(
|
||||
rdapJsonFormatter
|
||||
.createRdapContactEntity(
|
||||
Optional.of(contactRegistrant),
|
||||
contactRegistrant,
|
||||
ImmutableSet.of(RdapEntity.Role.REGISTRANT),
|
||||
OutputDataType.FULL)
|
||||
.toJson())
|
||||
@@ -386,7 +385,7 @@ class RdapJsonFormatterTest {
|
||||
.that(
|
||||
rdapJsonFormatter
|
||||
.createRdapContactEntity(
|
||||
Optional.of(contactRegistrant),
|
||||
contactRegistrant,
|
||||
ImmutableSet.of(RdapEntity.Role.REGISTRANT),
|
||||
OutputDataType.SUMMARY)
|
||||
.toJson())
|
||||
@@ -400,7 +399,7 @@ class RdapJsonFormatterTest {
|
||||
.that(
|
||||
rdapJsonFormatter
|
||||
.createRdapContactEntity(
|
||||
Optional.of(contactRegistrant),
|
||||
contactRegistrant,
|
||||
ImmutableSet.of(RdapEntity.Role.REGISTRANT),
|
||||
OutputDataType.FULL)
|
||||
.toJson())
|
||||
@@ -420,7 +419,7 @@ class RdapJsonFormatterTest {
|
||||
.that(
|
||||
rdapJsonFormatter
|
||||
.createRdapContactEntity(
|
||||
Optional.of(contactRegistrant),
|
||||
contactRegistrant,
|
||||
ImmutableSet.of(RdapEntity.Role.REGISTRANT),
|
||||
OutputDataType.FULL)
|
||||
.toJson())
|
||||
@@ -433,9 +432,7 @@ class RdapJsonFormatterTest {
|
||||
.that(
|
||||
rdapJsonFormatter
|
||||
.createRdapContactEntity(
|
||||
Optional.of(contactAdmin),
|
||||
ImmutableSet.of(RdapEntity.Role.ADMIN),
|
||||
OutputDataType.FULL)
|
||||
contactAdmin, ImmutableSet.of(RdapEntity.Role.ADMIN), OutputDataType.FULL)
|
||||
.toJson())
|
||||
.isEqualTo(loadJson("rdapjson_admincontact.json"));
|
||||
}
|
||||
@@ -446,9 +443,7 @@ class RdapJsonFormatterTest {
|
||||
.that(
|
||||
rdapJsonFormatter
|
||||
.createRdapContactEntity(
|
||||
Optional.of(contactTech),
|
||||
ImmutableSet.of(RdapEntity.Role.TECH),
|
||||
OutputDataType.FULL)
|
||||
contactTech, ImmutableSet.of(RdapEntity.Role.TECH), OutputDataType.FULL)
|
||||
.toJson())
|
||||
.isEqualTo(loadJson("rdapjson_techcontact.json"));
|
||||
}
|
||||
@@ -458,8 +453,7 @@ class RdapJsonFormatterTest {
|
||||
assertAboutJson()
|
||||
.that(
|
||||
rdapJsonFormatter
|
||||
.createRdapContactEntity(
|
||||
Optional.of(contactTech), ImmutableSet.of(), OutputDataType.FULL)
|
||||
.createRdapContactEntity(contactTech, ImmutableSet.of(), OutputDataType.FULL)
|
||||
.toJson())
|
||||
.isEqualTo(loadJson("rdapjson_rolelesscontact.json"));
|
||||
}
|
||||
@@ -469,8 +463,7 @@ class RdapJsonFormatterTest {
|
||||
assertAboutJson()
|
||||
.that(
|
||||
rdapJsonFormatter
|
||||
.createRdapContactEntity(
|
||||
Optional.of(contactNotLinked), ImmutableSet.of(), OutputDataType.FULL)
|
||||
.createRdapContactEntity(contactNotLinked, ImmutableSet.of(), OutputDataType.FULL)
|
||||
.toJson())
|
||||
.isEqualTo(loadJson("rdapjson_unlinkedcontact.json"));
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.google.common.base.Throwables;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.request.Response;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
@@ -69,7 +70,7 @@ public final class FakeResponse implements Response {
|
||||
|
||||
@Override
|
||||
public void sendRedirect(String url) throws IOException {
|
||||
status = 302;
|
||||
status = HttpServletResponse.SC_FOUND;
|
||||
this.payload = String.format("Redirected to %s", url);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_OPTIONAL;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_PROHIBITED;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.TEST_FEATURE;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.ACTIVE;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.INACTIVE;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.common.FeatureFlag.FeatureStatus;
|
||||
import google.registry.model.common.TimedTransitionProperty;
|
||||
import google.registry.testing.FakeClock;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link ConfigureFeatureFlagCommand}. */
|
||||
public class ConfigureFeatureFlagCommandTest extends CommandTestCase<ConfigureFeatureFlagCommand> {
|
||||
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2000-01-01T00:00:00Z"));
|
||||
|
||||
@Test
|
||||
void testCreate() throws Exception {
|
||||
DateTime featureStart = clock.nowUtc().plusWeeks(2);
|
||||
|
||||
runCommandForced(
|
||||
"TEST_FEATURE",
|
||||
"--status_map",
|
||||
String.format("%s=INACTIVE,%s=ACTIVE", START_OF_TIME, featureStart));
|
||||
|
||||
assertThat(FeatureFlag.get(TEST_FEATURE).getStatusMap())
|
||||
.isEqualTo(
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, featureStart, ACTIVE)));
|
||||
assertThat(FeatureFlag.getAllUncached()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreate_multipleFlags() throws Exception {
|
||||
DateTime featureStart = clock.nowUtc().plusWeeks(2);
|
||||
|
||||
runCommandForced(
|
||||
"TEST_FEATURE",
|
||||
"MINIMUM_DATASET_CONTACTS_OPTIONAL",
|
||||
"MINIMUM_DATASET_CONTACTS_PROHIBITED",
|
||||
"--status_map",
|
||||
String.format("%s=INACTIVE,%s=ACTIVE", START_OF_TIME, featureStart));
|
||||
|
||||
assertThat(FeatureFlag.get(TEST_FEATURE).getStatusMap())
|
||||
.isEqualTo(
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, featureStart, ACTIVE)));
|
||||
assertThat(FeatureFlag.get(MINIMUM_DATASET_CONTACTS_OPTIONAL).getStatusMap())
|
||||
.isEqualTo(
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, featureStart, ACTIVE)));
|
||||
assertThat(FeatureFlag.get(MINIMUM_DATASET_CONTACTS_PROHIBITED).getStatusMap())
|
||||
.isEqualTo(
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, featureStart, ACTIVE)));
|
||||
assertThat(FeatureFlag.getAllUncached()).hasSize(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdate() throws Exception {
|
||||
persistResource(
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName(TEST_FEATURE)
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.build())
|
||||
.build());
|
||||
|
||||
DateTime featureStart = clock.nowUtc().plusWeeks(6);
|
||||
assertThat(FeatureFlag.get(TEST_FEATURE).getStatusMap())
|
||||
.isEqualTo(
|
||||
TimedTransitionProperty.fromValueMap(ImmutableSortedMap.of(START_OF_TIME, INACTIVE)));
|
||||
assertThat(FeatureFlag.getAllUncached()).hasSize(1);
|
||||
|
||||
runCommandForced(
|
||||
"TEST_FEATURE",
|
||||
"--status_map",
|
||||
String.format("%s=INACTIVE,%s=ACTIVE", START_OF_TIME, featureStart));
|
||||
|
||||
assertThat(FeatureFlag.get(TEST_FEATURE).getStatusMap())
|
||||
.isEqualTo(
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, featureStart, ACTIVE)));
|
||||
assertThat(FeatureFlag.getAllUncached()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConfigure_multipleFlags() throws Exception {
|
||||
persistResource(
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName(TEST_FEATURE)
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.build())
|
||||
.build());
|
||||
|
||||
DateTime featureStart = clock.nowUtc().plusWeeks(6);
|
||||
assertThat(FeatureFlag.get(TEST_FEATURE).getStatusMap())
|
||||
.isEqualTo(
|
||||
TimedTransitionProperty.fromValueMap(ImmutableSortedMap.of(START_OF_TIME, INACTIVE)));
|
||||
assertThat(FeatureFlag.getAllUncached()).hasSize(1);
|
||||
|
||||
runCommandForced(
|
||||
"TEST_FEATURE",
|
||||
"MINIMUM_DATASET_CONTACTS_OPTIONAL",
|
||||
"MINIMUM_DATASET_CONTACTS_PROHIBITED",
|
||||
"--status_map",
|
||||
String.format("%s=INACTIVE,%s=ACTIVE", START_OF_TIME, featureStart));
|
||||
|
||||
assertThat(FeatureFlag.get(TEST_FEATURE).getStatusMap())
|
||||
.isEqualTo(
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, featureStart, ACTIVE)));
|
||||
assertThat(FeatureFlag.get(MINIMUM_DATASET_CONTACTS_OPTIONAL).getStatusMap())
|
||||
.isEqualTo(
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, featureStart, ACTIVE)));
|
||||
assertThat(FeatureFlag.get(MINIMUM_DATASET_CONTACTS_PROHIBITED).getStatusMap())
|
||||
.isEqualTo(
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, INACTIVE, featureStart, ACTIVE)));
|
||||
assertThat(FeatureFlag.getAllUncached()).hasSize(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreate_invalidFeatureName() throws Exception {
|
||||
ParameterException thrown =
|
||||
assertThrows(
|
||||
ParameterException.class,
|
||||
() ->
|
||||
runCommandForced(
|
||||
"INVALID_NAME", "--status_map", String.format("%s=ACTIVE", START_OF_TIME)));
|
||||
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains("Invalid value for [Main class] parameter. Allowed values");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreate_invalidStatusMap() throws Exception {
|
||||
DateTime featureStart = clock.nowUtc().plusWeeks(2);
|
||||
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
runCommandForced(
|
||||
"TEST_FEATURE", "--status_map", String.format("%s=ACTIVE", featureStart)));
|
||||
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Must provide transition entry for the start of time (Unix Epoch)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdate_invalidStatusMap() throws Exception {
|
||||
persistResource(
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName(TEST_FEATURE)
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.build())
|
||||
.build());
|
||||
|
||||
DateTime featureStart = clock.nowUtc().plusWeeks(6);
|
||||
assertThat(FeatureFlag.get(TEST_FEATURE).getStatusMap())
|
||||
.isEqualTo(
|
||||
TimedTransitionProperty.fromValueMap(ImmutableSortedMap.of(START_OF_TIME, INACTIVE)));
|
||||
assertThat(FeatureFlag.getAllUncached()).hasSize(1);
|
||||
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
runCommandForced(
|
||||
"TEST_FEATURE", "--status_map", String.format("%s=ACTIVE", featureStart)));
|
||||
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Must provide transition entry for the start of time (Unix Epoch)");
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user