Compare commits
20 Commits
nomulus-20
...
nomulus-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfef733360 | ||
|
|
04a0659197 | ||
|
|
70010886b1 | ||
|
|
3cd50dc929 | ||
|
|
03872b508f | ||
|
|
1096f201cd | ||
|
|
9dc3215624 | ||
|
|
af321fb65e | ||
|
|
c5132c04be | ||
|
|
a64dc21f96 | ||
|
|
0381533a35 | ||
|
|
4999a72d96 | ||
|
|
2d072c3844 | ||
|
|
c15dec4419 | ||
|
|
8340125bf4 | ||
|
|
98ba80d94e | ||
|
|
967d04efce | ||
|
|
20fd944e83 | ||
|
|
daa56e6d85 | ||
|
|
ed33c7424d |
@@ -90,7 +90,6 @@ explodeWar.doLast {
|
||||
|
||||
appengineDeployAll.mustRunAfter ':console-webapp:deploy'
|
||||
appengineDeployAll.finalizedBy ':deployCloudSchedulerAndQueue'
|
||||
rootProject.deploy.dependsOn appengineDeployAll
|
||||
|
||||
rootProject.stage.dependsOn appengineStage
|
||||
tasks['war'].dependsOn ':core:processResources'
|
||||
|
||||
@@ -25,7 +25,11 @@ import textwrap
|
||||
import re
|
||||
|
||||
# We should never analyze any generated files
|
||||
UNIVERSALLY_SKIPPED_PATTERNS = {"/build/", "cloudbuild-caches", "/out/", ".git/", ".gradle/", "/dist/", "/console-alpha/", "/console-crash/", "/console-qa", "/console-sandbox", "/console-production", "karma.conf.js", "polyfills.ts", "test.ts", "/docs/console-endpoints/"}
|
||||
UNIVERSALLY_SKIPPED_PATTERNS = {"/build/", "cloudbuild-caches", "/out/", ".git/",
|
||||
".gradle/", "/dist/", "/console-alpha/", "/console-crash/", "/console-qa",
|
||||
"/console-sandbox", "/console-production", "karma.conf.js", "polyfills.ts",
|
||||
"test.ts", "/docs/console-endpoints/", "/bin/generated-sources/",
|
||||
"/bin/generated-test-sources/", "src/main/generated", "src/test/generated"}
|
||||
# We can't rely on CI to have the Enum package installed so we do this instead.
|
||||
FORBIDDEN = 1
|
||||
REQUIRED = 2
|
||||
@@ -87,11 +91,9 @@ PRESUBMITS = {
|
||||
PresubmitCheck(
|
||||
r".*Copyright 20\d{2} The Nomulus Authors\. All Rights Reserved\.",
|
||||
("java", "js", "soy", "sql", "py", "sh", "gradle", "ts"), {
|
||||
".git", "/build/", "/bin/generated-sources/", "/bin/generated-test-sources/",
|
||||
"node_modules/", "LoggerConfig.java", "registrar_bin.",
|
||||
".git", "/build/", "node_modules/", "LoggerConfig.java", "registrar_bin.",
|
||||
"registrar_dbg.", "google-java-format-diff.py",
|
||||
"nomulus.golden.sql", "soyutils_usegoog.js", "javascript/checks.js",
|
||||
"/src/main/generated", "/src/test/generated"
|
||||
"nomulus.golden.sql", "soyutils_usegoog.js", "javascript/checks.js"
|
||||
}, REQUIRED):
|
||||
"File did not include the license header.",
|
||||
|
||||
|
||||
@@ -101,16 +101,9 @@ task checkFormatting(type: Exec) {
|
||||
args 'run', 'prettify:check'
|
||||
}
|
||||
|
||||
task deploy(type: Exec) {
|
||||
workingDir "${consoleDir}/staged"
|
||||
executable 'gcloud'
|
||||
args 'app', 'deploy', "${projectParam}", '--quiet'
|
||||
}
|
||||
|
||||
tasks.buildConsoleWebapp.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.runConsoleWebappUnitTests.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.applyFormatting.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.checkFormatting.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.build.dependsOn(tasks.checkFormatting)
|
||||
tasks.build.dependsOn(tasks.runConsoleWebappUnitTests)
|
||||
tasks.deploy.dependsOn(tasks.buildConsoleWebapp)
|
||||
|
||||
@@ -24,8 +24,8 @@ import { ResourcesComponent } from './resources/resources.component';
|
||||
import ContactComponent from './settings/contact/contact.component';
|
||||
import SecurityComponent from './settings/security/security.component';
|
||||
import { SettingsComponent } from './settings/settings.component';
|
||||
import WhoisComponent from './settings/whois/whois.component';
|
||||
import { SupportComponent } from './support/support.component';
|
||||
import RdapComponent from './settings/rdap/rdap.component';
|
||||
|
||||
export interface RouteWithIcon extends Route {
|
||||
iconName?: string;
|
||||
@@ -83,9 +83,9 @@ export const routes: RouteWithIcon[] = [
|
||||
title: 'Contacts',
|
||||
},
|
||||
{
|
||||
path: WhoisComponent.PATH,
|
||||
component: WhoisComponent,
|
||||
title: 'WHOIS Info',
|
||||
path: RdapComponent.PATH,
|
||||
component: RdapComponent,
|
||||
title: 'RDAP Info',
|
||||
},
|
||||
{
|
||||
path: SecurityComponent.PATH,
|
||||
|
||||
@@ -47,8 +47,6 @@ import EppPasswordEditComponent from './settings/security/eppPasswordEdit.compon
|
||||
import SecurityComponent from './settings/security/security.component';
|
||||
import SecurityEditComponent from './settings/security/securityEdit.component';
|
||||
import { SettingsComponent } from './settings/settings.component';
|
||||
import WhoisComponent from './settings/whois/whois.component';
|
||||
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';
|
||||
@@ -60,6 +58,8 @@ import { SnackBarModule } from './snackbar.module';
|
||||
import { SupportComponent } from './support/support.component';
|
||||
import { TldsComponent } from './tlds/tlds.component';
|
||||
import { ForceFocusDirective } from './shared/directives/forceFocus.directive';
|
||||
import RdapComponent from './settings/rdap/rdap.component';
|
||||
import RdapEditComponent from './settings/rdap/rdapEdit.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [SelectedRegistrarWrapper],
|
||||
@@ -76,30 +76,30 @@ export class SelectedRegistrarModule {}
|
||||
ContactDetailsComponent,
|
||||
DomainListComponent,
|
||||
EppPasswordEditComponent,
|
||||
ForceFocusDirective,
|
||||
HeaderComponent,
|
||||
HomeComponent,
|
||||
LocationBackDirective,
|
||||
ForceFocusDirective,
|
||||
UserLevelVisibility,
|
||||
NavigationComponent,
|
||||
NewRegistrarComponent,
|
||||
NotificationsComponent,
|
||||
RdapComponent,
|
||||
RdapEditComponent,
|
||||
ReasonDialogComponent,
|
||||
RegistrarComponent,
|
||||
RegistrarDetailsComponent,
|
||||
RegistryLockComponent,
|
||||
RegistrarSelectorComponent,
|
||||
RegistryLockComponent,
|
||||
RegistryLockVerifyComponent,
|
||||
ResourcesComponent,
|
||||
ResponseDialogComponent,
|
||||
SecurityComponent,
|
||||
SecurityEditComponent,
|
||||
SettingsComponent,
|
||||
SettingsContactComponent,
|
||||
SupportComponent,
|
||||
TldsComponent,
|
||||
WhoisComponent,
|
||||
WhoisEditComponent,
|
||||
ReasonDialogComponent,
|
||||
ResponseDialogComponent,
|
||||
UserLevelVisibility,
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
imports: [
|
||||
@@ -108,8 +108,8 @@ export class SelectedRegistrarModule {}
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
MaterialModule,
|
||||
SnackBarModule,
|
||||
SelectedRegistrarModule,
|
||||
SnackBarModule,
|
||||
],
|
||||
providers: [
|
||||
BackendService,
|
||||
|
||||
@@ -48,7 +48,6 @@ export default class NewRegistrarComponent {
|
||||
this.newRegistrar = {
|
||||
registrarId: '',
|
||||
url: '',
|
||||
whoisServer: '',
|
||||
registrarName: '',
|
||||
icannReferralEmail: '',
|
||||
localizedAddress: {
|
||||
|
||||
@@ -50,17 +50,16 @@ export interface SecuritySettings
|
||||
ipAddressAllowList?: Array<IpAllowListItem>;
|
||||
}
|
||||
|
||||
export interface WhoisRegistrarFields {
|
||||
export interface RdapRegistrarFields {
|
||||
ianaIdentifier?: number;
|
||||
icannReferralEmail: string;
|
||||
localizedAddress: Address;
|
||||
registrarId: string;
|
||||
url: string;
|
||||
whoisServer: string;
|
||||
}
|
||||
|
||||
export interface Registrar
|
||||
extends WhoisRegistrarFields,
|
||||
extends RdapRegistrarFields,
|
||||
SecuritySettingsBackendModel {
|
||||
allowedTlds?: string[];
|
||||
billingAccountMap?: object;
|
||||
|
||||
@@ -24,7 +24,7 @@ export type contactType =
|
||||
| 'LEGAL'
|
||||
| 'MARKETING'
|
||||
| 'TECH'
|
||||
| 'WHOIS';
|
||||
| 'RDAP';
|
||||
|
||||
type contactTypesToUserFriendlyTypes = { [type in contactType]: string };
|
||||
|
||||
@@ -35,7 +35,7 @@ export const contactTypeToTextMap: contactTypesToUserFriendlyTypes = {
|
||||
LEGAL: 'Legal contact',
|
||||
MARKETING: 'Marketing contact',
|
||||
TECH: 'Technical contact',
|
||||
WHOIS: 'WHOIS-Inquiry contact',
|
||||
RDAP: 'RDAP-Inquiry contact',
|
||||
};
|
||||
|
||||
type UserFriendlyType = (typeof contactTypeToTextMap)[contactType];
|
||||
|
||||
@@ -97,12 +97,12 @@
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h1>WHOIS Preferences</h1>
|
||||
<h1>RDAP Preferences</h1>
|
||||
<div>
|
||||
<mat-checkbox
|
||||
[(ngModel)]="contactService.contactInEdit.visibleInWhoisAsAdmin"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
>Show in Registrar WHOIS record as admin contact</mat-checkbox
|
||||
>Show in Registrar RDAP record as admin contact</mat-checkbox
|
||||
>
|
||||
</div>
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
<mat-checkbox
|
||||
[(ngModel)]="contactService.contactInEdit.visibleInWhoisAsTech"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
>Show in Registrar WHOIS record as technical contact</mat-checkbox
|
||||
>Show in Registrar RDAP record as technical contact</mat-checkbox
|
||||
>
|
||||
</div>
|
||||
|
||||
@@ -118,8 +118,8 @@
|
||||
<mat-checkbox
|
||||
[(ngModel)]="contactService.contactInEdit.visibleInDomainWhoisAsAbuse"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
>Show Phone and Email in Domain WHOIS Record as registrar abuse
|
||||
contact (per CL&D requirements)</mat-checkbox
|
||||
>Show Phone and Email in Domain RDAP Record as registrar abuse contact
|
||||
(per CL&D requirements)</mat-checkbox
|
||||
>
|
||||
</div>
|
||||
</section>
|
||||
@@ -176,13 +176,13 @@
|
||||
<mat-card-content>
|
||||
<mat-list role="list">
|
||||
<mat-list-item role="listitem">
|
||||
<h2>WHOIS Preferences</h2>
|
||||
<h2>RDAP Preferences</h2>
|
||||
</mat-list-item>
|
||||
@if(contactService.contactInEdit.visibleInWhoisAsAdmin) {
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item role="listitem">
|
||||
<span class="console-app__list-value"
|
||||
>Show in Registrar WHOIS record as admin contact</span
|
||||
>Show in Registrar RDAP record as admin contact</span
|
||||
>
|
||||
</mat-list-item>
|
||||
} @if(contactService.contactInEdit.visibleInWhoisAsTech) {
|
||||
@@ -192,14 +192,14 @@
|
||||
*ngIf="contactService.contactInEdit.visibleInWhoisAsTech"
|
||||
>
|
||||
<span class="console-app__list-value"
|
||||
>Show in Registrar WHOIS record as technical contact</span
|
||||
>Show in Registrar RDAP record as technical contact</span
|
||||
>
|
||||
</mat-list-item>
|
||||
} @if(contactService.contactInEdit.visibleInDomainWhoisAsAbuse) {
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item role="listitem">
|
||||
<span class="console-app__list-value"
|
||||
>Show Phone and Email in Domain WHOIS Record as registrar abuse
|
||||
>Show Phone and Email in Domain RDAP Record as registrar abuse
|
||||
contact (per CL&D requirements)</span
|
||||
>
|
||||
</mat-list-item>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
@if(whoisService.editing) {
|
||||
<app-whois-edit></app-whois-edit>
|
||||
@if(rdapService.editing) {
|
||||
<app-rdap-edit></app-rdap-edit>
|
||||
} @else {
|
||||
<div class="console-app__whois">
|
||||
<div class="console-app__whois-controls">
|
||||
<div class="console-app__rdap">
|
||||
<div class="console-app__rdap-controls">
|
||||
<span>
|
||||
General registrar information for your WHOIS record. This information is
|
||||
always visible in WHOIS.
|
||||
General registrar information for your RDAP record. This information is
|
||||
always visible in RDAP.
|
||||
</span>
|
||||
<div class="spacer"></div>
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
aria-label="Edit WHOIS record"
|
||||
(click)="whoisService.editing = true"
|
||||
aria-label="Edit RDAP record"
|
||||
(click)="rdapService.editing = true"
|
||||
>
|
||||
<mat-icon>edit</mat-icon>
|
||||
Edit
|
||||
@@ -61,45 +61,5 @@
|
||||
</mat-list>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
<mat-card appearance="outlined">
|
||||
<mat-card-content>
|
||||
<mat-list role="list">
|
||||
<mat-list-item role="listitem">
|
||||
<h2>Technical Info</h2>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item role="listitem">
|
||||
<span class="console-app__list-key">IANA Identifier</span>
|
||||
<span class="console-app__list-value">{{
|
||||
registrarService.registrar()?.ianaIdentifier
|
||||
}}</span>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item role="listitem">
|
||||
<div>
|
||||
<span class="console-app__list-key">ICANN Referral Email</span>
|
||||
<span class="console-app__list-value">{{
|
||||
registrarService.registrar()?.icannReferralEmail
|
||||
}}</span>
|
||||
</div>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item role="listitem">
|
||||
<span class="console-app__list-key">WHOIS server</span>
|
||||
<span class="console-app__list-value">{{
|
||||
registrarService.registrar()?.whoisServer
|
||||
}}</span>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item role="listitem">
|
||||
<span class="console-app__list-key">Referral URL</span>
|
||||
<span class="console-app__list-value">{{
|
||||
registrarService.registrar()?.url
|
||||
}}</span>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
.console-app__whois {
|
||||
.console-app__rdap {
|
||||
max-width: 616px;
|
||||
|
||||
&-controls {
|
||||
@@ -20,15 +20,15 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { RegistrarService } from 'src/app/registrar/registrar.service';
|
||||
import { BackendService } from 'src/app/shared/services/backend.service';
|
||||
import WhoisComponent from './whois.component';
|
||||
import RdapComponent from './rdap.component';
|
||||
|
||||
describe('WhoisComponent', () => {
|
||||
let component: WhoisComponent;
|
||||
let fixture: ComponentFixture<WhoisComponent>;
|
||||
describe('RdapComponent', () => {
|
||||
let component: RdapComponent;
|
||||
let fixture: ComponentFixture<RdapComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [WhoisComponent],
|
||||
declarations: [RdapComponent],
|
||||
imports: [MaterialModule, BrowserAnimationsModule],
|
||||
providers: [
|
||||
BackendService,
|
||||
@@ -45,7 +45,7 @@ describe('WhoisComponent', () => {
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(WhoisComponent);
|
||||
fixture = TestBed.createComponent(RdapComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
@@ -14,17 +14,16 @@
|
||||
|
||||
import { Component, computed } from '@angular/core';
|
||||
import { RegistrarService } from 'src/app/registrar/registrar.service';
|
||||
|
||||
import { WhoisService } from './whois.service';
|
||||
import { RdapService } from './rdap.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-whois',
|
||||
templateUrl: './whois.component.html',
|
||||
styleUrls: ['./whois.component.scss'],
|
||||
selector: 'app-rdap',
|
||||
templateUrl: './rdap.component.html',
|
||||
styleUrls: ['./rdap.component.scss'],
|
||||
standalone: false,
|
||||
})
|
||||
export default class WhoisComponent {
|
||||
public static PATH = 'whois';
|
||||
export default class RdapComponent {
|
||||
public static PATH = 'rdap';
|
||||
formattedAddress = computed(() => {
|
||||
let result = '';
|
||||
const registrar = this.registrarService.registrar();
|
||||
@@ -47,7 +46,7 @@ export default class WhoisComponent {
|
||||
});
|
||||
|
||||
constructor(
|
||||
public whoisService: WhoisService,
|
||||
public rdapService: RdapService,
|
||||
public registrarService: RegistrarService
|
||||
) {}
|
||||
}
|
||||
@@ -16,14 +16,14 @@ import { Injectable } from '@angular/core';
|
||||
import { switchMap } from 'rxjs';
|
||||
import {
|
||||
RegistrarService,
|
||||
WhoisRegistrarFields,
|
||||
RdapRegistrarFields,
|
||||
} from 'src/app/registrar/registrar.service';
|
||||
import { BackendService } from 'src/app/shared/services/backend.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class WhoisService {
|
||||
export class RdapService {
|
||||
editing: boolean = false;
|
||||
|
||||
constructor(
|
||||
@@ -31,8 +31,8 @@ export class WhoisService {
|
||||
private registrarService: RegistrarService
|
||||
) {}
|
||||
|
||||
saveChanges(newWhoisRegistrarFields: WhoisRegistrarFields) {
|
||||
return this.backend.postWhoisRegistrarFields(newWhoisRegistrarFields).pipe(
|
||||
saveChanges(newRdapRegistrarFields: RdapRegistrarFields) {
|
||||
return this.backend.postRdapRegistrarFields(newRdapRegistrarFields).pipe(
|
||||
switchMap(() => {
|
||||
return this.registrarService.loadRegistrars();
|
||||
})
|
||||
@@ -1,27 +1,27 @@
|
||||
<div
|
||||
class="console-app__whois-edit"
|
||||
class="console-app__rdap-edit"
|
||||
*ngIf="registrarInEdit"
|
||||
cdkTrapFocus
|
||||
[cdkTrapFocusAutoCapture]="true"
|
||||
>
|
||||
<button
|
||||
mat-icon-button
|
||||
class="console-app__whois-edit-back"
|
||||
aria-label="Back to whois view"
|
||||
(click)="whoisService.editing = false"
|
||||
class="console-app__rdap-edit-back"
|
||||
aria-label="Back to rdap view"
|
||||
(click)="rdapService.editing = false"
|
||||
>
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
</button>
|
||||
|
||||
<div class="console-app__whois-edit-controls">
|
||||
<div class="console-app__rdap-edit-controls">
|
||||
<span>
|
||||
General registrar information for your WHOIS record. This information is
|
||||
always visible in WHOIS.
|
||||
General registrar information for your RDAP record. This information is
|
||||
always visible in RDAP.
|
||||
</span>
|
||||
<div class="spacer"></div>
|
||||
</div>
|
||||
|
||||
<div class="console-app__whois-edit">
|
||||
<div class="console-app__rdap-edit">
|
||||
<h1>Personal info</h1>
|
||||
|
||||
<form (ngSubmit)="save($event)">
|
||||
@@ -115,45 +115,11 @@
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<h1>Technical info</h1>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>WHOIS server: </mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
[(ngModel)]="registrarInEdit.whoisServer"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Referral URL: </mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
[(ngModel)]="registrarInEdit.url"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
@if((userDataService.userData()?.globalRole || 'NONE') !== "NONE") {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>ICANN Referral Email: </mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
[(ngModel)]="registrarInEdit.icannReferralEmail"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
/>
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
type="submit"
|
||||
aria-label="Save WHOIS settings"
|
||||
aria-label="Save RDAO settings"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
@@ -1,4 +1,4 @@
|
||||
.console-app__whois-edit {
|
||||
.console-app__rdap-edit {
|
||||
max-width: 616px;
|
||||
|
||||
&-controls {
|
||||
@@ -20,20 +20,20 @@ import {
|
||||
RegistrarService,
|
||||
} from 'src/app/registrar/registrar.service';
|
||||
import { UserDataService } from 'src/app/shared/services/userData.service';
|
||||
import { WhoisService } from './whois.service';
|
||||
import { RdapService } from './rdap.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-whois-edit',
|
||||
templateUrl: './whoisEdit.component.html',
|
||||
styleUrls: ['./whoisEdit.component.scss'],
|
||||
selector: 'app-rdap-edit',
|
||||
templateUrl: './rdapEdit.component.html',
|
||||
styleUrls: ['./rdapEdit.component.scss'],
|
||||
standalone: false,
|
||||
})
|
||||
export default class WhoisEditComponent {
|
||||
export default class RdapEditComponent {
|
||||
registrarInEdit: Registrar | undefined;
|
||||
|
||||
constructor(
|
||||
public userDataService: UserDataService,
|
||||
public whoisService: WhoisService,
|
||||
public rdapService: RdapService,
|
||||
public registrarService: RegistrarService,
|
||||
private _snackBar: MatSnackBar
|
||||
) {
|
||||
@@ -49,9 +49,9 @@ export default class WhoisEditComponent {
|
||||
e.preventDefault();
|
||||
if (!this.registrarInEdit) return;
|
||||
|
||||
this.whoisService.saveChanges(this.registrarInEdit).subscribe({
|
||||
this.rdapService.saveChanges(this.registrarInEdit).subscribe({
|
||||
complete: () => {
|
||||
this.whoisService.editing = false;
|
||||
this.rdapService.editing = false;
|
||||
},
|
||||
error: (err: HttpErrorResponse) => {
|
||||
this._snackBar.open(err.error);
|
||||
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { switchMap, timeout } from 'rxjs';
|
||||
import { switchMap } from 'rxjs';
|
||||
import {
|
||||
IpAllowListItem,
|
||||
RegistrarService,
|
||||
@@ -69,7 +69,6 @@ export class SecurityService {
|
||||
uiToApiConverter(newSecuritySettings)
|
||||
)
|
||||
.pipe(
|
||||
timeout(2000),
|
||||
switchMap(() => {
|
||||
return this.registrarService.loadRegistrars();
|
||||
})
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
>
|
||||
<a
|
||||
mat-tab-link
|
||||
routerLink="whois"
|
||||
routerLink="rdap"
|
||||
routerLinkActive
|
||||
queryParamsHandling="merge"
|
||||
#rla2="routerLinkActive"
|
||||
[active]="rla2.isActive"
|
||||
aria-label="Access whois settings"
|
||||
>WHOIS Info</a
|
||||
aria-label="Access rdap settings"
|
||||
>RDAP Info</a
|
||||
>
|
||||
<a
|
||||
mat-tab-link
|
||||
|
||||
@@ -25,7 +25,7 @@ import { User } from 'src/app/users/users.service';
|
||||
import {
|
||||
Registrar,
|
||||
SecuritySettingsBackendModel,
|
||||
WhoisRegistrarFields,
|
||||
RdapRegistrarFields,
|
||||
} from '../../registrar/registrar.service';
|
||||
import { Contact } from '../../settings/contact/contact.service';
|
||||
import { EppPasswordBackendModel } from '../../settings/security/security.service';
|
||||
@@ -209,12 +209,12 @@ export class BackendService {
|
||||
.pipe(catchError((err) => this.errorCatcher<UserData>(err)));
|
||||
}
|
||||
|
||||
postWhoisRegistrarFields(
|
||||
whoisRegistrarFields: WhoisRegistrarFields
|
||||
): Observable<WhoisRegistrarFields> {
|
||||
return this.http.post<WhoisRegistrarFields>(
|
||||
'/console-api/settings/whois-fields',
|
||||
whoisRegistrarFields
|
||||
postRdapRegistrarFields(
|
||||
rdapRegistrarFields: RdapRegistrarFields
|
||||
): Observable<RdapRegistrarFields> {
|
||||
return this.http.post<RdapRegistrarFields>(
|
||||
'/console-api/settings/rdap-fields',
|
||||
rdapRegistrarFields
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1111,12 +1111,6 @@ public final class RegistryConfig {
|
||||
return config.registryPolicy.whoisCommandFactoryClass;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("allocationTokenCustomLogicClass")
|
||||
public static String provideAllocationTokenCustomLogicClass(RegistryConfigSettings config) {
|
||||
return config.registryPolicy.allocationTokenCustomLogicClass;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("dnsCountQueryCoordinatorClass")
|
||||
public static String dnsCountQueryCoordinatorClass(RegistryConfigSettings config) {
|
||||
|
||||
@@ -91,7 +91,6 @@ public class RegistryConfigSettings {
|
||||
public String productName;
|
||||
public String customLogicFactoryClass;
|
||||
public String whoisCommandFactoryClass;
|
||||
public String allocationTokenCustomLogicClass;
|
||||
public String dnsCountQueryCoordinatorClass;
|
||||
public int contactAutomaticTransferDays;
|
||||
public String greetingServerId;
|
||||
|
||||
@@ -69,10 +69,6 @@ registryPolicy:
|
||||
# See whois/WhoisCommandFactory.java
|
||||
whoisCommandFactoryClass: google.registry.whois.WhoisCommandFactory
|
||||
|
||||
# Custom logic class for handling allocation tokens.
|
||||
# See flows/domain/token/AllocationTokenCustomLogic.java
|
||||
allocationTokenCustomLogicClass: google.registry.flows.domain.token.AllocationTokenCustomLogic
|
||||
|
||||
# Custom logic class for handling DNS query count reporting for ICANN.
|
||||
# See reporting/icann/DnsCountQueryCoordinator.java
|
||||
dnsCountQueryCoordinatorClass: google.registry.reporting.icann.DummyDnsCountQueryCoordinator
|
||||
@@ -247,7 +243,7 @@ hibernate:
|
||||
# that BEAM pipelines are not subject to the maximumPoolSize value defined
|
||||
# here. See PersistenceModule.java for more information.
|
||||
hikariMinimumIdle: 1
|
||||
hikariMaximumPoolSize: 10
|
||||
hikariMaximumPoolSize: 20
|
||||
hikariIdleTimeout: 300000
|
||||
# The batch size is basically the number of insertions / updates in a single
|
||||
# transaction that will be batched together into one INSERT/UPDATE statement.
|
||||
|
||||
@@ -78,7 +78,7 @@ public class ExportDomainListsAction implements Runnable {
|
||||
ORDER BY d.domain_name""";
|
||||
|
||||
// This may be a CSV, but it is uses a .txt file extension for back-compatibility
|
||||
static final String REGISTERED_DOMAINS_FILENAME = "registered_domains.txt";
|
||||
static final String REGISTERED_DOMAINS_FILENAME_FORMAT = "registered_domains_%s.txt";
|
||||
|
||||
@Inject Clock clock;
|
||||
@Inject DriveConnection driveConnection;
|
||||
@@ -146,7 +146,7 @@ public class ExportDomainListsAction implements Runnable {
|
||||
} else {
|
||||
String resultMsg =
|
||||
driveConnection.createOrUpdateFile(
|
||||
REGISTERED_DOMAINS_FILENAME,
|
||||
String.format(REGISTERED_DOMAINS_FILENAME_FORMAT, tldStr),
|
||||
MediaType.PLAIN_TEXT_UTF_8,
|
||||
tld.getDriveFolderId(),
|
||||
domains.getBytes(UTF_8));
|
||||
|
||||
@@ -43,7 +43,7 @@ public class ExportReservedTermsAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
static final MediaType EXPORT_MIME_TYPE = MediaType.PLAIN_TEXT_UTF_8;
|
||||
static final String RESERVED_TERMS_FILENAME = "reserved_terms.txt";
|
||||
static final String RESERVED_TERMS_FILENAME_FORMAT = "reserved_terms_%s.txt";
|
||||
|
||||
@Inject DriveConnection driveConnection;
|
||||
@Inject ExportUtils exportUtils;
|
||||
@@ -79,7 +79,7 @@ public class ExportReservedTermsAction implements Runnable {
|
||||
} else {
|
||||
resultMsg =
|
||||
driveConnection.createOrUpdateFile(
|
||||
RESERVED_TERMS_FILENAME,
|
||||
String.format(RESERVED_TERMS_FILENAME_FORMAT, tldStr),
|
||||
EXPORT_MIME_TYPE,
|
||||
tld.getDriveFolderId(),
|
||||
exportUtils.exportReservedTerms(tld).getBytes(UTF_8));
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
// Copyright 2025 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.flows;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import google.registry.request.Response;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A metadata class that saves the data directly in cookies.
|
||||
*
|
||||
* <p>Unlike {@link HttpSessionMetadata}, this class does not rely on a session manager to translate
|
||||
* an opaque session cookie into the metadata. This means that the locality of the session manager
|
||||
* is irrelevant and as long as the client (the proxy) respects the {@code Set-Cookie} headers and
|
||||
* sets the respective cookies in subsequent requests in a session, the metadata will be available
|
||||
* to all servers, not just the one that created the session.
|
||||
*
|
||||
* <p>The string representation of the metadata is saved in Base64 URL-safe format in a cookie named
|
||||
* {@code SESSION_INFO}.
|
||||
*/
|
||||
public class CookieSessionMetadata extends SessionMetadata {
|
||||
|
||||
protected static final String COOKIE_NAME = "SESSION_INFO";
|
||||
protected static final String REGISTRAR_ID = "clientId";
|
||||
protected static final String SERVICE_EXTENSIONS = "serviceExtensionUris";
|
||||
protected static final String FAILED_LOGIN_ATTEMPTS = "failedLoginAttempts";
|
||||
|
||||
private static final Pattern COOKIE_PATTERN = Pattern.compile("SESSION_INFO=([^;\\s]+)?");
|
||||
private static final Pattern REGISTRAR_ID_PATTERN = Pattern.compile("clientId=([^,\\s]+)?");
|
||||
private static final Pattern SERVICE_EXTENSIONS_PATTERN =
|
||||
Pattern.compile("serviceExtensionUris=([^,\\s}]+)?");
|
||||
private static final Pattern FAILED_LOGIN_ATTEMPTS_PATTERN =
|
||||
Pattern.compile("failedLoginAttempts=([^,\\s]+)?");
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private final Map<String, String> data = new HashMap<>();
|
||||
|
||||
public CookieSessionMetadata(HttpServletRequest request) {
|
||||
Optional.ofNullable(request.getHeader("Cookie"))
|
||||
.ifPresent(
|
||||
cookie -> {
|
||||
Matcher matcher = COOKIE_PATTERN.matcher(cookie);
|
||||
if (matcher.find()) {
|
||||
String sessionInfo = decode(matcher.group(1));
|
||||
logger.atInfo().log("SESSION INFO: %s", sessionInfo);
|
||||
matcher = REGISTRAR_ID_PATTERN.matcher(sessionInfo);
|
||||
if (matcher.find()) {
|
||||
String registrarId = matcher.group(1);
|
||||
if (!registrarId.equals("null")) {
|
||||
data.put(REGISTRAR_ID, registrarId);
|
||||
}
|
||||
}
|
||||
matcher = SERVICE_EXTENSIONS_PATTERN.matcher(sessionInfo);
|
||||
if (matcher.find()) {
|
||||
String serviceExtensions = matcher.group(1);
|
||||
if (serviceExtensions != null) {
|
||||
data.put(SERVICE_EXTENSIONS, serviceExtensions);
|
||||
}
|
||||
}
|
||||
matcher = FAILED_LOGIN_ATTEMPTS_PATTERN.matcher(sessionInfo);
|
||||
if (matcher.find()) {
|
||||
String failedLoginAttempts = matcher.group(1);
|
||||
data.put(FAILED_LOGIN_ATTEMPTS, failedLoginAttempts);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
data.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRegistrarId() {
|
||||
return data.getOrDefault(REGISTRAR_ID, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getServiceExtensionUris() {
|
||||
return Optional.ofNullable(data.getOrDefault(SERVICE_EXTENSIONS, null))
|
||||
.map(s -> Splitter.on(URI_SEPARATOR).splitToList(s))
|
||||
.map(ImmutableSet::copyOf)
|
||||
.orElse(ImmutableSet.of());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFailedLoginAttempts() {
|
||||
return Optional.ofNullable(data.getOrDefault(FAILED_LOGIN_ATTEMPTS, null))
|
||||
.map(Integer::parseInt)
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRegistrarId(String registrarId) {
|
||||
data.put(REGISTRAR_ID, registrarId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServiceExtensionUris(Set<String> serviceExtensionUris) {
|
||||
if (serviceExtensionUris == null || serviceExtensionUris.isEmpty()) {
|
||||
data.remove(SERVICE_EXTENSIONS);
|
||||
} else {
|
||||
data.put(SERVICE_EXTENSIONS, Joiner.on(URI_SEPARATOR).join(serviceExtensionUris));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementFailedLoginAttempts() {
|
||||
data.put(FAILED_LOGIN_ATTEMPTS, String.valueOf(getFailedLoginAttempts() + 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetFailedLoginAttempts() {
|
||||
data.remove(FAILED_LOGIN_ATTEMPTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Response response) {
|
||||
String value = encode(toString());
|
||||
response.setHeader("Set-Cookie", COOKIE_NAME + "=" + value);
|
||||
}
|
||||
|
||||
protected static String encode(String plainText) {
|
||||
return BaseEncoding.base64Url().encode(plainText.getBytes(US_ASCII));
|
||||
}
|
||||
|
||||
protected static String decode(String cipherText) {
|
||||
return new String(BaseEncoding.base64Url().decode(cipherText), US_ASCII);
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,8 @@ public class EppRequestHandler {
|
||||
} catch (Exception e) {
|
||||
logger.atWarning().withCause(e).log("handleEppCommand general exception.");
|
||||
response.setStatus(SC_BAD_REQUEST);
|
||||
} finally {
|
||||
sessionMetadata.save(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import google.registry.request.Action.Method;
|
||||
import google.registry.request.Payload;
|
||||
import google.registry.request.auth.Auth;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Establishes a transport for EPP+TLS over HTTP. All commands and responses are EPP XML according
|
||||
@@ -35,18 +35,18 @@ public class EppTlsAction implements Runnable {
|
||||
|
||||
@Inject @Payload byte[] inputXmlBytes;
|
||||
@Inject TlsCredentials tlsCredentials;
|
||||
@Inject HttpSession session;
|
||||
@Inject HttpServletRequest request;
|
||||
@Inject EppRequestHandler eppRequestHandler;
|
||||
@Inject EppTlsAction() {}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
eppRequestHandler.executeEpp(
|
||||
new HttpSessionMetadata(session),
|
||||
new CookieSessionMetadata(request),
|
||||
tlsCredentials,
|
||||
EppRequestSource.TLS,
|
||||
false, // This endpoint is never a dry run.
|
||||
false, // This endpoint is never a superuser.
|
||||
false, // This endpoint is never a dry run.
|
||||
false, // This endpoint is never a superuser.
|
||||
inputXmlBytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ import google.registry.flows.domain.DomainTransferQueryFlow;
|
||||
import google.registry.flows.domain.DomainTransferRejectFlow;
|
||||
import google.registry.flows.domain.DomainTransferRequestFlow;
|
||||
import google.registry.flows.domain.DomainUpdateFlow;
|
||||
import google.registry.flows.domain.token.AllocationTokenModule;
|
||||
import google.registry.flows.host.HostCheckFlow;
|
||||
import google.registry.flows.host.HostCreateFlow;
|
||||
import google.registry.flows.host.HostDeleteFlow;
|
||||
@@ -59,7 +58,6 @@ import google.registry.model.eppcommon.Trid;
|
||||
/** Dagger component for flow classes. */
|
||||
@FlowScope
|
||||
@Subcomponent(modules = {
|
||||
AllocationTokenModule.class,
|
||||
BatchModule.class,
|
||||
CustomLogicModule.class,
|
||||
DnsModule.class,
|
||||
|
||||
@@ -14,16 +14,14 @@
|
||||
|
||||
package google.registry.flows;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/** A metadata class that is a wrapper around {@link HttpSession}. */
|
||||
public class HttpSessionMetadata implements SessionMetadata {
|
||||
public class HttpSessionMetadata extends SessionMetadata {
|
||||
|
||||
private static final String REGISTRAR_ID = "REGISTRAR_ID";
|
||||
private static final String SERVICE_EXTENSIONS = "SERVICE_EXTENSIONS";
|
||||
@@ -75,13 +73,4 @@ public class HttpSessionMetadata implements SessionMetadata {
|
||||
public void resetFailedLoginAttempts() {
|
||||
session.removeAttribute(FAILED_LOGIN_ATTEMPTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(getClass())
|
||||
.add("clientId", getRegistrarId())
|
||||
.add("failedLoginAttempts", getFailedLoginAttempts())
|
||||
.add("serviceExtensionUris", Joiner.on('.').join(nullToEmpty(getServiceExtensionUris())))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,29 +14,49 @@
|
||||
|
||||
package google.registry.flows;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import google.registry.request.Response;
|
||||
import java.util.Set;
|
||||
|
||||
/** Object to allow setting and retrieving session information in flows. */
|
||||
public interface SessionMetadata {
|
||||
public abstract class SessionMetadata {
|
||||
|
||||
protected static final char URI_SEPARATOR = '|';
|
||||
|
||||
/**
|
||||
* Invalidates the session. A new instance must be created after this for future sessions.
|
||||
* Attempts to invoke methods of this class after this method has been called will throw
|
||||
* {@code IllegalStateException}.
|
||||
* Attempts to invoke methods of this class after this method has been called will throw {@code
|
||||
* IllegalStateException}.
|
||||
*/
|
||||
void invalidate();
|
||||
public abstract void invalidate();
|
||||
|
||||
String getRegistrarId();
|
||||
public abstract String getRegistrarId();
|
||||
|
||||
Set<String> getServiceExtensionUris();
|
||||
public abstract Set<String> getServiceExtensionUris();
|
||||
|
||||
int getFailedLoginAttempts();
|
||||
public abstract int getFailedLoginAttempts();
|
||||
|
||||
void setRegistrarId(String registrarId);
|
||||
public abstract void setRegistrarId(String registrarId);
|
||||
|
||||
void setServiceExtensionUris(Set<String> serviceExtensionUris);
|
||||
public abstract void setServiceExtensionUris(Set<String> serviceExtensionUris);
|
||||
|
||||
void incrementFailedLoginAttempts();
|
||||
public abstract void incrementFailedLoginAttempts();
|
||||
|
||||
void resetFailedLoginAttempts();
|
||||
public abstract void resetFailedLoginAttempts();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(getClass())
|
||||
.add("clientId", getRegistrarId())
|
||||
.add("failedLoginAttempts", getFailedLoginAttempts())
|
||||
.add(
|
||||
"serviceExtensionUris",
|
||||
Joiner.on(URI_SEPARATOR).join(nullToEmpty(getServiceExtensionUris())))
|
||||
.toString();
|
||||
}
|
||||
|
||||
public void save(Response response) {}
|
||||
}
|
||||
|
||||
@@ -14,16 +14,13 @@
|
||||
|
||||
package google.registry.flows;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Set;
|
||||
|
||||
/** A read-only {@link SessionMetadata} that doesn't support login/logout. */
|
||||
public class StatelessRequestSessionMetadata implements SessionMetadata {
|
||||
public class StatelessRequestSessionMetadata extends SessionMetadata {
|
||||
|
||||
private final String registrarId;
|
||||
private final ImmutableSet<String> serviceExtensionUris;
|
||||
@@ -74,13 +71,6 @@ public class StatelessRequestSessionMetadata implements SessionMetadata {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(getClass())
|
||||
.add("clientId", getRegistrarId())
|
||||
.add("failedLoginAttempts", getFailedLoginAttempts())
|
||||
.add("serviceExtensionUris", Joiner.on('.').join(nullToEmpty(getServiceExtensionUris())))
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.flows.domain.token;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainCommand;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.tld.Tld;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* A no-op base class for allocation token custom logic.
|
||||
*
|
||||
* <p>Extend this class and override the hook(s) to perform custom logic.
|
||||
*/
|
||||
public class AllocationTokenCustomLogic {
|
||||
|
||||
/** Performs additional custom logic for validating a token on a domain create. */
|
||||
public AllocationToken validateToken(
|
||||
DomainCommand.Create command,
|
||||
AllocationToken token,
|
||||
Tld tld,
|
||||
String registrarId,
|
||||
DateTime now)
|
||||
throws EppException {
|
||||
// Do nothing.
|
||||
return token;
|
||||
}
|
||||
|
||||
/** Performs additional custom logic for validating a token on an existing domain. */
|
||||
public AllocationToken validateToken(
|
||||
Domain domain, AllocationToken token, Tld tld, String registrarId, DateTime now)
|
||||
throws EppException {
|
||||
// Do nothing.
|
||||
return token;
|
||||
}
|
||||
|
||||
/** Performs additional custom logic for performing domain checks using a token. */
|
||||
public ImmutableMap<InternetDomainName, String> checkDomainsWithToken(
|
||||
ImmutableList<InternetDomainName> domainNames,
|
||||
AllocationToken token,
|
||||
String registrarId,
|
||||
DateTime now) {
|
||||
// Do nothing.
|
||||
return Maps.toMap(domainNames, k -> "");
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import static google.registry.pricing.PricingEngineProxy.isDomainPremium;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
@@ -48,12 +47,8 @@ import org.joda.time.DateTime;
|
||||
/** Utility functions for dealing with {@link AllocationToken}s in domain flows. */
|
||||
public class AllocationTokenFlowUtils {
|
||||
|
||||
private final AllocationTokenCustomLogic tokenCustomLogic;
|
||||
|
||||
@Inject
|
||||
AllocationTokenFlowUtils(AllocationTokenCustomLogic tokenCustomLogic) {
|
||||
this.tokenCustomLogic = tokenCustomLogic;
|
||||
}
|
||||
public AllocationTokenFlowUtils() {}
|
||||
|
||||
/**
|
||||
* Checks if the allocation token applies to the given domain names, used for domain checks.
|
||||
@@ -75,7 +70,6 @@ public class AllocationTokenFlowUtils {
|
||||
|
||||
// If the token is only invalid for some domain names (e.g. an invalid TLD), include those error
|
||||
// results for only those domain names
|
||||
ImmutableList.Builder<InternetDomainName> validDomainNames = new ImmutableList.Builder<>();
|
||||
ImmutableMap.Builder<InternetDomainName, String> resultsBuilder = new ImmutableMap.Builder<>();
|
||||
for (InternetDomainName domainName : domainNames) {
|
||||
try {
|
||||
@@ -86,16 +80,11 @@ public class AllocationTokenFlowUtils {
|
||||
registrarId,
|
||||
isDomainPremium(domainName.toString(), now),
|
||||
now);
|
||||
validDomainNames.add(domainName);
|
||||
resultsBuilder.put(domainName, "");
|
||||
} catch (EppException e) {
|
||||
resultsBuilder.put(domainName, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// For all valid domain names, run the custom logic and include the results
|
||||
resultsBuilder.putAll(
|
||||
tokenCustomLogic.checkDomainsWithToken(
|
||||
validDomainNames.build(), tokenEntity, registrarId, now));
|
||||
return new AllocationTokenDomainCheckResults(Optional.of(tokenEntity), resultsBuilder.build());
|
||||
}
|
||||
|
||||
@@ -209,7 +198,7 @@ public class AllocationTokenFlowUtils {
|
||||
registrarId,
|
||||
isDomainPremium(command.getDomainName(), now),
|
||||
now);
|
||||
return Optional.of(tokenCustomLogic.validateToken(command, tokenEntity, tld, registrarId, now));
|
||||
return Optional.of(tokenEntity);
|
||||
}
|
||||
|
||||
/** Verifies and returns the allocation token if one is specified, otherwise does nothing. */
|
||||
@@ -232,8 +221,7 @@ public class AllocationTokenFlowUtils {
|
||||
registrarId,
|
||||
isDomainPremium(existingDomain.getDomainName(), now),
|
||||
now);
|
||||
return Optional.of(
|
||||
tokenCustomLogic.validateToken(existingDomain, tokenEntity, tld, registrarId, now));
|
||||
return Optional.of(tokenEntity);
|
||||
}
|
||||
|
||||
public static void verifyTokenAllowedOnDomain(
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.flows.domain.token;
|
||||
|
||||
import static google.registry.util.TypeUtils.getClassFromString;
|
||||
import static google.registry.util.TypeUtils.instantiate;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
|
||||
/** Dagger module for allocation token classes. */
|
||||
@Module
|
||||
public class AllocationTokenModule {
|
||||
|
||||
@Provides
|
||||
static AllocationTokenCustomLogic provideAllocationTokenCustomLogic(
|
||||
@Config("allocationTokenCustomLogicClass") String customClass) {
|
||||
return instantiate(getClassFromString(customClass, AllocationTokenCustomLogic.class));
|
||||
}
|
||||
}
|
||||
@@ -41,10 +41,12 @@ import org.joda.time.DateTime;
|
||||
public abstract class ConsoleUpdateHistory extends ImmutableObject implements Buildable {
|
||||
|
||||
public enum Type {
|
||||
EPP_ACTION,
|
||||
POC_CREATE,
|
||||
POC_UPDATE,
|
||||
POC_DELETE,
|
||||
DOMAIN_DELETE,
|
||||
DOMAIN_SUSPEND,
|
||||
DOMAIN_UNSUSPEND,
|
||||
EPP_PASSWORD_UPDATE,
|
||||
REGISTRAR_CREATE,
|
||||
REGISTRAR_SECURITY_UPDATE,
|
||||
REGISTRAR_UPDATE,
|
||||
USER_CREATE,
|
||||
USER_DELETE,
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
// Copyright 2025 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.console;
|
||||
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.IdAllocation;
|
||||
import google.registry.persistence.WithVKey;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@Entity
|
||||
@WithVKey(Long.class)
|
||||
@Table(
|
||||
name = "ConsoleUpdateHistory",
|
||||
indexes = {
|
||||
@Index(columnList = "actingUser", name = "idx_console_update_history_acting_user"),
|
||||
@Index(columnList = "type", name = "idx_console_update_history_type"),
|
||||
@Index(columnList = "modificationTime", name = "idx_console_update_history_modification_time")
|
||||
})
|
||||
// TODO: rename this to ConsoleUpdateHistory when that class is removed
|
||||
public class SimpleConsoleUpdateHistory extends ImmutableObject implements Buildable {
|
||||
|
||||
@Id @IdAllocation @Column Long revisionId;
|
||||
|
||||
@Column(nullable = false)
|
||||
DateTime modificationTime;
|
||||
|
||||
/** The HTTP method (e.g. POST, PUT) used to make this modification. */
|
||||
@Column(nullable = false)
|
||||
String method;
|
||||
|
||||
/** The type of modification. */
|
||||
@Column(nullable = false)
|
||||
@Enumerated(EnumType.STRING)
|
||||
ConsoleUpdateHistory.Type type;
|
||||
|
||||
/** The URL of the action that was used to make the modification. */
|
||||
@Column(nullable = false)
|
||||
String url;
|
||||
|
||||
/** An optional further description of the action. */
|
||||
String description;
|
||||
|
||||
/** The user that performed the modification. */
|
||||
@JoinColumn(name = "actingUser", referencedColumnName = "emailAddress", nullable = false)
|
||||
@ManyToOne
|
||||
User actingUser;
|
||||
|
||||
public Long getRevisionId() {
|
||||
return revisionId;
|
||||
}
|
||||
|
||||
public DateTime getModificationTime() {
|
||||
return modificationTime;
|
||||
}
|
||||
|
||||
public Optional<String> getDescription() {
|
||||
return Optional.ofNullable(description);
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public ConsoleUpdateHistory.Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public User getActingUser() {
|
||||
return actingUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
return new Builder(clone(this));
|
||||
}
|
||||
|
||||
public static class Builder extends Buildable.Builder<SimpleConsoleUpdateHistory> {
|
||||
public Builder() {}
|
||||
|
||||
private Builder(SimpleConsoleUpdateHistory instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SimpleConsoleUpdateHistory build() {
|
||||
checkArgumentNotNull(getInstance().modificationTime, "Modification time must be specified");
|
||||
checkArgumentNotNull(getInstance().actingUser, "Acting user must be specified");
|
||||
checkArgumentNotNull(getInstance().url, "URL must be specified");
|
||||
checkArgumentNotNull(getInstance().method, "HTTP method must be specified");
|
||||
checkArgumentNotNull(getInstance().type, "ConsoleUpdateHistory type must be specified");
|
||||
return super.build();
|
||||
}
|
||||
|
||||
public Builder setModificationTime(DateTime modificationTime) {
|
||||
getInstance().modificationTime = modificationTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setActingUser(User actingUser) {
|
||||
getInstance().actingUser = actingUser;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUrl(String url) {
|
||||
getInstance().url = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setMethod(String method) {
|
||||
getInstance().method = method;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDescription(String description) {
|
||||
getInstance().description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setType(ConsoleUpdateHistory.Type type) {
|
||||
getInstance().type = type;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright 2025 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.module;
|
||||
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.GaeService;
|
||||
import google.registry.request.Action.GkeService;
|
||||
import google.registry.request.auth.Auth;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
public class ReadinessProbeAction implements Runnable {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private final HttpServletResponse rsp;
|
||||
|
||||
public ReadinessProbeAction(HttpServletResponse rsp) {
|
||||
this.rsp = rsp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the readiness check.
|
||||
*
|
||||
* <p>Performs a simple database query and sets the HTTP response status to OK (200) upon
|
||||
* successful completion. Throws a runtime exception if the database query fails.
|
||||
*/
|
||||
@Override
|
||||
public final void run() {
|
||||
logger.atInfo().log("Performing readiness check database query...");
|
||||
try {
|
||||
tm().transact(() -> tm().query("SELECT version()", Void.class));
|
||||
rsp.setStatus(SC_OK);
|
||||
logger.atInfo().log("Readiness check successful.");
|
||||
} catch (Exception e) {
|
||||
logger.atWarning().withCause(e).log("Readiness check failed:");
|
||||
throw new RuntimeException("Readiness check failed during database query", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Action(
|
||||
service = GaeService.DEFAULT,
|
||||
gkeService = GkeService.CONSOLE,
|
||||
path = ReadinessProbeConsoleAction.PATH,
|
||||
auth = Auth.AUTH_PUBLIC)
|
||||
public static class ReadinessProbeConsoleAction extends ReadinessProbeAction {
|
||||
public static final String PATH = "/ready/console";
|
||||
|
||||
@Inject
|
||||
public ReadinessProbeConsoleAction(HttpServletResponse rsp) {
|
||||
super(rsp);
|
||||
}
|
||||
}
|
||||
|
||||
@Action(
|
||||
service = GaeService.PUBAPI,
|
||||
gkeService = GkeService.PUBAPI,
|
||||
path = ReadinessProbeActionPubApi.PATH,
|
||||
auth = Auth.AUTH_PUBLIC)
|
||||
public static class ReadinessProbeActionPubApi extends ReadinessProbeAction {
|
||||
public static final String PATH = "/ready/pubapi";
|
||||
|
||||
@Inject
|
||||
public ReadinessProbeActionPubApi(HttpServletResponse rsp) {
|
||||
super(rsp);
|
||||
}
|
||||
}
|
||||
|
||||
@Action(
|
||||
service = GaeService.DEFAULT,
|
||||
gkeService = GkeService.FRONTEND,
|
||||
path = ReadinessProbeActionFrontend.PATH,
|
||||
auth = Auth.AUTH_PUBLIC)
|
||||
public static final class ReadinessProbeActionFrontend extends ReadinessProbeAction {
|
||||
public static final String PATH = "/ready/frontend";
|
||||
|
||||
@Inject
|
||||
public ReadinessProbeActionFrontend(HttpServletResponse rsp) {
|
||||
super(rsp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,10 +58,14 @@ import google.registry.flows.TlsCredentials.EppTlsModule;
|
||||
import google.registry.flows.custom.CustomLogicModule;
|
||||
import google.registry.loadtest.LoadTestAction;
|
||||
import google.registry.loadtest.LoadTestModule;
|
||||
import google.registry.module.ReadinessProbeAction.ReadinessProbeActionFrontend;
|
||||
import google.registry.module.ReadinessProbeAction.ReadinessProbeActionPubApi;
|
||||
import google.registry.module.ReadinessProbeAction.ReadinessProbeConsoleAction;
|
||||
import google.registry.monitoring.whitebox.WhiteboxModule;
|
||||
import google.registry.rdap.RdapAutnumAction;
|
||||
import google.registry.rdap.RdapDomainAction;
|
||||
import google.registry.rdap.RdapDomainSearchAction;
|
||||
import google.registry.rdap.RdapEmptyAction;
|
||||
import google.registry.rdap.RdapEntityAction;
|
||||
import google.registry.rdap.RdapEntitySearchAction;
|
||||
import google.registry.rdap.RdapHelpAction;
|
||||
@@ -123,8 +127,8 @@ import google.registry.ui.server.console.ConsoleUsersAction;
|
||||
import google.registry.ui.server.console.RegistrarsAction;
|
||||
import google.registry.ui.server.console.domains.ConsoleBulkDomainAction;
|
||||
import google.registry.ui.server.console.settings.ContactAction;
|
||||
import google.registry.ui.server.console.settings.RdapRegistrarFieldsAction;
|
||||
import google.registry.ui.server.console.settings.SecurityAction;
|
||||
import google.registry.ui.server.console.settings.WhoisRegistrarFieldsAction;
|
||||
import google.registry.whois.WhoisAction;
|
||||
import google.registry.whois.WhoisHttpAction;
|
||||
import google.registry.whois.WhoisModule;
|
||||
@@ -255,12 +259,20 @@ interface RequestComponent {
|
||||
|
||||
PublishSpec11ReportAction publishSpec11ReportAction();
|
||||
|
||||
ReadinessProbeConsoleAction readinessProbeConsoleAction();
|
||||
|
||||
ReadinessProbeActionPubApi readinessProbeActionPubApi();
|
||||
|
||||
ReadinessProbeActionFrontend readinessProbeActionFrontend();
|
||||
|
||||
RdapAutnumAction rdapAutnumAction();
|
||||
|
||||
RdapDomainAction rdapDomainAction();
|
||||
|
||||
RdapDomainSearchAction rdapDomainSearchAction();
|
||||
|
||||
RdapEmptyAction rdapEmptyAction();
|
||||
|
||||
RdapEntityAction rdapEntityAction();
|
||||
|
||||
RdapEntitySearchAction rdapEntitySearchAction();
|
||||
@@ -325,7 +337,7 @@ interface RequestComponent {
|
||||
|
||||
WhoisHttpAction whoisHttpAction();
|
||||
|
||||
WhoisRegistrarFieldsAction whoisRegistrarFieldsAction();
|
||||
RdapRegistrarFieldsAction rdapRegistrarFieldsAction();
|
||||
|
||||
WipeOutContactHistoryPiiAction wipeOutContactHistoryPiiAction();
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ import google.registry.dns.DnsModule;
|
||||
import google.registry.flows.EppTlsAction;
|
||||
import google.registry.flows.FlowComponent;
|
||||
import google.registry.flows.TlsCredentials.EppTlsModule;
|
||||
import google.registry.module.ReadinessProbeAction.ReadinessProbeActionFrontend;
|
||||
import google.registry.module.ReadinessProbeAction.ReadinessProbeConsoleAction;
|
||||
import google.registry.monitoring.whitebox.WhiteboxModule;
|
||||
import google.registry.request.RequestComponentBuilder;
|
||||
import google.registry.request.RequestModule;
|
||||
@@ -39,8 +41,8 @@ import google.registry.ui.server.console.ConsoleUsersAction;
|
||||
import google.registry.ui.server.console.RegistrarsAction;
|
||||
import google.registry.ui.server.console.domains.ConsoleBulkDomainAction;
|
||||
import google.registry.ui.server.console.settings.ContactAction;
|
||||
import google.registry.ui.server.console.settings.RdapRegistrarFieldsAction;
|
||||
import google.registry.ui.server.console.settings.SecurityAction;
|
||||
import google.registry.ui.server.console.settings.WhoisRegistrarFieldsAction;
|
||||
|
||||
/** Dagger component with per-request lifetime for "default" App Engine module. */
|
||||
@RequestScope
|
||||
@@ -82,11 +84,15 @@ public interface FrontendRequestComponent {
|
||||
|
||||
FlowComponent.Builder flowComponentBuilder();
|
||||
|
||||
ReadinessProbeActionFrontend readinessProbeActionFrontend();
|
||||
|
||||
ReadinessProbeConsoleAction readinessProbeConsoleAction();
|
||||
|
||||
RegistrarsAction registrarsAction();
|
||||
|
||||
SecurityAction securityAction();
|
||||
|
||||
WhoisRegistrarFieldsAction whoisRegistrarFieldsAction();
|
||||
RdapRegistrarFieldsAction rdapRegistrarFieldsAction();
|
||||
|
||||
@Subcomponent.Builder
|
||||
abstract class Builder implements RequestComponentBuilder<FrontendRequestComponent> {
|
||||
|
||||
@@ -20,10 +20,12 @@ import google.registry.dns.DnsModule;
|
||||
import google.registry.flows.CheckApiAction;
|
||||
import google.registry.flows.CheckApiAction.CheckApiModule;
|
||||
import google.registry.flows.TlsCredentials.EppTlsModule;
|
||||
import google.registry.module.ReadinessProbeAction.ReadinessProbeActionPubApi;
|
||||
import google.registry.monitoring.whitebox.WhiteboxModule;
|
||||
import google.registry.rdap.RdapAutnumAction;
|
||||
import google.registry.rdap.RdapDomainAction;
|
||||
import google.registry.rdap.RdapDomainSearchAction;
|
||||
import google.registry.rdap.RdapEmptyAction;
|
||||
import google.registry.rdap.RdapEntityAction;
|
||||
import google.registry.rdap.RdapEntitySearchAction;
|
||||
import google.registry.rdap.RdapHelpAction;
|
||||
@@ -55,12 +57,16 @@ public interface PubApiRequestComponent {
|
||||
RdapAutnumAction rdapAutnumAction();
|
||||
RdapDomainAction rdapDomainAction();
|
||||
RdapDomainSearchAction rdapDomainSearchAction();
|
||||
RdapEmptyAction rdapEmptyAction();
|
||||
RdapEntityAction rdapEntityAction();
|
||||
RdapEntitySearchAction rdapEntitySearchAction();
|
||||
RdapHelpAction rdapHelpAction();
|
||||
RdapIpAction rdapDefaultAction();
|
||||
RdapNameserverAction rdapNameserverAction();
|
||||
RdapNameserverSearchAction rdapNameserverSearchAction();
|
||||
|
||||
ReadinessProbeActionPubApi readinessProbeActionPubApi();
|
||||
|
||||
WhoisHttpAction whoisHttpAction();
|
||||
WhoisAction whoisAction();
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ import org.joda.time.DateTime;
|
||||
public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private static final Retrier retrier = new Retrier(new SystemSleeper(), 3);
|
||||
private static final Retrier retrier = new Retrier(new SystemSleeper(), 6);
|
||||
private static final String NESTED_TRANSACTION_MESSAGE =
|
||||
"Nested transaction detected. Try refactoring to avoid nested transactions. If unachievable,"
|
||||
+ " use reTransact() in nested transactions";
|
||||
|
||||
54
core/src/main/java/google/registry/rdap/RdapEmptyAction.java
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2025 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.rdap;
|
||||
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.HEAD;
|
||||
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import jakarta.inject.Inject;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* RDAP action that serves the empty string, redirecting to the help page.
|
||||
*
|
||||
* <p>This isn't technically required, but if someone requests the base url it seems nice to give
|
||||
* them the help response.
|
||||
*/
|
||||
@Action(
|
||||
service = Action.GaeService.PUBAPI,
|
||||
path = "/rdap/",
|
||||
method = {GET, HEAD},
|
||||
auth = Auth.AUTH_PUBLIC)
|
||||
public class RdapEmptyAction implements Runnable {
|
||||
|
||||
private final Response response;
|
||||
|
||||
@Inject
|
||||
public RdapEmptyAction(Response response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
response.sendRedirect(RdapHelpAction.PATH);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,12 +31,14 @@ import java.util.Optional;
|
||||
/** RDAP (new WHOIS) action for help requests. */
|
||||
@Action(
|
||||
service = GaeService.PUBAPI,
|
||||
path = "/rdap/help",
|
||||
path = RdapHelpAction.PATH,
|
||||
method = {GET, HEAD},
|
||||
isPrefix = true,
|
||||
auth = Auth.AUTH_PUBLIC)
|
||||
public class RdapHelpAction extends RdapActionBase {
|
||||
|
||||
public static final String PATH = "/rdap/help";
|
||||
|
||||
/** The help path for the RDAP terms of service. */
|
||||
public static final String TOS_PATH = "/tos";
|
||||
|
||||
|
||||
@@ -85,9 +85,6 @@ public final class ActivityReportingQueryBuilder implements QueryBuilder {
|
||||
String monthlyLogsQuery =
|
||||
SqlTemplate.create(getQueryFromFile(MONTHLY_LOGS + ".sql"))
|
||||
.put("PROJECT_ID", projectId)
|
||||
.put("APPENGINE_LOGS_DATA_SET", "appengine_logs")
|
||||
.put("GKE_LOGS_DATA_SET", "gke_logs")
|
||||
.put("REQUEST_TABLE", "appengine_googleapis_com_request_log_")
|
||||
.put("FIRST_DAY_OF_MONTH", logTableFormatter.print(firstDayOfMonth))
|
||||
.put("LAST_DAY_OF_MONTH", logTableFormatter.print(lastDayOfMonth))
|
||||
.build();
|
||||
@@ -96,9 +93,6 @@ public final class ActivityReportingQueryBuilder implements QueryBuilder {
|
||||
String eppQuery =
|
||||
SqlTemplate.create(getQueryFromFile(EPP_METRICS + ".sql"))
|
||||
.put("PROJECT_ID", projectId)
|
||||
.put("APPENGINE_LOGS_DATA_SET", "appengine_logs")
|
||||
.put("GKE_LOGS_DATA_SET", "gke_logs")
|
||||
.put("APP_LOGS_TABLE", "_var_log_app_")
|
||||
.put("FIRST_DAY_OF_MONTH", logTableFormatter.print(firstDayOfMonth))
|
||||
.put("LAST_DAY_OF_MONTH", logTableFormatter.print(lastDayOfMonth))
|
||||
.build();
|
||||
|
||||
@@ -112,9 +112,6 @@ public final class TransactionsReportingQueryBuilder implements QueryBuilder {
|
||||
String attemptedAddsQuery =
|
||||
SqlTemplate.create(getQueryFromFile(ATTEMPTED_ADDS + ".sql"))
|
||||
.put("PROJECT_ID", projectId)
|
||||
.put("APPENGINE_LOGS_DATA_SET", "appengine_logs")
|
||||
.put("GKE_LOGS_DATA_SET", "gke_logs")
|
||||
.put("APP_LOGS_TABLE", "_var_log_app_")
|
||||
.put("FIRST_DAY_OF_MONTH", logTableFormatter.print(earliestReportTime))
|
||||
.put("LAST_DAY_OF_MONTH", logTableFormatter.print(latestReportTime))
|
||||
.build();
|
||||
|
||||
@@ -143,8 +143,11 @@ public class RequestHandler<C> {
|
||||
GkeService service = Action.ServiceGetter.get(route.get().action());
|
||||
String expectedDomain = RegistryConfig.getServiceUrl(service).getHost();
|
||||
String actualDomain = req.getServerName();
|
||||
// If the hostname is "localhost", it must have come from the sidecar proxy.
|
||||
if (!Objects.equals("localhost", actualDomain)
|
||||
// If the request doesn't come from GKE readiness prober
|
||||
String maybeUserAgent = Optional.ofNullable(req.getHeader("User-Agent")).orElse("");
|
||||
if (!maybeUserAgent.startsWith("kube-probe")
|
||||
// If the hostname is "localhost", it must have come from the sidecar proxy.
|
||||
&& !Objects.equals("localhost", actualDomain)
|
||||
&& !Objects.equals(actualDomain, expectedDomain)) {
|
||||
logger.atWarning().log(
|
||||
"Actual domain %s does not match expected domain %s", actualDomain, expectedDomain);
|
||||
|
||||
@@ -37,7 +37,7 @@ 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.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
@@ -262,7 +262,7 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
protected void finishAndPersistConsoleUpdateHistory(ConsoleUpdateHistory.Builder<?, ?> builder) {
|
||||
protected void finishAndPersistConsoleUpdateHistory(SimpleConsoleUpdateHistory.Builder builder) {
|
||||
builder.setActingUser(consoleApiParams.authResult().user().get());
|
||||
builder.setUrl(consoleApiParams.request().getRequestURI());
|
||||
builder.setMethod(consoleApiParams.request().getMethod());
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.google.gson.annotations.Expose;
|
||||
import google.registry.flows.EppException.AuthenticationErrorException;
|
||||
import google.registry.flows.PasswordOnlyTransportCredentials;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.request.Action;
|
||||
@@ -107,14 +107,10 @@ public class ConsoleEppPasswordAction extends ConsoleApiAction {
|
||||
Registrar updatedRegistrar =
|
||||
registrar.asBuilder().setPassword(eppRequestBody.newPassword()).build();
|
||||
tm().put(updatedRegistrar);
|
||||
EppPasswordData sanitizedData =
|
||||
new EppPasswordData(
|
||||
eppRequestBody.registrarId, "********", "••••••••", "••••••••");
|
||||
finishAndPersistConsoleUpdateHistory(
|
||||
new RegistrarUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
|
||||
.setRegistrar(updatedRegistrar)
|
||||
.setRequestBody(consoleApiParams.gson().toJson(sanitizedData)));
|
||||
new SimpleConsoleUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.EPP_PASSWORD_UPDATE)
|
||||
.setDescription(registrar.getRegistrarId()));
|
||||
sendExternalUpdates(
|
||||
ImmutableMap.of("password", new DiffUtils.DiffPair("********", "••••••••")),
|
||||
registrar,
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.request.Action;
|
||||
@@ -102,10 +102,9 @@ public class ConsoleUpdateRegistrarAction extends ConsoleApiAction {
|
||||
|
||||
tm().put(updatedRegistrar);
|
||||
finishAndPersistConsoleUpdateHistory(
|
||||
new RegistrarUpdateHistory.Builder()
|
||||
new SimpleConsoleUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
|
||||
.setRegistrar(updatedRegistrar)
|
||||
.setRequestBody(consoleApiParams.gson().toJson(registrarParam)));
|
||||
.setDescription(updatedRegistrar.getRegistrarId()));
|
||||
sendExternalUpdatesIfNecessary(
|
||||
EmailInfo.create(
|
||||
existingRegistrar.get(),
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarBase;
|
||||
@@ -174,10 +174,9 @@ public class RegistrarsAction extends ConsoleApiAction {
|
||||
registrar.getRegistrarId());
|
||||
tm().putAll(registrar, contact);
|
||||
finishAndPersistConsoleUpdateHistory(
|
||||
new RegistrarUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
|
||||
.setRegistrar(registrar)
|
||||
.setRequestBody(consoleApiParams.gson().toJson(registrar)));
|
||||
new SimpleConsoleUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.REGISTRAR_CREATE)
|
||||
.setDescription(registrar.getRegistrarId()));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.ui.server.console.domains;
|
||||
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
@@ -25,6 +26,7 @@ import google.registry.flows.EppController;
|
||||
import google.registry.flows.EppRequestSource;
|
||||
import google.registry.flows.PasswordOnlyTransportCredentials;
|
||||
import google.registry.flows.StatelessRequestSessionMetadata;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.eppcommon.ProtocolDefinition;
|
||||
import google.registry.model.eppoutput.EppOutput;
|
||||
@@ -93,11 +95,29 @@ public class ConsoleBulkDomainAction extends ConsoleApiAction {
|
||||
domainList.domainList.stream()
|
||||
.collect(
|
||||
toImmutableMap(d -> d, d -> executeEpp(actionType.getXmlContentsToRun(d), user)));
|
||||
handleHistoryAdditions(result, actionType);
|
||||
// Front end should parse situations where only some commands worked
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(result));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
private void handleHistoryAdditions(
|
||||
ImmutableMap<String, ConsoleEppOutput> result, ConsoleDomainActionType actionType) {
|
||||
if (result.values().stream().noneMatch(ConsoleEppOutput::isSuccess)) {
|
||||
return;
|
||||
}
|
||||
tm().transact(
|
||||
() ->
|
||||
result.entrySet().stream()
|
||||
.filter(e -> e.getValue().isSuccess())
|
||||
.forEach(
|
||||
e ->
|
||||
finishAndPersistConsoleUpdateHistory(
|
||||
new SimpleConsoleUpdateHistory.Builder()
|
||||
.setDescription(e.getKey())
|
||||
.setType(actionType.getConsoleUpdateHistoryType()))));
|
||||
}
|
||||
|
||||
private ConsoleEppOutput executeEpp(String xml, User user) {
|
||||
return ConsoleEppOutput.fromEppOutput(
|
||||
eppController.handleEppCommand(
|
||||
@@ -115,5 +135,9 @@ public class ConsoleBulkDomainAction extends ConsoleApiAction {
|
||||
Result result = eppOutput.getResponse().getResult();
|
||||
return new ConsoleEppOutput(result.getMsg(), result.getCode().code);
|
||||
}
|
||||
|
||||
boolean isSuccess() {
|
||||
return responseCode < 2000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.ui.server.console.domains;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
|
||||
/** An action that will run a delete EPP command on the given domain. */
|
||||
public class ConsoleBulkDomainDeleteActionType extends ConsoleDomainActionType {
|
||||
@@ -54,4 +55,9 @@ public class ConsoleBulkDomainDeleteActionType extends ConsoleDomainActionType {
|
||||
public ConsolePermission getNecessaryPermission() {
|
||||
return ConsolePermission.EXECUTE_EPP_COMMANDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConsoleUpdateHistory.Type getConsoleUpdateHistoryType() {
|
||||
return ConsoleUpdateHistory.Type.DOMAIN_DELETE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.ui.server.console.domains;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
|
||||
/** An action that will suspend the given domain, assigning all 5 server*Prohibited statuses. */
|
||||
public class ConsoleBulkDomainSuspendActionType extends ConsoleDomainActionType {
|
||||
@@ -64,4 +65,9 @@ public class ConsoleBulkDomainSuspendActionType extends ConsoleDomainActionType
|
||||
public ConsolePermission getNecessaryPermission() {
|
||||
return ConsolePermission.SUSPEND_DOMAIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConsoleUpdateHistory.Type getConsoleUpdateHistoryType() {
|
||||
return ConsoleUpdateHistory.Type.DOMAIN_SUSPEND;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.ui.server.console.domains;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
|
||||
/** An action that will unsuspend the given domain, removing all 5 server*Prohibited statuses. */
|
||||
public class ConsoleBulkDomainUnsuspendActionType extends ConsoleDomainActionType {
|
||||
@@ -64,4 +65,9 @@ public class ConsoleBulkDomainUnsuspendActionType extends ConsoleDomainActionTyp
|
||||
public ConsolePermission getNecessaryPermission() {
|
||||
return ConsolePermission.SUSPEND_DOMAIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConsoleUpdateHistory.Type getConsoleUpdateHistoryType() {
|
||||
return ConsoleUpdateHistory.Type.DOMAIN_UNSUSPEND;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.google.common.escape.Escaper;
|
||||
import com.google.common.xml.XmlEscapers;
|
||||
import com.google.gson.JsonElement;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
|
||||
/**
|
||||
* A type of EPP action to perform on domain(s), run by the {@link ConsoleBulkDomainAction}.
|
||||
@@ -68,6 +69,9 @@ public abstract class ConsoleDomainActionType {
|
||||
/** Returns the permission necessary to successfully perform this action. */
|
||||
public abstract ConsolePermission getNecessaryPermission();
|
||||
|
||||
/** Returns the type of history / audit logging object to save. */
|
||||
public abstract ConsoleUpdateHistory.Type getConsoleUpdateHistoryType();
|
||||
|
||||
/** Returns the XML template contents for this action. */
|
||||
protected abstract String getXmlTemplate();
|
||||
|
||||
|
||||
@@ -17,13 +17,12 @@ package google.registry.ui.server.console.settings;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.request.Action;
|
||||
@@ -36,7 +35,6 @@ import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAcce
|
||||
import google.registry.ui.server.console.ConsoleApiAction;
|
||||
import google.registry.ui.server.console.ConsoleApiParams;
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -48,17 +46,17 @@ import java.util.Optional;
|
||||
@Action(
|
||||
service = GaeService.DEFAULT,
|
||||
gkeService = GkeService.CONSOLE,
|
||||
path = WhoisRegistrarFieldsAction.PATH,
|
||||
path = RdapRegistrarFieldsAction.PATH,
|
||||
method = {POST},
|
||||
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
||||
public class WhoisRegistrarFieldsAction extends ConsoleApiAction {
|
||||
public class RdapRegistrarFieldsAction extends ConsoleApiAction {
|
||||
|
||||
static final String PATH = "/console-api/settings/whois-fields";
|
||||
static final String PATH = "/console-api/settings/rdap-fields";
|
||||
private final AuthenticatedRegistrarAccessor registrarAccessor;
|
||||
private final Optional<Registrar> registrar;
|
||||
|
||||
@Inject
|
||||
public WhoisRegistrarFieldsAction(
|
||||
public RdapRegistrarFieldsAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
AuthenticatedRegistrarAccessor registrarAccessor,
|
||||
@Parameter("registrar") Optional<Registrar> registrar) {
|
||||
@@ -72,10 +70,10 @@ public class WhoisRegistrarFieldsAction extends ConsoleApiAction {
|
||||
checkArgument(registrar.isPresent(), "'registrar' parameter is not present");
|
||||
checkPermission(
|
||||
user, registrar.get().getRegistrarId(), ConsolePermission.EDIT_REGISTRAR_DETAILS);
|
||||
tm().transact(() -> loadAndModifyRegistrar(registrar.get(), user));
|
||||
tm().transact(() -> loadAndModifyRegistrar(registrar.get()));
|
||||
}
|
||||
|
||||
private void loadAndModifyRegistrar(Registrar providedRegistrar, User user) {
|
||||
private void loadAndModifyRegistrar(Registrar providedRegistrar) {
|
||||
Registrar savedRegistrar;
|
||||
try {
|
||||
// reload to make sure the object has all the correct fields
|
||||
@@ -85,32 +83,19 @@ public class WhoisRegistrarFieldsAction extends ConsoleApiAction {
|
||||
return;
|
||||
}
|
||||
|
||||
// icannReferralEmail can't be updated by partners, only by global users with
|
||||
// EDIT_REGISTRAR_DETAILS permission
|
||||
if (!Objects.equals(
|
||||
savedRegistrar.getIcannReferralEmail(), providedRegistrar.getIcannReferralEmail())
|
||||
&& !user.getUserRoles().hasGlobalPermission(ConsolePermission.EDIT_REGISTRAR_DETAILS)) {
|
||||
setFailedResponse(
|
||||
"Icann Referral Email update is not permitted for this user", SC_BAD_REQUEST);
|
||||
}
|
||||
|
||||
Registrar newRegistrar =
|
||||
savedRegistrar
|
||||
.asBuilder()
|
||||
.setWhoisServer(providedRegistrar.getWhoisServer())
|
||||
.setUrl(providedRegistrar.getUrl())
|
||||
.setLocalizedAddress(providedRegistrar.getLocalizedAddress())
|
||||
.setPhoneNumber(providedRegistrar.getPhoneNumber())
|
||||
.setFaxNumber(providedRegistrar.getFaxNumber())
|
||||
.setIcannReferralEmail(providedRegistrar.getIcannReferralEmail())
|
||||
.setEmailAddress(providedRegistrar.getEmailAddress())
|
||||
.build();
|
||||
tm().put(newRegistrar);
|
||||
finishAndPersistConsoleUpdateHistory(
|
||||
new RegistrarUpdateHistory.Builder()
|
||||
new SimpleConsoleUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
|
||||
.setRegistrar(newRegistrar)
|
||||
.setRequestBody(consoleApiParams.gson().toJson(registrar.get())));
|
||||
.setDescription(newRegistrar.getRegistrarId()));
|
||||
sendExternalUpdatesIfNecessary(
|
||||
EmailInfo.create(
|
||||
savedRegistrar,
|
||||
@@ -26,7 +26,7 @@ import google.registry.flows.certs.CertificateChecker;
|
||||
import google.registry.flows.certs.CertificateChecker.InsecureCertificateException;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.request.Action;
|
||||
@@ -120,10 +120,9 @@ public class SecurityAction extends ConsoleApiAction {
|
||||
Registrar updatedRegistrar = updatedRegistrarBuilder.build();
|
||||
tm().put(updatedRegistrar);
|
||||
finishAndPersistConsoleUpdateHistory(
|
||||
new RegistrarUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
|
||||
.setRegistrar(updatedRegistrar)
|
||||
.setRequestBody(consoleApiParams.gson().toJson(registrar.get())));
|
||||
new SimpleConsoleUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.REGISTRAR_SECURITY_UPDATE)
|
||||
.setDescription(registrarId));
|
||||
|
||||
sendExternalUpdatesIfNecessary(
|
||||
EmailInfo.create(savedRegistrar, updatedRegistrar, ImmutableSet.of(), ImmutableSet.of()));
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
<class>google.registry.model.console.ConsoleEppActionHistory</class>
|
||||
<class>google.registry.model.console.RegistrarPocUpdateHistory</class>
|
||||
<class>google.registry.model.console.RegistrarUpdateHistory</class>
|
||||
<class>google.registry.model.console.SimpleConsoleUpdateHistory</class>
|
||||
<class>google.registry.model.console.User</class>
|
||||
<class>google.registry.model.console.UserUpdateHistory</class>
|
||||
<class>google.registry.model.contact.ContactHistory</class>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
-- Determine the number of attempted adds each registrar made.
|
||||
|
||||
-- Since the specification requests all 'attempted' adds, we regex the
|
||||
-- monthly App Engine logs, searching for all create commands and associating
|
||||
-- monthly GKE logs, searching for all create commands and associating
|
||||
-- them with their corresponding registrars.
|
||||
|
||||
-- Example log generated by FlowReporter in App Engine and GKE logs:
|
||||
@@ -27,7 +27,7 @@
|
||||
-- ,"targetId":"","targetIds":[],"tld":"",
|
||||
-- "tlds":[],"icannActivityReportField":""}
|
||||
|
||||
-- This outer select just converts the registrar's clientId to their name.
|
||||
-- This outer select just converts the registrar's ID to their name.
|
||||
SELECT
|
||||
tld,
|
||||
registrar_table.registrar_name AS registrar_name,
|
||||
@@ -38,34 +38,20 @@ FROM (
|
||||
JSON_EXTRACT_SCALAR(json, '$.tld') AS tld,
|
||||
JSON_EXTRACT_SCALAR(json, '$.clientId') AS clientId,
|
||||
COUNT(json) AS count
|
||||
FROM ((
|
||||
-- Extract JSON metadata package from monthly logs
|
||||
FROM (
|
||||
-- Extract JSON metadata package from monthly logs
|
||||
SELECT
|
||||
REGEXP_EXTRACT(textPayload, r'FLOW-LOG-SIGNATURE-METADATA: (.*)\n?$') AS json
|
||||
REGEXP_EXTRACT(jsonPayload.message, r'FLOW-LOG-SIGNATURE-METADATA: (.*)\n?$') AS json
|
||||
FROM
|
||||
`%PROJECT_ID%.%APPENGINE_LOGS_DATA_SET%.%APP_LOGS_TABLE%*`
|
||||
`%PROJECT_ID%.gke_logs.stderr_*`
|
||||
WHERE
|
||||
_TABLE_SUFFIX BETWEEN '%FIRST_DAY_OF_MONTH%'
|
||||
AND '%LAST_DAY_OF_MONTH%'
|
||||
AND STARTS_WITH(textPayload, "FLOW-LOG-SIGNATURE-METADATA")
|
||||
AND STARTS_WITH(jsonPayload.message, "FLOW-LOG-SIGNATURE-METADATA")
|
||||
-- Look for domain creates
|
||||
AND REGEXP_CONTAINS(textPayload, r'"commandType":"create","resourceType":"domain"')
|
||||
AND REGEXP_CONTAINS(jsonPayload.message, r'"commandType":"create","resourceType":"domain"')
|
||||
-- Filter prober data
|
||||
AND NOT REGEXP_CONTAINS(textPayload, r'"prober-[a-z]{2}-((any)|(canary))"'))
|
||||
UNION ALL (
|
||||
-- Extract JSON metadata package from monthly logs
|
||||
SELECT
|
||||
REGEXP_EXTRACT(jsonPayload.message, r'FLOW-LOG-SIGNATURE-METADATA: (.*)\n?$') AS json
|
||||
FROM
|
||||
`%PROJECT_ID%.%GKE_LOGS_DATA_SET%.stderr_*`
|
||||
WHERE
|
||||
_TABLE_SUFFIX BETWEEN '%FIRST_DAY_OF_MONTH%'
|
||||
AND '%LAST_DAY_OF_MONTH%'
|
||||
AND STARTS_WITH(jsonPayload.message, "FLOW-LOG-SIGNATURE-METADATA")
|
||||
-- Look for domain creates
|
||||
AND REGEXP_CONTAINS(jsonPayload.message, r'"commandType":"create","resourceType":"domain"')
|
||||
-- Filter prober data
|
||||
AND NOT REGEXP_CONTAINS(jsonPayload.message, r'"prober-[a-z]{2}-((any)|(canary))"')))
|
||||
AND NOT REGEXP_CONTAINS(jsonPayload.message, r'"prober-[a-z]{2}-((any)|(canary))"'))
|
||||
GROUP BY
|
||||
tld,
|
||||
clientId ) AS logs_table
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
-- Query FlowReporter JSON log messages and calculate SRS metrics.
|
||||
|
||||
-- We use ugly regex's over the monthly appengine logs to determine how many
|
||||
-- We use ugly regexes over the monthly GKE logs to determine how many
|
||||
-- EPP requests we received for each command. For example:
|
||||
-- {"commandType":"check"...,"targetIds":["ais.a.how"],
|
||||
-- "tld":"","tlds":["a.how"],"icannActivityReportField":"srs-dom-check"}
|
||||
@@ -35,30 +35,15 @@ FROM (
|
||||
JSON_EXTRACT_SCALAR(json,
|
||||
'$.icannActivityReportField') AS activityReportField
|
||||
FROM (
|
||||
-- For reasons that I don't understand, if I directly select the three columns
|
||||
-- from the union, BigQuery complains about column number mismatch, so I have to
|
||||
-- make a temporary union table and select on it.
|
||||
SELECT
|
||||
*
|
||||
FROM (
|
||||
SELECT
|
||||
-- Extract the logged JSON payload.
|
||||
REGEXP_EXTRACT(textPayload, r'FLOW-LOG-SIGNATURE-METADATA: (.*)\n?$')
|
||||
AS json
|
||||
FROM `%PROJECT_ID%.%APPENGINE_LOGS_DATA_SET%.%APP_LOGS_TABLE%*`
|
||||
WHERE
|
||||
STARTS_WITH(textPayload, "FLOW-LOG-SIGNATURE-METADATA")
|
||||
AND _TABLE_SUFFIX BETWEEN '%FIRST_DAY_OF_MONTH%' AND '%LAST_DAY_OF_MONTH%')
|
||||
UNION ALL (
|
||||
SELECT
|
||||
-- Extract the logged JSON payload.
|
||||
REGEXP_EXTRACT(jsonPayload.message, r'FLOW-LOG-SIGNATURE-METADATA: (.*)\n?$')
|
||||
AS json
|
||||
FROM `%PROJECT_ID%.%GKE_LOGS_DATA_SET%.stderr_*`
|
||||
WHERE
|
||||
STARTS_WITH(jsonPayload.message, "FLOW-LOG-SIGNATURE-METADATA")
|
||||
AND _TABLE_SUFFIX BETWEEN '%FIRST_DAY_OF_MONTH%' AND '%LAST_DAY_OF_MONTH%')
|
||||
)) AS regexes
|
||||
-- Extract the logged JSON payload.
|
||||
REGEXP_EXTRACT(jsonPayload.message, r'FLOW-LOG-SIGNATURE-METADATA: (.*)\n?$')
|
||||
AS json
|
||||
FROM `%PROJECT_ID%.gke_logs.stderr_*`
|
||||
WHERE
|
||||
STARTS_WITH(jsonPayload.message, "FLOW-LOG-SIGNATURE-METADATA")
|
||||
AND _TABLE_SUFFIX BETWEEN '%FIRST_DAY_OF_MONTH%' AND '%LAST_DAY_OF_MONTH%')
|
||||
) AS regexes
|
||||
JOIN
|
||||
-- Unnest the JSON-parsed tlds.
|
||||
UNNEST(regexes.tlds) AS tld
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
-- See the License for the specific language governing permissions and
|
||||
-- limitations under the License.
|
||||
|
||||
-- Query to fetch AppEngine and GKE request logs for the report month.
|
||||
-- Query to fetch GKE request logs for the report month.
|
||||
|
||||
-- START_OF_MONTH and END_OF_MONTH should be in YYYYMM01 format.
|
||||
|
||||
@@ -23,13 +23,6 @@ FROM (
|
||||
SELECT
|
||||
jsonPayload.httrequest.requesturl AS requestPath
|
||||
FROM
|
||||
`%PROJECT_ID%.%GKE_LOGS_DATA_SET%.stderr_*`
|
||||
WHERE
|
||||
_TABLE_SUFFIX BETWEEN '%FIRST_DAY_OF_MONTH%' AND '%LAST_DAY_OF_MONTH%')
|
||||
UNION ALL (
|
||||
SELECT
|
||||
protoPayload.resource AS requestPath
|
||||
FROM
|
||||
`%PROJECT_ID%.%APPENGINE_LOGS_DATA_SET%.%REQUEST_TABLE%*`
|
||||
`%PROJECT_ID%.gke_logs.stderr_*`
|
||||
WHERE
|
||||
_TABLE_SUFFIX BETWEEN '%FIRST_DAY_OF_MONTH%' AND '%LAST_DAY_OF_MONTH%')
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
package google.registry.export;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.export.ExportDomainListsAction.REGISTERED_DOMAINS_FILENAME;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.ACTIVE;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.INACTIVE;
|
||||
@@ -83,10 +82,11 @@ class ExportDomainListsActionTest {
|
||||
persistFeatureFlag(INACTIVE);
|
||||
}
|
||||
|
||||
private void verifyExportedToDrive(String folderId, String domains) throws Exception {
|
||||
private void verifyExportedToDrive(String folderId, String filename, String domains)
|
||||
throws Exception {
|
||||
verify(driveConnection)
|
||||
.createOrUpdateFile(
|
||||
eq(REGISTERED_DOMAINS_FILENAME),
|
||||
eq(filename),
|
||||
eq(MediaType.PLAIN_TEXT_UTF_8),
|
||||
eq(folderId),
|
||||
bytesExportedToDrive.capture());
|
||||
@@ -103,7 +103,7 @@ class ExportDomainListsActionTest {
|
||||
String tlds = new String(gcsUtils.readBytesFrom(existingFile), UTF_8);
|
||||
// Check that it only contains the active domains, not the dead one.
|
||||
assertThat(tlds).isEqualTo("onetwo.tld\nrudnitzky.tld");
|
||||
verifyExportedToDrive("brouhaha", "onetwo.tld\nrudnitzky.tld");
|
||||
verifyExportedToDrive("brouhaha", "registered_domains_tld.txt", "onetwo.tld\nrudnitzky.tld");
|
||||
verifyNoMoreInteractions(driveConnection);
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ class ExportDomainListsActionTest {
|
||||
String tlds = new String(gcsUtils.readBytesFrom(existingFile), UTF_8);
|
||||
// Check that it only contains the active domains, not the dead one.
|
||||
assertThat(tlds).isEqualTo("onetwo.tld,\nrudnitzky.tld,");
|
||||
verifyExportedToDrive("brouhaha", "onetwo.tld,\nrudnitzky.tld,");
|
||||
verifyExportedToDrive("brouhaha", "registered_domains_tld.txt", "onetwo.tld,\nrudnitzky.tld,");
|
||||
verifyNoMoreInteractions(driveConnection);
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ class ExportDomainListsActionTest {
|
||||
assertThrows(StorageException.class, () -> gcsUtils.readBytesFrom(nonexistentFile));
|
||||
ImmutableList<String> ls = gcsUtils.listFolderObjects("outputbucket", "");
|
||||
assertThat(ls).containsExactly("tld.txt");
|
||||
verifyExportedToDrive("brouhaha", "onetwo.tld\nrudnitzky.tld");
|
||||
verifyExportedToDrive("brouhaha", "registered_domains_tld.txt", "onetwo.tld\nrudnitzky.tld");
|
||||
verifyNoMoreInteractions(driveConnection);
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ class ExportDomainListsActionTest {
|
||||
assertThrows(StorageException.class, () -> gcsUtils.readBytesFrom(nonexistentFile));
|
||||
ImmutableList<String> ls = gcsUtils.listFolderObjects("outputbucket", "");
|
||||
assertThat(ls).containsExactly("tld.txt");
|
||||
verifyExportedToDrive("brouhaha", "onetwo.tld,\nrudnitzky.tld,");
|
||||
verifyExportedToDrive("brouhaha", "registered_domains_tld.txt", "onetwo.tld,\nrudnitzky.tld,");
|
||||
verifyNoMoreInteractions(driveConnection);
|
||||
}
|
||||
|
||||
@@ -189,7 +189,9 @@ class ExportDomainListsActionTest {
|
||||
action.run();
|
||||
|
||||
verifyExportedToDrive(
|
||||
"brouhaha", "active.tld,\npendingdelete.tld,2020-02-05T02:02:02.000Z\nredemption.tld,");
|
||||
"brouhaha",
|
||||
"registered_domains_tld.txt",
|
||||
"active.tld,\npendingdelete.tld,2020-02-05T02:02:02.000Z\nredemption.tld,");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -215,8 +217,9 @@ class ExportDomainListsActionTest {
|
||||
BlobId thirdTldFile = BlobId.of("outputbucket", "tldthree.txt");
|
||||
String evenMoreTlds = new String(gcsUtils.readBytesFrom(thirdTldFile), UTF_8).trim();
|
||||
assertThat(evenMoreTlds).isEqualTo("cupid.tldthree");
|
||||
verifyExportedToDrive("brouhaha", "dasher.tld\nprancer.tld");
|
||||
verifyExportedToDrive("hooray", "buddy.tldtwo\nrudolph.tldtwo\nsanta.tldtwo");
|
||||
verifyExportedToDrive("brouhaha", "registered_domains_tld.txt", "dasher.tld\nprancer.tld");
|
||||
verifyExportedToDrive(
|
||||
"hooray", "registered_domains_tldtwo.txt", "buddy.tldtwo\nrudolph.tldtwo\nsanta.tldtwo");
|
||||
// tldthree does not have a drive id, so no export to drive is performed.
|
||||
verifyNoMoreInteractions(driveConnection);
|
||||
}
|
||||
@@ -245,8 +248,9 @@ class ExportDomainListsActionTest {
|
||||
BlobId thirdTldFile = BlobId.of("outputbucket", "tldthree.txt");
|
||||
String evenMoreTlds = new String(gcsUtils.readBytesFrom(thirdTldFile), UTF_8).trim();
|
||||
assertThat(evenMoreTlds).isEqualTo("cupid.tldthree,");
|
||||
verifyExportedToDrive("brouhaha", "dasher.tld,\nprancer.tld,");
|
||||
verifyExportedToDrive("hooray", "buddy.tldtwo,\nrudolph.tldtwo,\nsanta.tldtwo,");
|
||||
verifyExportedToDrive("brouhaha", "registered_domains_tld.txt", "dasher.tld,\nprancer.tld,");
|
||||
verifyExportedToDrive(
|
||||
"hooray", "registered_domains_tldtwo.txt", "buddy.tldtwo,\nrudolph.tldtwo,\nsanta.tldtwo,");
|
||||
// tldthree does not have a drive id, so no export to drive is performed.
|
||||
verifyNoMoreInteractions(driveConnection);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ package google.registry.export;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.export.ExportReservedTermsAction.EXPORT_MIME_TYPE;
|
||||
import static google.registry.export.ExportReservedTermsAction.RESERVED_TERMS_FILENAME;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.persistReservedList;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
@@ -77,7 +76,7 @@ public class ExportReservedTermsActionTest {
|
||||
runAction("tld");
|
||||
byte[] expected = "# This is a disclaimer.\ncat\nlol\n".getBytes(UTF_8);
|
||||
verify(driveConnection)
|
||||
.createOrUpdateFile(RESERVED_TERMS_FILENAME, EXPORT_MIME_TYPE, "brouhaha", expected);
|
||||
.createOrUpdateFile("reserved_terms_tld.txt", EXPORT_MIME_TYPE, "brouhaha", expected);
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
assertThat(response.getPayload()).isEqualTo("1001");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
// Copyright 2025 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.flows;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.flows.CookieSessionMetadata.COOKIE_NAME;
|
||||
import static google.registry.flows.CookieSessionMetadata.decode;
|
||||
import static google.registry.flows.CookieSessionMetadata.encode;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link CookieSessionMetadata}. */
|
||||
public class CookieSessionMetadataTest {
|
||||
|
||||
private HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
private FakeResponse response = new FakeResponse();
|
||||
private CookieSessionMetadata cookieSessionMetadata = new CookieSessionMetadata(request);
|
||||
|
||||
@Test
|
||||
void testNoCookie() {
|
||||
assertThat(cookieSessionMetadata.getRegistrarId()).isNull();
|
||||
assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(0);
|
||||
assertThat(cookieSessionMetadata.getServiceExtensionUris()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCookieWithAllFields() {
|
||||
when(request.getHeader("Cookie"))
|
||||
.thenReturn(
|
||||
"THIS_COOKIE=foo; SESSION_INFO="
|
||||
+ encode(
|
||||
"CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, "
|
||||
+ " serviceExtensionUris=A|B|C}")
|
||||
+ "; THAT_COOKIE=bar");
|
||||
cookieSessionMetadata = new CookieSessionMetadata(request);
|
||||
assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar");
|
||||
assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5);
|
||||
assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("A", "B", "C");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCookieWithNullRegistrar() {
|
||||
when(request.getHeader("Cookie"))
|
||||
.thenReturn(
|
||||
"SESSION_INFO="
|
||||
+ encode(
|
||||
"CookieSessionMetadata{clientId=null, failedLoginAttempts=5, "
|
||||
+ " serviceExtensionUris=A|B|C}"));
|
||||
cookieSessionMetadata = new CookieSessionMetadata(request);
|
||||
assertThat(cookieSessionMetadata.getRegistrarId()).isNull();
|
||||
assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5);
|
||||
assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("A", "B", "C");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCookieWithEmptyExtension() {
|
||||
when(request.getHeader("Cookie"))
|
||||
.thenReturn(
|
||||
"SESSION_INFO="
|
||||
+ encode(
|
||||
"CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, "
|
||||
+ " serviceExtensionUris=}"));
|
||||
cookieSessionMetadata = new CookieSessionMetadata(request);
|
||||
assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar");
|
||||
assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5);
|
||||
assertThat(cookieSessionMetadata.getServiceExtensionUris()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCookieWithSingleExtension() {
|
||||
when(request.getHeader("Cookie"))
|
||||
.thenReturn(
|
||||
"SESSION_INFO="
|
||||
+ encode(
|
||||
"CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, "
|
||||
+ " serviceExtensionUris=Foo}"));
|
||||
cookieSessionMetadata = new CookieSessionMetadata(request);
|
||||
assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar");
|
||||
assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5);
|
||||
assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("Foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIncrementFailedLoginAttempts() {
|
||||
when(request.getHeader("Cookie"))
|
||||
.thenReturn(
|
||||
"SESSION_INFO="
|
||||
+ encode(
|
||||
"CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, "
|
||||
+ " serviceExtensionUris=Foo}"));
|
||||
cookieSessionMetadata = new CookieSessionMetadata(request);
|
||||
cookieSessionMetadata.incrementFailedLoginAttempts();
|
||||
assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar");
|
||||
assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(6);
|
||||
assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("Foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testResetFailedLoginAttempts() {
|
||||
when(request.getHeader("Cookie"))
|
||||
.thenReturn(
|
||||
"SESSION_INFO="
|
||||
+ encode(
|
||||
"CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, "
|
||||
+ " serviceExtensionUris=Foo}"));
|
||||
cookieSessionMetadata = new CookieSessionMetadata(request);
|
||||
cookieSessionMetadata.resetFailedLoginAttempts();
|
||||
assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar");
|
||||
assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(0);
|
||||
assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("Foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetRegistrarId() {
|
||||
when(request.getHeader("Cookie"))
|
||||
.thenReturn(
|
||||
"SESSION_INFO="
|
||||
+ encode(
|
||||
"CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, "
|
||||
+ " serviceExtensionUris=Foo}"));
|
||||
cookieSessionMetadata = new CookieSessionMetadata(request);
|
||||
cookieSessionMetadata.setRegistrarId("new_registrar");
|
||||
assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("new_registrar");
|
||||
assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5);
|
||||
assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("Foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetExtensions() {
|
||||
when(request.getHeader("Cookie"))
|
||||
.thenReturn(
|
||||
"SESSION_INFO="
|
||||
+ encode(
|
||||
"CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, "
|
||||
+ " serviceExtensionUris=Foo}"));
|
||||
cookieSessionMetadata = new CookieSessionMetadata(request);
|
||||
cookieSessionMetadata.setServiceExtensionUris(ImmutableSet.of("Bar", "Baz", "foo:bar:baz-1.3"));
|
||||
assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar");
|
||||
assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5);
|
||||
assertThat(cookieSessionMetadata.getServiceExtensionUris())
|
||||
.containsExactly("Bar", "Baz", "foo:bar:baz-1.3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetEmptyExtensions() {
|
||||
when(request.getHeader("Cookie"))
|
||||
.thenReturn(
|
||||
"SESSION_INFO="
|
||||
+ encode(
|
||||
"CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, "
|
||||
+ " serviceExtensionUris=Foo}"));
|
||||
cookieSessionMetadata = new CookieSessionMetadata(request);
|
||||
cookieSessionMetadata.setServiceExtensionUris(ImmutableSet.of());
|
||||
assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar");
|
||||
assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5);
|
||||
assertThat(cookieSessionMetadata.getServiceExtensionUris()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidate() {
|
||||
when(request.getHeader("Cookie"))
|
||||
.thenReturn(
|
||||
"SESSION_INFO="
|
||||
+ encode(
|
||||
"CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, "
|
||||
+ " serviceExtensionUris=Foo}"));
|
||||
cookieSessionMetadata = new CookieSessionMetadata(request);
|
||||
cookieSessionMetadata.invalidate();
|
||||
assertThat(cookieSessionMetadata.getRegistrarId()).isNull();
|
||||
assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(0);
|
||||
assertThat(cookieSessionMetadata.getServiceExtensionUris()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSave() {
|
||||
cookieSessionMetadata.save(response);
|
||||
String value =
|
||||
decode(
|
||||
response.getHeaders().get("Set-Cookie").toString().substring(COOKIE_NAME.length() + 1));
|
||||
assertThat(value)
|
||||
.isEqualTo(
|
||||
"CookieSessionMetadata{clientId=null, failedLoginAttempts=0, serviceExtensionUris=}");
|
||||
cookieSessionMetadata.setRegistrarId("new_registrar");
|
||||
cookieSessionMetadata.setServiceExtensionUris(ImmutableSet.of("Bar", "Baz"));
|
||||
cookieSessionMetadata.incrementFailedLoginAttempts();
|
||||
cookieSessionMetadata.save(response);
|
||||
value =
|
||||
decode(
|
||||
response.getHeaders().get("Set-Cookie").toString().substring(COOKIE_NAME.length() + 1));
|
||||
assertThat(value)
|
||||
.isEqualTo(
|
||||
"CookieSessionMetadata{clientId=new_registrar, failedLoginAttempts=1,"
|
||||
+ " serviceExtensionUris=Bar|Baz}");
|
||||
}
|
||||
}
|
||||
@@ -12,17 +12,19 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
package google.registry.flows;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.same;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import google.registry.testing.FakeHttpSession;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
@@ -36,18 +38,22 @@ class EppTlsActionTest {
|
||||
EppTlsAction action = new EppTlsAction();
|
||||
action.inputXmlBytes = INPUT_XML_BYTES;
|
||||
action.tlsCredentials = mock(TlsCredentials.class);
|
||||
action.session = new FakeHttpSession();
|
||||
action.session.setAttribute("REGISTRAR_ID", "ClientIdentifier");
|
||||
action.request = mock(HttpServletRequest.class);
|
||||
when(action.request.getHeader("Cookie"))
|
||||
.thenReturn(
|
||||
"SESSION_INFO="
|
||||
+ BaseEncoding.base64Url().encode("clientId=ClientIdentifier".getBytes(US_ASCII)));
|
||||
action.eppRequestHandler = mock(EppRequestHandler.class);
|
||||
action.run();
|
||||
ArgumentCaptor<SessionMetadata> captor = ArgumentCaptor.forClass(SessionMetadata.class);
|
||||
verify(action.eppRequestHandler).executeEpp(
|
||||
captor.capture(),
|
||||
same(action.tlsCredentials),
|
||||
eq(EppRequestSource.TLS),
|
||||
eq(false),
|
||||
eq(false),
|
||||
eq(INPUT_XML_BYTES));
|
||||
verify(action.eppRequestHandler)
|
||||
.executeEpp(
|
||||
captor.capture(),
|
||||
same(action.tlsCredentials),
|
||||
eq(EppRequestSource.TLS),
|
||||
eq(false),
|
||||
eq(false),
|
||||
eq(INPUT_XML_BYTES));
|
||||
assertThat(captor.getValue().getRegistrarId()).isEqualTo("ClientIdentifier");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ 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.net.InternetDomainName;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException;
|
||||
@@ -63,8 +62,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
/** Unit tests for {@link AllocationTokenFlowUtils}. */
|
||||
class AllocationTokenFlowUtilsTest {
|
||||
|
||||
private final AllocationTokenFlowUtils flowUtils =
|
||||
new AllocationTokenFlowUtils(new AllocationTokenCustomLogic());
|
||||
private final AllocationTokenFlowUtils flowUtils = new AllocationTokenFlowUtils();
|
||||
|
||||
@RegisterExtension
|
||||
final JpaIntegrationTestExtension jpa =
|
||||
@@ -185,47 +183,6 @@ class AllocationTokenFlowUtilsTest {
|
||||
.marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_validateTokenCreate_callsCustomLogic() {
|
||||
AllocationTokenFlowUtils failingFlowUtils =
|
||||
new AllocationTokenFlowUtils(new FailingAllocationTokenCustomLogic());
|
||||
persistResource(
|
||||
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
||||
when(allocationTokenExtension.getAllocationToken()).thenReturn("tokeN");
|
||||
Exception thrown =
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() ->
|
||||
failingFlowUtils.verifyAllocationTokenCreateIfPresent(
|
||||
createCommand("blah.tld"),
|
||||
Tld.get("tld"),
|
||||
"TheRegistrar",
|
||||
DateTime.now(UTC),
|
||||
Optional.of(allocationTokenExtension)));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("failed for tests");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_validateTokenExistingDomain_callsCustomLogic() {
|
||||
AllocationTokenFlowUtils failingFlowUtils =
|
||||
new AllocationTokenFlowUtils(new FailingAllocationTokenCustomLogic());
|
||||
persistResource(
|
||||
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
||||
when(allocationTokenExtension.getAllocationToken()).thenReturn("tokeN");
|
||||
Exception thrown =
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() ->
|
||||
failingFlowUtils.verifyAllocationTokenIfPresent(
|
||||
DatabaseHelper.newDomain("blah.tld"),
|
||||
Tld.get("tld"),
|
||||
"TheRegistrar",
|
||||
DateTime.now(UTC),
|
||||
CommandName.RENEW,
|
||||
Optional.of(allocationTokenExtension)));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("failed for tests");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_validateTokenCreate_invalidForClientId() {
|
||||
persistResource(
|
||||
@@ -383,49 +340,6 @@ class AllocationTokenFlowUtilsTest {
|
||||
.inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_checkDomainsWithToken_callsCustomLogic() {
|
||||
persistResource(
|
||||
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
||||
AllocationTokenFlowUtils failingFlowUtils =
|
||||
new AllocationTokenFlowUtils(new FailingAllocationTokenCustomLogic());
|
||||
Exception thrown =
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() ->
|
||||
failingFlowUtils.checkDomainsWithToken(
|
||||
ImmutableList.of(
|
||||
InternetDomainName.from("blah.tld"), InternetDomainName.from("blah2.tld")),
|
||||
"tokeN",
|
||||
"TheRegistrar",
|
||||
DateTime.now(UTC)));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("failed for tests");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_checkDomainsWithToken_resultsFromCustomLogicAreIntegrated() {
|
||||
persistResource(
|
||||
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
||||
AllocationTokenFlowUtils customResultFlowUtils =
|
||||
new AllocationTokenFlowUtils(new CustomResultAllocationTokenCustomLogic());
|
||||
assertThat(
|
||||
customResultFlowUtils
|
||||
.checkDomainsWithToken(
|
||||
ImmutableList.of(
|
||||
InternetDomainName.from("blah.tld"), InternetDomainName.from("bunny.tld")),
|
||||
"tokeN",
|
||||
"TheRegistrar",
|
||||
DateTime.now(UTC))
|
||||
.domainCheckResults())
|
||||
.containsExactlyEntriesIn(
|
||||
ImmutableMap.of(
|
||||
InternetDomainName.from("blah.tld"),
|
||||
"",
|
||||
InternetDomainName.from("bunny.tld"),
|
||||
"fufu"))
|
||||
.inOrder();
|
||||
}
|
||||
|
||||
private void assertValidateCreateThrowsEppException(Class<? extends EppException> clazz) {
|
||||
assertAboutEppExceptions()
|
||||
.that(
|
||||
@@ -475,46 +389,4 @@ class AllocationTokenFlowUtilsTest {
|
||||
.put(promoStart.plusMonths(1), ENDED)
|
||||
.build());
|
||||
}
|
||||
|
||||
/** An {@link AllocationTokenCustomLogic} class that throws exceptions on every method. */
|
||||
private static class FailingAllocationTokenCustomLogic extends AllocationTokenCustomLogic {
|
||||
|
||||
@Override
|
||||
public AllocationToken validateToken(
|
||||
DomainCommand.Create command,
|
||||
AllocationToken token,
|
||||
Tld tld,
|
||||
String registrarId,
|
||||
DateTime now) {
|
||||
throw new IllegalStateException("failed for tests");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllocationToken validateToken(
|
||||
Domain domain, AllocationToken token, Tld tld, String registrarId, DateTime now) {
|
||||
throw new IllegalStateException("failed for tests");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableMap<InternetDomainName, String> checkDomainsWithToken(
|
||||
ImmutableList<InternetDomainName> domainNames,
|
||||
AllocationToken tokenEntity,
|
||||
String registrarId,
|
||||
DateTime now) {
|
||||
throw new IllegalStateException("failed for tests");
|
||||
}
|
||||
}
|
||||
|
||||
/** An {@link AllocationTokenCustomLogic} class that returns custom check results for bunnies. */
|
||||
private static class CustomResultAllocationTokenCustomLogic extends AllocationTokenCustomLogic {
|
||||
|
||||
@Override
|
||||
public ImmutableMap<InternetDomainName, String> checkDomainsWithToken(
|
||||
ImmutableList<InternetDomainName> domainNames,
|
||||
AllocationToken tokenEntity,
|
||||
String registrarId,
|
||||
DateTime now) {
|
||||
return Maps.toMap(domainNames, domain -> domain.toString().contains("bunny") ? "fufu" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class ConsoleEppActionHistoryTest extends EntityTestCase {
|
||||
DomainHistory domainHistory = getOnlyElement(DatabaseHelper.loadAllOf(DomainHistory.class));
|
||||
ConsoleEppActionHistory history =
|
||||
new ConsoleEppActionHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.EPP_ACTION)
|
||||
.setType(ConsoleUpdateHistory.Type.DOMAIN_DELETE)
|
||||
.setActingUser(user)
|
||||
.setModificationTime(fakeClock.nowUtc())
|
||||
.setMethod("POST")
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2025 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.console;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.loadByEntity;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistDomainWithDependentResources;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
|
||||
import google.registry.model.EntityTestCase;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.util.DateTimeUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SimpleConsoleUpdateHistoryTest extends EntityTestCase {
|
||||
SimpleConsoleUpdateHistoryTest() {
|
||||
super(JpaEntityCoverageCheck.ENABLED);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("tld");
|
||||
persistDomainWithDependentResources(
|
||||
"example",
|
||||
"tld",
|
||||
persistActiveContact("contact1234"),
|
||||
fakeClock.nowUtc(),
|
||||
fakeClock.nowUtc(),
|
||||
DateTimeUtils.END_OF_TIME);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPersistence() {
|
||||
User user = persistResource(DatabaseHelper.createAdminUser("email@email.com"));
|
||||
SimpleConsoleUpdateHistory history =
|
||||
new SimpleConsoleUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.DOMAIN_SUSPEND)
|
||||
.setActingUser(user)
|
||||
.setMethod("POST")
|
||||
.setUrl("/console-api/bulk-domain")
|
||||
.setDescription("example.tld")
|
||||
.setModificationTime(fakeClock.nowUtc())
|
||||
.build();
|
||||
persistResource(history);
|
||||
assertThat(loadByEntity(history)).isEqualTo(history);
|
||||
}
|
||||
}
|
||||
@@ -293,11 +293,11 @@ class JpaTransactionManagerImplTest {
|
||||
assertThrows(
|
||||
OptimisticLockException.class,
|
||||
() -> spyJpaTm.transact(() -> spyJpaTm.delete(theEntityKey)));
|
||||
verify(spyJpaTm, times(3)).delete(theEntityKey);
|
||||
verify(spyJpaTm, times(6)).delete(theEntityKey);
|
||||
assertThrows(
|
||||
OptimisticLockException.class,
|
||||
() -> spyJpaTm.transact(() -> spyJpaTm.delete(theEntityKey)));
|
||||
verify(spyJpaTm, times(6)).delete(theEntityKey);
|
||||
verify(spyJpaTm, times(12)).delete(theEntityKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -355,10 +355,10 @@ class JpaTransactionManagerImplTest {
|
||||
spyJpaTm.transact(() -> spyJpaTm.insert(theEntity));
|
||||
assertThrows(
|
||||
RuntimeException.class, () -> spyJpaTm.transact(() -> spyJpaTm.delete(theEntityKey)));
|
||||
verify(spyJpaTm, times(3)).delete(theEntityKey);
|
||||
verify(spyJpaTm, times(6)).delete(theEntityKey);
|
||||
assertThrows(
|
||||
RuntimeException.class, () -> spyJpaTm.transact(() -> spyJpaTm.delete(theEntityKey)));
|
||||
verify(spyJpaTm, times(6)).delete(theEntityKey);
|
||||
verify(spyJpaTm, times(12)).delete(theEntityKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -759,11 +759,11 @@ class JpaTransactionManagerImplTest {
|
||||
spyJpaTm.transact(
|
||||
() -> {
|
||||
spyJpaTm.exists(theEntity);
|
||||
spyJpaTm.transact(() -> spyJpaTm.delete(theEntityKey));
|
||||
spyJpaTm.delete(theEntityKey);
|
||||
}));
|
||||
|
||||
verify(spyJpaTm, times(3)).exists(theEntity);
|
||||
verify(spyJpaTm, times(3)).delete(theEntityKey);
|
||||
verify(spyJpaTm, times(6)).exists(theEntity);
|
||||
verify(spyJpaTm, times(6)).delete(theEntityKey);
|
||||
}
|
||||
|
||||
private static void insertPerson(int age) {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright 2025 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.rdap;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import google.registry.testing.FakeResponse;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Tests for {@link RdapEmptyAction}. */
|
||||
public class RdapEmptyActionTest {
|
||||
|
||||
private FakeResponse fakeResponse;
|
||||
private RdapEmptyAction action;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
fakeResponse = new FakeResponse();
|
||||
action = new RdapEmptyAction(fakeResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRedirect() {
|
||||
action.run();
|
||||
assertThat(fakeResponse.getStatus()).isEqualTo(HttpServletResponse.SC_FOUND);
|
||||
assertThat(fakeResponse.getPayload()).isEqualTo("Redirected to /rdap/help");
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import google.registry.model.common.FeatureFlagTest;
|
||||
import google.registry.model.console.ConsoleEppActionHistoryTest;
|
||||
import google.registry.model.console.RegistrarPocUpdateHistoryTest;
|
||||
import google.registry.model.console.RegistrarUpdateHistoryTest;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistoryTest;
|
||||
import google.registry.model.console.UserTest;
|
||||
import google.registry.model.console.UserUpdateHistoryTest;
|
||||
import google.registry.model.contact.ContactTest;
|
||||
@@ -113,12 +114,13 @@ import org.junit.runner.RunWith;
|
||||
RegistrarDaoTest.class,
|
||||
RegistrarPocUpdateHistoryTest.class,
|
||||
RegistrarUpdateHistoryTest.class,
|
||||
TldTest.class,
|
||||
ReservedListDaoTest.class,
|
||||
RegistryLockDaoTest.class,
|
||||
ServerSecretTest.class,
|
||||
SimpleConsoleUpdateHistoryTest.class,
|
||||
SignedMarkRevocationListDaoTest.class,
|
||||
Spec11ThreatMatchTest.class,
|
||||
TldTest.class,
|
||||
TmchCrlTest.class,
|
||||
UserTest.class,
|
||||
UserUpdateHistoryTest.class,
|
||||
|
||||
@@ -32,8 +32,9 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.flows.PasswordOnlyTransportCredentials;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
@@ -138,14 +139,10 @@ class ConsoleEppPasswordActionTest {
|
||||
createAction("TheRegistrar", "foobar", "randomPassword", "randomPassword");
|
||||
action.run();
|
||||
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
|
||||
assertDoesNotThrow(
|
||||
() -> {
|
||||
credentials.validate(loadRegistrar("TheRegistrar"), "randomPassword");
|
||||
});
|
||||
assertThat(loadSingleton(RegistrarUpdateHistory.class).get().getRequestBody())
|
||||
.isEqualTo(
|
||||
"{\"registrarId\":\"TheRegistrar\",\"oldPassword\":\"********\",\"newPassword\":"
|
||||
+ "\"••••••••\",\"newPasswordRepeat\":\"••••••••\"}");
|
||||
assertDoesNotThrow(() -> credentials.validate(loadRegistrar("TheRegistrar"), "randomPassword"));
|
||||
SimpleConsoleUpdateHistory history = loadSingleton(SimpleConsoleUpdateHistory.class).get();
|
||||
assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.EPP_PASSWORD_UPDATE);
|
||||
assertThat(history.getDescription()).hasValue("TheRegistrar");
|
||||
}
|
||||
|
||||
private ConsoleEppPasswordAction createAction(
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
package google.registry.ui.server.console;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.model.registrar.RegistrarPocBase.Type.WHOIS;
|
||||
import static google.registry.testing.DatabaseHelper.createTlds;
|
||||
import static google.registry.testing.DatabaseHelper.loadSingleton;
|
||||
@@ -30,8 +29,9 @@ import static org.mockito.Mockito.when;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
@@ -108,9 +108,9 @@ class ConsoleUpdateRegistrarActionTest {
|
||||
assertThat(newRegistrar.getAllowedTlds()).containsExactly("app", "dev");
|
||||
assertThat(newRegistrar.isRegistryLockAllowed()).isFalse();
|
||||
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
|
||||
assertAboutImmutableObjects()
|
||||
.that(newRegistrar)
|
||||
.hasFieldsEqualTo(loadSingleton(RegistrarUpdateHistory.class).get().getRegistrar());
|
||||
SimpleConsoleUpdateHistory history = loadSingleton(SimpleConsoleUpdateHistory.class).get();
|
||||
assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE);
|
||||
assertThat(history.getDescription()).hasValue("TheRegistrar");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
package google.registry.ui.server.console;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.testing.DatabaseHelper.loadAllOf;
|
||||
import static google.registry.testing.DatabaseHelper.loadRegistrar;
|
||||
import static google.registry.testing.DatabaseHelper.loadSingleton;
|
||||
@@ -30,9 +29,10 @@ import static org.mockito.Mockito.when;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.RegistrarRole;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
@@ -186,9 +186,9 @@ class RegistrarsActionTest {
|
||||
.findAny()
|
||||
.isPresent())
|
||||
.isTrue();
|
||||
assertAboutImmutableObjects()
|
||||
.that(r)
|
||||
.isEqualExceptFields(loadSingleton(RegistrarUpdateHistory.class).get().getRegistrar());
|
||||
SimpleConsoleUpdateHistory history = loadSingleton(SimpleConsoleUpdateHistory.class).get();
|
||||
assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.REGISTRAR_CREATE);
|
||||
assertThat(history.getDescription()).hasValue("regIdTest");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -19,6 +19,7 @@ import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATAS
|
||||
import static google.registry.model.common.FeatureFlag.FeatureStatus.INACTIVE;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.loadByEntity;
|
||||
import static google.registry.testing.DatabaseHelper.loadSingleton;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistDomainWithDependentResources;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
@@ -38,8 +39,10 @@ import google.registry.flows.DaggerEppTestComponent;
|
||||
import google.registry.flows.EppController;
|
||||
import google.registry.flows.EppTestComponent;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.RegistrarRole;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.model.domain.Domain;
|
||||
@@ -120,6 +123,9 @@ public class ConsoleBulkDomainActionTest {
|
||||
{"example.tld":{"message":"Command completed successfully; action pending",\
|
||||
"responseCode":1001}}""");
|
||||
assertThat(loadByEntity(domain).getDeletionTime()).isEqualTo(clock.nowUtc().plusDays(35));
|
||||
SimpleConsoleUpdateHistory history = loadSingleton(SimpleConsoleUpdateHistory.class).get();
|
||||
assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.DOMAIN_DELETE);
|
||||
assertThat(history.getDescription()).hasValue("example.tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -145,6 +151,9 @@ public class ConsoleBulkDomainActionTest {
|
||||
{"example.tld":{"message":"Command completed successfully","responseCode":1000}}""");
|
||||
assertThat(loadByEntity(domain).getStatusValues())
|
||||
.containsAtLeastElementsIn(serverSuspensionStatuses);
|
||||
SimpleConsoleUpdateHistory history = loadSingleton(SimpleConsoleUpdateHistory.class).get();
|
||||
assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.DOMAIN_SUSPEND);
|
||||
assertThat(history.getDescription()).hasValue("example.tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -172,6 +181,9 @@ public class ConsoleBulkDomainActionTest {
|
||||
"""
|
||||
{"example.tld":{"message":"Command completed successfully","responseCode":1000}}""");
|
||||
assertThat(loadByEntity(domain).getStatusValues()).containsNoneIn(serverSuspensionStatuses);
|
||||
SimpleConsoleUpdateHistory history = loadSingleton(SimpleConsoleUpdateHistory.class).get();
|
||||
assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.DOMAIN_UNSUSPEND);
|
||||
assertThat(history.getDescription()).hasValue("example.tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -194,6 +206,9 @@ public class ConsoleBulkDomainActionTest {
|
||||
"nonexistent.tld":{"message":"The domain with given ID (nonexistent.tld) doesn\\u0027t exist.",\
|
||||
"responseCode":2303}}""");
|
||||
assertThat(loadByEntity(domain).getDeletionTime()).isEqualTo(clock.nowUtc().plusDays(35));
|
||||
SimpleConsoleUpdateHistory history = loadSingleton(SimpleConsoleUpdateHistory.class).get();
|
||||
assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.DOMAIN_DELETE);
|
||||
assertThat(history.getDescription()).hasValue("example.tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -27,8 +27,9 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.RegistrarRole;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
@@ -52,8 +53,8 @@ import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Tests for {@link WhoisRegistrarFieldsAction}. */
|
||||
public class WhoisRegistrarFieldsActionTest {
|
||||
/** Tests for {@link RdapRegistrarFieldsAction}. */
|
||||
public class RdapRegistrarFieldsActionTest {
|
||||
|
||||
private ConsoleApiParams consoleApiParams;
|
||||
private static final Gson GSON = RequestModule.provideGson();
|
||||
@@ -88,8 +89,6 @@ public class WhoisRegistrarFieldsActionTest {
|
||||
@Test
|
||||
void testSuccess_setsAllFields() throws Exception {
|
||||
Registrar oldRegistrar = Registrar.loadRequiredRegistrarCached("TheRegistrar");
|
||||
assertThat(oldRegistrar.getWhoisServer()).isEqualTo("whois.nic.fakewhois.example");
|
||||
assertThat(oldRegistrar.getUrl()).isEqualTo("http://my.fake.url");
|
||||
ImmutableMap<String, Object> addressMap =
|
||||
ImmutableMap.of(
|
||||
"street",
|
||||
@@ -104,36 +103,29 @@ public class WhoisRegistrarFieldsActionTest {
|
||||
"CA");
|
||||
uiRegistrarMap.putAll(
|
||||
ImmutableMap.of(
|
||||
"whoisServer",
|
||||
"whois.nic.google",
|
||||
"icannReferralEmail",
|
||||
"lol@sloth.test",
|
||||
"phoneNumber",
|
||||
"+1.4155552671",
|
||||
"faxNumber",
|
||||
"+1.4155552672",
|
||||
"url",
|
||||
"\"https://newurl.example\"",
|
||||
"localizedAddress",
|
||||
"{\"street\": [\"123 Fake St\"], \"city\": \"Fakeville\", \"state\":"
|
||||
+ " \"NL\", \"zip\": \"10011\", \"countryCode\": \"CA\"}"));
|
||||
WhoisRegistrarFieldsAction action = createAction();
|
||||
RdapRegistrarFieldsAction action = createAction();
|
||||
action.run();
|
||||
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
|
||||
Registrar newRegistrar = Registrar.loadByRegistrarId("TheRegistrar").get(); // skip cache
|
||||
assertThat(newRegistrar.getWhoisServer()).isEqualTo("whois.nic.google");
|
||||
assertThat(newRegistrar.getUrl()).isEqualTo("https://newurl.example");
|
||||
assertThat(newRegistrar.getLocalizedAddress().toJsonMap()).isEqualTo(addressMap);
|
||||
assertThat(newRegistrar.getPhoneNumber()).isEqualTo("+1.4155552671");
|
||||
assertThat(newRegistrar.getFaxNumber()).isEqualTo("+1.4155552672");
|
||||
// the non-changed fields should be the same
|
||||
assertAboutImmutableObjects()
|
||||
.that(newRegistrar)
|
||||
.isEqualExceptFields(
|
||||
oldRegistrar, "whoisServer", "url", "localizedAddress", "phoneNumber", "faxNumber");
|
||||
assertAboutImmutableObjects()
|
||||
.that(loadSingleton(RegistrarUpdateHistory.class).get().getRegistrar())
|
||||
.hasFieldsEqualTo(newRegistrar);
|
||||
.isEqualExceptFields(oldRegistrar, "localizedAddress", "phoneNumber", "faxNumber");
|
||||
SimpleConsoleUpdateHistory history = loadSingleton(SimpleConsoleUpdateHistory.class).get();
|
||||
assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE);
|
||||
assertThat(history.getDescription()).hasValue("TheRegistrar");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -150,7 +142,7 @@ public class WhoisRegistrarFieldsActionTest {
|
||||
.build())
|
||||
.build());
|
||||
uiRegistrarMap.put("registrarId", "NewRegistrar");
|
||||
WhoisRegistrarFieldsAction action = createAction(onlyTheRegistrar);
|
||||
RdapRegistrarFieldsAction action = createAction(onlyTheRegistrar);
|
||||
action.run();
|
||||
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_FORBIDDEN);
|
||||
// should be no change
|
||||
@@ -161,17 +153,17 @@ public class WhoisRegistrarFieldsActionTest {
|
||||
return AuthResult.createUser(DatabaseHelper.createAdminUser("email@email.example"));
|
||||
}
|
||||
|
||||
private WhoisRegistrarFieldsAction createAction() throws IOException {
|
||||
private RdapRegistrarFieldsAction createAction() throws IOException {
|
||||
return createAction(defaultUserAuth());
|
||||
}
|
||||
|
||||
private WhoisRegistrarFieldsAction createAction(AuthResult authResult) throws IOException {
|
||||
private RdapRegistrarFieldsAction createAction(AuthResult authResult) throws IOException {
|
||||
consoleApiParams = ConsoleApiParamsUtils.createFake(authResult);
|
||||
when(consoleApiParams.request().getMethod()).thenReturn(Action.Method.POST.toString());
|
||||
doReturn(new BufferedReader(new StringReader(uiRegistrarMap.toString())))
|
||||
.when(consoleApiParams.request())
|
||||
.getReader();
|
||||
return new WhoisRegistrarFieldsAction(
|
||||
return new RdapRegistrarFieldsAction(
|
||||
consoleApiParams,
|
||||
registrarAccessor,
|
||||
ConsoleModule.provideRegistrar(
|
||||
@@ -15,7 +15,6 @@
|
||||
package google.registry.ui.server.console.settings;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.testing.CertificateSamples.SAMPLE_CERT2;
|
||||
import static google.registry.testing.DatabaseHelper.loadRegistrar;
|
||||
import static google.registry.testing.DatabaseHelper.loadSingleton;
|
||||
@@ -30,7 +29,8 @@ import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.flows.certs.CertificateChecker;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.SimpleConsoleUpdateHistory;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.request.Action;
|
||||
@@ -101,9 +101,9 @@ class SecurityActionTest {
|
||||
.isEqualTo("GNd6ZP8/n91t9UTnpxR8aH7aAW4+CpvufYx9ViGbcMY");
|
||||
assertThat(r.getIpAddressAllowList().get(0).getIp()).isEqualTo("192.168.1.1");
|
||||
assertThat(r.getIpAddressAllowList().get(0).getNetmask()).isEqualTo(32);
|
||||
assertAboutImmutableObjects()
|
||||
.that(loadSingleton(RegistrarUpdateHistory.class).get().getRegistrar())
|
||||
.hasFieldsEqualTo(r);
|
||||
SimpleConsoleUpdateHistory history = loadSingleton(SimpleConsoleUpdateHistory.class).get();
|
||||
assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.REGISTRAR_SECURITY_UPDATE);
|
||||
assertThat(history.getDescription()).hasValue("registrarId");
|
||||
}
|
||||
|
||||
private SecurityAction createAction(AuthResult authResult, String registrarId)
|
||||
|
||||
@@ -101,7 +101,7 @@ public class ConsoleScreenshotTest extends WebDriverTestCase {
|
||||
driver.diffPage("noRegistrarSelected");
|
||||
selectRegistrar();
|
||||
driver.diffPage("registrarSelected_contacts");
|
||||
driver.findElement(By.cssSelector("a[routerLink=\"whois\"]")).click();
|
||||
driver.findElement(By.cssSelector("a[routerLink=\"rdap\"]")).click();
|
||||
Thread.sleep(500);
|
||||
driver.diffPage("registrarSelected_whois");
|
||||
driver.findElement(By.cssSelector("a[routerLink=\"security\"]")).click();
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
SERVICE PATH CLASS METHODS OK MIN USER_POLICY
|
||||
FRONTEND /_dr/epp EppTlsAction POST n APP ADMIN
|
||||
CONSOLE /console-api/bulk-domain ConsoleBulkDomainAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/domain ConsoleDomainGetAction GET n USER PUBLIC
|
||||
CONSOLE /console-api/domain-list ConsoleDomainListAction GET n USER PUBLIC
|
||||
CONSOLE /console-api/dum-download ConsoleDumDownloadAction GET n USER PUBLIC
|
||||
CONSOLE /console-api/eppPassword ConsoleEppPasswordAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/ote ConsoleOteAction GET,POST n USER PUBLIC
|
||||
CONSOLE /console-api/registrar ConsoleUpdateRegistrarAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/registrars RegistrarsAction GET,POST n USER PUBLIC
|
||||
CONSOLE /console-api/registry-lock ConsoleRegistryLockAction GET,POST n USER PUBLIC
|
||||
CONSOLE /console-api/registry-lock-verify ConsoleRegistryLockVerifyAction GET n USER PUBLIC
|
||||
CONSOLE /console-api/settings/contacts ContactAction GET,POST n USER PUBLIC
|
||||
CONSOLE /console-api/settings/security SecurityAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/settings/whois-fields WhoisRegistrarFieldsAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/userdata ConsoleUserDataAction GET n USER PUBLIC
|
||||
CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE,PUT n USER PUBLIC
|
||||
SERVICE PATH CLASS METHODS OK MIN USER_POLICY
|
||||
FRONTEND /_dr/epp EppTlsAction POST n APP ADMIN
|
||||
FRONTEND /ready/frontend ReadinessProbeActionFrontend GET n NONE PUBLIC
|
||||
CONSOLE /console-api/bulk-domain ConsoleBulkDomainAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/domain ConsoleDomainGetAction GET n USER PUBLIC
|
||||
CONSOLE /console-api/domain-list ConsoleDomainListAction GET n USER PUBLIC
|
||||
CONSOLE /console-api/dum-download ConsoleDumDownloadAction GET n USER PUBLIC
|
||||
CONSOLE /console-api/eppPassword ConsoleEppPasswordAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/ote ConsoleOteAction GET,POST n USER PUBLIC
|
||||
CONSOLE /console-api/registrar ConsoleUpdateRegistrarAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/registrars RegistrarsAction GET,POST n USER PUBLIC
|
||||
CONSOLE /console-api/registry-lock ConsoleRegistryLockAction GET,POST n USER PUBLIC
|
||||
CONSOLE /console-api/registry-lock-verify ConsoleRegistryLockVerifyAction GET n USER PUBLIC
|
||||
CONSOLE /console-api/settings/contacts ContactAction GET,POST n USER PUBLIC
|
||||
CONSOLE /console-api/settings/rdap-fields RdapRegistrarFieldsAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/settings/security SecurityAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/userdata ConsoleUserDataAction GET n USER PUBLIC
|
||||
CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE,PUT n USER PUBLIC
|
||||
CONSOLE /ready/console ReadinessProbeConsoleAction GET n NONE PUBLIC
|
||||
@@ -1,6 +1,7 @@
|
||||
SERVICE PATH CLASS METHODS OK MIN USER_POLICY
|
||||
PUBAPI /_dr/whois WhoisAction POST n APP ADMIN
|
||||
PUBAPI /check CheckApiAction GET n NONE PUBLIC
|
||||
PUBAPI /rdap/ RdapEmptyAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /rdap/autnum/(*) RdapAutnumAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /rdap/domain/(*) RdapDomainAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /rdap/domains RdapDomainSearchAction GET,HEAD n NONE PUBLIC
|
||||
@@ -10,4 +11,5 @@ PUBAPI /rdap/help(*) RdapHelpAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /rdap/ip/(*) RdapIpAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /rdap/nameserver/(*) RdapNameserverAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /rdap/nameservers RdapNameserverSearchAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /ready/pubapi ReadinessProbeActionPubApi GET n NONE PUBLIC
|
||||
PUBAPI /whois/(*) WhoisHttpAction GET n NONE PUBLIC
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
SERVICE PATH CLASS METHODS OK MIN USER_POLICY
|
||||
FRONTEND /_dr/epp EppTlsAction POST n APP ADMIN
|
||||
FRONTEND /ready/frontend ReadinessProbeActionFrontend GET n NONE PUBLIC
|
||||
BACKEND /_dr/admin/createGroups CreateGroupsAction POST n APP ADMIN
|
||||
BACKEND /_dr/admin/list/domains ListDomainsAction GET,POST n APP ADMIN
|
||||
BACKEND /_dr/admin/list/hosts ListHostsAction GET,POST n APP ADMIN
|
||||
@@ -56,6 +57,7 @@ BACKEND /_dr/task/uploadBsaUnavailableNames UploadBsaUnavailable
|
||||
BACKEND /_dr/task/wipeOutContactHistoryPii WipeOutContactHistoryPiiAction GET n APP ADMIN
|
||||
PUBAPI /_dr/whois WhoisAction POST n APP ADMIN
|
||||
PUBAPI /check CheckApiAction GET n NONE PUBLIC
|
||||
PUBAPI /rdap/ RdapEmptyAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /rdap/autnum/(*) RdapAutnumAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /rdap/domain/(*) RdapDomainAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /rdap/domains RdapDomainSearchAction GET,HEAD n NONE PUBLIC
|
||||
@@ -65,6 +67,7 @@ PUBAPI /rdap/help(*) RdapHelpAction
|
||||
PUBAPI /rdap/ip/(*) RdapIpAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /rdap/nameserver/(*) RdapNameserverAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /rdap/nameservers RdapNameserverSearchAction GET,HEAD n NONE PUBLIC
|
||||
PUBAPI /ready/pubapi ReadinessProbeActionPubApi GET n NONE PUBLIC
|
||||
PUBAPI /whois/(*) WhoisHttpAction GET n NONE PUBLIC
|
||||
CONSOLE /console-api/bulk-domain ConsoleBulkDomainAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/domain ConsoleDomainGetAction GET n USER PUBLIC
|
||||
@@ -77,7 +80,8 @@ CONSOLE /console-api/registrars RegistrarsAction
|
||||
CONSOLE /console-api/registry-lock ConsoleRegistryLockAction GET,POST n USER PUBLIC
|
||||
CONSOLE /console-api/registry-lock-verify ConsoleRegistryLockVerifyAction GET n USER PUBLIC
|
||||
CONSOLE /console-api/settings/contacts ContactAction GET,POST n USER PUBLIC
|
||||
CONSOLE /console-api/settings/rdap-fields RdapRegistrarFieldsAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/settings/security SecurityAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/settings/whois-fields WhoisRegistrarFieldsAction POST n USER PUBLIC
|
||||
CONSOLE /console-api/userdata ConsoleUserDataAction GET n USER PUBLIC
|
||||
CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE,PUT n USER PUBLIC
|
||||
CONSOLE /ready/console ReadinessProbeConsoleAction GET n NONE PUBLIC
|
||||
@@ -16,7 +16,7 @@
|
||||
-- Determine the number of attempted adds each registrar made.
|
||||
|
||||
-- Since the specification requests all 'attempted' adds, we regex the
|
||||
-- monthly App Engine logs, searching for all create commands and associating
|
||||
-- monthly GKE logs, searching for all create commands and associating
|
||||
-- them with their corresponding registrars.
|
||||
|
||||
-- Example log generated by FlowReporter in App Engine and GKE logs:
|
||||
@@ -27,7 +27,7 @@
|
||||
-- ,"targetId":"","targetIds":[],"tld":"",
|
||||
-- "tlds":[],"icannActivityReportField":""}
|
||||
|
||||
-- This outer select just converts the registrar's clientId to their name.
|
||||
-- This outer select just converts the registrar's ID to their name.
|
||||
SELECT
|
||||
tld,
|
||||
registrar_table.registrar_name AS registrar_name,
|
||||
@@ -38,34 +38,20 @@ FROM (
|
||||
JSON_EXTRACT_SCALAR(json, '$.tld') AS tld,
|
||||
JSON_EXTRACT_SCALAR(json, '$.clientId') AS clientId,
|
||||
COUNT(json) AS count
|
||||
FROM ((
|
||||
-- Extract JSON metadata package from monthly logs
|
||||
FROM (
|
||||
-- Extract JSON metadata package from monthly logs
|
||||
SELECT
|
||||
REGEXP_EXTRACT(textPayload, r'FLOW-LOG-SIGNATURE-METADATA: (.*)\n?$') AS json
|
||||
REGEXP_EXTRACT(jsonPayload.message, r'FLOW-LOG-SIGNATURE-METADATA: (.*)\n?$') AS json
|
||||
FROM
|
||||
`domain-registry-alpha.appengine_logs._var_log_app_*`
|
||||
`domain-registry-alpha.gke_logs.stderr_*`
|
||||
WHERE
|
||||
_TABLE_SUFFIX BETWEEN '20170901'
|
||||
AND '20170930'
|
||||
AND STARTS_WITH(textPayload, "FLOW-LOG-SIGNATURE-METADATA")
|
||||
AND STARTS_WITH(jsonPayload.message, "FLOW-LOG-SIGNATURE-METADATA")
|
||||
-- Look for domain creates
|
||||
AND REGEXP_CONTAINS(textPayload, r'"commandType":"create","resourceType":"domain"')
|
||||
AND REGEXP_CONTAINS(jsonPayload.message, r'"commandType":"create","resourceType":"domain"')
|
||||
-- Filter prober data
|
||||
AND NOT REGEXP_CONTAINS(textPayload, r'"prober-[a-z]{2}-((any)|(canary))"'))
|
||||
UNION ALL (
|
||||
-- Extract JSON metadata package from monthly logs
|
||||
SELECT
|
||||
REGEXP_EXTRACT(jsonPayload.message, r'FLOW-LOG-SIGNATURE-METADATA: (.*)\n?$') AS json
|
||||
FROM
|
||||
`domain-registry-alpha.gke_logs.stderr_*`
|
||||
WHERE
|
||||
_TABLE_SUFFIX BETWEEN '20170901'
|
||||
AND '20170930'
|
||||
AND STARTS_WITH(jsonPayload.message, "FLOW-LOG-SIGNATURE-METADATA")
|
||||
-- Look for domain creates
|
||||
AND REGEXP_CONTAINS(jsonPayload.message, r'"commandType":"create","resourceType":"domain"')
|
||||
-- Filter prober data
|
||||
AND NOT REGEXP_CONTAINS(jsonPayload.message, r'"prober-[a-z]{2}-((any)|(canary))"')))
|
||||
AND NOT REGEXP_CONTAINS(jsonPayload.message, r'"prober-[a-z]{2}-((any)|(canary))"'))
|
||||
GROUP BY
|
||||
tld,
|
||||
clientId ) AS logs_table
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
-- Query FlowReporter JSON log messages and calculate SRS metrics.
|
||||
|
||||
-- We use ugly regex's over the monthly appengine logs to determine how many
|
||||
-- We use ugly regexes over the monthly GKE logs to determine how many
|
||||
-- EPP requests we received for each command. For example:
|
||||
-- {"commandType":"check"...,"targetIds":["ais.a.how"],
|
||||
-- "tld":"","tlds":["a.how"],"icannActivityReportField":"srs-dom-check"}
|
||||
@@ -35,30 +35,15 @@ FROM (
|
||||
JSON_EXTRACT_SCALAR(json,
|
||||
'$.icannActivityReportField') AS activityReportField
|
||||
FROM (
|
||||
-- For reasons that I don't understand, if I directly select the three columns
|
||||
-- from the union, BigQuery complains about column number mismatch, so I have to
|
||||
-- make a temporary union table and select on it.
|
||||
SELECT
|
||||
*
|
||||
FROM (
|
||||
SELECT
|
||||
-- Extract the logged JSON payload.
|
||||
REGEXP_EXTRACT(textPayload, r'FLOW-LOG-SIGNATURE-METADATA: (.*)\n?$')
|
||||
AS json
|
||||
FROM `domain-registry-alpha.appengine_logs._var_log_app_*`
|
||||
WHERE
|
||||
STARTS_WITH(textPayload, "FLOW-LOG-SIGNATURE-METADATA")
|
||||
AND _TABLE_SUFFIX BETWEEN '20170901' AND '20170930')
|
||||
UNION ALL (
|
||||
SELECT
|
||||
-- Extract the logged JSON payload.
|
||||
REGEXP_EXTRACT(jsonPayload.message, r'FLOW-LOG-SIGNATURE-METADATA: (.*)\n?$')
|
||||
AS json
|
||||
FROM `domain-registry-alpha.gke_logs.stderr_*`
|
||||
WHERE
|
||||
STARTS_WITH(jsonPayload.message, "FLOW-LOG-SIGNATURE-METADATA")
|
||||
AND _TABLE_SUFFIX BETWEEN '20170901' AND '20170930')
|
||||
)) AS regexes
|
||||
-- Extract the logged JSON payload.
|
||||
REGEXP_EXTRACT(jsonPayload.message, r'FLOW-LOG-SIGNATURE-METADATA: (.*)\n?$')
|
||||
AS json
|
||||
FROM `domain-registry-alpha.gke_logs.stderr_*`
|
||||
WHERE
|
||||
STARTS_WITH(jsonPayload.message, "FLOW-LOG-SIGNATURE-METADATA")
|
||||
AND _TABLE_SUFFIX BETWEEN '20170901' AND '20170930')
|
||||
) AS regexes
|
||||
JOIN
|
||||
-- Unnest the JSON-parsed tlds.
|
||||
UNNEST(regexes.tlds) AS tld
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
-- See the License for the specific language governing permissions and
|
||||
-- limitations under the License.
|
||||
|
||||
-- Query to fetch AppEngine and GKE request logs for the report month.
|
||||
-- Query to fetch GKE request logs for the report month.
|
||||
|
||||
-- START_OF_MONTH and END_OF_MONTH should be in YYYYMM01 format.
|
||||
|
||||
@@ -26,10 +26,3 @@ FROM (
|
||||
`domain-registry-alpha.gke_logs.stderr_*`
|
||||
WHERE
|
||||
_TABLE_SUFFIX BETWEEN '20170901' AND '20170930')
|
||||
UNION ALL (
|
||||
SELECT
|
||||
protoPayload.resource AS requestPath
|
||||
FROM
|
||||
`domain-registry-alpha.appengine_logs.appengine_googleapis_com_request_log_*`
|
||||
WHERE
|
||||
_TABLE_SUFFIX BETWEEN '20170901' AND '20170930')
|
||||
|
||||
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
@@ -185,3 +185,7 @@ V184__remove_fk_pollmessage_domainhistory.sql
|
||||
V185__remove_fk_domaintransactionrecord_domainhistory.sql
|
||||
V186__remove_fk_domaindsdatahistory_domainhistory.sql
|
||||
V187__console_update_history.sql
|
||||
V188__remove_fk_userupdatehistory.sql
|
||||
V189__remove_fk_consoleeppactionhistory.sql
|
||||
V190__remove_fk_registrarupdatehistory.sql
|
||||
V191__remove_fk_registrarpocupdatehistory.sql
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
-- Copyright 2025 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.
|
||||
|
||||
ALTER TABLE "UserUpdateHistory" DROP CONSTRAINT fk1s7bopbl3pwrhv3jkkofnv3o0;
|
||||
ALTER TABLE "UserUpdateHistory" DROP CONSTRAINT fkuserupdatehistoryemailaddress;
|
||||
@@ -0,0 +1,15 @@
|
||||
-- Copyright 2025 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.
|
||||
|
||||
ALTER TABLE "ConsoleEppActionHistory" DROP CONSTRAINT fkb686b9os2nsjpv930npa4r3b4;
|
||||
@@ -0,0 +1,15 @@
|
||||
-- Copyright 2025 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.
|
||||
|
||||
ALTER TABLE "RegistrarUpdateHistory" DROP CONSTRAINT fksr7w342s7x5s5jvdti2axqeq8;
|
||||
@@ -0,0 +1,15 @@
|
||||
-- Copyright 2025 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.
|
||||
|
||||
ALTER TABLE "RegistrarPocUpdateHistory" DROP CONSTRAINT fkftpbwctxtkc1i0njc0tdcaa2g;
|
||||
@@ -139,7 +139,7 @@
|
||||
history_method text not null,
|
||||
history_modification_time timestamp(6) with time zone not null,
|
||||
history_request_body text,
|
||||
history_type text not null check (history_type in ('EPP_ACTION','POC_CREATE','POC_UPDATE','POC_DELETE','REGISTRAR_UPDATE','USER_CREATE','USER_DELETE','USER_UPDATE')),
|
||||
history_type text not null check (history_type in ('DOMAIN_DELETE','DOMAIN_SUSPEND','DOMAIN_UNSUSPEND','EPP_PASSWORD_UPDATE','REGISTRAR_CREATE','REGISTRAR_SECURITY_UPDATE','REGISTRAR_UPDATE','USER_CREATE','USER_DELETE','USER_UPDATE')),
|
||||
history_url text not null,
|
||||
history_entry_class text not null,
|
||||
repo_id text not null,
|
||||
@@ -148,6 +148,17 @@
|
||||
primary key (history_revision_id)
|
||||
);
|
||||
|
||||
create table "ConsoleUpdateHistory" (
|
||||
revision_id bigint not null,
|
||||
description text,
|
||||
method text not null,
|
||||
modification_time timestamp(6) with time zone not null,
|
||||
type text not null check (type in ('DOMAIN_DELETE','DOMAIN_SUSPEND','DOMAIN_UNSUSPEND','EPP_PASSWORD_UPDATE','REGISTRAR_CREATE','REGISTRAR_SECURITY_UPDATE','REGISTRAR_UPDATE','USER_CREATE','USER_DELETE','USER_UPDATE')),
|
||||
url text not null,
|
||||
acting_user text not null,
|
||||
primary key (revision_id)
|
||||
);
|
||||
|
||||
create table "Contact" (
|
||||
repo_id text not null,
|
||||
update_timestamp timestamp(6) with time zone,
|
||||
@@ -693,7 +704,7 @@
|
||||
history_method text not null,
|
||||
history_modification_time timestamp(6) with time zone not null,
|
||||
history_request_body text,
|
||||
history_type text not null check (history_type in ('EPP_ACTION','POC_CREATE','POC_UPDATE','POC_DELETE','REGISTRAR_UPDATE','USER_CREATE','USER_DELETE','USER_UPDATE')),
|
||||
history_type text not null check (history_type in ('DOMAIN_DELETE','DOMAIN_SUSPEND','DOMAIN_UNSUSPEND','EPP_PASSWORD_UPDATE','REGISTRAR_CREATE','REGISTRAR_SECURITY_UPDATE','REGISTRAR_UPDATE','USER_CREATE','USER_DELETE','USER_UPDATE')),
|
||||
history_url text not null,
|
||||
email_address text not null,
|
||||
registrar_id text not null,
|
||||
@@ -717,7 +728,7 @@
|
||||
history_method text not null,
|
||||
history_modification_time timestamp(6) with time zone not null,
|
||||
history_request_body text,
|
||||
history_type text not null check (history_type in ('EPP_ACTION','POC_CREATE','POC_UPDATE','POC_DELETE','REGISTRAR_UPDATE','USER_CREATE','USER_DELETE','USER_UPDATE')),
|
||||
history_type text not null check (history_type in ('DOMAIN_DELETE','DOMAIN_SUSPEND','DOMAIN_UNSUSPEND','EPP_PASSWORD_UPDATE','REGISTRAR_CREATE','REGISTRAR_SECURITY_UPDATE','REGISTRAR_UPDATE','USER_CREATE','USER_DELETE','USER_UPDATE')),
|
||||
history_url text not null,
|
||||
allowed_tlds text[],
|
||||
billing_account_map hstore,
|
||||
@@ -906,7 +917,7 @@
|
||||
history_method text not null,
|
||||
history_modification_time timestamp(6) with time zone not null,
|
||||
history_request_body text,
|
||||
history_type text not null check (history_type in ('EPP_ACTION','POC_CREATE','POC_UPDATE','POC_DELETE','REGISTRAR_UPDATE','USER_CREATE','USER_DELETE','USER_UPDATE')),
|
||||
history_type text not null check (history_type in ('DOMAIN_DELETE','DOMAIN_SUSPEND','DOMAIN_UNSUSPEND','EPP_PASSWORD_UPDATE','REGISTRAR_CREATE','REGISTRAR_SECURITY_UPDATE','REGISTRAR_UPDATE','USER_CREATE','USER_DELETE','USER_UPDATE')),
|
||||
history_url text not null,
|
||||
email_address text not null,
|
||||
registry_lock_email_address text,
|
||||
@@ -1010,6 +1021,15 @@
|
||||
create index IDXiahqo1d1fqdfknywmj2xbxl7t
|
||||
on "ConsoleEppActionHistory" (revision_id);
|
||||
|
||||
create index idx_console_update_history_acting_user
|
||||
on "ConsoleUpdateHistory" (acting_user);
|
||||
|
||||
create index idx_console_update_history_type
|
||||
on "ConsoleUpdateHistory" (type);
|
||||
|
||||
create index idx_console_update_history_modification_time
|
||||
on "ConsoleUpdateHistory" (modification_time);
|
||||
|
||||
create index IDX3y752kr9uh4kh6uig54vemx0l
|
||||
on "Contact" (creation_time);
|
||||
|
||||
@@ -1228,6 +1248,11 @@
|
||||
foreign key (history_acting_user)
|
||||
references "User";
|
||||
|
||||
alter table if exists "ConsoleUpdateHistory"
|
||||
add constraint FKnhl1eolgix64u90xv3pj6xa3x
|
||||
foreign key (acting_user)
|
||||
references "User";
|
||||
|
||||
alter table if exists "DelegationSignerData"
|
||||
add constraint FKtr24j9v14ph2mfuw2gsmt12kq
|
||||
foreign key (domain_repo_id)
|
||||
|
||||
@@ -2614,14 +2614,6 @@ CREATE INDEX spec11threatmatch_registrar_id_idx ON public."Spec11ThreatMatch" US
|
||||
CREATE INDEX spec11threatmatch_tld_idx ON public."Spec11ThreatMatch" USING btree (tld);
|
||||
|
||||
|
||||
--
|
||||
-- Name: UserUpdateHistory fk1s7bopbl3pwrhv3jkkofnv3o0; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."UserUpdateHistory"
|
||||
ADD CONSTRAINT fk1s7bopbl3pwrhv3jkkofnv3o0 FOREIGN KEY (history_acting_user) REFERENCES public."User"(email_address);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Contact fk1sfyj7o7954prbn1exk7lpnoe; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -3070,14 +3062,6 @@ ALTER TABLE ONLY public."DomainHistoryHost"
|
||||
ADD CONSTRAINT fka9woh3hu8gx5x0vly6bai327n FOREIGN KEY (domain_history_domain_repo_id, domain_history_history_revision_id) REFERENCES public."DomainHistory"(domain_repo_id, history_revision_id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
|
||||
--
|
||||
-- Name: ConsoleEppActionHistory fkb686b9os2nsjpv930npa4r3b4; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."ConsoleEppActionHistory"
|
||||
ADD CONSTRAINT fkb686b9os2nsjpv930npa4r3b4 FOREIGN KEY (history_acting_user) REFERENCES public."User"(email_address);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BsaUnblockableDomain fkbsaunblockabledomainlabel; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -3094,14 +3078,6 @@ ALTER TABLE ONLY public."DomainHost"
|
||||
ADD CONSTRAINT fkfmi7bdink53swivs390m2btxg FOREIGN KEY (domain_repo_id) REFERENCES public."Domain"(repo_id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
|
||||
--
|
||||
-- Name: RegistrarPocUpdateHistory fkftpbwctxtkc1i0njc0tdcaa2g; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."RegistrarPocUpdateHistory"
|
||||
ADD CONSTRAINT fkftpbwctxtkc1i0njc0tdcaa2g FOREIGN KEY (history_acting_user) REFERENCES public."User"(email_address);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ReservedEntry fkgq03rk0bt1hb915dnyvd3vnfc; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -3150,14 +3126,6 @@ ALTER TABLE ONLY public."RegistrarUpdateHistory"
|
||||
ADD CONSTRAINT fkregistrarupdatehistoryregistrarid FOREIGN KEY (registrar_id) REFERENCES public."Registrar"(registrar_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: RegistrarUpdateHistory fksr7w342s7x5s5jvdti2axqeq8; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."RegistrarUpdateHistory"
|
||||
ADD CONSTRAINT fksr7w342s7x5s5jvdti2axqeq8 FOREIGN KEY (history_acting_user) REFERENCES public."User"(email_address);
|
||||
|
||||
|
||||
--
|
||||
-- Name: DelegationSignerData fktr24j9v14ph2mfuw2gsmt12kq; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -3166,14 +3134,6 @@ ALTER TABLE ONLY public."DelegationSignerData"
|
||||
ADD CONSTRAINT fktr24j9v14ph2mfuw2gsmt12kq FOREIGN KEY (domain_repo_id) REFERENCES public."Domain"(repo_id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
|
||||
--
|
||||
-- Name: UserUpdateHistory fkuserupdatehistoryemailaddress; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."UserUpdateHistory"
|
||||
ADD CONSTRAINT fkuserupdatehistoryemailaddress FOREIGN KEY (email_address) REFERENCES public."User"(email_address);
|
||||
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
||||
@@ -38,7 +38,7 @@ dependencies {
|
||||
|
||||
tasks.register('copyConsole', Copy) {
|
||||
from("${rootDir}/console-webapp/staged/") {
|
||||
include "console-*/*"
|
||||
include "console-*/", "console-*/**"
|
||||
}
|
||||
into layout.buildDirectory.dir('jetty-base/webapps/')
|
||||
dependsOn(':console-webapp:buildConsoleForAll')
|
||||
@@ -50,7 +50,7 @@ tasks.register('stage') {
|
||||
}
|
||||
|
||||
tasks.register('buildNomulusImage', Exec) {
|
||||
commandLine 'docker', 'build', '-t', 'nomulus', '.'
|
||||
commandLine 'docker', 'build', '-t', 'nomulus', '.', '--pull'
|
||||
dependsOn(tasks.named('stage'))
|
||||
}
|
||||
|
||||
@@ -137,3 +137,4 @@ tasks.register('getEndpoints', Exec) {
|
||||
}
|
||||
|
||||
project.build.dependsOn(tasks.named('buildNomulusImage'))
|
||||
rootProject.deploy.dependsOn(tasks.named('deployNomulus'))
|
||||
|
||||