mirror of
https://github.com/google/nomulus
synced 2026-05-17 21:31:51 +00:00
Compare commits
27 Commits
nomulus-20
...
proxy-2025
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10925f2447 | ||
|
|
7641b05f12 | ||
|
|
d130e74004 | ||
|
|
c9c61e4f17 | ||
|
|
da8df1f4d9 | ||
|
|
f649d960c1 | ||
|
|
e5ebc5a2bb | ||
|
|
f9d2839590 | ||
|
|
c6a6bc7e25 | ||
|
|
fce126d426 | ||
|
|
8e41278717 | ||
|
|
cb3738d540 | ||
|
|
71afc25110 | ||
|
|
fa377733be | ||
|
|
21950f7d82 | ||
|
|
e66aee0416 | ||
|
|
c7e1fc17d2 | ||
|
|
0c0b0df36e | ||
|
|
304f0002b4 | ||
|
|
15cf3e1bc0 | ||
|
|
eeed166310 | ||
|
|
e54075fea3 | ||
|
|
78cc1b2937 | ||
|
|
35f95bbbe4 | ||
|
|
ae61cd443d | ||
|
|
cc20f7d76d | ||
|
|
5603b91526 |
@@ -36,7 +36,8 @@ commons-beanutils:commons-beanutils:1.9.4=checkstyle
|
||||
commons-collections:commons-collections:3.2.2=checkstyle
|
||||
info.picocli:picocli:4.6.2=checkstyle
|
||||
io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
|
||||
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
io.github.java-diff-utils:java-diff-utils:4.15=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
jakarta.inject:jakarta.inject-api:1.0.5=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
javax.inject:javax.inject:1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
joda-time:joda-time:2.13.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
@@ -55,11 +56,11 @@ org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
|
||||
org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
|
||||
org.javassist:javassist:3.28.0-GA=checkstyle
|
||||
org.jspecify:jspecify:0.3.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit:junit-bom:5.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit:junit-bom:5.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-commons:9.7=jacocoAnt
|
||||
org.ow2.asm:asm-tree:9.7=jacocoAnt
|
||||
|
||||
@@ -305,7 +305,6 @@
|
||||
{
|
||||
// "Apache License, Version 2.0".
|
||||
"moduleLicense": null,
|
||||
"moduleVersion": "26.26.0",
|
||||
"moduleName": "com.google.cloud:libraries-bom"
|
||||
},
|
||||
{
|
||||
@@ -370,7 +369,6 @@
|
||||
// "Apache License, Version 2.0".
|
||||
{
|
||||
"moduleLicense": null,
|
||||
"moduleVersion": "1.33.0",
|
||||
"moduleName": "io.opentelemetry:opentelemetry-bom"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -166,12 +166,26 @@ export class BackendService {
|
||||
.pipe(catchError((err) => this.errorCatcher<User[]>(err)));
|
||||
}
|
||||
|
||||
createUser(registrarId: string): Observable<User> {
|
||||
createUser(registrarId: string, maybeUser: User | null): Observable<User> {
|
||||
return this.http
|
||||
.post<User>(`/console-api/users?registrarId=${registrarId}`, {})
|
||||
.post<User>(`/console-api/users?registrarId=${registrarId}`, maybeUser)
|
||||
.pipe(catchError((err) => this.errorCatcher<User>(err)));
|
||||
}
|
||||
|
||||
deleteUser(registrarId: string, user: User): Observable<any> {
|
||||
return this.http
|
||||
.delete<any>(`/console-api/users?registrarId=${registrarId}`, {
|
||||
body: JSON.stringify(user),
|
||||
})
|
||||
.pipe(catchError((err) => this.errorCatcher<any>(err)));
|
||||
}
|
||||
|
||||
updateUser(registrarId: string, updatedUser: User): Observable<any> {
|
||||
return this.http
|
||||
.put<User>(`/console-api/users?registrarId=${registrarId}`, updatedUser)
|
||||
.pipe(catchError((err) => this.errorCatcher<any>(err)));
|
||||
}
|
||||
|
||||
getUserData(): Observable<UserData> {
|
||||
return this.http
|
||||
.get<UserData>('/console-api/userdata')
|
||||
|
||||
@@ -27,6 +27,7 @@ export interface UserData {
|
||||
supportEmail: string;
|
||||
supportPhoneNumber: string;
|
||||
technicalDocsUrl: string;
|
||||
userRoles?: Map<string, string>;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
|
||||
105
console-webapp/src/app/users/userDetails.component.html
Normal file
105
console-webapp/src/app/users/userDetails.component.html
Normal file
@@ -0,0 +1,105 @@
|
||||
<div class="console-app__user-details">
|
||||
@if(isEditing) {
|
||||
<h1 class="mat-headline-4">Editing {{ userDetails().emailAddress }}</h1>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="console-app__user-details-controls">
|
||||
<button
|
||||
mat-icon-button
|
||||
aria-label="Back to view user"
|
||||
(click)="isEditing = false"
|
||||
>
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<app-user-edit-form
|
||||
[user]="userDetails()"
|
||||
(onEditComplete)="saveEdit($event)"
|
||||
/>
|
||||
} @else { @if(isNewUser) {
|
||||
<h1 class="mat-headline-4">
|
||||
{{ userDetails().emailAddress + " successfully created" }}
|
||||
</h1>
|
||||
} @else {
|
||||
<h1 class="mat-headline-4">User details</h1>
|
||||
}
|
||||
<mat-divider></mat-divider>
|
||||
<div class="console-app__user-details-controls">
|
||||
<button mat-icon-button aria-label="Back to users list" (click)="goBack()">
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
</button>
|
||||
<div class="spacer"></div>
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
aria-label="Edit User"
|
||||
(click)="isEditing = true"
|
||||
>
|
||||
<mat-icon>edit</mat-icon>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
aria-label="Delete User"
|
||||
(click)="deleteUser()"
|
||||
[disabled]="isLoading"
|
||||
>
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="isNewUser" class="console-app__user-details-save-password">
|
||||
<mat-icon>priority_high</mat-icon>
|
||||
Please save the password. For your security, we do not store passwords in a
|
||||
recoverable format.
|
||||
</div>
|
||||
|
||||
<p *ngIf="isLoading">
|
||||
<mat-progress-bar mode="query"></mat-progress-bar>
|
||||
</p>
|
||||
|
||||
<mat-card appearance="outlined">
|
||||
<mat-card-content>
|
||||
<mat-list role="list">
|
||||
<mat-list-item role="listitem">
|
||||
<h2>User details</h2>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item role="listitem">
|
||||
<span class="console-app__list-key">User email</span>
|
||||
<span class="console-app__list-value">{{
|
||||
userDetails().emailAddress
|
||||
}}</span>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item role="listitem">
|
||||
<span class="console-app__list-key">User role</span>
|
||||
<span class="console-app__list-value">{{
|
||||
roleToDescription(userDetails().role)
|
||||
}}</span>
|
||||
</mat-list-item>
|
||||
@if (userDetails().password) {
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item role="listitem">
|
||||
<span class="console-app__list-key">Password</span>
|
||||
<span
|
||||
class="console-app__list-value console-app__user-details-password"
|
||||
>
|
||||
<input
|
||||
[type]="isPasswordVisible ? 'text' : 'password'"
|
||||
[value]="userDetails().password"
|
||||
disabled
|
||||
/>
|
||||
<button
|
||||
mat-button
|
||||
aria-label="Show password"
|
||||
(click)="isPasswordVisible = !isPasswordVisible"
|
||||
>
|
||||
{{ isPasswordVisible ? "Hide" : "View" }} password
|
||||
</button>
|
||||
</span>
|
||||
</mat-list-item>
|
||||
}
|
||||
</mat-list>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
}
|
||||
</div>
|
||||
39
console-webapp/src/app/users/userDetails.component.scss
Normal file
39
console-webapp/src/app/users/userDetails.component.scss
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
.console-app {
|
||||
&__user-details {
|
||||
&-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
&-password {
|
||||
input {
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
&-save-password {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 15px 10px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 10px;
|
||||
}
|
||||
max-width: 616px;
|
||||
}
|
||||
}
|
||||
101
console-webapp/src/app/users/userDetails.component.ts
Normal file
101
console-webapp/src/app/users/userDetails.component.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, computed } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { SelectedRegistrarModule } from '../app.module';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { SnackBarModule } from '../snackbar.module';
|
||||
import { UsersService, roleToDescription, User } from './users.service';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { UserEditFormComponent } from './userEditForm.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-user-edit',
|
||||
templateUrl: './userDetails.component.html',
|
||||
styleUrls: ['./userDetails.component.scss'],
|
||||
standalone: true,
|
||||
imports: [
|
||||
FormsModule,
|
||||
MaterialModule,
|
||||
SnackBarModule,
|
||||
CommonModule,
|
||||
SelectedRegistrarModule,
|
||||
UserEditFormComponent,
|
||||
],
|
||||
providers: [],
|
||||
})
|
||||
export class UserDetailsComponent {
|
||||
isEditing = false;
|
||||
isPasswordVisible = false;
|
||||
isNewUser = false;
|
||||
isLoading = false;
|
||||
|
||||
userDetails = computed(() => {
|
||||
return this.usersService
|
||||
.users()
|
||||
.filter(
|
||||
(u) => u.emailAddress === this.usersService.currentlyOpenUserEmail()
|
||||
)[0];
|
||||
});
|
||||
|
||||
constructor(
|
||||
protected registrarService: RegistrarService,
|
||||
protected usersService: UsersService,
|
||||
private _snackBar: MatSnackBar
|
||||
) {
|
||||
if (this.usersService.isNewUser) {
|
||||
this.isNewUser = true;
|
||||
this.usersService.isNewUser = false;
|
||||
}
|
||||
}
|
||||
|
||||
roleToDescription(role: string) {
|
||||
return roleToDescription(role);
|
||||
}
|
||||
|
||||
deleteUser() {
|
||||
this.isLoading = true;
|
||||
this.usersService.deleteUser(this.userDetails()).subscribe({
|
||||
error: (err) => {
|
||||
this._snackBar.open(err.error || err.message);
|
||||
this.isLoading = false;
|
||||
},
|
||||
complete: () => {
|
||||
this.isLoading = false;
|
||||
this.goBack();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
goBack() {
|
||||
this.usersService.currentlyOpenUserEmail.set('');
|
||||
}
|
||||
|
||||
saveEdit(user: User) {
|
||||
this.isLoading = true;
|
||||
this.usersService.updateUser(user).subscribe({
|
||||
error: (err) => {
|
||||
this._snackBar.open(err.error || err.message);
|
||||
this.isLoading = false;
|
||||
},
|
||||
complete: () => {
|
||||
this.isLoading = false;
|
||||
this.isEditing = false;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
39
console-webapp/src/app/users/userEditForm.component.html
Normal file
39
console-webapp/src/app/users/userEditForm.component.html
Normal file
@@ -0,0 +1,39 @@
|
||||
<form (ngSubmit)="saveEdit($event)" #form>
|
||||
<p *ngIf="isNew()">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label
|
||||
>User name prefix:
|
||||
<mat-icon
|
||||
matTooltip="Prefix will be combined with registrar ID to create a unique user name - {prefix}.{registrarId}@registry.google"
|
||||
>help_outline</mat-icon
|
||||
></mat-label
|
||||
>
|
||||
<input
|
||||
matInput
|
||||
minlength="3"
|
||||
maxlength="3"
|
||||
[required]="true"
|
||||
[(ngModel)]="user().emailAddress"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</p>
|
||||
<p>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label
|
||||
>User Role:
|
||||
<mat-icon
|
||||
matTooltip="Viewer role doesn't allow making updates; Editor role allows updates, like Contacts delete or SSL certificate change"
|
||||
>help_outline</mat-icon
|
||||
></mat-label
|
||||
>
|
||||
<mat-select [(ngModel)]="user().role" name="userRole">
|
||||
<mat-option value="PRIMARY_CONTACT">Editor</mat-option>
|
||||
<mat-option value="ACCOUNT_MANAGER">Viewer</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</p>
|
||||
<button mat-flat-button color="primary" aria-label="Save user" type="submit">
|
||||
Save
|
||||
</button>
|
||||
</form>
|
||||
58
console-webapp/src/app/users/userEditForm.component.ts
Normal file
58
console-webapp/src/app/users/userEditForm.component.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CommonModule } from '@angular/common';
|
||||
import {
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
input,
|
||||
Output,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { User } from './users.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-user-edit-form',
|
||||
templateUrl: './userEditForm.component.html',
|
||||
styleUrls: ['./userEditForm.component.scss'],
|
||||
standalone: true,
|
||||
imports: [FormsModule, MaterialModule, CommonModule],
|
||||
providers: [],
|
||||
})
|
||||
export class UserEditFormComponent {
|
||||
@ViewChild('form') form!: ElementRef;
|
||||
isNew = input<boolean>(false);
|
||||
user = input<User>(
|
||||
{
|
||||
emailAddress: '',
|
||||
role: 'ACCOUNT_MANAGER',
|
||||
},
|
||||
// @ts-ignore - legit option, typescript fails to match it to a proper type
|
||||
{ transform: (user: User) => structuredClone(user) }
|
||||
);
|
||||
|
||||
@Output() onEditComplete = new EventEmitter<User>();
|
||||
|
||||
saveEdit(e: SubmitEvent) {
|
||||
e.preventDefault();
|
||||
if (this.form.nativeElement.checkValidity()) {
|
||||
this.onEditComplete.emit(this.user());
|
||||
} else {
|
||||
this.form.nativeElement.reportValidity();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +1,107 @@
|
||||
<app-selected-registrar-wrapper>
|
||||
@if (!isLoading) {
|
||||
@if(isLoading) {
|
||||
<div class="console-app__users-spinner">
|
||||
<mat-spinner />
|
||||
</div>
|
||||
} @else if(selectingExistingUser) {
|
||||
<div class="console-app__users">
|
||||
<h1 class="mat-headline-4">Add existing user</h1>
|
||||
<p>
|
||||
<button
|
||||
mat-icon-button
|
||||
aria-label="Back to users list"
|
||||
(click)="selectingExistingUser = false"
|
||||
>
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
</button>
|
||||
</p>
|
||||
<h1>Select registrar from which to add a new user</h1>
|
||||
<p>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Registrar</mat-label>
|
||||
<mat-select
|
||||
[(ngModel)]="selectedRegistrarId"
|
||||
name="selectedRegistrarId"
|
||||
(selectionChange)="onRegistrarSelectionChange($event)"
|
||||
>
|
||||
@for (registrar of registrarService.registrars(); track registrar) {
|
||||
<mat-option [value]="registrar.registrarId">{{
|
||||
registrar.registrarId
|
||||
}}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</p>
|
||||
@if(usersSelection.length) {
|
||||
<app-users-list
|
||||
[users]="usersSelection"
|
||||
(onSelect)="existingUserSelected($event)"
|
||||
/>
|
||||
<p class="console-app__users-add-existing">
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
aria-label="Add user"
|
||||
(click)="submitExistingUser()"
|
||||
[disabled]="!selectedExistingUser"
|
||||
>
|
||||
Add user
|
||||
</button>
|
||||
<button
|
||||
mat-stroked-button
|
||||
aria-label="Cancel adding existing user"
|
||||
(click)="selectingExistingUser = false"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
} @else if(usersService.currentlyOpenUserEmail()) {
|
||||
<app-user-edit></app-user-edit>
|
||||
} @else if(isNew) {
|
||||
<h1 class="mat-headline-4">New User Form</h1>
|
||||
<div class="spacer"></div>
|
||||
<p>
|
||||
<button
|
||||
mat-icon-button
|
||||
aria-label="Back to users list"
|
||||
(click)="isNew = false"
|
||||
>
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
</button>
|
||||
</p>
|
||||
<app-user-edit-form [isNew]="true" (onEditComplete)="createNewUser($event)" />
|
||||
} @else {
|
||||
<div class="console-app__users">
|
||||
<div class="console-app__users-header">
|
||||
<h1 class="mat-headline-4">Users</h1>
|
||||
<div class="spacer"></div>
|
||||
<button
|
||||
mat-flat-button
|
||||
(click)="createNewUser()"
|
||||
aria-label="Create new user"
|
||||
color="primary"
|
||||
>
|
||||
Create a Viewer User
|
||||
</button>
|
||||
<div class="console-app__users-header-buttons">
|
||||
<button
|
||||
class="console-app__users-header-add"
|
||||
mat-stroked-button
|
||||
(click)="addExistingUser()"
|
||||
aria-label="Create new user"
|
||||
color="primary"
|
||||
>
|
||||
<mat-icon>add</mat-icon>
|
||||
Add existing user
|
||||
</button>
|
||||
<button
|
||||
mat-flat-button
|
||||
(click)="isNew = true"
|
||||
aria-label="Create new user"
|
||||
color="primary"
|
||||
>
|
||||
Create New User
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<mat-table
|
||||
[dataSource]="dataSource"
|
||||
class="mat-elevation-z0"
|
||||
class="console-app__users-table"
|
||||
matSort
|
||||
>
|
||||
<ng-container
|
||||
*ngFor="let column of columns"
|
||||
[matColumnDef]="column.columnDef"
|
||||
>
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
{{ column.header }}
|
||||
</mat-header-cell>
|
||||
<mat-cell
|
||||
*matCellDef="let row"
|
||||
[innerHTML]="column.cell(row)"
|
||||
></mat-cell>
|
||||
</ng-container>
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
|
||||
</mat-table>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="console-app__users-spinner">
|
||||
<mat-spinner />
|
||||
<app-users-list
|
||||
[users]="usersService.users()"
|
||||
(onSelect)="openDetails($event)"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</app-selected-registrar-wrapper>
|
||||
|
||||
@@ -13,26 +13,37 @@
|
||||
// limitations under the License.
|
||||
|
||||
.console-app {
|
||||
&__users {
|
||||
max-width: 1024px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
&__users-spinner {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
$min-width: 756px;
|
||||
$max-width: 1024px;
|
||||
|
||||
&__users-table {
|
||||
min-width: $min-width !important;
|
||||
max-width: $max-width;
|
||||
}
|
||||
|
||||
&__users-new {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
&__users-add-existing {
|
||||
margin-top: 20px;
|
||||
> button {
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
&__users-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
&-buttons {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
button {
|
||||
margin: 0 15px 15px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,36 +14,19 @@
|
||||
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { Component, effect, ViewChild } from '@angular/core';
|
||||
import { Component, effect } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { SelectedRegistrarModule } from '../app.module';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { SnackBarModule } from '../snackbar.module';
|
||||
import { UserDetailsComponent } from './userDetails.component';
|
||||
import { User, UsersService } from './users.service';
|
||||
|
||||
const roleToDescription = (role: String) => {
|
||||
if (!role) return 'N/A';
|
||||
else if (role.toLowerCase().startsWith('account_manager')) {
|
||||
return 'Viewer';
|
||||
}
|
||||
return 'Editor';
|
||||
};
|
||||
|
||||
export const columns = [
|
||||
{
|
||||
columnDef: 'emailAddress',
|
||||
header: 'User email',
|
||||
cell: (record: User) => `${record.emailAddress || ''}`,
|
||||
},
|
||||
{
|
||||
columnDef: 'role',
|
||||
header: 'User role',
|
||||
cell: (record: User) => `${roleToDescription(record.role)}`,
|
||||
},
|
||||
];
|
||||
import { UserDataService } from '../shared/services/userData.service';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { UsersListComponent } from './usersList.component';
|
||||
import { MatSelectChange } from '@angular/material/select';
|
||||
import { UserEditFormComponent } from './userEditForm.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-users',
|
||||
@@ -51,40 +34,47 @@ export const columns = [
|
||||
styleUrls: ['./users.component.scss'],
|
||||
standalone: true,
|
||||
imports: [
|
||||
FormsModule,
|
||||
MaterialModule,
|
||||
SnackBarModule,
|
||||
CommonModule,
|
||||
SelectedRegistrarModule,
|
||||
UsersListComponent,
|
||||
UserEditFormComponent,
|
||||
UserDetailsComponent,
|
||||
],
|
||||
providers: [UsersService],
|
||||
})
|
||||
export class UsersComponent {
|
||||
dataSource: MatTableDataSource<User>;
|
||||
columns = columns;
|
||||
displayedColumns = this.columns.map((c) => c.columnDef);
|
||||
isLoading = false;
|
||||
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
isNew = false;
|
||||
selectingExistingUser = false;
|
||||
selectedRegistrarId = '';
|
||||
usersSelection: User[] = [];
|
||||
selectedExistingUser: User | undefined;
|
||||
|
||||
constructor(
|
||||
protected registrarService: RegistrarService,
|
||||
protected usersService: UsersService,
|
||||
private userDataService: UserDataService,
|
||||
private _snackBar: MatSnackBar
|
||||
) {
|
||||
this.dataSource = new MatTableDataSource<User>(usersService.users());
|
||||
|
||||
effect(() => {
|
||||
if (registrarService.registrarId()) {
|
||||
this.loadUsers();
|
||||
}
|
||||
});
|
||||
effect(() => {
|
||||
this.dataSource.data = usersService.users();
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.dataSource.sort = this.sort;
|
||||
addExistingUser() {
|
||||
this.selectingExistingUser = true;
|
||||
this.selectedRegistrarId = '';
|
||||
this.usersSelection = [];
|
||||
this.selectedExistingUser = undefined;
|
||||
}
|
||||
|
||||
existingUserSelected(user: User) {
|
||||
this.selectedExistingUser = user;
|
||||
}
|
||||
|
||||
loadUsers() {
|
||||
@@ -92,6 +82,7 @@ export class UsersComponent {
|
||||
this.usersService.fetchUsers().subscribe({
|
||||
error: (err: HttpErrorResponse) => {
|
||||
this._snackBar.open(err.error || err.message);
|
||||
this.isLoading = false;
|
||||
},
|
||||
complete: () => {
|
||||
this.isLoading = false;
|
||||
@@ -99,24 +90,52 @@ export class UsersComponent {
|
||||
});
|
||||
}
|
||||
|
||||
createNewUser() {
|
||||
createNewUser(user: User) {
|
||||
this.isLoading = true;
|
||||
this.usersService.createNewUser().subscribe({
|
||||
next: (newUser) => {
|
||||
this._snackBar.open(
|
||||
`New user with email ${newUser.emailAddress} has been created.`,
|
||||
'',
|
||||
{
|
||||
duration: 2000,
|
||||
}
|
||||
);
|
||||
},
|
||||
this.usersService.createOrAddNewUser(user).subscribe({
|
||||
error: (err: HttpErrorResponse) => {
|
||||
this._snackBar.open(err.error || err.message);
|
||||
this.isLoading = false;
|
||||
},
|
||||
complete: () => {
|
||||
this.isLoading = false;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
openDetails(user: User) {
|
||||
this.usersService.currentlyOpenUserEmail.set(user.emailAddress);
|
||||
}
|
||||
|
||||
onRegistrarSelectionChange(e: MatSelectChange) {
|
||||
if (e.value) {
|
||||
this.usersService.fetchUsersForRegistrar(e.value).subscribe({
|
||||
error: (err) => {
|
||||
this._snackBar.open(err.error || err.message);
|
||||
},
|
||||
next: (users) => {
|
||||
this.usersSelection = users;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
submitExistingUser() {
|
||||
this.isLoading = true;
|
||||
if (this.selectedExistingUser) {
|
||||
this.usersService
|
||||
.createOrAddNewUser(this.selectedExistingUser)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
this._snackBar.open(err.error || err.message);
|
||||
this.isLoading = false;
|
||||
},
|
||||
complete: () => {
|
||||
this.isLoading = false;
|
||||
this.selectingExistingUser = false;
|
||||
this.loadUsers();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,29 +13,43 @@
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable, signal } from '@angular/core';
|
||||
import { tap } from 'rxjs';
|
||||
import { switchMap, tap } from 'rxjs';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { BackendService } from '../shared/services/backend.service';
|
||||
|
||||
export const roleToDescription = (role: string) => {
|
||||
if (!role) return 'N/A';
|
||||
else if (role === 'ACCOUNT_MANAGER') {
|
||||
return 'Viewer';
|
||||
}
|
||||
return 'Editor';
|
||||
};
|
||||
|
||||
export interface CreateAutoTimestamp {
|
||||
creationTime: string;
|
||||
}
|
||||
|
||||
export interface User {
|
||||
emailAddress: String;
|
||||
role: String;
|
||||
password?: String;
|
||||
emailAddress: string;
|
||||
role: string;
|
||||
password?: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class UsersService {
|
||||
users = signal<User[]>([]);
|
||||
currentlyOpenUserEmail = signal<string>('');
|
||||
isNewUser: boolean = false;
|
||||
|
||||
constructor(
|
||||
private backendService: BackendService,
|
||||
private registrarService: RegistrarService
|
||||
) {}
|
||||
|
||||
fetchUsersForRegistrar(registrarId: string) {
|
||||
return this.backendService.getUsers(registrarId);
|
||||
}
|
||||
|
||||
fetchUsers() {
|
||||
return this.backendService
|
||||
.getUsers(this.registrarService.registrarId())
|
||||
@@ -46,13 +60,29 @@ export class UsersService {
|
||||
);
|
||||
}
|
||||
|
||||
createNewUser() {
|
||||
createOrAddNewUser(user: User) {
|
||||
return this.backendService
|
||||
.createUser(this.registrarService.registrarId())
|
||||
.createUser(this.registrarService.registrarId(), user)
|
||||
.pipe(
|
||||
tap((newUser: User) => {
|
||||
this.users.set([...this.users(), newUser]);
|
||||
if (newUser) {
|
||||
this.users.set([...this.users(), newUser]);
|
||||
this.currentlyOpenUserEmail.set(newUser.emailAddress);
|
||||
this.isNewUser = true;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
deleteUser(user: User) {
|
||||
return this.backendService
|
||||
.deleteUser(this.registrarService.registrarId(), user)
|
||||
.pipe(switchMap((_) => this.fetchUsers()));
|
||||
}
|
||||
|
||||
updateUser(updatedUser: User) {
|
||||
return this.backendService
|
||||
.updateUser(this.registrarService.registrarId(), updatedUser)
|
||||
.pipe(switchMap((_) => this.fetchUsers()));
|
||||
}
|
||||
}
|
||||
|
||||
24
console-webapp/src/app/users/usersList.component.html
Normal file
24
console-webapp/src/app/users/usersList.component.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<div class="console-app__users-table-wrapper">
|
||||
<mat-table
|
||||
[dataSource]="dataSource"
|
||||
class="mat-elevation-z0"
|
||||
class="console-app__users-table"
|
||||
matSort
|
||||
>
|
||||
<ng-container
|
||||
*ngFor="let column of columns"
|
||||
[matColumnDef]="column.columnDef"
|
||||
>
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
{{ column.header }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" [innerHTML]="column.cell(row)"></mat-cell>
|
||||
</ng-container>
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row
|
||||
*matRowDef="let row; columns: displayedColumns"
|
||||
[class.rowSelected]="isRowSelected(row)"
|
||||
(click)="onClick(row)"
|
||||
></mat-row>
|
||||
</mat-table>
|
||||
</div>
|
||||
14
console-webapp/src/app/users/usersList.component.scss
Normal file
14
console-webapp/src/app/users/usersList.component.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
.console-app {
|
||||
&__users-table {
|
||||
min-width: 616px;
|
||||
.rowSelected {
|
||||
background-color: var(--light-highlight);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
&__users-table-wrapper {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
78
console-webapp/src/app/users/usersList.component.ts
Normal file
78
console-webapp/src/app/users/usersList.component.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CommonModule } from '@angular/common';
|
||||
import {
|
||||
Component,
|
||||
effect,
|
||||
EventEmitter,
|
||||
input,
|
||||
Output,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { User, roleToDescription } from './users.service';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
|
||||
export const columns = [
|
||||
{
|
||||
columnDef: 'emailAddress',
|
||||
header: 'User email',
|
||||
cell: (record: User) => `${record.emailAddress || ''}`,
|
||||
},
|
||||
{
|
||||
columnDef: 'role',
|
||||
header: 'User role',
|
||||
cell: (record: User) => `${roleToDescription(record.role)}`,
|
||||
},
|
||||
];
|
||||
|
||||
@Component({
|
||||
selector: 'app-users-list',
|
||||
templateUrl: './usersList.component.html',
|
||||
styleUrls: ['./usersList.component.scss'],
|
||||
standalone: true,
|
||||
imports: [MaterialModule, CommonModule],
|
||||
providers: [],
|
||||
})
|
||||
export class UsersListComponent {
|
||||
columns = columns;
|
||||
displayedColumns = this.columns.map((c) => c.columnDef);
|
||||
dataSource: MatTableDataSource<User>;
|
||||
selectedRow!: User;
|
||||
users = input<User[]>([]);
|
||||
@Output() onSelect = new EventEmitter<User>();
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
|
||||
constructor() {
|
||||
this.dataSource = new MatTableDataSource<User>(this.users());
|
||||
effect(() => {
|
||||
this.dataSource.data = this.users();
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.dataSource.sort = this.sort;
|
||||
}
|
||||
|
||||
onClick(row: User) {
|
||||
this.selectedRow = row;
|
||||
this.onSelect.emit(row);
|
||||
}
|
||||
|
||||
isRowSelected(row: User) {
|
||||
return row === this.selectedRow;
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import java.util.Optional
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id "org.flywaydb.flyway" version "10.8.1"
|
||||
id "org.flywaydb.flyway" version "11.0.1"
|
||||
id 'maven-publish'
|
||||
}
|
||||
|
||||
@@ -166,6 +166,7 @@ dependencies {
|
||||
// gradleLint.ignore('unused-dependency') {
|
||||
implementation deps['com.google.gwt:gwt-user']
|
||||
// }
|
||||
implementation deps['com.google.cloud:google-cloud-compute']
|
||||
implementation deps['com.google.cloud:google-cloud-core']
|
||||
implementation deps['com.google.cloud:google-cloud-storage']
|
||||
implementation deps['com.google.cloud:google-cloud-tasks']
|
||||
|
||||
@@ -5,9 +5,9 @@ com.fasterxml.jackson.core:jackson-annotations:2.15.2=classpath
|
||||
com.fasterxml.jackson.core:jackson-core:2.15.2=classpath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.15.2=classpath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.15.2=classpath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2=classpath
|
||||
com.fasterxml.jackson:jackson-bom:2.15.2=classpath
|
||||
com.google.code.gson:gson:2.10.1=classpath
|
||||
gradle.plugin.org.flywaydb:gradle-plugin-publishing:10.8.1=classpath
|
||||
org.flywaydb.flyway:org.flywaydb.flyway.gradle.plugin:10.8.1=classpath
|
||||
org.flywaydb:flyway-core:10.8.1=classpath
|
||||
gradle.plugin.org.flywaydb:gradle-plugin-publishing:11.0.1=classpath
|
||||
org.flywaydb.flyway:org.flywaydb.flyway.gradle.plugin:11.0.1=classpath
|
||||
org.flywaydb:flyway-core:11.0.1=classpath
|
||||
empty=
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
aopalliance:aopalliance:1.0=annotationProcessor,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
args4j:args4j:2.33=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
com.charleskorn.kaml:kaml:0.20.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.18.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.18.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.18.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.18.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.18.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.18.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml:classmate:1.5.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.github.ben-manes.caffeine:caffeine:3.1.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -29,118 +29,152 @@ com.github.jnr:jnr-x86asm:1.0.2=compileClasspath,deploy_jar,nonprodCompileClassp
|
||||
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.android:annotations:4.1.1.4=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-jackson2:2.0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api-client:google-api-client-jackson2:2.2.0=testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-jackson2:2.7.0=testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-java6:2.1.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-servlet:2.2.0=testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-servlet:2.7.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api-client:google-api-client:2.7.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-servlet:2.7.0=testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-servlet:2.7.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api-client:google-api-client:2.7.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.32.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.43.2-beta=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.5.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.177.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.177.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.39.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.111.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.13.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.46.0-beta=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.9.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.9.2=testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.181.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.181.2=testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.181.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.181.2=testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.44.1=testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.114.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.115.0=testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.14.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.14.3=testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.74.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.77.0=testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.74.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.77.0=testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.74.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.77.0=testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.32.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.43.2-beta=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.39.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.5.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.177.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.177.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.39.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.39.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-datastore-v1:0.110.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-firestore-v1:3.21.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.111.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.13.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.29.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:2.29.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-executor-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.46.0-beta=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.45.1=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.9.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.9.2=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1alpha:3.9.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1alpha:3.9.2=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.181.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.181.2=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.181.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.181.2=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.44.1=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.44.1=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-compute-v1:1.65.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-datastore-v1:0.112.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-datastore-v1:0.113.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-firestore-v1:3.25.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-firestore-v1:3.26.5=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.49.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.52.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.114.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.115.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.14.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.14.3=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.51.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.55.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.51.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.55.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.74.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.77.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.74.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.77.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-executor-v1:6.74.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:6.74.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:6.77.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.32.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.43.2-beta=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.29.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.119.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.142.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.119.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.142.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:api-common:2.38.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-grpc:2.55.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:2.55.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.55.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev20240924-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20240919-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.46.0-beta=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.51.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.55.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.141.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.145.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.141.0=testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.145.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:api-common:2.42.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-grpc:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev20241210-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20240815-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20240310-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20240817-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20241209-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dns:v1-rev20240719-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-drive:v3-rev20240914-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-drive:v3-rev20241027-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-gmail:v1-rev20240520-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev20220614-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-healthcare:v1-rev20240130-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-iam:v2-rev20240530-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-iamcredentials:v1-rev20211203-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-monitoring:v3-rev20240929-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-monitoring:v3-rev20241017-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-pubsub:v1-rev20220904-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sheets:v4-rev20241001-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sheets:v4-rev20241203-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sqladmin:v1beta4-rev20240925-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240319-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240924-2.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240706-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20241206-2.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.30.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.30.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.service:auto-service-annotations:1.0.1=errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.auto.service:auto-service-annotations:1.1.1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.service:auto-service:1.1.1=annotationProcessor
|
||||
com.google.auto.value:auto-value-annotations:1.11.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.auto.value:auto-value:1.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value:1.11.0=annotationProcessor,testAnnotationProcessor
|
||||
com.google.auto.value:auto-value:1.11.0=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto:auto-common:1.2.1=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.cloud.bigdataoss:gcsio:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigdataoss:util:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigtable:bigtable-client-core-config:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.datastore:datastore-v1-proto-client:2.19.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.opentelemetry:detector-resources-support:0.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud.opentelemetry:detector-resources-support:0.32.0=testRuntimeClasspath
|
||||
com.google.cloud.opentelemetry:exporter-metrics:0.31.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.opentelemetry:shared-resourcemapping:0.32.0=testRuntimeClasspath
|
||||
com.google.cloud.datastore:datastore-v1-proto-client:2.21.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.opentelemetry:detector-resources-support:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud.opentelemetry:detector-resources-support:0.33.0=testRuntimeClasspath
|
||||
com.google.cloud.opentelemetry:exporter-metrics:0.33.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.opentelemetry:shared-resourcemapping:0.33.0=testRuntimeClasspath
|
||||
com.google.cloud.sql:jdbc-socket-factory-core:1.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:postgres-socket-factory:1.21.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigquerystorage:3.5.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable:2.39.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.38.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigquerystorage:3.9.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud:google-cloud-bigquerystorage:3.9.2=testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable:2.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud:google-cloud-bigtable:2.44.1=testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-compute:1.65.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.42.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.49.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.38.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-firestore:3.21.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-monitoring:3.44.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-nio:0.127.25=testCompileClasspath
|
||||
com.google.cloud:google-cloud-nio:0.127.6=testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsub:1.129.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsublite:1.13.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.29.0=testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud:google-cloud-spanner:6.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.49.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.42.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.49.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-firestore:3.25.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud:google-cloud-firestore:3.26.5=testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-monitoring:3.49.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-monitoring:3.52.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-nio:0.127.24=testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-nio:0.127.28=testCompileClasspath
|
||||
com.google.cloud:google-cloud-pubsub:1.132.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud:google-cloud-pubsub:1.133.0=testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsublite:1.14.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud:google-cloud-pubsublite:1.14.3=testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.51.0=testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.55.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud:google-cloud-spanner:6.74.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud:google-cloud-spanner:6.77.0=testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.32.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.43.2=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.29.0=testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud:grpc-gcp:1.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:libraries-bom:26.26.0=testRuntimeClasspath
|
||||
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.21.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.46.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.51.0=testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.55.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud:grpc-gcp:1.6.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:libraries-bom:26.48.0=testRuntimeClasspath
|
||||
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.25.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.26.5=testRuntimeClasspath
|
||||
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.gson:gson:2.10.1=soy
|
||||
com.google.code.gson:gson:2.11.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -152,7 +186,7 @@ com.google.devtools.ksp:symbol-processing-api:1.9.20-1.0.14=annotationProcessor,
|
||||
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.20.0=soy
|
||||
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.33.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle
|
||||
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
@@ -171,21 +205,25 @@ com.google.googlejavaformat:google-java-format:1.5=annotationProcessor,testAnnot
|
||||
com.google.guava:failureaccess:1.0.1=checkstyle,errorprone,nonprodAnnotationProcessor,soy
|
||||
com.google.guava:failureaccess:1.0.2=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:guava-parent:32.1.1-jre=errorprone,nonprodAnnotationProcessor,soy
|
||||
com.google.guava:guava-testlib:33.3.1-jre=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:guava-testlib:33.3.0-jre=testRuntimeClasspath
|
||||
com.google.guava:guava-testlib:33.4.0-jre=testCompileClasspath
|
||||
com.google.guava:guava:31.0.1-jre=checkstyle
|
||||
com.google.guava:guava:32.1.1-jre=errorprone,nonprodAnnotationProcessor,soy
|
||||
com.google.guava:guava:33.0.0-jre=annotationProcessor,testAnnotationProcessor
|
||||
com.google.guava:guava:33.3.1-jre=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:guava:33.3.1-jre=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.guava:guava:33.4.0-jre=testCompileClasspath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.gwt:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.45.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.45.3=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-gson:1.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.45.3=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-gson:1.45.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-protobuf:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client:1.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.45.3=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-protobuf:1.44.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.http-client:google-http-client-protobuf:1.45.0=testRuntimeClasspath
|
||||
com.google.http-client:google-http-client:1.45.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.inject:guice:7.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.j2objc:j2objc-annotations:1.3=checkstyle
|
||||
@@ -195,12 +233,12 @@ com.google.jsinterop:jsinterop-annotations:2.0.0=compileClasspath,deploy_jar,non
|
||||
com.google.monitoring-client:contrib:1.0.7=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.monitoring-client:metrics:1.0.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.monitoring-client:stackdriver:1.0.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-java6:1.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.34.1=testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.34.1=testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.oauth-client:google-oauth-client:1.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-java6:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.36.0=testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.36.0=testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
com.google.oauth-client:google-oauth-client:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java-util:3.25.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.protobuf:protobuf-java:3.25.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -238,7 +276,7 @@ com.sun.istack:istack-commons-tools:4.1.2=jaxb
|
||||
com.sun.xml.bind.external:relaxng-datatype:4.0.5=jaxb
|
||||
com.sun.xml.bind.external:rngom:4.0.5=jaxb
|
||||
com.sun.xml.dtd-parser:dtd-parser:1.5.1=jaxb
|
||||
com.zaxxer:HikariCP:6.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.zaxxer:HikariCP:6.2.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-beanutils:commons-beanutils:1.9.4=checkstyle
|
||||
commons-codec:commons-codec:1.17.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-collections:commons-collections:3.2.2=checkstyle
|
||||
@@ -258,43 +296,57 @@ info.picocli:picocli:4.6.2=checkstyle
|
||||
io.apicurio:apicurio-registry-protobuf-schema-utilities:3.0.0.M2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.github.classgraph:classgraph:4.8.162=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-alts:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-api:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-auth:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-census:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-context:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-core:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-googleapis:1.67.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-grpclb:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-inprocess:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-netty-shaded:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-netty:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-opentelemetry:1.67.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf-lite:1.67.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-rls:1.62.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.grpc:grpc-rls:1.67.1=testRuntimeClasspath
|
||||
io.grpc:grpc-services:1.62.2=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-services:1.67.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-stub:1.67.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-util:1.62.2=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-util:1.67.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-xds:1.62.2=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-xds:1.67.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-buffer:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-http2:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-http:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-socks:4.1.100.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-common:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-handler-proxy:4.1.100.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-handler:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-resolver:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
io.github.java-diff-utils:java-diff-utils:4.15=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-alts:1.69.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-api:1.69.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-auth:1.69.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-census:1.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
io.grpc:grpc-census:1.68.0=testRuntimeClasspath
|
||||
io.grpc:grpc-context:1.69.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-core:1.69.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-googleapis:1.69.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-grpclb:1.69.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-inprocess:1.69.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-netty-shaded:1.69.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-netty:1.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
io.grpc:grpc-netty:1.68.0=testRuntimeClasspath
|
||||
io.grpc:grpc-opentelemetry:1.69.0=testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf-lite:1.69.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf:1.69.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-rls:1.66.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.grpc:grpc-rls:1.69.0=testRuntimeClasspath
|
||||
io.grpc:grpc-services:1.66.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-services:1.69.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-stub:1.69.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-util:1.66.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-util:1.69.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-xds:1.66.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
io.grpc:grpc-xds:1.69.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-buffer:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
io.netty:netty-buffer:4.1.110.Final=testRuntimeClasspath
|
||||
io.netty:netty-codec-http2:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
io.netty:netty-codec-http2:4.1.110.Final=testRuntimeClasspath
|
||||
io.netty:netty-codec-http:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
io.netty:netty-codec-http:4.1.110.Final=testRuntimeClasspath
|
||||
io.netty:netty-codec-socks:4.1.100.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.netty:netty-codec-socks:4.1.110.Final=testRuntimeClasspath
|
||||
io.netty:netty-codec:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
io.netty:netty-codec:4.1.110.Final=testRuntimeClasspath
|
||||
io.netty:netty-common:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
io.netty:netty-common:4.1.110.Final=testRuntimeClasspath
|
||||
io.netty:netty-handler-proxy:4.1.100.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.netty:netty-handler-proxy:4.1.110.Final=testRuntimeClasspath
|
||||
io.netty:netty-handler:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
io.netty:netty-handler:4.1.110.Final=testRuntimeClasspath
|
||||
io.netty:netty-resolver:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
io.netty:netty-resolver:4.1.110.Final=testRuntimeClasspath
|
||||
io.netty:netty-tcnative-boringssl-static:2.0.52.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-tcnative-classes:2.0.52.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-transport-native-unix-common:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-transport:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-transport-native-unix-common:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
io.netty:netty-transport-native-unix-common:4.1.110.Final=testRuntimeClasspath
|
||||
io.netty:netty-transport:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
|
||||
io.netty:netty-transport:4.1.110.Final=testRuntimeClasspath
|
||||
io.opencensus:opencensus-api:0.31.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-exemplar-util:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-grpc-metrics:0.31.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
@@ -306,29 +358,35 @@ io.opencensus:opencensus-exporter-metrics-util:0.31.0=compileClasspath,deploy_ja
|
||||
io.opencensus:opencensus-exporter-stats-stackdriver:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-impl-core:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-impl:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-proto:0.2.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-proto:0.2.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry.contrib:opentelemetry-gcp-resources:1.37.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry.semconv:opentelemetry-semconv:1.25.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-api-incubator:1.37.0-alpha=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-api-incubator:1.42.1-alpha=testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-api:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-api:1.42.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-bom:1.33.0=testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-context:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-context:1.42.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-exporter-logging:1.42.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-common:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-common:1.42.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.42.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.42.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-logs:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-logs:1.42.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-metrics:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-metrics:1.42.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-trace:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-trace:1.42.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk:1.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk:1.42.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry.instrumentation:opentelemetry-grpc-1.6:2.1.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator:2.1.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry.semconv:opentelemetry-semconv:1.23.1-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry.semconv:opentelemetry-semconv:1.27.0-alpha=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-api-incubator:1.41.0-alpha=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-api-incubator:1.45.0-alpha=testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-api:1.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-api:1.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-bom:1.42.1=testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-context:1.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-context:1.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-exporter-logging:1.44.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-extension-incubator:1.35.0-alpha=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-common:1.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-common:1.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.44.1=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-logs:1.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-logs:1.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-metrics:1.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-metrics:1.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-trace:1.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk-trace:1.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk:1.41.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
io.opentelemetry:opentelemetry-sdk:1.45.0=testCompileClasspath,testRuntimeClasspath
|
||||
io.opentelemetry:opentelemetry-semconv:1.26.0-alpha=testRuntimeClasspath
|
||||
io.outfoxx:swiftpoet:1.3.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.perfmark:perfmark-api:0.27.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
io.smallrye:jandex:3.1.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
@@ -346,15 +404,14 @@ javax.annotation:javax.annotation-api:1.3.2=compileClasspath,deploy_jar,nonprodC
|
||||
javax.annotation:jsr250-api:1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
|
||||
javax.inject:javax.inject:1=annotationProcessor,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
javax.jdo:jdo2-api:2.3-20090302111651=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.servlet:servlet-api:2.5=testRuntimeClasspath
|
||||
javax.validation:validation-api:1.0.0.GA=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
joda-time:joda-time:2.12.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
junit:junit:4.13.2=nonprodCompileClasspath,nonprodRuntimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
net.arnx:nashorn-promise:0.1.1=testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy-agent:1.15.3=testCompileClasspath,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy-agent:1.15.4=testCompileClasspath,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.14.12=compileClasspath,nonprodCompileClasspath
|
||||
net.bytebuddy:byte-buddy:1.14.15=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.15.3=testCompileClasspath,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.15.10=testCompileClasspath,testRuntimeClasspath
|
||||
net.java.dev.jna:jna:5.13.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
net.ltgt.gradle.incap:incap:0.2=annotationProcessor,testAnnotationProcessor
|
||||
net.sf.saxon:Saxon-HE:10.6=checkstyle
|
||||
@@ -368,31 +425,32 @@ org.apache.arrow:arrow-format:15.0.2=compileClasspath,deploy_jar,nonprodCompileC
|
||||
org.apache.arrow:arrow-memory-core:15.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.arrow:arrow-vector:15.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.avro:avro:1.12.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-fn-execution:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-job-management:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-pipeline:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-fn-execution:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-job-management:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-pipeline:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-construction-java:2.54.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-java:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-direct-java:2.59.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-java-fn-execution:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-core:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-expansion-service:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-arrow:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-avro:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-java:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-direct-java:2.61.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-java-fn-execution:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-core:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-expansion-service:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-arrow:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-avro:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-fn-execution:2.54.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-harness:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-transform-service-launcher:2.59.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-grpc-1_60_1:0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-harness:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-transform-service-launcher:2.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-grpc-1_60_1:0.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-guava-32_1_2-jre:0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-compress:1.26.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-csv:1.12.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-exec:1.4.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-lang3:3.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-text:1.12.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-lang3:3.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
org.apache.commons:commons-lang3:3.17.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-text:1.13.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.ftpserver:ftplet-api:1.2.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.ftpserver:ftpserver-core:1.2.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -402,37 +460,37 @@ org.apache.sshd:sshd-common:2.14.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-core:2.14.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-scp:2.14.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-sftp:2.14.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.tomcat:tomcat-annotations-api:11.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.tomcat:tomcat-annotations-api:11.0.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
|
||||
org.bouncycastle:bcpg-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpkix-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcprov-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcutil-jdk18on:1.78.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpg-jdk18on:1.79=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpkix-jdk18on:1.79=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcprov-jdk18on:1.79=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcutil-jdk18on:1.79=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-compat-qual:2.5.3=compileClasspath,nonprodCompileClasspath,soy,testCompileClasspath
|
||||
org.checkerframework:checker-compat-qual:2.5.5=annotationProcessor,testAnnotationProcessor
|
||||
org.checkerframework:checker-compat-qual:2.5.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-qual:3.12.0=checkstyle
|
||||
org.checkerframework:checker-qual:3.33.0=errorprone,nonprodAnnotationProcessor,soy
|
||||
org.checkerframework:checker-qual:3.41.0=annotationProcessor,testAnnotationProcessor
|
||||
org.checkerframework:checker-qual:3.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-qual:3.48.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.24=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.conscrypt:conscrypt-openjdk-uber:2.5.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.angus:angus-activation:2.0.2=deploy_jar,jaxb,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.eclipse.angus:jakarta.mail:2.0.3=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.eclipse.collections:eclipse-collections-api:11.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.collections:eclipse-collections:11.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.0.14=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.0.14=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-ee:12.0.14=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-http:12.0.14=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-io:12.0.14=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-security:12.0.14=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-server:12.0.14=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-session:12.0.14=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util:12.0.14=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-xml:12.0.14=testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-core:10.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-database-postgresql:10.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.1.0.alpha0=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.1.0.alpha0=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-ee:12.1.0.alpha0=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-http:12.1.0.alpha0=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-io:12.1.0.alpha0=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-security:12.1.0.alpha0=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-server:12.1.0.alpha0=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-session:12.1.0.alpha0=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util:12.1.0.alpha0=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-xml:12.1.0.alpha0=testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-core:11.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-database-postgresql:11.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:codemodel:4.0.5=jaxb
|
||||
org.glassfish.jaxb:jaxb-core:4.0.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:jaxb-core:4.0.5=jaxb
|
||||
@@ -476,27 +534,27 @@ org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.0.1=deploy_jar,nonprodRun
|
||||
org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.jetbrains:annotations:13.0=annotationProcessor,testAnnotationProcessor
|
||||
org.jetbrains:annotations:17.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jline:jline:3.27.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jline:jline:3.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.joda:joda-money:2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.json:json:20230618=soy
|
||||
org.json:json:20240303=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jsoup:jsoup:1.18.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jsoup:jsoup:1.18.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jspecify:jspecify:0.3.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
|
||||
org.jspecify:jspecify:1.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit-pioneer:junit-pioneer:2.3.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-migrationsupport:5.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-params:5.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-launcher:1.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-runner:1.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-api:1.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-commons:1.11.2=testRuntimeClasspath
|
||||
org.junit:junit-bom:5.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.mockito:mockito-core:5.14.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.mockito:mockito-junit-jupiter:5.14.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-migrationsupport:5.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-launcher:1.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-runner:1.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-api:1.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-commons:1.11.4=testRuntimeClasspath
|
||||
org.junit:junit-bom:5.11.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.objenesis:objenesis:3.3=testRuntimeClasspath
|
||||
org.ogce:xpp3:1.1.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
|
||||
@@ -509,50 +567,50 @@ org.ow2.asm:asm-util:9.5=compileClasspath,deploy_jar,nonprodCompileClasspath,non
|
||||
org.ow2.asm:asm:9.5=compileClasspath,nonprodCompileClasspath,soy
|
||||
org.ow2.asm:asm:9.7=deploy_jar,jacocoAnt,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
org.postgresql:postgresql:42.7.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.postgresql:postgresql:42.7.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.reflections:reflections:0.10.2=checkstyle
|
||||
org.rnorth.duct-tape:duct-tape:1.0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-api:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-chrome-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-chromium-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-devtools-v127:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-devtools-v128:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-devtools-v129:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-devtools-v85:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-edge-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-firefox-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-http:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-ie-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-java:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-json:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-manager:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-os:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-remote-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-safari-driver:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-support:4.25.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-api:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-chrome-driver:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-chromium-driver:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-devtools-v129:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-devtools-v130:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-devtools-v131:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-devtools-v85:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-edge-driver:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-firefox-driver:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-http:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-ie-driver:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-java:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-json:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-manager:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-os:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-remote-driver:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-safari-driver:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-support:4.27.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:jcl-over-slf4j:1.7.36=testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:jul-to-slf4j:1.7.30=testRuntimeClasspath
|
||||
org.slf4j:slf4j-api:2.0.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:slf4j-jdk14:2.0.13=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:slf4j-jdk14:2.0.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.snakeyaml:snakeyaml-engine:2.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.testcontainers:database-commons:1.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:jdbc:1.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:junit-jupiter:1.20.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:postgresql:1.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:selenium:1.20.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:testcontainers:1.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:database-commons:1.20.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:jdbc:1.20.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:junit-jupiter:1.20.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:postgresql:1.20.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:selenium:1.20.4=testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:testcontainers:1.20.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.threeten:threetenbp:1.7.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.w3c.css:sac:1.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.webjars.npm:viz.js-graphviz-java:2.1.3=testRuntimeClasspath
|
||||
org.xerial.snappy:snappy-java:1.1.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.yaml:snakeyaml:2.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-api:16.22.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-diagram:16.22.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-loader:16.22.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-postgresql:16.22.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-text:16.22.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-tools:16.22.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-utility:16.22.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler:16.22.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.yaml:snakeyaml:2.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-api:16.24.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-diagram:16.24.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-loader:16.24.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-postgresql:16.24.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-text:16.24.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-tools:16.24.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-utility:16.24.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler:16.24.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
xerces:xmlParserAPIs:2.6.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
empty=devtool,nomulus_test
|
||||
|
||||
@@ -46,7 +46,6 @@ import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
@@ -118,12 +117,6 @@ public final class RegistryConfig {
|
||||
return config.gcpProject.projectIdNumber;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("backendServiceIds")
|
||||
public static Map<String, Long> provideBackendServiceIds(RegistryConfigSettings config) {
|
||||
return config.gcpProject.backendServiceIds;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("baseDomain")
|
||||
public static String provideBaseDomain(RegistryConfigSettings config) {
|
||||
@@ -391,27 +384,6 @@ public final class RegistryConfig {
|
||||
return config.cloudSql.jdbcUrl;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("cloudSqlInstanceConnectionName")
|
||||
public static String provideCloudSqlInstanceConnectionName(RegistryConfigSettings config) {
|
||||
return config.cloudSql.instanceConnectionName;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("cloudSqlReplicaInstanceConnectionName")
|
||||
public static Optional<String> provideCloudSqlReplicaInstanceConnectionName(
|
||||
RegistryConfigSettings config) {
|
||||
return Optional.ofNullable(config.cloudSql.replicaInstanceConnectionName);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("cloudSqlDbInstanceName")
|
||||
public static String provideCloudSqlDbInstance(RegistryConfigSettings config) {
|
||||
// Format of instanceConnectionName: project-id:region:instance-name
|
||||
int lastColonIndex = config.cloudSql.instanceConnectionName.lastIndexOf(':');
|
||||
return config.cloudSql.instanceConnectionName.substring(lastColonIndex + 1);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("cloudDnsRootUrl")
|
||||
public static Optional<String> getCloudDnsRootUrl(RegistryConfigSettings config) {
|
||||
@@ -1743,6 +1715,17 @@ public final class RegistryConfig {
|
||||
CONFIG_SETTINGS.get().registryPolicy.tieredPricingPromotionRegistrarIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of registrars for which we do not send poll messages on standard domain deletion.
|
||||
*
|
||||
* <p>For these registrars we won't send a poll message in order to avoid database contention. See
|
||||
* b/379331882 for more details.
|
||||
*/
|
||||
public static ImmutableSet<String> getNoPollMessageOnDeletionRegistrarIds() {
|
||||
return ImmutableSet.copyOf(
|
||||
CONFIG_SETTINGS.get().registryPolicy.noPollMessageOnDeletionRegistrarIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Memoizes loading of the {@link RegistryConfigSettings} POJO.
|
||||
*
|
||||
|
||||
@@ -56,7 +56,6 @@ public class RegistryConfigSettings {
|
||||
public String bsaServiceUrl;
|
||||
public String toolsServiceUrl;
|
||||
public String pubapiServiceUrl;
|
||||
public Map<String, Long> backendServiceIds;
|
||||
public String baseDomain;
|
||||
}
|
||||
|
||||
@@ -115,6 +114,7 @@ public class RegistryConfigSettings {
|
||||
public boolean requireSslCertificates;
|
||||
public double sunriseDomainCreateDiscount;
|
||||
public Set<String> tieredPricingPromotionRegistrarIds;
|
||||
public Set<String> noPollMessageOnDeletionRegistrarIds;
|
||||
}
|
||||
|
||||
/** Configuration for Hibernate. */
|
||||
@@ -133,7 +133,7 @@ public class RegistryConfigSettings {
|
||||
/** Configuration for Cloud SQL. */
|
||||
public static class CloudSql {
|
||||
public String jdbcUrl;
|
||||
// TODO(05012021): remove username field after it is removed from all yaml files.
|
||||
// TODO(05012021): remove 3 fields below after they are removed from all yaml files.
|
||||
public String username;
|
||||
public String instanceConnectionName;
|
||||
public String replicaInstanceConnectionName;
|
||||
|
||||
@@ -24,15 +24,6 @@ gcpProject:
|
||||
toolsServiceUrl: https://tools.example.com
|
||||
pubapiServiceUrl: https://pubapi.example.com
|
||||
|
||||
# The backend service IDs created when setting up GKE routes. They will be included in the
|
||||
# audience field in the JWT that IAP creates.
|
||||
# See: https://cloud.google.com/iap/docs/signed-headers-howto#verifying_the_jwt_payload
|
||||
backendServiceIds:
|
||||
frontend: 12345
|
||||
backend: 12345
|
||||
pubapi: 12345
|
||||
console: 12345
|
||||
|
||||
# The base domain name of the registry service. Services are reachable at [service].baseDomain.
|
||||
baseDomain: registry.test
|
||||
|
||||
@@ -220,6 +211,9 @@ registryPolicy:
|
||||
# In addition, we will return the non-promotional (i.e. incorrect) price on
|
||||
# domain create requests.
|
||||
tieredPricingPromotionRegistrarIds: []
|
||||
# List of registrars for which we won't send poll message on standard domain
|
||||
# deletions.
|
||||
noPollMessageOnDeletionRegistrarIds: []
|
||||
|
||||
hibernate:
|
||||
# If set to false, calls to tm().transact() cannot be nested. If set to true,
|
||||
|
||||
@@ -11,6 +11,8 @@ registryPolicy:
|
||||
Line 2 is this 1.
|
||||
tieredPricingPromotionRegistrarIds:
|
||||
- NewRegistrar
|
||||
noPollMessageOnDeletionRegistrarIds:
|
||||
- NewRegistrar
|
||||
|
||||
caching:
|
||||
singletonCacheRefreshSeconds: 0
|
||||
|
||||
@@ -17,6 +17,7 @@ package google.registry.export;
|
||||
import static com.google.common.base.Verify.verifyNotNull;
|
||||
import static google.registry.model.tld.Tlds.getTldsOfType;
|
||||
import static google.registry.persistence.PersistenceModule.TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
@@ -28,6 +29,9 @@ import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.tld.Tld;
|
||||
import google.registry.model.tld.Tld.TldType;
|
||||
import google.registry.request.Action;
|
||||
@@ -38,8 +42,13 @@ import google.registry.util.Clock;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.TupleTransformer;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
/**
|
||||
* An action that exports the list of active domains on all real TLDs to Google Drive and GCS.
|
||||
@@ -55,7 +64,21 @@ import javax.inject.Inject;
|
||||
public class ExportDomainListsAction implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
public static final String REGISTERED_DOMAINS_FILENAME = "registered_domains.txt";
|
||||
private static final String SELECT_DOMAINS_STATEMENT =
|
||||
"SELECT domainName FROM Domain WHERE tld = :tld AND deletionTime > :now ORDER by domainName";
|
||||
private static final String SELECT_DOMAINS_AND_DELETION_TIMES_STATEMENT =
|
||||
"""
|
||||
SELECT d.domain_name, d.deletion_time, d.statuses, gp.type FROM "Domain" d
|
||||
LEFT JOIN (SELECT type, domain_repo_id FROM "GracePeriod"
|
||||
WHERE type = 'REDEMPTION'
|
||||
AND expiration_time > CAST(:now AS timestamptz)) AS gp
|
||||
ON d.repo_id = gp.domain_repo_id
|
||||
WHERE d.tld = :tld
|
||||
AND d.deletion_time > CAST(:now AS timestamptz)
|
||||
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";
|
||||
|
||||
@Inject Clock clock;
|
||||
@Inject DriveConnection driveConnection;
|
||||
@@ -68,47 +91,50 @@ public class ExportDomainListsAction implements Runnable {
|
||||
public void run() {
|
||||
ImmutableSet<String> realTlds = getTldsOfType(TldType.REAL);
|
||||
logger.atInfo().log("Exporting domain lists for TLDs %s.", realTlds);
|
||||
|
||||
boolean includeDeletionTimes =
|
||||
tm().transact(
|
||||
() ->
|
||||
FeatureFlag.isActiveNowOrElse(
|
||||
FeatureFlag.FeatureName.INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS, false));
|
||||
realTlds.forEach(
|
||||
tld -> {
|
||||
List<String> domains =
|
||||
tm().transact(
|
||||
List<String> domainsList =
|
||||
replicaTm()
|
||||
.transact(
|
||||
TRANSACTION_REPEATABLE_READ,
|
||||
() ->
|
||||
// Note that if we had "creationTime <= :now" in the condition (not
|
||||
// necessary as there is no pending creation, the order of deletionTime
|
||||
// and creationTime in the query would have been significant and it
|
||||
// should come after deletionTime. When Hibernate substitutes "now" it
|
||||
// will first validate that the **first** field that is to be compared
|
||||
// with it (deletionTime) is assignable from the substituted Java object
|
||||
// (click.nowUtc()). Since creationTime is a CreateAutoTimestamp, if it
|
||||
// comes first, we will need to substitute "now" with
|
||||
// CreateAutoTimestamp.create(clock.nowUtc()). This might look a bit
|
||||
// strange as the Java object type is clearly incompatible between the
|
||||
// two fields deletionTime (DateTime) and creationTime, yet they are
|
||||
// compared with the same "now". It is actually OK because in the end
|
||||
// Hibernate converts everything to SQL types (and Java field names to
|
||||
// SQL column names) to run the query. Both CreateAutoTimestamp and
|
||||
// DateTime are persisted as timestamp_z in SQL. It is only the
|
||||
// validation that compares the Java types, and only with the first
|
||||
// field that compares with the substituted value.
|
||||
tm().query(
|
||||
"SELECT domainName FROM Domain "
|
||||
+ "WHERE tld = :tld "
|
||||
+ "AND deletionTime > :now "
|
||||
+ "ORDER by domainName ASC",
|
||||
String.class)
|
||||
() -> {
|
||||
if (includeDeletionTimes) {
|
||||
// We want to include deletion times, but only for domains in the 5-day
|
||||
// PENDING_DELETE period after the REDEMPTION grace period. In order to
|
||||
// accomplish this without loading the entire list of domains, we use a
|
||||
// native query to join against the GracePeriod table to find
|
||||
// PENDING_DELETE domains that don't have a REDEMPTION grace period.
|
||||
return replicaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(SELECT_DOMAINS_AND_DELETION_TIMES_STATEMENT)
|
||||
.unwrap(NativeQuery.class)
|
||||
.setTupleTransformer(new DomainResultTransformer())
|
||||
.setParameter("tld", tld)
|
||||
.setParameter("now", clock.nowUtc())
|
||||
.getResultList());
|
||||
String domainsList = Joiner.on("\n").join(domains);
|
||||
.setParameter("now", replicaTm().getTransactionTime().toString())
|
||||
.getResultList();
|
||||
} else {
|
||||
return replicaTm()
|
||||
.query(SELECT_DOMAINS_STATEMENT, String.class)
|
||||
.setParameter("tld", tld)
|
||||
.setParameter("now", replicaTm().getTransactionTime())
|
||||
.getResultList();
|
||||
}
|
||||
});
|
||||
logger.atInfo().log(
|
||||
"Exporting %d domains for TLD %s to GCS and Drive.", domains.size(), tld);
|
||||
exportToGcs(tld, domainsList, gcsBucket, gcsUtils);
|
||||
exportToDrive(tld, domainsList, driveConnection);
|
||||
"Exporting %d domains for TLD %s to GCS and Drive.", domainsList.size(), tld);
|
||||
String domainsListOutput = Joiner.on('\n').join(domainsList);
|
||||
exportToGcs(tld, domainsListOutput, gcsBucket, gcsUtils);
|
||||
exportToDrive(tld, domainsListOutput, driveConnection);
|
||||
});
|
||||
}
|
||||
|
||||
protected static boolean exportToDrive(
|
||||
protected static void exportToDrive(
|
||||
String tldStr, String domains, DriveConnection driveConnection) {
|
||||
verifyNotNull(driveConnection, "Expecting non-null driveConnection");
|
||||
try {
|
||||
@@ -131,12 +157,10 @@ public class ExportDomainListsAction implements Runnable {
|
||||
} catch (Throwable e) {
|
||||
logger.atSevere().withCause(e).log(
|
||||
"Error exporting registered domains for TLD %s to Drive, skipping...", tldStr);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static boolean exportToGcs(
|
||||
protected static void exportToGcs(
|
||||
String tld, String domains, String gcsBucket, GcsUtils gcsUtils) {
|
||||
BlobId blobId = BlobId.of(gcsBucket, tld + ".txt");
|
||||
try (OutputStream gcsOutput = gcsUtils.openOutputStream(blobId);
|
||||
@@ -145,8 +169,22 @@ public class ExportDomainListsAction implements Runnable {
|
||||
} catch (Throwable e) {
|
||||
logger.atSevere().withCause(e).log(
|
||||
"Error exporting registered domains for TLD %s to GCS, skipping...", tld);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Transforms the multiple columns selected from SQL into the output line. */
|
||||
private static class DomainResultTransformer implements TupleTransformer<String> {
|
||||
@Override
|
||||
public String transformTuple(Object[] domainResult, String[] strings) {
|
||||
String domainName = (String) domainResult[0];
|
||||
Instant deletionInstant = (Instant) domainResult[1];
|
||||
DateTime deletionTime = new DateTime(deletionInstant.toEpochMilli(), DateTimeZone.UTC);
|
||||
String[] domainStatuses = (String[]) domainResult[2];
|
||||
String gracePeriodType = (String) domainResult[3];
|
||||
boolean inPendingDelete =
|
||||
ImmutableSet.copyOf(domainStatuses).contains(StatusValue.PENDING_DELETE.toString())
|
||||
&& !GracePeriodStatus.REDEMPTION.toString().equals(gracePeriodType);
|
||||
return String.format("%s,%s", domainName, inPendingDelete ? deletionTime : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ public final class ExtensionManager {
|
||||
}
|
||||
|
||||
private static final ImmutableSet<EppRequestSource> ALLOWED_METADATA_EPP_REQUEST_SOURCES =
|
||||
ImmutableSet.of(EppRequestSource.TOOL, EppRequestSource.BACKEND);
|
||||
ImmutableSet.of(EppRequestSource.BACKEND, EppRequestSource.CONSOLE, EppRequestSource.TOOL);
|
||||
|
||||
private void checkForRestrictedExtensions(
|
||||
ImmutableSet<Class<? extends CommandExtension>> suppliedExtensions)
|
||||
|
||||
@@ -75,7 +75,8 @@ public class FlowRunner {
|
||||
flowReporter.recordToLogs();
|
||||
}
|
||||
eppMetricBuilder.setCommandNameFromFlow(flowClass.getSimpleName());
|
||||
if (!isTransactional) {
|
||||
// We may already be in a transaction, e.g., when invoked by DeleteExpiredDomainsAction.
|
||||
if (!isTransactional || jpaTransactionManager.inTransaction()) {
|
||||
return EppOutput.create(flowProvider.get().run());
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -44,7 +44,9 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.batch.AsyncTaskEnqueuer;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.AssociationProhibitsOperationException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
@@ -117,6 +119,8 @@ import org.joda.time.Duration;
|
||||
@ReportingSpec(ActivityReportField.DOMAIN_DELETE)
|
||||
public final class DomainDeleteFlow implements MutatingFlow {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
||||
StatusValue.CLIENT_DELETE_PROHIBITED,
|
||||
StatusValue.PENDING_DELETE,
|
||||
@@ -212,10 +216,17 @@ public final class DomainDeleteFlow implements MutatingFlow {
|
||||
// superuser (i.e. the registrar didn't request this delete and thus should be notified even if
|
||||
// it is synchronous).
|
||||
if (durationUntilDelete.isLongerThan(Duration.ZERO) || isSuperuser) {
|
||||
PollMessage.OneTime deletePollMessage =
|
||||
createDeletePollMessage(existingDomain, domainHistoryId, deletionTime);
|
||||
entitiesToSave.add(deletePollMessage);
|
||||
builder.setDeletePollMessage(deletePollMessage.createVKey());
|
||||
if (RegistryConfig.getNoPollMessageOnDeletionRegistrarIds()
|
||||
.contains(existingDomain.getCurrentSponsorRegistrarId())) {
|
||||
logger.atInfo().log(
|
||||
"Skipping poll message on domain deletion for registrar %s due to configuration",
|
||||
existingDomain.getCurrentSponsorRegistrarId());
|
||||
} else {
|
||||
PollMessage.OneTime deletePollMessage =
|
||||
createDeletePollMessage(existingDomain, domainHistoryId, deletionTime);
|
||||
entitiesToSave.add(deletePollMessage);
|
||||
builder.setDeletePollMessage(deletePollMessage.createVKey());
|
||||
}
|
||||
}
|
||||
|
||||
// Send a second poll message immediately if the domain is being deleted asynchronously by a
|
||||
|
||||
@@ -183,7 +183,9 @@ public final class DomainRestoreRequestFlow implements MutatingFlow {
|
||||
DomainHistory domainHistory = buildDomainHistory(newDomain, now);
|
||||
entitiesToSave.add(newDomain, domainHistory, autorenewEvent, autorenewPollMessage);
|
||||
tm().putAll(entitiesToSave.build());
|
||||
tm().delete(existingDomain.getDeletePollMessage());
|
||||
if (existingDomain.getDeletePollMessage() != null) {
|
||||
tm().delete(existingDomain.getDeletePollMessage());
|
||||
}
|
||||
requestDomainDnsRefresh(existingDomain.getDomainName());
|
||||
return responseBuilder
|
||||
.setExtensions(createResponseExtensions(feesAndCredits, feeUpdate, isExpired))
|
||||
|
||||
@@ -37,6 +37,8 @@ import google.registry.model.poll.MessageQueueInfo;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.poll.PollMessageExternalKeyConverter;
|
||||
import google.registry.model.poll.PollMessageExternalKeyConverter.PollMessageExternalKeyParseException;
|
||||
import google.registry.persistence.IsolationLevel;
|
||||
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
@@ -55,6 +57,7 @@ import org.joda.time.DateTime;
|
||||
* @error {@link PollAckFlow.MissingMessageIdException}
|
||||
* @error {@link PollAckFlow.NotAuthorizedToAckMessageException}
|
||||
*/
|
||||
@IsolationLevel(value = TransactionIsolationLevel.TRANSACTION_READ_COMMITTED)
|
||||
public final class PollAckFlow implements MutatingFlow {
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
|
||||
@@ -32,6 +32,8 @@ import google.registry.model.eppoutput.EppResponse;
|
||||
import google.registry.model.poll.MessageQueueInfo;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.poll.PollMessageExternalKeyConverter;
|
||||
import google.registry.persistence.IsolationLevel;
|
||||
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -47,6 +49,7 @@ import org.joda.time.DateTime;
|
||||
*
|
||||
* @error {@link PollRequestFlow.UnexpectedMessageIdException}
|
||||
*/
|
||||
@IsolationLevel(value = TransactionIsolationLevel.TRANSACTION_READ_COMMITTED)
|
||||
public final class PollRequestFlow implements TransactionalFlow {
|
||||
|
||||
@Inject ExtensionManager extensionManager;
|
||||
|
||||
@@ -21,6 +21,7 @@ import dagger.Provides;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.keyring.api.Keyring;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/** Dagger module for {@link Keyring} */
|
||||
@@ -38,4 +39,25 @@ public final class KeyringModule {
|
||||
keyrings.keySet());
|
||||
return keyrings.get(activeKeyring);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("cloudSqlInstanceConnectionName")
|
||||
public static String provideCloudSqlInstanceConnectionName(Keyring keyring) {
|
||||
return keyring.getSqlPrimaryConnectionName();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("cloudSqlReplicaInstanceConnectionName")
|
||||
public static Optional<String> provideCloudSqlReplicaInstanceConnectionName(Keyring keyring) {
|
||||
return Optional.ofNullable(keyring.getSqlReplicaConnectionName());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("cloudSqlDbInstanceName")
|
||||
public static String provideCloudSqlDbInstance(
|
||||
@Config("cloudSqlInstanceConnectionName") String instanceConnectionName) {
|
||||
// Format of instanceConnectionName: project-id:region:instance-name
|
||||
int lastColonIndex = instanceConnectionName.lastIndexOf(':');
|
||||
return instanceConnectionName.substring(lastColonIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,9 @@ public abstract class DummyKeyringModule {
|
||||
"not a real login",
|
||||
"not a real credential",
|
||||
"not a real password",
|
||||
"not a real password");
|
||||
"not a real password",
|
||||
"not the real primary connection",
|
||||
"not the real replica connection");
|
||||
}
|
||||
|
||||
private DummyKeyringModule() {}
|
||||
|
||||
@@ -39,6 +39,8 @@ public final class InMemoryKeyring implements Keyring {
|
||||
private final String marksdbLordnPassword;
|
||||
private final String marksdbSmdrlLoginAndPassword;
|
||||
private final String bsaApiKey;
|
||||
private final String sqlPrimaryConnectionName;
|
||||
private final String sqlReplicaConnectionName;
|
||||
|
||||
public InMemoryKeyring(
|
||||
PGPKeyPair rdeStagingKey,
|
||||
@@ -55,7 +57,9 @@ public final class InMemoryKeyring implements Keyring {
|
||||
String marksdbSmdrlLoginAndPassword,
|
||||
String cloudSqlPassword,
|
||||
String toolsCloudSqlPassword,
|
||||
String bsaApiKey) {
|
||||
String bsaApiKey,
|
||||
String sqlPrimaryConnectionName,
|
||||
String sqlReplicaConnectionName) {
|
||||
checkArgument(PgpHelper.isSigningKey(rdeSigningKey.getPublicKey()),
|
||||
"RDE signing key must support signing: %s", rdeSigningKey.getKeyID());
|
||||
checkArgument(rdeStagingKey.getPublicKey().isEncryptionKey(),
|
||||
@@ -81,6 +85,8 @@ public final class InMemoryKeyring implements Keyring {
|
||||
this.marksdbSmdrlLoginAndPassword =
|
||||
checkNotNull(marksdbSmdrlLoginAndPassword, "marksdbSmdrlLoginAndPassword");
|
||||
this.bsaApiKey = checkNotNull(bsaApiKey, "bsaApiKey");
|
||||
this.sqlPrimaryConnectionName = sqlPrimaryConnectionName;
|
||||
this.sqlReplicaConnectionName = sqlReplicaConnectionName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,6 +159,16 @@ public final class InMemoryKeyring implements Keyring {
|
||||
return bsaApiKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlPrimaryConnectionName() {
|
||||
return sqlPrimaryConnectionName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlReplicaConnectionName() {
|
||||
return sqlReplicaConnectionName;
|
||||
}
|
||||
|
||||
/** Does nothing. */
|
||||
@Override
|
||||
public void close() {}
|
||||
|
||||
@@ -148,6 +148,12 @@ public interface Keyring extends AutoCloseable {
|
||||
/** Returns the API_KEY for authentication with the BSA portal. */
|
||||
String getBsaApiKey();
|
||||
|
||||
/** Returns the Cloud SQL connection name of the primary database instance. */
|
||||
String getSqlPrimaryConnectionName();
|
||||
|
||||
/** Returns the Cloud SQL connection name of the replica database instance. */
|
||||
String getSqlReplicaConnectionName();
|
||||
|
||||
// Don't throw so try-with-resources works better.
|
||||
@Override
|
||||
void close();
|
||||
|
||||
@@ -57,14 +57,16 @@ public class SecretManagerKeyring implements Keyring {
|
||||
|
||||
/** Key labels for string secrets. */
|
||||
enum StringKeyLabel {
|
||||
SAFE_BROWSING_API_KEY,
|
||||
BSA_API_KEY_STRING,
|
||||
ICANN_REPORTING_PASSWORD_STRING,
|
||||
MARKSDB_DNL_LOGIN_STRING,
|
||||
MARKSDB_LORDN_PASSWORD_STRING,
|
||||
MARKSDB_SMDRL_LOGIN_STRING,
|
||||
RDE_SSH_CLIENT_PRIVATE_STRING,
|
||||
RDE_SSH_CLIENT_PUBLIC_STRING;
|
||||
RDE_SSH_CLIENT_PUBLIC_STRING,
|
||||
SAFE_BROWSING_API_KEY,
|
||||
SQL_PRIMARY_CONN_NAME,
|
||||
SQL_REPLICA_CONN_NAME;
|
||||
|
||||
String getLabel() {
|
||||
return UPPER_UNDERSCORE.to(LOWER_HYPHEN, name());
|
||||
@@ -148,6 +150,16 @@ public class SecretManagerKeyring implements Keyring {
|
||||
return getString(StringKeyLabel.BSA_API_KEY_STRING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlPrimaryConnectionName() {
|
||||
return getString(StringKeyLabel.SQL_PRIMARY_CONN_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlReplicaConnectionName() {
|
||||
return getString(StringKeyLabel.SQL_REPLICA_CONN_NAME);
|
||||
}
|
||||
|
||||
/** No persistent resources are maintained for this Keyring implementation. */
|
||||
@Override
|
||||
public void close() {}
|
||||
|
||||
@@ -32,6 +32,8 @@ import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringK
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.RDE_SSH_CLIENT_PRIVATE_STRING;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.RDE_SSH_CLIENT_PUBLIC_STRING;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.SAFE_BROWSING_API_KEY;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.SQL_PRIMARY_CONN_NAME;
|
||||
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.SQL_REPLICA_CONN_NAME;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
@@ -124,6 +126,14 @@ public final class SecretManagerKeyringUpdater {
|
||||
return setString(credential, BSA_API_KEY_STRING);
|
||||
}
|
||||
|
||||
public SecretManagerKeyringUpdater setSqlPrimaryConnectionName(String name) {
|
||||
return setString(name, SQL_PRIMARY_CONN_NAME);
|
||||
}
|
||||
|
||||
public SecretManagerKeyringUpdater setSqlReplicaConnectionName(String name) {
|
||||
return setString(name, SQL_REPLICA_CONN_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists the secrets in the Secret Manager.
|
||||
*
|
||||
|
||||
@@ -45,10 +45,11 @@ import org.joda.time.DateTime;
|
||||
@Index(columnList = "eventTime"),
|
||||
@Index(columnList = "domainRepoId"),
|
||||
@Index(columnList = "billingTime"),
|
||||
@Index(columnList = "billing_event_id"),
|
||||
@Index(columnList = "billing_recurrence_id")
|
||||
@Index(columnList = "billingEventId"),
|
||||
@Index(columnList = "billingRecurrenceId"),
|
||||
@Index(columnList = "domainRepoId,domainHistoryRevisionId")
|
||||
})
|
||||
@AttributeOverride(name = "id", column = @Column(name = "billing_cancellation_id"))
|
||||
@AttributeOverride(name = "id", column = @Column(name = "billingCancellationId"))
|
||||
@WithVKey(Long.class)
|
||||
public class BillingCancellation extends BillingBase {
|
||||
|
||||
|
||||
@@ -42,7 +42,9 @@ import org.joda.time.DateTime;
|
||||
@Index(columnList = "syntheticCreationTime"),
|
||||
@Index(columnList = "domainRepoId"),
|
||||
@Index(columnList = "allocationToken"),
|
||||
@Index(columnList = "cancellation_matching_billing_recurrence_id")
|
||||
@Index(columnList = "cancellationMatchingBillingRecurrenceId"),
|
||||
@Index(columnList = "domainRepoId,domainHistoryRevisionId"),
|
||||
@Index(columnList = "domainRepoId,recurrenceHistoryRevisionId")
|
||||
})
|
||||
@AttributeOverride(name = "id", column = @Column(name = "billing_event_id"))
|
||||
@WithVKey(Long.class)
|
||||
|
||||
@@ -50,7 +50,8 @@ import org.joda.time.DateTime;
|
||||
@Index(columnList = "domainRepoId"),
|
||||
@Index(columnList = "recurrenceEndTime"),
|
||||
@Index(columnList = "recurrenceLastExpansion"),
|
||||
@Index(columnList = "recurrence_time_of_year")
|
||||
@Index(columnList = "recurrenceTimeOfYear"),
|
||||
@Index(columnList = "domainRepoId,domainHistoryRevisionId")
|
||||
})
|
||||
@AttributeOverride(name = "id", column = @Column(name = "billing_recurrence_id"))
|
||||
@WithVKey(Long.class)
|
||||
|
||||
@@ -66,6 +66,7 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
|
||||
TEST_FEATURE,
|
||||
MINIMUM_DATASET_CONTACTS_OPTIONAL,
|
||||
MINIMUM_DATASET_CONTACTS_PROHIBITED,
|
||||
INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS
|
||||
}
|
||||
|
||||
/** The name of the flag/feature. */
|
||||
@@ -154,6 +155,15 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
|
||||
return status.getValueAtTime(time);
|
||||
}
|
||||
|
||||
/** Returns if the flag is active, or the default value if the flag does not exist. */
|
||||
public static boolean isActiveNowOrElse(FeatureName featureName, boolean defaultValue) {
|
||||
tm().assertInTransaction();
|
||||
return CACHE
|
||||
.get(featureName)
|
||||
.map(flag -> flag.getStatus(tm().getTransactionTime()).equals(ACTIVE))
|
||||
.orElse(defaultValue);
|
||||
}
|
||||
|
||||
/** Returns if the FeatureFlag with the given FeatureName is active now. */
|
||||
public static boolean isActiveNow(FeatureName featureName) {
|
||||
tm().assertInTransaction();
|
||||
|
||||
@@ -185,4 +185,9 @@ public class TimedTransitionProperty<V extends Serializable> implements UnsafeSe
|
||||
public int hashCode() {
|
||||
return this.backingMap.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.backingMap.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +180,11 @@ public class GracePeriod extends GracePeriodBase {
|
||||
|
||||
/** Entity class to represent a historic {@link GracePeriod}. */
|
||||
@Entity(name = "GracePeriodHistory")
|
||||
@Table(indexes = @Index(columnList = "domainRepoId"))
|
||||
@Table(
|
||||
indexes = {
|
||||
@Index(columnList = "domainRepoId"),
|
||||
@Index(columnList = "domainRepoId,domainHistoryRevisionId")
|
||||
})
|
||||
public static class GracePeriodHistory extends GracePeriodBase {
|
||||
@Id Long gracePeriodHistoryRevisionId;
|
||||
|
||||
|
||||
@@ -23,9 +23,12 @@ import jakarta.persistence.AccessType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
/** Entity class to represent a historic {@link DomainDsData}. */
|
||||
@Entity
|
||||
@Table(indexes = @Index(columnList = "domainRepoId,domainHistoryRevisionId"))
|
||||
public class DomainDsDataHistory extends DomainDsDataBase {
|
||||
|
||||
@Id Long dsDataHistoryRevisionId;
|
||||
|
||||
@@ -89,8 +89,9 @@ import org.joda.time.DateTime;
|
||||
@Table(
|
||||
indexes = {
|
||||
@Index(columnList = "domainRepoId"),
|
||||
@Index(columnList = "registrar_id"),
|
||||
@Index(columnList = "eventTime")
|
||||
@Index(columnList = "registrarId"),
|
||||
@Index(columnList = "eventTime"),
|
||||
@Index(columnList = "domainRepoId,domainHistoryRevisionId")
|
||||
})
|
||||
public abstract class PollMessage extends ImmutableObject
|
||||
implements Buildable, TransferServerApproveEntity, UnsafeSerializable {
|
||||
|
||||
@@ -29,6 +29,8 @@ import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.Table;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
@@ -42,6 +44,7 @@ import org.joda.time.DateTime;
|
||||
* uses HistoryEntry.otherClientId because the losing party in a transfer is always the otherClient.
|
||||
*/
|
||||
@Entity
|
||||
@Table(indexes = @Index(columnList = "domainRepoId,historyRevisionId"))
|
||||
public class DomainTransactionRecord extends ImmutableObject
|
||||
implements Buildable, UnsafeSerializable {
|
||||
|
||||
|
||||
@@ -21,12 +21,15 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.google.monitoring.metrics.MetricReporter;
|
||||
import com.google.monitoring.metrics.MetricWriter;
|
||||
import com.google.monitoring.metrics.stackdriver.StackdriverWriter;
|
||||
import dagger.Lazy;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.ApplicationDefaultCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import google.registry.util.MetricParameters;
|
||||
import google.registry.util.RegistryEnvironment;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import org.joda.time.Duration;
|
||||
@@ -66,23 +69,28 @@ public final class StackdriverModule {
|
||||
@Provides
|
||||
static MetricWriter provideMetricWriter(
|
||||
Monitoring monitoringClient,
|
||||
Lazy<MetricParameters> gkeParameters,
|
||||
@Config("projectId") String projectId,
|
||||
@Config("stackdriverMaxQps") int maxQps,
|
||||
@Config("stackdriverMaxPointsPerRequest") int maxPointsPerRequest,
|
||||
@Named("spoofedGceInstanceId") String instanceId) {
|
||||
// The MonitoredResource for GAE apps is not writable (and missing fields anyway) so we just
|
||||
// use the gce_instance resource type instead.
|
||||
MonitoredResource resource =
|
||||
RegistryEnvironment.isOnJetty()
|
||||
? new MonitoredResource()
|
||||
.setType("gke_container")
|
||||
.setLabels(gkeParameters.get().makeLabelsMap())
|
||||
:
|
||||
// The MonitoredResource for GAE apps is not writable (and missing fields anyway) so we
|
||||
// just use the gce_instance resource type instead.
|
||||
new MonitoredResource()
|
||||
.setType("gce_instance")
|
||||
.setLabels(
|
||||
ImmutableMap.of(
|
||||
// The "zone" field MUST be a valid GCE zone, so we fake one.
|
||||
"zone", SPOOFED_GCE_ZONE, "instance_id", instanceId));
|
||||
|
||||
return new StackdriverWriter(
|
||||
monitoringClient,
|
||||
projectId,
|
||||
new MonitoredResource()
|
||||
.setType("gce_instance")
|
||||
.setLabels(
|
||||
ImmutableMap.of(
|
||||
// The "zone" field MUST be a valid GCE zone, so we fake one.
|
||||
"zone", SPOOFED_GCE_ZONE, "instance_id", instanceId)),
|
||||
maxQps,
|
||||
maxPointsPerRequest);
|
||||
monitoringClient, projectId, resource, maxQps, maxPointsPerRequest);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -34,10 +34,13 @@ import dagger.BindsOptionalOf;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.keyring.KeyringModule;
|
||||
import google.registry.keyring.api.DummyKeyringModule;
|
||||
import google.registry.persistence.transaction.CloudSqlCredentialSupplier;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import google.registry.persistence.transaction.JpaTransactionManagerImpl;
|
||||
import google.registry.persistence.transaction.TransactionManager;
|
||||
import google.registry.privileges.secretmanager.SecretManagerModule;
|
||||
import google.registry.privileges.secretmanager.SqlCredential;
|
||||
import google.registry.privileges.secretmanager.SqlCredentialStore;
|
||||
import google.registry.privileges.secretmanager.SqlUser;
|
||||
@@ -63,7 +66,7 @@ import javax.inject.Singleton;
|
||||
import org.hibernate.cfg.Environment;
|
||||
|
||||
/** Dagger module class for the persistence layer. */
|
||||
@Module
|
||||
@Module(includes = {KeyringModule.class, SecretManagerModule.class, DummyKeyringModule.class})
|
||||
public abstract class PersistenceModule {
|
||||
|
||||
// This name must be the same as the one defined in persistence.xml.
|
||||
|
||||
@@ -71,6 +71,7 @@ import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
@@ -177,9 +178,9 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
||||
if (!getHibernateAllowNestedTransactions()) {
|
||||
throw new IllegalStateException(NESTED_TRANSACTION_MESSAGE);
|
||||
}
|
||||
if (RegistryEnvironment.get() != RegistryEnvironment.PRODUCTION
|
||||
&& RegistryEnvironment.get() != RegistryEnvironment.UNITTEST) {
|
||||
logger.atWarning().withStackTrace(StackSize.MEDIUM).log(NESTED_TRANSACTION_MESSAGE);
|
||||
if (RegistryEnvironment.get() != RegistryEnvironment.UNITTEST) {
|
||||
logger.atWarning().withStackTrace(StackSize.MEDIUM).atMostEvery(1, TimeUnit.MINUTES).log(
|
||||
NESTED_TRANSACTION_MESSAGE);
|
||||
}
|
||||
// This prevents inner transaction from retrying, thus avoiding a cascade retry effect.
|
||||
return transactNoRetry(isolationLevel, work);
|
||||
|
||||
@@ -31,18 +31,21 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import com.google.gson.JsonArray;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.adapters.EnumToAttributeAdapter.EppEnum;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactPhoneNumber;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.DesignatedContact.Type;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.eppcommon.Address;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.Host;
|
||||
@@ -175,10 +178,8 @@ public class RdapJsonFormatter {
|
||||
+ " repoId = '%repoIdValue%' and type is not null group by type)";
|
||||
|
||||
/** Map of EPP status values to the RDAP equivalents. */
|
||||
private static final ImmutableMap<StatusValue, RdapStatus> STATUS_TO_RDAP_STATUS_MAP =
|
||||
new ImmutableMap.Builder<StatusValue, RdapStatus>()
|
||||
// RdapStatus.ADD_PERIOD not defined in our system
|
||||
// RdapStatus.AUTO_RENEW_PERIOD not defined in our system
|
||||
private static final ImmutableMap<EppEnum, RdapStatus> STATUS_TO_RDAP_STATUS_MAP =
|
||||
new ImmutableMap.Builder<EppEnum, RdapStatus>()
|
||||
.put(StatusValue.CLIENT_DELETE_PROHIBITED, RdapStatus.CLIENT_DELETE_PROHIBITED)
|
||||
.put(StatusValue.CLIENT_HOLD, RdapStatus.CLIENT_HOLD)
|
||||
.put(StatusValue.CLIENT_RENEW_PROHIBITED, RdapStatus.CLIENT_RENEW_PROHIBITED)
|
||||
@@ -190,17 +191,21 @@ public class RdapJsonFormatter {
|
||||
.put(StatusValue.PENDING_CREATE, RdapStatus.PENDING_CREATE)
|
||||
.put(StatusValue.PENDING_DELETE, RdapStatus.PENDING_DELETE)
|
||||
// RdapStatus.PENDING_RENEW not defined in our system
|
||||
// RdapStatus.PENDING_RESTORE not defined in our system
|
||||
.put(StatusValue.PENDING_TRANSFER, RdapStatus.PENDING_TRANSFER)
|
||||
.put(StatusValue.PENDING_UPDATE, RdapStatus.PENDING_UPDATE)
|
||||
// RdapStatus.REDEMPTION_PERIOD not defined in our system
|
||||
// RdapStatus.RENEW_PERIOD not defined in our system
|
||||
.put(StatusValue.SERVER_DELETE_PROHIBITED, RdapStatus.SERVER_DELETE_PROHIBITED)
|
||||
.put(StatusValue.SERVER_HOLD, RdapStatus.SERVER_HOLD)
|
||||
.put(StatusValue.SERVER_RENEW_PROHIBITED, RdapStatus.SERVER_RENEW_PROHIBITED)
|
||||
.put(StatusValue.SERVER_TRANSFER_PROHIBITED, RdapStatus.SERVER_TRANSFER_PROHIBITED)
|
||||
.put(StatusValue.SERVER_UPDATE_PROHIBITED, RdapStatus.SERVER_UPDATE_PROHIBITED)
|
||||
// RdapStatus.TRANSFER_PERIOD not defined in our system
|
||||
.put(GracePeriodStatus.ADD, RdapStatus.ADD_PERIOD)
|
||||
.put(GracePeriodStatus.AUTO_RENEW, RdapStatus.AUTO_RENEW_PERIOD)
|
||||
.put(GracePeriodStatus.REDEMPTION, RdapStatus.REDEMPTION_PERIOD)
|
||||
.put(GracePeriodStatus.RENEW, RdapStatus.RENEW_PERIOD)
|
||||
.put(GracePeriodStatus.PENDING_DELETE, RdapStatus.PENDING_DELETE)
|
||||
// In practice, PENDING_RESTORE is unused. We just perform the restore immediately
|
||||
.put(GracePeriodStatus.PENDING_RESTORE, RdapStatus.PENDING_RESTORE)
|
||||
.put(GracePeriodStatus.TRANSFER, RdapStatus.TRANSFER_PERIOD)
|
||||
.build();
|
||||
|
||||
/**
|
||||
@@ -348,9 +353,11 @@ public class RdapJsonFormatter {
|
||||
}
|
||||
// RDAP Response Profile 2.6.1: must have at least one status member
|
||||
// makeStatusValueList should in theory always contain one of either "active" or "inactive".
|
||||
Set<EppEnum> allStatusValues =
|
||||
Sets.union(domain.getStatusValues(), domain.getGracePeriodStatuses());
|
||||
ImmutableSet<RdapStatus> status =
|
||||
makeStatusValueList(
|
||||
domain.getStatusValues(),
|
||||
allStatusValues,
|
||||
false, // isRedacted
|
||||
domain.getDeletionTime().isBefore(getRequestTime()));
|
||||
builder.statusBuilder().addAll(status);
|
||||
@@ -1045,7 +1052,7 @@ public class RdapJsonFormatter {
|
||||
* redacted objects.
|
||||
*/
|
||||
private static ImmutableSet<RdapStatus> makeStatusValueList(
|
||||
ImmutableSet<StatusValue> statusValues, boolean isRedacted, boolean isDeleted) {
|
||||
Set<? extends EppEnum> statusValues, boolean isRedacted, boolean isDeleted) {
|
||||
Stream<RdapStatus> stream =
|
||||
statusValues.stream()
|
||||
.map(status -> STATUS_TO_RDAP_STATUS_MAP.getOrDefault(status, RdapStatus.OBSCURED));
|
||||
|
||||
@@ -51,7 +51,7 @@ final class RdapObjectClasses {
|
||||
*/
|
||||
@RestrictJsonNames({})
|
||||
@AutoValue
|
||||
abstract static class Vcard implements Jsonable {
|
||||
public abstract static class Vcard implements Jsonable {
|
||||
abstract String property();
|
||||
abstract ImmutableMap<String, ImmutableList<String>> parameters();
|
||||
abstract String valueType();
|
||||
@@ -94,7 +94,7 @@ final class RdapObjectClasses {
|
||||
|
||||
@RestrictJsonNames("vcardArray")
|
||||
@AutoValue
|
||||
abstract static class VcardArray implements Jsonable {
|
||||
public abstract static class VcardArray implements Jsonable {
|
||||
|
||||
private static final String VCARD_VERSION_NUMBER = "4.0";
|
||||
private static final Vcard VCARD_ENTRY_VERSION =
|
||||
@@ -148,7 +148,7 @@ final class RdapObjectClasses {
|
||||
*
|
||||
* <p>All Actions need to return an object of this type.
|
||||
*/
|
||||
abstract static class ReplyPayloadBase extends AbstractJsonableObject {
|
||||
public abstract static class ReplyPayloadBase extends AbstractJsonableObject {
|
||||
final BoilerplateType boilerplateType;
|
||||
|
||||
ReplyPayloadBase(BoilerplateType boilerplateType) {
|
||||
@@ -165,7 +165,7 @@ final class RdapObjectClasses {
|
||||
*/
|
||||
@AutoValue
|
||||
@RestrictJsonNames({})
|
||||
abstract static class TopLevelReplyObject extends AbstractJsonableObject {
|
||||
public abstract static class TopLevelReplyObject extends AbstractJsonableObject {
|
||||
@JsonableElement("rdapConformance")
|
||||
static final RdapConformance RDAP_CONFORMANCE = RdapConformance.INSTANCE;
|
||||
|
||||
@@ -257,7 +257,7 @@ final class RdapObjectClasses {
|
||||
* <p>We're missing the "autnums" and "networks" fields
|
||||
*/
|
||||
@RestrictJsonNames({"entities[]", "entitySearchResults[]"})
|
||||
abstract static class RdapEntity extends RdapObjectBase {
|
||||
public abstract static class RdapEntity extends RdapObjectBase {
|
||||
|
||||
/** Role values specified in RFC 9083 § 10.2.4. */
|
||||
@RestrictJsonNames("roles[]")
|
||||
@@ -311,7 +311,7 @@ final class RdapObjectClasses {
|
||||
* for each one for type safety.
|
||||
*/
|
||||
@AutoValue
|
||||
abstract static class RdapRegistrarEntity extends RdapEntity {
|
||||
public abstract static class RdapRegistrarEntity extends RdapEntity {
|
||||
|
||||
static Builder builder() {
|
||||
return new AutoValue_RdapObjectClasses_RdapRegistrarEntity.Builder();
|
||||
@@ -330,7 +330,7 @@ final class RdapObjectClasses {
|
||||
* for each one for type safety.
|
||||
*/
|
||||
@AutoValue
|
||||
abstract static class RdapContactEntity extends RdapEntity {
|
||||
public abstract static class RdapContactEntity extends RdapEntity {
|
||||
|
||||
static Builder builder() {
|
||||
return new AutoValue_RdapObjectClasses_RdapContactEntity.Builder();
|
||||
@@ -387,7 +387,7 @@ final class RdapObjectClasses {
|
||||
/** The Nameserver Object Class defined in 5.2 of RFC 9083. */
|
||||
@RestrictJsonNames({"nameservers[]", "nameserverSearchResults[]"})
|
||||
@AutoValue
|
||||
abstract static class RdapNameserver extends RdapNamedObjectBase {
|
||||
public abstract static class RdapNameserver extends RdapNamedObjectBase {
|
||||
|
||||
@JsonableElement Optional<IpAddresses> ipAddresses() {
|
||||
if (ipv6().isEmpty() && ipv4().isEmpty()) {
|
||||
@@ -429,7 +429,7 @@ final class RdapObjectClasses {
|
||||
/** Object defined in RFC 9083 section 5.3, only used for RdapDomain. */
|
||||
@RestrictJsonNames("secureDNS")
|
||||
@AutoValue
|
||||
abstract static class SecureDns extends AbstractJsonableObject {
|
||||
public abstract static class SecureDns extends AbstractJsonableObject {
|
||||
@RestrictJsonNames("dsData[]")
|
||||
@AutoValue
|
||||
abstract static class DsData extends AbstractJsonableObject {
|
||||
@@ -507,7 +507,7 @@ final class RdapObjectClasses {
|
||||
*/
|
||||
@RestrictJsonNames("domainSearchResults[]")
|
||||
@AutoValue
|
||||
abstract static class RdapDomain extends RdapNamedObjectBase {
|
||||
public abstract static class RdapDomain extends RdapNamedObjectBase {
|
||||
|
||||
@JsonableElement abstract ImmutableList<RdapNameserver> nameservers();
|
||||
|
||||
@@ -535,7 +535,7 @@ final class RdapObjectClasses {
|
||||
/** Error Response Body defined in 6 of RFC 9083. */
|
||||
@RestrictJsonNames({})
|
||||
@AutoValue
|
||||
abstract static class ErrorResponse extends ReplyPayloadBase {
|
||||
public abstract static class ErrorResponse extends ReplyPayloadBase {
|
||||
|
||||
@JsonableElement final LanguageIdentifier lang = LanguageIdentifier.EN;
|
||||
|
||||
@@ -561,7 +561,7 @@ final class RdapObjectClasses {
|
||||
*/
|
||||
@RestrictJsonNames({})
|
||||
@AutoValue
|
||||
abstract static class HelpResponse extends ReplyPayloadBase {
|
||||
public abstract static class HelpResponse extends ReplyPayloadBase {
|
||||
@JsonableElement("notices[]") abstract Optional<Notice> helpNotice();
|
||||
|
||||
HelpResponse() {
|
||||
|
||||
@@ -33,7 +33,9 @@ public @interface Action {
|
||||
enum Method {
|
||||
GET,
|
||||
HEAD,
|
||||
POST
|
||||
POST,
|
||||
PUT,
|
||||
DELETE
|
||||
}
|
||||
|
||||
interface Service {
|
||||
|
||||
@@ -143,7 +143,9 @@ public class RequestHandler<C> {
|
||||
GkeService service = Action.ServiceGetter.get(route.get().action());
|
||||
String expectedDomain = RegistryConfig.getServiceUrl(service).getHost();
|
||||
String actualDomain = req.getServerName();
|
||||
if (!Objects.equals(actualDomain, expectedDomain)) {
|
||||
// If the hostname is "localhost", it must have come from the sidecar proxy.
|
||||
if (!Objects.equals("localhost", actualDomain)
|
||||
&& !Objects.equals(actualDomain, expectedDomain)) {
|
||||
logger.atWarning().log(
|
||||
"Actual domain %s does not match expected domain %s", actualDomain, expectedDomain);
|
||||
rsp.sendError(SC_NOT_FOUND);
|
||||
|
||||
@@ -14,19 +14,35 @@
|
||||
|
||||
package google.registry.request.auth;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Suppliers.memoizeWithExpiration;
|
||||
import static com.google.common.net.HttpHeaders.AUTHORIZATION;
|
||||
import static google.registry.util.RegistryEnvironment.UNITTEST;
|
||||
|
||||
import com.google.cloud.compute.v1.BackendService;
|
||||
import com.google.cloud.compute.v1.BackendServicesClient;
|
||||
import com.google.cloud.compute.v1.BackendServicesSettings;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.re2j.Matcher;
|
||||
import com.google.re2j.Pattern;
|
||||
import dagger.Lazy;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.ApplicationDefaultCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.request.auth.OidcTokenAuthenticationMechanism.IapOidcAuthenticationMechanism;
|
||||
import google.registry.request.auth.OidcTokenAuthenticationMechanism.RegularOidcAuthenticationMechanism;
|
||||
import google.registry.request.auth.OidcTokenAuthenticationMechanism.TokenExtractor;
|
||||
import google.registry.request.auth.OidcTokenAuthenticationMechanism.TokenVerifier;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import google.registry.util.RegistryEnvironment;
|
||||
import java.util.Map;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Qualifier;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@@ -44,6 +60,13 @@ public class AuthModule {
|
||||
private static final String IAP_GKE_AUDIENCE_FORMAT = "/projects/%d/global/backendServices/%d";
|
||||
private static final String IAP_ISSUER_URL = "https://cloud.google.com/iap";
|
||||
private static final String REGULAR_ISSUER_URL = "https://accounts.google.com";
|
||||
// The backend service IDs created when setting up GKE routes. They will be included in the
|
||||
// audience field in the JWT that IAP creates.
|
||||
// See: https://cloud.google.com/iap/docs/signed-headers-howto#verifying_the_jwt_payload
|
||||
// The automatically generated backend service ID has the following format:
|
||||
// gkemcg1-default-console[-canary]-80-(some random string)
|
||||
private static final Pattern BACKEND_END_PATTERN =
|
||||
Pattern.compile(".*-default-((frontend|backend|console|pubapi)(-canary)?)-80-.*");
|
||||
|
||||
/** Provides the custom authentication mechanisms. */
|
||||
@Provides
|
||||
@@ -68,13 +91,18 @@ public class AuthModule {
|
||||
TokenVerifier provideIapTokenVerifier(
|
||||
@Config("projectId") String projectId,
|
||||
@Config("projectIdNumber") long projectIdNumber,
|
||||
@Config("backendServiceIds") Map<String, Long> backendServiceIds) {
|
||||
@Named("backendServiceIdMap") Supplier<ImmutableMap<String, Long>> backendServiceIdMap) {
|
||||
com.google.auth.oauth2.TokenVerifier.Builder tokenVerifierBuilder =
|
||||
com.google.auth.oauth2.TokenVerifier.newBuilder().setIssuer(IAP_ISSUER_URL);
|
||||
return (String service, String token) -> {
|
||||
String audience;
|
||||
if (RegistryEnvironment.isOnJetty()) {
|
||||
long backendServiceId = backendServiceIds.get(service);
|
||||
Long backendServiceId = backendServiceIdMap.get().get(service);
|
||||
checkNotNull(
|
||||
backendServiceId,
|
||||
"Backend service ID not found for service: %s, available IDs are %s",
|
||||
service,
|
||||
backendServiceIdMap);
|
||||
audience = String.format(IAP_GKE_AUDIENCE_FORMAT, projectIdNumber, backendServiceId);
|
||||
} else {
|
||||
audience = String.format(IAP_GAE_AUDIENCE_FORMAT, projectIdNumber, projectId);
|
||||
@@ -116,4 +144,48 @@ public class AuthModule {
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static BackendServicesClient provideBackendServicesClients(
|
||||
@ApplicationDefaultCredential GoogleCredentialsBundle credentialsBundle) {
|
||||
try {
|
||||
return BackendServicesClient.create(
|
||||
BackendServicesSettings.newBuilder()
|
||||
.setCredentialsProvider(credentialsBundle::getGoogleCredentials)
|
||||
.build());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named("backendServiceIdMap")
|
||||
static ImmutableMap<String, Long> provideBackendServiceList(
|
||||
Lazy<BackendServicesClient> client, @Config("projectId") String projectId) {
|
||||
if (RegistryEnvironment.isInTestServer() || RegistryEnvironment.get() == UNITTEST) {
|
||||
return ImmutableMap.of();
|
||||
}
|
||||
ImmutableMap.Builder<String, Long> builder = ImmutableMap.builder();
|
||||
for (BackendService service : client.get().list(projectId).iterateAll()) {
|
||||
String name = service.getName();
|
||||
Matcher matcher = BACKEND_END_PATTERN.matcher(name);
|
||||
if (!matcher.matches()) {
|
||||
continue;
|
||||
}
|
||||
builder.put(matcher.group(1), service.getId());
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
// Use an expiring cache so that the backend service ID map can be refreshed without restarting
|
||||
// the server. The map is very unlikely to change, except for when services are just deployed
|
||||
// for the first time, because some pods might receive traffic before all services are deployed.
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("backendServiceIdMap")
|
||||
static Supplier<ImmutableMap<String, Long>> provideBackendServiceIdMapSupplier(
|
||||
@Named("backendServiceIdMap") Provider<ImmutableMap<String, Long>> backendServiceIdMap) {
|
||||
return memoizeWithExpiration(backendServiceIdMap::get, Duration.ofMinutes(15));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,9 +36,9 @@ import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* An authenticam mechanism that verifies the OIDC token.
|
||||
* An authentication mechanism that verifies the OIDC token.
|
||||
*
|
||||
* <p>Currently, two flavors are supported: one that checkes for the OIDC token as a regular bearer
|
||||
* <p>Currently, two flavors are supported: one that checks for the OIDC token as a regular bearer
|
||||
* token, and another that checks for the OIDC token passed by IAP. In both cases, the {@link
|
||||
* AuthResult} with the highest {@link AuthLevel} possible is returned. So, if the email address for
|
||||
* which the token is minted exists both as a {@link User} and as a service account, the returned
|
||||
@@ -87,6 +87,9 @@ public abstract class OidcTokenAuthenticationMechanism implements Authentication
|
||||
if (RegistryEnvironment.isOnJetty()) {
|
||||
String hostname = request.getServerName();
|
||||
service = Splitter.on('.').split(hostname).iterator().next();
|
||||
if (request.getHeader("canary") != null) {
|
||||
service += "-canary";
|
||||
}
|
||||
}
|
||||
token = tokenVerifier.verify(service, rawIdToken);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
@@ -41,6 +42,15 @@ public abstract class CreateOrUpdateUserCommand extends ConfirmingCommand {
|
||||
+ " to remove the field.")
|
||||
private String registryLockEmailAddress;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
names = "--registry_lock_password",
|
||||
description =
|
||||
"Sets the registry lock password for this user, or removes it (allowing the user to"
|
||||
+ " re-set it). Do not set the password explicitly unless in exceptional"
|
||||
+ " circumstances.")
|
||||
private String registryLockPassword;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
names = "--admin",
|
||||
@@ -94,6 +104,25 @@ public abstract class CreateOrUpdateUserCommand extends ConfirmingCommand {
|
||||
builder.setRegistryLockEmailAddress(registryLockEmailAddress);
|
||||
}
|
||||
}
|
||||
// Ditto the registry lock password
|
||||
if (registryLockPassword != null) {
|
||||
if (registryLockEmailAddress != null) {
|
||||
// Edge case, make sure we're not removing an email and setting a password at the same time
|
||||
checkArgument(
|
||||
!registryLockEmailAddress.isEmpty(),
|
||||
"Cannot set/remove registry lock password on a user without a registry lock email"
|
||||
+ " address");
|
||||
} else {
|
||||
checkArgument(
|
||||
user != null && user.getRegistryLockEmailAddress().isPresent(),
|
||||
"Cannot set/remove registry lock password on a user without a registry lock email"
|
||||
+ " address");
|
||||
}
|
||||
builder.removeRegistryLockPassword();
|
||||
if (!registryLockPassword.isEmpty()) {
|
||||
builder.setRegistryLockPassword(registryLockPassword);
|
||||
}
|
||||
}
|
||||
tm().put(builder.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,15 +80,14 @@ class CurlCommand implements CommandWithConnection {
|
||||
required = true)
|
||||
private String serviceName;
|
||||
|
||||
@Parameter(
|
||||
names = {"--canary"},
|
||||
description = "If set, use the canary end-point; otherwise use the regular end-point.")
|
||||
private Boolean canary = Boolean.FALSE;
|
||||
|
||||
@Inject
|
||||
@Config("useGke")
|
||||
boolean useGke;
|
||||
|
||||
@Inject
|
||||
@Config("useCanary")
|
||||
boolean useCanary;
|
||||
|
||||
@Override
|
||||
public void setConnection(ServiceConnection connection) {
|
||||
this.connection = connection;
|
||||
@@ -109,7 +108,7 @@ class CurlCommand implements CommandWithConnection {
|
||||
? GkeService.valueOf(Ascii.toUpperCase(serviceName))
|
||||
: GaeService.valueOf(Ascii.toUpperCase(serviceName));
|
||||
|
||||
ServiceConnection connectionToService = connection.withService(service, canary);
|
||||
ServiceConnection connectionToService = connection.withService(service, useCanary);
|
||||
String response =
|
||||
(method == Method.GET)
|
||||
? connectionToService.sendGetRequest(path, ImmutableMap.<String, String>of())
|
||||
|
||||
@@ -64,8 +64,6 @@ final class GetKeyringSecretCommand implements Command {
|
||||
case BSA_API_KEY -> out.write(KeySerializer.serializeString(keyring.getBsaApiKey()));
|
||||
case ICANN_REPORTING_PASSWORD ->
|
||||
out.write(KeySerializer.serializeString(keyring.getIcannReportingPassword()));
|
||||
case SAFE_BROWSING_API_KEY ->
|
||||
out.write(KeySerializer.serializeString(keyring.getSafeBrowsingAPIKey()));
|
||||
case MARKSDB_DNL_LOGIN_AND_PASSWORD ->
|
||||
out.write(KeySerializer.serializeString(keyring.getMarksdbDnlLoginAndPassword()));
|
||||
case MARKSDB_LORDN_PASSWORD ->
|
||||
@@ -91,6 +89,12 @@ final class GetKeyringSecretCommand implements Command {
|
||||
keyring.getRdeStagingEncryptionKey(), keyring.getRdeStagingDecryptionKey())));
|
||||
case RDE_STAGING_PUBLIC_KEY ->
|
||||
out.write(KeySerializer.serializePublicKey(keyring.getRdeStagingEncryptionKey()));
|
||||
case SAFE_BROWSING_API_KEY ->
|
||||
out.write(KeySerializer.serializeString(keyring.getSafeBrowsingAPIKey()));
|
||||
case SQL_PRIMARY_CONN_NAME ->
|
||||
out.write(KeySerializer.serializeString(keyring.getSqlPrimaryConnectionName()));
|
||||
case SQL_REPLICA_CONN_NAME ->
|
||||
out.write(KeySerializer.serializeString(keyring.getSqlReplicaConnectionName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.beust.jcommander.Parameters;
|
||||
import com.beust.jcommander.ParametersDelegate;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import google.registry.persistence.transaction.TransactionManagerFactory;
|
||||
@@ -41,6 +42,9 @@ import org.postgresql.util.PSQLException;
|
||||
@Parameters(separators = " =", commandDescription = "Command-line interface to the registry")
|
||||
final class RegistryCli implements CommandRunner {
|
||||
|
||||
private static final ImmutableSet<RegistryToolEnvironment> DEFAULT_GKE_ENVIRONMENTS =
|
||||
ImmutableSet.of(RegistryToolEnvironment.ALPHA, RegistryToolEnvironment.QA);
|
||||
|
||||
// The environment parameter is parsed twice: once here, and once with {@link
|
||||
// RegistryToolEnvironment#parseFromArgs} in the {@link RegistryTool#main} function.
|
||||
//
|
||||
@@ -73,6 +77,12 @@ final class RegistryCli implements CommandRunner {
|
||||
@Parameter(names = "--gke", description = "Whether to use GKE runtime, instead of GAE")
|
||||
private boolean useGke = false;
|
||||
|
||||
@Parameter(names = "--gae", description = "Whether to use GAE runtime, instead of GKE")
|
||||
private boolean useGae = false;
|
||||
|
||||
@Parameter(names = "--canary", description = "Whether to connect to the canary instances")
|
||||
private boolean useCanary = false;
|
||||
|
||||
// Do not make this final - compile-time constant inlining may interfere with JCommander.
|
||||
@ParametersDelegate private LoggingParameters loggingParams = new LoggingParameters();
|
||||
|
||||
@@ -146,6 +156,13 @@ final class RegistryCli implements CommandRunner {
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
checkState(!useGke || !useGae, "Cannot specify both --gke and --gae");
|
||||
// Special logic to set the default based on the environment if neither --gae nor --gke is set.
|
||||
if (!useGke && !useGae) {
|
||||
useGke = DEFAULT_GKE_ENVIRONMENTS.contains(environment);
|
||||
}
|
||||
|
||||
String parsedCommand = jcommander.getParsedCommand();
|
||||
// Show the list of all commands either if requested or if no subcommand name was specified
|
||||
// (which does not throw a ParameterException parse error above).
|
||||
@@ -166,6 +183,7 @@ final class RegistryCli implements CommandRunner {
|
||||
.credentialFilePath(credentialJson)
|
||||
.sqlAccessInfoFile(sqlAccessInfoFile)
|
||||
.useGke(useGke)
|
||||
.useCanary(useCanary)
|
||||
.build();
|
||||
|
||||
// JCommander stores sub-commands as nested JCommander objects containing a list of user objects
|
||||
@@ -196,9 +214,9 @@ final class RegistryCli implements CommandRunner {
|
||||
System.err.println("===================================================================");
|
||||
System.err.println(
|
||||
"""
|
||||
This error is likely the result of having another instance of
|
||||
nomulus running at the same time. Check your system, shut down
|
||||
the other instance, and try again.""");
|
||||
This error is likely the result of having another instance of
|
||||
nomulus running at the same time. Check your system, shut down
|
||||
the other instance, and try again.""");
|
||||
System.err.println("===================================================================");
|
||||
} else {
|
||||
throw e;
|
||||
|
||||
@@ -195,6 +195,9 @@ interface RegistryToolComponent {
|
||||
@BindsInstance
|
||||
Builder useGke(@Config("useGke") boolean useGke);
|
||||
|
||||
@BindsInstance
|
||||
Builder useCanary(@Config("useCanary") boolean useCanary);
|
||||
|
||||
RegistryToolComponent build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,8 +65,11 @@ public class ServiceConnection {
|
||||
private final HttpRequestFactory requestFactory;
|
||||
|
||||
@Inject
|
||||
ServiceConnection(@Config("useGke") boolean useGke, HttpRequestFactory requestFactory) {
|
||||
this(useGke ? GkeService.BACKEND : GaeService.TOOLS, requestFactory, false);
|
||||
ServiceConnection(
|
||||
@Config("useGke") boolean useGke,
|
||||
@Config("useCanary") boolean useCanary,
|
||||
HttpRequestFactory requestFactory) {
|
||||
this(useGke ? GkeService.BACKEND : GaeService.TOOLS, requestFactory, useCanary);
|
||||
}
|
||||
|
||||
private ServiceConnection(Service service, HttpRequestFactory requestFactory, boolean useCanary) {
|
||||
|
||||
@@ -90,12 +90,16 @@ final class UpdateKeyringSecretCommand implements Command {
|
||||
secretManagerKeyringUpdater.setRdeSshClientPublicKey(deserializeString(input));
|
||||
case RDE_STAGING_KEY_PAIR ->
|
||||
secretManagerKeyringUpdater.setRdeStagingKey(deserializeKeyPair(input));
|
||||
case SAFE_BROWSING_API_KEY ->
|
||||
secretManagerKeyringUpdater.setSafeBrowsingAPIKey(deserializeString(input));
|
||||
case RDE_STAGING_PUBLIC_KEY ->
|
||||
throw new IllegalArgumentException(
|
||||
"Can't update RDE_STAGING_PUBLIC_KEY directly."
|
||||
+ " Must update public and private keys together using RDE_STAGING_KEY_PAIR.");
|
||||
case SAFE_BROWSING_API_KEY ->
|
||||
secretManagerKeyringUpdater.setSafeBrowsingAPIKey(deserializeString(input));
|
||||
case SQL_PRIMARY_CONN_NAME ->
|
||||
secretManagerKeyringUpdater.setSqlPrimaryConnectionName(deserializeString(input));
|
||||
case SQL_REPLICA_CONN_NAME ->
|
||||
secretManagerKeyringUpdater.setSqlReplicaConnectionName(deserializeString(input));
|
||||
}
|
||||
|
||||
secretManagerKeyringUpdater.update();
|
||||
|
||||
@@ -30,6 +30,7 @@ import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -174,7 +175,8 @@ public class UpdateRecurrenceCommand extends ConfirmingCommand {
|
||||
"Domain %s has already had a deletion time set",
|
||||
domainName);
|
||||
checkArgument(
|
||||
domain.getTransferData().isEmpty(),
|
||||
domain.getTransferData().isEmpty()
|
||||
|| domain.getTransferData().getTransferStatus() != TransferStatus.PENDING,
|
||||
"Domain %s has a pending transfer: %s",
|
||||
domainName,
|
||||
domain.getTransferData());
|
||||
|
||||
@@ -36,5 +36,7 @@ public enum KeyringKeyName {
|
||||
RDE_SSH_CLIENT_PUBLIC_KEY,
|
||||
RDE_STAGING_KEY_PAIR,
|
||||
RDE_STAGING_PUBLIC_KEY,
|
||||
SAFE_BROWSING_API_KEY
|
||||
SAFE_BROWSING_API_KEY,
|
||||
SQL_PRIMARY_CONN_NAME,
|
||||
SQL_REPLICA_CONN_NAME
|
||||
}
|
||||
|
||||
@@ -16,8 +16,12 @@ package google.registry.ui.server.console;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.DELETE;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.HEAD;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.request.Action.Method.PUT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
@@ -33,6 +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.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
@@ -75,13 +80,21 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
return;
|
||||
}
|
||||
User user = consoleApiParams.authResult().user().get();
|
||||
|
||||
String requestMethod = consoleApiParams.request().getMethod();
|
||||
try {
|
||||
if (consoleApiParams.request().getMethod().equals(GET.toString())) {
|
||||
if (requestMethod.equals(GET.toString())) {
|
||||
getHandler(user);
|
||||
} else if (requestMethod.equals(HEAD.toString())) {
|
||||
headHandler(user);
|
||||
} else {
|
||||
if (verifyXSRF(user)) {
|
||||
postHandler(user);
|
||||
if (requestMethod.equals(DELETE.toString())) {
|
||||
deleteHandler(user);
|
||||
} else if (requestMethod.equals(PUT.toString())) {
|
||||
putHandler(user);
|
||||
} else {
|
||||
postHandler(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ConsolePermissionForbiddenException e) {
|
||||
@@ -109,10 +122,22 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
throw new UnsupportedOperationException("Console API POST handler not implemented");
|
||||
}
|
||||
|
||||
protected void putHandler(User user) {
|
||||
throw new UnsupportedOperationException("Console API PUT handler not implemented");
|
||||
}
|
||||
|
||||
protected void getHandler(User user) {
|
||||
throw new UnsupportedOperationException("Console API GET handler not implemented");
|
||||
}
|
||||
|
||||
protected void deleteHandler(User user) {
|
||||
throw new UnsupportedOperationException("Console API DELETE handler not implemented");
|
||||
}
|
||||
|
||||
protected void headHandler(User user) {
|
||||
throw new UnsupportedOperationException("Console API HEAD handler not implemented");
|
||||
}
|
||||
|
||||
protected void setFailedResponse(String message, int code) {
|
||||
consoleApiParams.response().setStatus(code);
|
||||
consoleApiParams.response().setPayload(message);
|
||||
@@ -237,6 +262,14 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
protected void finishAndPersistConsoleUpdateHistory(ConsoleUpdateHistory.Builder<?, ?> builder) {
|
||||
builder.setActingUser(consoleApiParams.authResult().user().get());
|
||||
builder.setUrl(consoleApiParams.request().getRequestURI());
|
||||
builder.setMethod(consoleApiParams.request().getMethod());
|
||||
builder.setModificationTime(tm().getTransactionTime());
|
||||
tm().put(builder.build());
|
||||
}
|
||||
|
||||
/** Specialized exception class used for failure when a user doesn't have the right permission. */
|
||||
private static class ConsolePermissionForbiddenException extends RuntimeException {
|
||||
private ConsolePermissionForbiddenException(String message) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.ui.server.console;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
@@ -26,13 +27,16 @@ public record ConsoleApiParams(
|
||||
Response response,
|
||||
AuthResult authResult,
|
||||
SendEmailUtils sendEmailUtils,
|
||||
XsrfTokenManager xsrfTokenManager) {
|
||||
XsrfTokenManager xsrfTokenManager,
|
||||
Gson gson) {
|
||||
public static ConsoleApiParams create(
|
||||
HttpServletRequest request,
|
||||
Response response,
|
||||
AuthResult authResult,
|
||||
SendEmailUtils sendEmailUtils,
|
||||
XsrfTokenManager xsrfTokenManager) {
|
||||
return new ConsoleApiParams(request, response, authResult, sendEmailUtils, xsrfTokenManager);
|
||||
XsrfTokenManager xsrfTokenManager,
|
||||
Gson gson) {
|
||||
return new ConsoleApiParams(
|
||||
request, response, authResult, sendEmailUtils, xsrfTokenManager, gson);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.ui.server.console;
|
||||
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.escape.Escaper;
|
||||
import com.google.common.xml.XmlEscapers;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.annotations.Expose;
|
||||
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.ConsolePermission;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.eppcommon.ProtocolDefinition;
|
||||
import google.registry.model.eppoutput.EppOutput;
|
||||
import google.registry.model.eppoutput.Result;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.OptionalJsonPayload;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.auth.Auth;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Console endpoint to perform the same action to a list of domains.
|
||||
*
|
||||
* <p>All requests must include the {@link BulkAction} to perform as well as a {@link
|
||||
* BulkDomainList} of domains on which to apply the action. The remaining contents of the request
|
||||
* body depend on the type of action -- some requests may require more data than others.
|
||||
*/
|
||||
@Action(
|
||||
service = Action.GaeService.DEFAULT,
|
||||
gkeService = Action.GkeService.CONSOLE,
|
||||
path = ConsoleBulkDomainAction.PATH,
|
||||
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
||||
public class ConsoleBulkDomainAction extends ConsoleApiAction {
|
||||
|
||||
public static final String PATH = "/console-api/bulk-domain";
|
||||
|
||||
private static Escaper XML_ESCAPER = XmlEscapers.xmlContentEscaper();
|
||||
|
||||
public enum BulkAction {
|
||||
DELETE,
|
||||
SUSPEND
|
||||
}
|
||||
|
||||
/** All requests must include at least a list of domain names on which to perform the action. */
|
||||
public record BulkDomainList(@Expose List<String> domainList) {}
|
||||
|
||||
public record BulkDomainDeleteRequest(@Expose String reason) {}
|
||||
|
||||
public record BulkDomainSuspendRequest(@Expose String reason) {}
|
||||
|
||||
private static final String DOMAIN_DELETE_XML =
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
||||
<command>
|
||||
<delete>
|
||||
<domain:delete
|
||||
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
|
||||
<domain:name>%DOMAIN_NAME%</domain:name>
|
||||
</domain:delete>
|
||||
</delete>
|
||||
<extension>
|
||||
<metadata:metadata xmlns:metadata="urn:google:params:xml:ns:metadata-1.0">
|
||||
<metadata:reason>%REASON%</metadata:reason>
|
||||
<metadata:requestedByRegistrar>true</metadata:requestedByRegistrar>
|
||||
</metadata:metadata>
|
||||
</extension>
|
||||
<clTRID>RegistryConsole</clTRID>
|
||||
</command>
|
||||
</epp>""";
|
||||
|
||||
private static final String DOMAIN_SUSPEND_XML =
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<epp
|
||||
xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
||||
<command>
|
||||
<update>
|
||||
<domain:update
|
||||
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
|
||||
<domain:name>%DOMAIN_NAME%</domain:name>
|
||||
<domain:add>
|
||||
<domain:status s="serverDeleteProhibited" lang="en"></domain:status>
|
||||
<domain:status s="serverHold" lang="en"></domain:status>
|
||||
<domain:status s="serverRenewProhibited" lang="en"></domain:status>
|
||||
<domain:status s="serverTransferProhibited" lang="en"></domain:status>
|
||||
<domain:status s="serverUpdateProhibited" lang="en"></domain:status>
|
||||
</domain:add>
|
||||
<domain:rem></domain:rem>
|
||||
</domain:update>
|
||||
</update>
|
||||
<extension>
|
||||
<metadata:metadata
|
||||
xmlns:metadata="urn:google:params:xml:ns:metadata-1.0">
|
||||
<metadata:reason>Console suspension: %REASON%</metadata:reason>
|
||||
<metadata:requestedByRegistrar>false</metadata:requestedByRegistrar>
|
||||
</metadata:metadata>
|
||||
</extension>
|
||||
<clTRID>RegistryTool</clTRID>
|
||||
</command>
|
||||
</epp>""";
|
||||
|
||||
private final EppController eppController;
|
||||
private final String registrarId;
|
||||
private final String bulkDomainAction;
|
||||
private final Optional<JsonElement> optionalJsonPayload;
|
||||
|
||||
@Inject
|
||||
public ConsoleBulkDomainAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
EppController eppController,
|
||||
@Parameter("registrarId") String registrarId,
|
||||
@Parameter("bulkDomainAction") String bulkDomainAction,
|
||||
@OptionalJsonPayload Optional<JsonElement> optionalJsonPayload) {
|
||||
super(consoleApiParams);
|
||||
this.eppController = eppController;
|
||||
this.registrarId = registrarId;
|
||||
this.bulkDomainAction = bulkDomainAction;
|
||||
this.optionalJsonPayload = optionalJsonPayload;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postHandler(User user) {
|
||||
BulkAction bulkAction = BulkAction.valueOf(bulkDomainAction);
|
||||
JsonElement jsonPayload =
|
||||
optionalJsonPayload.orElseThrow(
|
||||
() -> new IllegalArgumentException("Bulk action payload must be present"));
|
||||
BulkDomainList domainList = consoleApiParams.gson().fromJson(jsonPayload, BulkDomainList.class);
|
||||
checkPermission(user, registrarId, ConsolePermission.EXECUTE_EPP_COMMANDS);
|
||||
ImmutableMap<String, ConsoleEppOutput> result =
|
||||
switch (bulkAction) {
|
||||
case DELETE -> handleBulkDelete(jsonPayload, domainList, user);
|
||||
case SUSPEND -> handleBulkSuspend(jsonPayload, domainList, user);
|
||||
};
|
||||
// Front end should parse situations where only some commands worked
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(result));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
private ImmutableMap<String, ConsoleEppOutput> handleBulkDelete(
|
||||
JsonElement jsonPayload, BulkDomainList domainList, User user) {
|
||||
String reason =
|
||||
consoleApiParams.gson().fromJson(jsonPayload, BulkDomainDeleteRequest.class).reason;
|
||||
return runCommandOverDomains(
|
||||
domainList,
|
||||
DOMAIN_DELETE_XML,
|
||||
new ImmutableMap.Builder<String, String>().put("REASON", reason),
|
||||
user);
|
||||
}
|
||||
|
||||
private ImmutableMap<String, ConsoleEppOutput> handleBulkSuspend(
|
||||
JsonElement jsonPayload, BulkDomainList domainList, User user) {
|
||||
String reason =
|
||||
consoleApiParams.gson().fromJson(jsonPayload, BulkDomainSuspendRequest.class).reason;
|
||||
return runCommandOverDomains(
|
||||
domainList,
|
||||
DOMAIN_SUSPEND_XML,
|
||||
new ImmutableMap.Builder<String, String>().put("REASON", reason),
|
||||
user);
|
||||
}
|
||||
|
||||
/** Runs the provided XML template and substitutions over a provided list of domains. */
|
||||
private ImmutableMap<String, ConsoleEppOutput> runCommandOverDomains(
|
||||
BulkDomainList domainList,
|
||||
String xmlTemplate,
|
||||
ImmutableMap.Builder<String, String> replacements,
|
||||
User user) {
|
||||
return domainList.domainList.stream()
|
||||
.collect(
|
||||
toImmutableMap(
|
||||
d -> d,
|
||||
d ->
|
||||
executeEpp(
|
||||
fillSubstitutions(xmlTemplate, replacements.put("DOMAIN_NAME", d)), user)));
|
||||
}
|
||||
|
||||
private ConsoleEppOutput executeEpp(String xml, User user) {
|
||||
return ConsoleEppOutput.fromEppOutput(
|
||||
eppController.handleEppCommand(
|
||||
new StatelessRequestSessionMetadata(
|
||||
registrarId, ProtocolDefinition.getVisibleServiceExtensionUris()),
|
||||
new PasswordOnlyTransportCredentials(),
|
||||
EppRequestSource.CONSOLE,
|
||||
false,
|
||||
user.getUserRoles().isAdmin(),
|
||||
xml.getBytes(UTF_8)));
|
||||
}
|
||||
|
||||
/** Fills the provided XML template with the replacement values, including escaping the values. */
|
||||
private String fillSubstitutions(
|
||||
String xmlTemplate, ImmutableMap.Builder<String, String> replacements) {
|
||||
String xml = xmlTemplate;
|
||||
for (Map.Entry<String, String> entry : replacements.buildKeepingLast().entrySet()) {
|
||||
xml = xml.replaceAll("%" + entry.getKey() + "%", XML_ESCAPER.escape(entry.getValue()));
|
||||
}
|
||||
return xml;
|
||||
}
|
||||
|
||||
public record ConsoleEppOutput(@Expose String message, @Expose int responseCode) {
|
||||
static ConsoleEppOutput fromEppOutput(EppOutput eppOutput) {
|
||||
Result result = eppOutput.getResponse().getResult();
|
||||
return new ConsoleEppOutput(result.getMsg(), result.getCode().code);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.model.EppResourceUtils;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.User;
|
||||
@@ -41,17 +40,14 @@ public class ConsoleDomainGetAction extends ConsoleApiAction {
|
||||
|
||||
public static final String PATH = "/console-api/domain";
|
||||
|
||||
private final Gson gson;
|
||||
private final String paramDomain;
|
||||
|
||||
@Inject
|
||||
public ConsoleDomainGetAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
Gson gson,
|
||||
@Parameter("consoleDomain") String paramDomain) {
|
||||
super(consoleApiParams);
|
||||
this.paramDomain = paramDomain;
|
||||
this.gson = gson;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,6 +68,6 @@ public class ConsoleDomainGetAction extends ConsoleApiAction {
|
||||
return;
|
||||
}
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
consoleApiParams.response().setPayload(gson.toJson(domain));
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(domain));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import google.registry.model.console.User;
|
||||
@@ -55,7 +54,6 @@ public class ConsoleDomainListAction extends ConsoleApiAction {
|
||||
private static final String SEARCH_TERM_QUERY = " AND LOWER(domainName) LIKE :searchTerm";
|
||||
private static final String ORDER_BY_STATEMENT = " ORDER BY creationTime DESC";
|
||||
|
||||
private final Gson gson;
|
||||
private final String registrarId;
|
||||
private final Optional<DateTime> checkpointTime;
|
||||
private final int pageNumber;
|
||||
@@ -66,7 +64,6 @@ public class ConsoleDomainListAction extends ConsoleApiAction {
|
||||
@Inject
|
||||
public ConsoleDomainListAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
Gson gson,
|
||||
@Parameter("registrarId") String registrarId,
|
||||
@Parameter("checkpointTime") Optional<DateTime> checkpointTime,
|
||||
@Parameter("pageNumber") Optional<Integer> pageNumber,
|
||||
@@ -74,7 +71,6 @@ public class ConsoleDomainListAction extends ConsoleApiAction {
|
||||
@Parameter("totalResults") Optional<Long> totalResults,
|
||||
@Parameter("searchTerm") Optional<String> searchTerm) {
|
||||
super(consoleApiParams);
|
||||
this.gson = gson;
|
||||
this.registrarId = registrarId;
|
||||
this.checkpointTime = checkpointTime;
|
||||
this.pageNumber = pageNumber.orElse(0);
|
||||
@@ -120,7 +116,10 @@ public class ConsoleDomainListAction extends ConsoleApiAction {
|
||||
|
||||
consoleApiParams
|
||||
.response()
|
||||
.setPayload(gson.toJson(new DomainListResult(domains, checkpoint, actualTotalResults)));
|
||||
.setPayload(
|
||||
consoleApiParams
|
||||
.gson()
|
||||
.toJson(new DomainListResult(domains, checkpoint, actualTotalResults)));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import google.registry.flows.EppException.AuthenticationErrorException;
|
||||
import google.registry.flows.PasswordOnlyTransportCredentials;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.request.Action;
|
||||
@@ -53,7 +55,6 @@ public class ConsoleEppPasswordAction extends ConsoleApiAction {
|
||||
private final PasswordOnlyTransportCredentials credentials =
|
||||
new PasswordOnlyTransportCredentials();
|
||||
private final AuthenticatedRegistrarAccessor registrarAccessor;
|
||||
|
||||
private final Optional<EppPasswordData> eppPasswordChangeRequest;
|
||||
|
||||
@Inject
|
||||
@@ -106,6 +107,14 @@ 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)));
|
||||
sendExternalUpdates(
|
||||
ImmutableMap.of("password", new DiffUtils.DiffPair("********", "••••••••")),
|
||||
registrar,
|
||||
|
||||
@@ -36,6 +36,7 @@ import google.registry.ui.server.SendEmailUtils;
|
||||
import google.registry.ui.server.console.ConsoleEppPasswordAction.EppPasswordData;
|
||||
import google.registry.ui.server.console.ConsoleOteAction.OteCreateData;
|
||||
import google.registry.ui.server.console.ConsoleRegistryLockAction.ConsoleRegistryLockPostInput;
|
||||
import google.registry.ui.server.console.ConsoleUsersAction.UserData;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -52,8 +53,10 @@ public final class ConsoleModule {
|
||||
Response response,
|
||||
AuthResult authResult,
|
||||
SendEmailUtils sendEmailUtils,
|
||||
XsrfTokenManager xsrfTokenManager) {
|
||||
return ConsoleApiParams.create(request, response, authResult, sendEmailUtils, xsrfTokenManager);
|
||||
XsrfTokenManager xsrfTokenManager,
|
||||
Gson gson) {
|
||||
return ConsoleApiParams.create(
|
||||
request, response, authResult, sendEmailUtils, xsrfTokenManager, gson);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -238,6 +241,12 @@ public final class ConsoleModule {
|
||||
return extractOptionalParameter(req, "searchTerm");
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter("bulkDomainAction")
|
||||
public static String provideBulkDomainAction(HttpServletRequest req) {
|
||||
return extractRequiredParameter(req, "bulkDomainAction");
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter("eppPasswordChangeRequest")
|
||||
public static Optional<EppPasswordData> provideEppPasswordChangeRequest(
|
||||
@@ -245,6 +254,13 @@ public final class ConsoleModule {
|
||||
return payload.map(s -> gson.fromJson(s, EppPasswordData.class));
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter("userData")
|
||||
public static Optional<UserData> provideUserData(
|
||||
Gson gson, @OptionalJsonPayload Optional<JsonElement> payload) {
|
||||
return payload.map(s -> gson.fromJson(s, UserData.class));
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter("oteCreateData")
|
||||
public static Optional<OteCreateData> provideOteCreateData(
|
||||
|
||||
@@ -27,7 +27,6 @@ import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.OteAccountBuilder;
|
||||
@@ -62,7 +61,6 @@ public class ConsoleOteAction extends ConsoleApiAction {
|
||||
private static final String STAT_TYPE_DESCRIPTION_PARAM = "description";
|
||||
private static final String STAT_TYPE_REQUIREMENT_PARAM = "requirement";
|
||||
private static final String STAT_TYPE_TIMES_PERFORMED_PARAM = "timesPerformed";
|
||||
private final Gson gson;
|
||||
private final StringGenerator passwordGenerator;
|
||||
private final Optional<OteCreateData> oteCreateData;
|
||||
private final Optional<String> maybeGroupEmailAddress;
|
||||
@@ -72,14 +70,12 @@ public class ConsoleOteAction extends ConsoleApiAction {
|
||||
@Inject
|
||||
public ConsoleOteAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
Gson gson,
|
||||
IamClient iamClient,
|
||||
@Parameter("registrarId") String registrarId, // Get request param
|
||||
@Config("gSuiteConsoleUserGroupEmailAddress") Optional<String> maybeGroupEmailAddress,
|
||||
@Named("base58StringGenerator") StringGenerator passwordGenerator,
|
||||
@Parameter("oteCreateData") Optional<OteCreateData> oteCreateData) {
|
||||
super(consoleApiParams);
|
||||
this.gson = gson;
|
||||
this.passwordGenerator = passwordGenerator;
|
||||
this.oteCreateData = oteCreateData;
|
||||
this.maybeGroupEmailAddress = maybeGroupEmailAddress;
|
||||
@@ -116,8 +112,13 @@ public class ConsoleOteAction extends ConsoleApiAction {
|
||||
consoleApiParams
|
||||
.response()
|
||||
.setPayload(
|
||||
gson.toJson(
|
||||
ImmutableMap.builder().putAll(registrarIdToTld).put("password", password).build()));
|
||||
consoleApiParams
|
||||
.gson()
|
||||
.toJson(
|
||||
ImmutableMap.builder()
|
||||
.putAll(registrarIdToTld)
|
||||
.put("password", password)
|
||||
.build()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,7 +154,7 @@ public class ConsoleOteAction extends ConsoleApiAction {
|
||||
convertSingleRequirement(statType, oteStats.getCount(statType)))
|
||||
.collect(toImmutableList());
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
consoleApiParams.response().setPayload(gson.toJson(stats));
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(stats));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.domain.DomainFlowUtils;
|
||||
@@ -72,7 +71,6 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
|
||||
private final DomainLockUtils domainLockUtils;
|
||||
private final GmailClient gmailClient;
|
||||
private final Gson gson;
|
||||
private final Optional<ConsoleRegistryLockPostInput> optionalPostInput;
|
||||
private final String registrarId;
|
||||
|
||||
@@ -81,14 +79,12 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
ConsoleApiParams consoleApiParams,
|
||||
DomainLockUtils domainLockUtils,
|
||||
GmailClient gmailClient,
|
||||
Gson gson,
|
||||
@Parameter("consoleRegistryLockPostInput")
|
||||
Optional<ConsoleRegistryLockPostInput> optionalPostInput,
|
||||
@Parameter("registrarId") String registrarId) {
|
||||
super(consoleApiParams);
|
||||
this.domainLockUtils = domainLockUtils;
|
||||
this.gmailClient = gmailClient;
|
||||
this.gson = gson;
|
||||
this.optionalPostInput = optionalPostInput;
|
||||
this.registrarId = registrarId;
|
||||
}
|
||||
@@ -96,7 +92,7 @@ public class ConsoleRegistryLockAction extends ConsoleApiAction {
|
||||
@Override
|
||||
protected void getHandler(User user) {
|
||||
checkPermission(user, registrarId, ConsolePermission.REGISTRY_LOCK);
|
||||
consoleApiParams.response().setPayload(gson.toJson(getLockedDomains()));
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(getLockedDomains()));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ package google.registry.ui.server.console;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.domain.RegistryLock;
|
||||
@@ -42,18 +41,15 @@ public class ConsoleRegistryLockVerifyAction extends ConsoleApiAction {
|
||||
static final String PATH = "/console-api/registry-lock-verify";
|
||||
|
||||
private final DomainLockUtils domainLockUtils;
|
||||
private final Gson gson;
|
||||
private final String lockVerificationCode;
|
||||
|
||||
@Inject
|
||||
public ConsoleRegistryLockVerifyAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
DomainLockUtils domainLockUtils,
|
||||
Gson gson,
|
||||
@Parameter("lockVerificationCode") String lockVerificationCode) {
|
||||
super(consoleApiParams);
|
||||
this.domainLockUtils = domainLockUtils;
|
||||
this.gson = gson;
|
||||
this.lockVerificationCode = lockVerificationCode;
|
||||
}
|
||||
|
||||
@@ -68,7 +64,7 @@ public class ConsoleRegistryLockVerifyAction extends ConsoleApiAction {
|
||||
RegistryLockVerificationResponse lockResponse =
|
||||
new RegistryLockVerificationResponse(
|
||||
Ascii.toLowerCase(action.toString()), lock.getDomainName(), lock.getRegistrarId());
|
||||
consoleApiParams.response().setPayload(gson.toJson(lockResponse));
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(lockResponse));
|
||||
consoleApiParams.response().setStatus(HttpServletResponse.SC_OK);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ import static org.apache.http.HttpStatus.SC_OK;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.request.Action;
|
||||
@@ -99,6 +101,11 @@ public class ConsoleUpdateRegistrarAction extends ConsoleApiAction {
|
||||
.build();
|
||||
|
||||
tm().put(updatedRegistrar);
|
||||
finishAndPersistConsoleUpdateHistory(
|
||||
new RegistrarUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
|
||||
.setRegistrar(updatedRegistrar)
|
||||
.setRequestBody(consoleApiParams.gson().toJson(registrarParam)));
|
||||
sendExternalUpdatesIfNecessary(
|
||||
EmailInfo.create(
|
||||
existingRegistrar.get(),
|
||||
|
||||
@@ -82,6 +82,8 @@ public class ConsoleUserDataAction extends ConsoleApiAction {
|
||||
// auth checks.
|
||||
"isAdmin", user.getUserRoles().isAdmin(),
|
||||
"globalRole", user.getUserRoles().getGlobalRole(),
|
||||
// registrar-specific roles
|
||||
"userRoles", user.getUserRoles().getRegistrarRoles(),
|
||||
// Include static contact resources in this call to minimize round trips
|
||||
"productName", productName,
|
||||
"supportEmail", supportEmail,
|
||||
|
||||
@@ -14,22 +14,27 @@
|
||||
|
||||
package google.registry.ui.server.console;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.model.console.RegistrarRole.ACCOUNT_MANAGER;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.DELETE;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.request.Action.Method.PUT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_CREATED;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.api.services.directory.Directory;
|
||||
import com.google.api.services.directory.model.UserName;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.RegistrarRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.persistence.VKey;
|
||||
@@ -38,11 +43,15 @@ import google.registry.request.Action.GkeService;
|
||||
import google.registry.request.HttpException.BadRequestException;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.tools.IamClient;
|
||||
import google.registry.util.StringGenerator;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
@@ -50,36 +59,39 @@ import javax.inject.Named;
|
||||
service = Action.GaeService.DEFAULT,
|
||||
gkeService = GkeService.CONSOLE,
|
||||
path = ConsoleUsersAction.PATH,
|
||||
method = {GET, POST},
|
||||
method = {GET, POST, DELETE, PUT},
|
||||
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
||||
public class ConsoleUsersAction extends ConsoleApiAction {
|
||||
static final String PATH = "/console-api/users";
|
||||
|
||||
private static final int PASSWORD_LENGTH = 16;
|
||||
|
||||
private static final Splitter EMAIL_SPLITTER = Splitter.on('@').trimResults();
|
||||
|
||||
private final Gson gson;
|
||||
private final String registrarId;
|
||||
private final Directory directory;
|
||||
private final StringGenerator passwordGenerator;
|
||||
private final Optional<UserData> userData;
|
||||
private final Optional<String> maybeGroupEmailAddress;
|
||||
private final IamClient iamClient;
|
||||
private final String gSuiteDomainName;
|
||||
|
||||
@Inject
|
||||
public ConsoleUsersAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
Gson gson,
|
||||
Directory directory,
|
||||
IamClient iamClient,
|
||||
@Config("gSuiteDomainName") String gSuiteDomainName,
|
||||
@Config("gSuiteConsoleUserGroupEmailAddress") Optional<String> maybeGroupEmailAddress,
|
||||
@Named("base58StringGenerator") StringGenerator passwordGenerator,
|
||||
@Parameter("userData") Optional<UserData> userData,
|
||||
@Parameter("registrarId") String registrarId) {
|
||||
super(consoleApiParams);
|
||||
this.gson = gson;
|
||||
this.registrarId = registrarId;
|
||||
this.directory = directory;
|
||||
this.passwordGenerator = passwordGenerator;
|
||||
}
|
||||
|
||||
private static String generateNewEmailAddress(User user, String increment) {
|
||||
List<String> emailParts = EMAIL_SPLITTER.splitToList(user.getEmailAddress());
|
||||
return String.format("%s-%s@%s", emailParts.get(0), increment, emailParts.get(1));
|
||||
this.userData = userData;
|
||||
this.maybeGroupEmailAddress = maybeGroupEmailAddress;
|
||||
this.iamClient = iamClient;
|
||||
this.gSuiteDomainName = gSuiteDomainName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,7 +99,18 @@ public class ConsoleUsersAction extends ConsoleApiAction {
|
||||
// Temporary flag while testing
|
||||
if (user.getUserRoles().isAdmin()) {
|
||||
checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
|
||||
tm().transact(() -> runInTransaction(user));
|
||||
tm().transact(this::runPostInTransaction);
|
||||
} else {
|
||||
consoleApiParams.response().setStatus(SC_FORBIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putHandler(User user) {
|
||||
// Temporary flag while testing
|
||||
if (user.getUserRoles().isAdmin()) {
|
||||
checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
|
||||
tm().transact(this::runUpdateInTransaction);
|
||||
} else {
|
||||
consoleApiParams.response().setStatus(SC_FORBIDDEN);
|
||||
}
|
||||
@@ -96,40 +119,102 @@ public class ConsoleUsersAction extends ConsoleApiAction {
|
||||
@Override
|
||||
protected void getHandler(User user) {
|
||||
checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
|
||||
List<ImmutableMap> users =
|
||||
getAllUsers().stream()
|
||||
.filter(u -> u.getUserRoles().getRegistrarRoles().containsKey(registrarId))
|
||||
List<UserData> users =
|
||||
getAllRegistrarUsers(registrarId).stream()
|
||||
.map(
|
||||
u ->
|
||||
ImmutableMap.of(
|
||||
"emailAddress",
|
||||
new UserData(
|
||||
u.getEmailAddress(),
|
||||
"role",
|
||||
u.getUserRoles().getRegistrarRoles().get(registrarId)))
|
||||
u.getUserRoles().getRegistrarRoles().get(registrarId).toString(),
|
||||
null))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
consoleApiParams.response().setPayload(gson.toJson(users));
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(users));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
private void runInTransaction(User user) throws IOException {
|
||||
String nextAvailableIncrement =
|
||||
Stream.of("1", "2", "3")
|
||||
.filter(
|
||||
increment ->
|
||||
tm().loadByKeyIfPresent(
|
||||
VKey.create(User.class, generateNewEmailAddress(user, increment)))
|
||||
.isEmpty())
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new BadRequestException("Extra users amount is limited to 3"));
|
||||
@Override
|
||||
protected void deleteHandler(User user) {
|
||||
// Temporary flag while testing
|
||||
if (user.getUserRoles().isAdmin()) {
|
||||
checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
|
||||
tm().transact(this::runDeleteInTransaction);
|
||||
} else {
|
||||
consoleApiParams.response().setStatus(SC_FORBIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
private void runPostInTransaction() throws IOException {
|
||||
validateRequestParams();
|
||||
if (!tm().exists(VKey.create(User.class, this.userData.get().emailAddress))) {
|
||||
this.runCreate();
|
||||
} else {
|
||||
this.runAppendUserToExistingRegistrar();
|
||||
}
|
||||
}
|
||||
|
||||
private void runAppendUserToExistingRegistrar() {
|
||||
ImmutableList<User> allRegistrarUsers = getAllRegistrarUsers(registrarId);
|
||||
if (allRegistrarUsers.size() >= 4) {
|
||||
throw new BadRequestException("Total users amount per registrar is limited to 4");
|
||||
}
|
||||
|
||||
updateUserRegistrarRoles(
|
||||
this.userData.get().emailAddress,
|
||||
registrarId,
|
||||
RegistrarRole.valueOf(this.userData.get().role));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
private void runDeleteInTransaction() throws IOException {
|
||||
if (!isModifyingRequestValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String email = this.userData.get().emailAddress;
|
||||
User updatedUser = updateUserRegistrarRoles(email, registrarId, null);
|
||||
|
||||
// User has no registrars assigned
|
||||
if (updatedUser.getUserRoles().getRegistrarRoles().size() == 0) {
|
||||
try {
|
||||
directory.users().delete(email).execute();
|
||||
} catch (IOException e) {
|
||||
setFailedResponse("Failed to delete the user workspace account", SC_INTERNAL_SERVER_ERROR);
|
||||
throw e;
|
||||
}
|
||||
|
||||
VKey<User> key = VKey.create(User.class, email);
|
||||
tm().delete(key);
|
||||
User.revokeIapPermission(email, maybeGroupEmailAddress, cloudTasksUtils, null, iamClient);
|
||||
}
|
||||
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
private void runCreate() throws IOException {
|
||||
ImmutableList<User> allRegistrarUsers = getAllRegistrarUsers(registrarId);
|
||||
if (allRegistrarUsers.size() >= 4) {
|
||||
throw new BadRequestException("Total users amount per registrar is limited to 4");
|
||||
}
|
||||
|
||||
String newEmailPrefix = userData.get().emailAddress.trim();
|
||||
|
||||
if (!newEmailPrefix.matches("^[a-zA-Z0-9]{3}$")) {
|
||||
throw new BadRequestException("Email prefix is invalid");
|
||||
}
|
||||
|
||||
String newEmail = String.format("%s.%s@%s", newEmailPrefix, registrarId, gSuiteDomainName);
|
||||
if (tm().loadByKeyIfPresent(VKey.create(User.class, newEmail)).isPresent()) {
|
||||
throw new BadRequestException("Email prefix is not available");
|
||||
}
|
||||
|
||||
com.google.api.services.directory.model.User newUser =
|
||||
new com.google.api.services.directory.model.User();
|
||||
|
||||
newUser.setName(
|
||||
new UserName().setFamilyName(registrarId).setGivenName("User" + nextAvailableIncrement));
|
||||
new UserName().setFamilyName(registrarId).setGivenName(newEmailPrefix + "." + registrarId));
|
||||
newUser.setPassword(passwordGenerator.createString(PASSWORD_LENGTH));
|
||||
newUser.setPrimaryEmail(generateNewEmailAddress(user, nextAvailableIncrement));
|
||||
newUser.setPrimaryEmail(newEmail);
|
||||
|
||||
try {
|
||||
directory.users().insert(newUser).execute();
|
||||
@@ -143,29 +228,92 @@ public class ConsoleUsersAction extends ConsoleApiAction {
|
||||
.setRegistrarRoles(ImmutableMap.of(registrarId, ACCOUNT_MANAGER))
|
||||
.build();
|
||||
|
||||
User.Builder builder =
|
||||
new User.Builder().setUserRoles(userRoles).setEmailAddress(newUser.getPrimaryEmail());
|
||||
User.Builder builder = new User.Builder().setUserRoles(userRoles).setEmailAddress(newEmail);
|
||||
tm().put(builder.build());
|
||||
User.grantIapPermission(newEmail, maybeGroupEmailAddress, cloudTasksUtils, null, iamClient);
|
||||
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
consoleApiParams.response().setStatus(SC_CREATED);
|
||||
consoleApiParams
|
||||
.response()
|
||||
.setPayload(
|
||||
gson.toJson(
|
||||
ImmutableMap.of(
|
||||
"password",
|
||||
newUser.getPassword(),
|
||||
"emailAddress",
|
||||
newUser.getPrimaryEmail(),
|
||||
"role",
|
||||
ACCOUNT_MANAGER)));
|
||||
consoleApiParams
|
||||
.gson()
|
||||
.toJson(new UserData(newEmail, ACCOUNT_MANAGER.toString(), newUser.getPassword())));
|
||||
}
|
||||
|
||||
private ImmutableList<User> getAllUsers() {
|
||||
private void runUpdateInTransaction() {
|
||||
if (!isModifyingRequestValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateUserRegistrarRoles(
|
||||
this.userData.get().emailAddress,
|
||||
registrarId,
|
||||
RegistrarRole.valueOf(this.userData.get().role));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
private boolean isModifyingRequestValid() {
|
||||
validateRequestParams();
|
||||
User userToUpdate = verifyUserExists(userData.get().emailAddress);
|
||||
return validateUserRegistrarAssociation(userToUpdate);
|
||||
}
|
||||
|
||||
private void validateRequestParams() {
|
||||
if (userData.isEmpty()
|
||||
|| isNullOrEmpty(userData.get().emailAddress)
|
||||
|| isNullOrEmpty(userData.get().role)) {
|
||||
throw new BadRequestException("User data is missing or incomplete");
|
||||
}
|
||||
}
|
||||
|
||||
private User verifyUserExists(String email) {
|
||||
return tm().loadByKeyIfPresent(VKey.create(User.class, email))
|
||||
.orElseThrow(() -> new BadRequestException(String.format("User %s doesn't exist", email)));
|
||||
}
|
||||
|
||||
private boolean validateUserRegistrarAssociation(User user) {
|
||||
if (user.getUserRoles().getRegistrarRoles().containsKey(registrarId)) {
|
||||
return true;
|
||||
}
|
||||
setFailedResponse(
|
||||
String.format("Can't update user not associated with registrarId %s", registrarId),
|
||||
SC_FORBIDDEN);
|
||||
return false;
|
||||
}
|
||||
|
||||
private User updateUserRegistrarRoles(String email, String registrarId, RegistrarRole newRole) {
|
||||
Map<String, RegistrarRole> updatedRegistrarRoles;
|
||||
User user = verifyUserExists(email);
|
||||
if (newRole == null) {
|
||||
updatedRegistrarRoles =
|
||||
user.getUserRoles().getRegistrarRoles().entrySet().stream()
|
||||
.filter(entry -> !Objects.equals(entry.getKey(), registrarId))
|
||||
.collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
} else {
|
||||
updatedRegistrarRoles =
|
||||
ImmutableMap.<String, RegistrarRole>builder()
|
||||
.putAll(user.getUserRoles().getRegistrarRoles())
|
||||
.put(registrarId, newRole)
|
||||
.buildKeepingLast();
|
||||
}
|
||||
var updatedUser =
|
||||
user.asBuilder()
|
||||
.setUserRoles(
|
||||
user.getUserRoles().asBuilder().setRegistrarRoles(updatedRegistrarRoles).build())
|
||||
.build();
|
||||
tm().put(updatedUser);
|
||||
return updatedUser;
|
||||
}
|
||||
|
||||
private ImmutableList<User> getAllRegistrarUsers(String registrarId) {
|
||||
return tm().transact(
|
||||
() ->
|
||||
tm().loadAllOf(User.class).stream()
|
||||
.filter(u -> !u.getUserRoles().getRegistrarRoles().isEmpty())
|
||||
.filter(u -> u.getUserRoles().getRegistrarRoles().containsKey(registrarId))
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
|
||||
public record UserData(
|
||||
@Expose String emailAddress, @Expose String role, @Expose @Nullable String password) {}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,9 @@ import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.RegistrarUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarBase;
|
||||
@@ -62,7 +63,6 @@ public class RegistrarsAction extends ConsoleApiAction {
|
||||
WHERE registrar_id in :registrarIds
|
||||
""";
|
||||
static final String PATH = "/console-api/registrars";
|
||||
private final Gson gson;
|
||||
private final Optional<Registrar> registrar;
|
||||
private final StringGenerator passwordGenerator;
|
||||
private final StringGenerator passcodeGenerator;
|
||||
@@ -70,12 +70,10 @@ public class RegistrarsAction extends ConsoleApiAction {
|
||||
@Inject
|
||||
public RegistrarsAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
Gson gson,
|
||||
@Parameter("registrar") Optional<Registrar> registrar,
|
||||
@Named("base58StringGenerator") StringGenerator passwordGenerator,
|
||||
@Named("digitOnlyStringGenerator") StringGenerator passcodeGenerator) {
|
||||
super(consoleApiParams);
|
||||
this.gson = gson;
|
||||
this.registrar = registrar;
|
||||
this.passcodeGenerator = passcodeGenerator;
|
||||
this.passwordGenerator = passwordGenerator;
|
||||
@@ -88,7 +86,7 @@ public class RegistrarsAction extends ConsoleApiAction {
|
||||
Streams.stream(Registrar.loadAll())
|
||||
.filter(r -> allowedRegistrarTypes.contains(r.getType()))
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
consoleApiParams.response().setPayload(gson.toJson(registrars));
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(registrars));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
} else if (user.getUserRoles().getRegistrarRoles().values().stream()
|
||||
.anyMatch(role -> role.hasPermission(ConsolePermission.VIEW_REGISTRAR_DETAILS))) {
|
||||
@@ -106,7 +104,7 @@ public class RegistrarsAction extends ConsoleApiAction {
|
||||
.setParameter("registrarIds", accessibleRegistrarIds)
|
||||
.getResultList());
|
||||
|
||||
consoleApiParams.response().setPayload(gson.toJson(registrars));
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(registrars));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
} else {
|
||||
consoleApiParams.response().setStatus(SC_FORBIDDEN);
|
||||
@@ -175,6 +173,11 @@ public class RegistrarsAction extends ConsoleApiAction {
|
||||
"Registrar with registrarId %s already exists",
|
||||
registrar.getRegistrarId());
|
||||
tm().putAll(registrar, contact);
|
||||
finishAndPersistConsoleUpdateHistory(
|
||||
new RegistrarUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
|
||||
.setRegistrar(registrar)
|
||||
.setRequestBody(consoleApiParams.gson().toJson(registrar)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.gson.Gson;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
@@ -60,18 +59,15 @@ import javax.inject.Inject;
|
||||
public class ContactAction extends ConsoleApiAction {
|
||||
static final String PATH = "/console-api/settings/contacts";
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private final Gson gson;
|
||||
private final Optional<ImmutableSet<RegistrarPoc>> contacts;
|
||||
private final String registrarId;
|
||||
|
||||
@Inject
|
||||
public ContactAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
Gson gson,
|
||||
@Parameter("registrarId") String registrarId,
|
||||
@Parameter("contacts") Optional<ImmutableSet<RegistrarPoc>> contacts) {
|
||||
super(consoleApiParams);
|
||||
this.gson = gson;
|
||||
this.registrarId = registrarId;
|
||||
this.contacts = contacts;
|
||||
}
|
||||
@@ -90,7 +86,7 @@ public class ContactAction extends ConsoleApiAction {
|
||||
.collect(toImmutableList()));
|
||||
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
consoleApiParams.response().setPayload(gson.toJson(am));
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(am));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,8 @@ import com.google.common.collect.ImmutableSet;
|
||||
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.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.request.Action;
|
||||
@@ -117,6 +119,11 @@ 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())));
|
||||
|
||||
sendExternalUpdatesIfNecessary(
|
||||
EmailInfo.create(savedRegistrar, updatedRegistrar, ImmutableSet.of(), ImmutableSet.of()));
|
||||
|
||||
@@ -22,6 +22,8 @@ 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.User;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.request.Action;
|
||||
@@ -104,6 +106,11 @@ public class WhoisRegistrarFieldsAction extends ConsoleApiAction {
|
||||
.setEmailAddress(providedRegistrar.getEmailAddress())
|
||||
.build();
|
||||
tm().put(newRegistrar);
|
||||
finishAndPersistConsoleUpdateHistory(
|
||||
new RegistrarUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
|
||||
.setRegistrar(newRegistrar)
|
||||
.setRequestBody(consoleApiParams.gson().toJson(registrar.get())));
|
||||
sendExternalUpdatesIfNecessary(
|
||||
EmailInfo.create(
|
||||
savedRegistrar,
|
||||
|
||||
@@ -16,10 +16,14 @@ 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;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistDeletedDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -31,8 +35,14 @@ import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.StorageException;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.tld.Tld;
|
||||
import google.registry.model.tld.Tld.TldType;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
@@ -56,7 +66,7 @@ class ExportDomainListsActionTest {
|
||||
|
||||
@RegisterExtension
|
||||
final JpaIntegrationTestExtension jpa =
|
||||
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
|
||||
new JpaTestExtensions.Builder().withClock(clock).buildIntegrationTestExtension();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
@@ -70,6 +80,7 @@ class ExportDomainListsActionTest {
|
||||
action.gcsUtils = gcsUtils;
|
||||
action.clock = clock;
|
||||
action.driveConnection = driveConnection;
|
||||
persistFeatureFlag(INACTIVE);
|
||||
}
|
||||
|
||||
private void verifyExportedToDrive(String folderId, String domains) throws Exception {
|
||||
@@ -83,7 +94,7 @@ class ExportDomainListsActionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_outputsOnlyActiveDomains() throws Exception {
|
||||
void test_outputsOnlyActiveDomains_txt() throws Exception {
|
||||
persistActiveDomain("onetwo.tld");
|
||||
persistActiveDomain("rudnitzky.tld");
|
||||
persistDeletedDomain("mortuary.tld", DateTime.parse("2001-03-14T10:11:12Z"));
|
||||
@@ -97,7 +108,22 @@ class ExportDomainListsActionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_outputsOnlyDomainsOnRealTlds() throws Exception {
|
||||
void test_outputsOnlyActiveDomains_csv() throws Exception {
|
||||
persistFeatureFlag(ACTIVE);
|
||||
persistActiveDomain("onetwo.tld");
|
||||
persistActiveDomain("rudnitzky.tld");
|
||||
persistDeletedDomain("mortuary.tld", DateTime.parse("2001-03-14T10:11:12Z"));
|
||||
action.run();
|
||||
BlobId existingFile = BlobId.of("outputbucket", "tld.txt");
|
||||
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,");
|
||||
verifyNoMoreInteractions(driveConnection);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_outputsOnlyDomainsOnRealTlds_txt() throws Exception {
|
||||
persistActiveDomain("onetwo.tld");
|
||||
persistActiveDomain("rudnitzky.tld");
|
||||
persistActiveDomain("wontgo.testtld");
|
||||
@@ -116,7 +142,58 @@ class ExportDomainListsActionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_outputsDomainsFromDifferentTldsToMultipleFiles() throws Exception {
|
||||
void test_outputsOnlyDomainsOnRealTlds_csv() throws Exception {
|
||||
persistFeatureFlag(ACTIVE);
|
||||
persistActiveDomain("onetwo.tld");
|
||||
persistActiveDomain("rudnitzky.tld");
|
||||
persistActiveDomain("wontgo.testtld");
|
||||
action.run();
|
||||
BlobId existingFile = BlobId.of("outputbucket", "tld.txt");
|
||||
String tlds = new String(gcsUtils.readBytesFrom(existingFile), UTF_8).trim();
|
||||
// Check that it only contains the domains on the real TLD, and not the test one.
|
||||
assertThat(tlds).isEqualTo("onetwo.tld,\nrudnitzky.tld,");
|
||||
// Make sure that the test TLD file wasn't written out.
|
||||
BlobId nonexistentFile = BlobId.of("outputbucket", "testtld.txt");
|
||||
assertThrows(StorageException.class, () -> gcsUtils.readBytesFrom(nonexistentFile));
|
||||
ImmutableList<String> ls = gcsUtils.listFolderObjects("outputbucket", "");
|
||||
assertThat(ls).containsExactly("tld.txt");
|
||||
verifyExportedToDrive("brouhaha", "onetwo.tld,\nrudnitzky.tld,");
|
||||
verifyNoMoreInteractions(driveConnection);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_outputIncludesDeletionTimes_forPendingDeletes_notRdemption() throws Exception {
|
||||
persistFeatureFlag(ACTIVE);
|
||||
// Domains pending delete (meaning the 5 day period, not counting the 30 day redemption period)
|
||||
// should include their pending deletion date
|
||||
persistActiveDomain("active.tld");
|
||||
Domain redemption = persistActiveDomain("redemption.tld");
|
||||
persistResource(
|
||||
redemption
|
||||
.asBuilder()
|
||||
.addStatusValue(StatusValue.PENDING_DELETE)
|
||||
.addGracePeriod(
|
||||
GracePeriod.createWithoutBillingEvent(
|
||||
GracePeriodStatus.REDEMPTION,
|
||||
redemption.getRepoId(),
|
||||
clock.nowUtc().plusDays(20),
|
||||
redemption.getCurrentSponsorRegistrarId()))
|
||||
.build());
|
||||
persistResource(
|
||||
persistActiveDomain("pendingdelete.tld")
|
||||
.asBuilder()
|
||||
.addStatusValue(StatusValue.PENDING_DELETE)
|
||||
.setDeletionTime(clock.nowUtc().plusDays(3))
|
||||
.build());
|
||||
|
||||
action.run();
|
||||
|
||||
verifyExportedToDrive(
|
||||
"brouhaha", "active.tld,\npendingdelete.tld,2020-02-05T02:02:02.000Z\nredemption.tld,");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_outputsDomainsFromDifferentTldsToMultipleFiles_txt() throws Exception {
|
||||
createTld("tldtwo");
|
||||
persistResource(Tld.get("tldtwo").asBuilder().setDriveFolderId("hooray").build());
|
||||
|
||||
@@ -143,4 +220,43 @@ class ExportDomainListsActionTest {
|
||||
// tldthree does not have a drive id, so no export to drive is performed.
|
||||
verifyNoMoreInteractions(driveConnection);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_outputsDomainsFromDifferentTldsToMultipleFiles_csv() throws Exception {
|
||||
persistFeatureFlag(ACTIVE);
|
||||
createTld("tldtwo");
|
||||
persistResource(Tld.get("tldtwo").asBuilder().setDriveFolderId("hooray").build());
|
||||
|
||||
createTld("tldthree");
|
||||
// You'd think this test was written around Christmas, but it wasn't.
|
||||
persistActiveDomain("dasher.tld");
|
||||
persistActiveDomain("prancer.tld");
|
||||
persistActiveDomain("rudolph.tldtwo");
|
||||
persistActiveDomain("santa.tldtwo");
|
||||
persistActiveDomain("buddy.tldtwo");
|
||||
persistActiveDomain("cupid.tldthree");
|
||||
action.run();
|
||||
BlobId firstTldFile = BlobId.of("outputbucket", "tld.txt");
|
||||
String tlds = new String(gcsUtils.readBytesFrom(firstTldFile), UTF_8).trim();
|
||||
assertThat(tlds).isEqualTo("dasher.tld,\nprancer.tld,");
|
||||
BlobId secondTldFile = BlobId.of("outputbucket", "tldtwo.txt");
|
||||
String moreTlds = new String(gcsUtils.readBytesFrom(secondTldFile), UTF_8).trim();
|
||||
assertThat(moreTlds).isEqualTo("buddy.tldtwo,\nrudolph.tldtwo,\nsanta.tldtwo,");
|
||||
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,");
|
||||
// tldthree does not have a drive id, so no export to drive is performed.
|
||||
verifyNoMoreInteractions(driveConnection);
|
||||
}
|
||||
|
||||
private void persistFeatureFlag(FeatureFlag.FeatureStatus status) {
|
||||
persistResource(
|
||||
new FeatureFlag()
|
||||
.asBuilder()
|
||||
.setFeatureName(INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS)
|
||||
.setStatusMap(ImmutableSortedMap.of(START_OF_TIME, status))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ class ExtensionManagerTest {
|
||||
void testMetadataExtension_forbiddenWhenNotToolSource() {
|
||||
ExtensionManager manager =
|
||||
new TestInstanceBuilder()
|
||||
.setEppRequestSource(EppRequestSource.CONSOLE)
|
||||
.setEppRequestSource(EppRequestSource.TLS)
|
||||
.setDeclaredUris()
|
||||
.setSuppliedExtensions(MetadataExtension.class)
|
||||
.build();
|
||||
|
||||
@@ -1247,4 +1247,15 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
|
||||
clock.advanceOneMilli();
|
||||
runFlowAssertResponse(loadFile("domain_delete_response_fee_free_grace.xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_skipsPollMessage_whenConfigured() throws Exception {
|
||||
setUpSuccessfulTest();
|
||||
domain =
|
||||
persistResource(
|
||||
domain.asBuilder().setPersistedCurrentSponsorRegistrarId("NewRegistrar").build());
|
||||
setRegistrarIdForFlow("NewRegistrar");
|
||||
runFlowAssertResponse(loadFile("domain_delete_response_pending.xml"));
|
||||
assertPollMessages();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.tld.Tld;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -103,12 +104,12 @@ class DomainRestoreRequestFlowTest extends ResourceFlowTestCase<DomainRestoreReq
|
||||
setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "example.tld"));
|
||||
}
|
||||
|
||||
void persistPendingDeleteDomain() throws Exception {
|
||||
Domain persistPendingDeleteDomain() throws Exception {
|
||||
// The domain is now past what had been its expiration date at the time of deletion.
|
||||
persistPendingDeleteDomain(clock.nowUtc().minusDays(5));
|
||||
return persistPendingDeleteDomain(clock.nowUtc().minusDays(5));
|
||||
}
|
||||
|
||||
void persistPendingDeleteDomain(DateTime expirationTime) throws Exception {
|
||||
Domain persistPendingDeleteDomain(DateTime expirationTime) throws Exception {
|
||||
Domain domain = persistResource(DatabaseHelper.newDomain(getUniqueIdFromCommand()));
|
||||
HistoryEntry historyEntry =
|
||||
persistResource(
|
||||
@@ -118,29 +119,31 @@ class DomainRestoreRequestFlowTest extends ResourceFlowTestCase<DomainRestoreReq
|
||||
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
|
||||
.setDomain(domain)
|
||||
.build());
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.setRegistrationExpirationTime(expirationTime)
|
||||
.setDeletionTime(clock.nowUtc().plusDays(35))
|
||||
.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.REDEMPTION,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE))
|
||||
.setDeletePollMessage(
|
||||
persistResource(
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setEventTime(clock.nowUtc().plusDays(5))
|
||||
.setHistoryEntry(historyEntry)
|
||||
.build())
|
||||
.createVKey())
|
||||
.build());
|
||||
domain =
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.setRegistrationExpirationTime(expirationTime)
|
||||
.setDeletionTime(clock.nowUtc().plusDays(35))
|
||||
.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.REDEMPTION,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE))
|
||||
.setDeletePollMessage(
|
||||
persistResource(
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setEventTime(clock.nowUtc().plusDays(5))
|
||||
.setHistoryEntry(historyEntry)
|
||||
.build())
|
||||
.createVKey())
|
||||
.build());
|
||||
clock.advanceOneMilli();
|
||||
return domain;
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -491,6 +494,15 @@ class DomainRestoreRequestFlowTest extends ResourceFlowTestCase<DomainRestoreReq
|
||||
loadFile("domain_update_restore_request_response_premium.xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_worksWithoutPollMessage() throws Exception {
|
||||
Domain domain = persistPendingDeleteDomain();
|
||||
VKey<PollMessage.OneTime> deletePollMessage = domain.getDeletePollMessage();
|
||||
persistResource(domain.asBuilder().setDeletePollMessage(null).build());
|
||||
DatabaseHelper.deleteByKey(deletePollMessage);
|
||||
runFlowAssertResponse(loadFile("generic_success_response.xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_doesNotExist() throws Exception {
|
||||
ResourceDoesNotExistException thrown =
|
||||
|
||||
@@ -102,6 +102,24 @@ public class SecretManagerKeyringUpdaterTest {
|
||||
verifyPersistedSecret("bsa-api-key-string", secret);
|
||||
}
|
||||
|
||||
@Test
|
||||
void sqlPrimaryConnectionName() {
|
||||
String name = "name";
|
||||
updater.setSqlPrimaryConnectionName(name).update();
|
||||
|
||||
assertThat(keyring.getSqlPrimaryConnectionName()).isEqualTo(name);
|
||||
verifyPersistedSecret("sql-primary-conn-name", name);
|
||||
}
|
||||
|
||||
@Test
|
||||
void sqlReplicaConnectionName() {
|
||||
String name = "name";
|
||||
updater.setSqlReplicaConnectionName(name).update();
|
||||
|
||||
assertThat(keyring.getSqlReplicaConnectionName()).isEqualTo(name);
|
||||
verifyPersistedSecret("sql-replica-conn-name", name);
|
||||
}
|
||||
|
||||
@Test
|
||||
void marksdbDnlLoginAndPassword() {
|
||||
String secret = "marksdbDnlLoginAndPassword";
|
||||
|
||||
@@ -24,7 +24,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import static google.registry.testing.DatabaseHelper.loadByEntity;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -33,6 +32,7 @@ import google.registry.model.EntityTestCase;
|
||||
import google.registry.model.common.FeatureFlag.FeatureFlagNotFoundException;
|
||||
import google.registry.model.common.FeatureFlag.FeatureStatus;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link FeatureFlag}. */
|
||||
@@ -50,7 +50,7 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
.put(fakeClock.nowUtc().plusWeeks(8), ACTIVE)
|
||||
.build())
|
||||
.build();
|
||||
persistResource(featureFlag);
|
||||
@@ -66,7 +66,7 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
.put(fakeClock.nowUtc().plusWeeks(8), ACTIVE)
|
||||
.build())
|
||||
.build();
|
||||
persistResource(featureFlag);
|
||||
@@ -82,7 +82,7 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
.put(fakeClock.nowUtc().plusWeeks(8), ACTIVE)
|
||||
.build())
|
||||
.build());
|
||||
FeatureFlag featureFlag2 =
|
||||
@@ -92,7 +92,7 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(3), INACTIVE)
|
||||
.put(fakeClock.nowUtc().plusWeeks(3), INACTIVE)
|
||||
.build())
|
||||
.build());
|
||||
FeatureFlag featureFlag3 =
|
||||
@@ -122,7 +122,7 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
.put(fakeClock.nowUtc().plusWeeks(8), ACTIVE)
|
||||
.build())
|
||||
.build());
|
||||
persistResource(
|
||||
@@ -131,7 +131,7 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(3), INACTIVE)
|
||||
.put(fakeClock.nowUtc().plusWeeks(3), INACTIVE)
|
||||
.build())
|
||||
.build());
|
||||
FeatureFlagNotFoundException thrown =
|
||||
@@ -164,7 +164,7 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
.put(fakeClock.nowUtc().plusWeeks(8), ACTIVE)
|
||||
.build());
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(IllegalArgumentException.class, () -> featureFlagBuilder.build());
|
||||
@@ -180,7 +180,7 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
() ->
|
||||
featureFlagBuilder.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(DateTime.now(UTC).plusWeeks(8), ACTIVE)
|
||||
.put(fakeClock.nowUtc().plusWeeks(8), ACTIVE)
|
||||
.build()));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
@@ -203,4 +203,37 @@ public class FeatureFlagTest extends EntityTestCase {
|
||||
fakeClock.setTo(DateTime.parse("2011-10-17TZ"));
|
||||
assertThat(tm().transact(() -> FeatureFlag.isActiveNow(TEST_FEATURE))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_default_exists() {
|
||||
persistResource(
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName(TEST_FEATURE)
|
||||
.setStatusMap(
|
||||
ImmutableSortedMap.<DateTime, FeatureStatus>naturalOrder()
|
||||
.put(START_OF_TIME, INACTIVE)
|
||||
.put(fakeClock.nowUtc().plusWeeks(8), ACTIVE)
|
||||
.build())
|
||||
.build());
|
||||
tm().transact(
|
||||
() -> {
|
||||
assertThat(FeatureFlag.isActiveNowOrElse(TEST_FEATURE, false)).isFalse();
|
||||
assertThat(FeatureFlag.isActiveNowOrElse(TEST_FEATURE, true)).isFalse();
|
||||
});
|
||||
fakeClock.advanceBy(Duration.standardDays(365));
|
||||
tm().transact(
|
||||
() -> {
|
||||
assertThat(FeatureFlag.isActiveNowOrElse(TEST_FEATURE, false)).isTrue();
|
||||
assertThat(FeatureFlag.isActiveNowOrElse(TEST_FEATURE, true)).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_default_doesNotExist() {
|
||||
tm().transact(
|
||||
() -> {
|
||||
assertThat(FeatureFlag.isActiveNowOrElse(TEST_FEATURE, false)).isFalse();
|
||||
assertThat(FeatureFlag.isActiveNowOrElse(TEST_FEATURE, true)).isTrue();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,9 +42,11 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
/** Common unit test code for actions inheriting {@link RdapActionBase}. */
|
||||
abstract class RdapActionBaseTestCase<A extends RdapActionBase> {
|
||||
|
||||
protected final FakeClock clock = new FakeClock(DateTime.parse("2000-01-01TZ"));
|
||||
|
||||
@RegisterExtension
|
||||
final JpaIntegrationTestExtension jpa =
|
||||
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
|
||||
new JpaTestExtensions.Builder().withClock(clock).buildIntegrationTestExtension();
|
||||
|
||||
protected static final AuthResult AUTH_RESULT =
|
||||
AuthResult.createUser(
|
||||
@@ -61,7 +63,6 @@ abstract class RdapActionBaseTestCase<A extends RdapActionBase> {
|
||||
.build());
|
||||
|
||||
protected FakeResponse response = new FakeResponse();
|
||||
protected final FakeClock clock = new FakeClock(DateTime.parse("2000-01-01TZ"));
|
||||
final RdapMetrics rdapMetrics = mock(RdapMetrics.class);
|
||||
|
||||
RdapAuthorization.Role metricRole = PUBLIC;
|
||||
|
||||
@@ -17,6 +17,8 @@ package google.registry.rdap;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistDomainWithDependentResources;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.testing.DatabaseHelper.persistSimpleResources;
|
||||
import static google.registry.testing.FullFieldsTestEntityHelper.makeAndPersistHost;
|
||||
@@ -31,7 +33,10 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.gson.JsonObject;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
@@ -43,6 +48,7 @@ import google.registry.rdap.RdapSearchResults.IncompletenessWarningType;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.testing.FullFieldsTestEntityHelper;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -59,6 +65,9 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
|
||||
super(RdapDomainAction.class);
|
||||
}
|
||||
|
||||
private Contact registrantLol;
|
||||
private Host host1;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
// lol
|
||||
@@ -66,7 +75,7 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
|
||||
Registrar registrarLol = persistResource(makeRegistrar(
|
||||
"evilregistrar", "Yes Virginia <script>", Registrar.State.ACTIVE));
|
||||
persistSimpleResources(makeRegistrarPocs(registrarLol));
|
||||
Contact registrantLol =
|
||||
registrantLol =
|
||||
FullFieldsTestEntityHelper.makeAndPersistContact(
|
||||
"5372808-ERL",
|
||||
"Goblin Market",
|
||||
@@ -83,7 +92,7 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
|
||||
Contact techContactLol =
|
||||
FullFieldsTestEntityHelper.makeAndPersistContact(
|
||||
"5372808-TRL", "The Raven", "bog@cat.lol", clock.nowUtc().minusYears(3), registrarLol);
|
||||
Host host1 = makeAndPersistHost("ns1.cat.lol", "1.2.3.4", null, clock.nowUtc().minusYears(1));
|
||||
host1 = makeAndPersistHost("ns1.cat.lol", "1.2.3.4", null, clock.nowUtc().minusYears(1));
|
||||
Host host2 =
|
||||
makeAndPersistHost(
|
||||
"ns2.cat.lol", "bad:f00d:cafe:0:0:0:15:beef", clock.nowUtc().minusYears(2));
|
||||
@@ -493,6 +502,93 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
|
||||
assertThat(response.getStatus()).isEqualTo(200);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddGracePeriod() {
|
||||
persistActiveDomainWithHost(
|
||||
"addgraceperiod", "lol", clock.nowUtc(), clock.nowUtc().plusYears(1));
|
||||
assertAboutJson()
|
||||
.that(generateActualJson("addgraceperiod.lol"))
|
||||
.isEqualTo(addBoilerplate(jsonFileBuilder().load("rdap_domain_add_grace_period.json")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAutoRenewGracePeriod() {
|
||||
persistActiveDomainWithHost(
|
||||
"autorenew", "lol", clock.nowUtc().minusYears(1).minusDays(1), clock.nowUtc().minusDays(1));
|
||||
assertAboutJson()
|
||||
.that(generateActualJson("autorenew.lol"))
|
||||
.isEqualTo(
|
||||
addBoilerplate(jsonFileBuilder().load("rdap_domain_auto_renew_grace_period.json")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRedemptionGracePeriod() {
|
||||
Domain domain = persistActiveDomain("redemption.lol", clock.nowUtc().minusYears(1));
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.addNameserver(host1.createVKey())
|
||||
.setDeletionTime(clock.nowUtc().plusDays(1))
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE))
|
||||
.setGracePeriods(
|
||||
ImmutableSet.of(
|
||||
GracePeriod.createWithoutBillingEvent(
|
||||
GracePeriodStatus.REDEMPTION,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(4),
|
||||
"TheRegistrar")))
|
||||
.build());
|
||||
assertAboutJson()
|
||||
.that(generateActualJson("redemption.lol"))
|
||||
.isEqualTo(
|
||||
addBoilerplate(
|
||||
jsonFileBuilder().load("rdap_domain_pending_delete_redemption_grace_period.json")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRenewGracePeriod() {
|
||||
Domain domain =
|
||||
persistActiveDomainWithHost(
|
||||
"renew", "lol", clock.nowUtc().minusYears(1), clock.nowUtc().plusYears(1));
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.RENEW,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.build());
|
||||
assertAboutJson()
|
||||
.that(generateActualJson("renew.lol"))
|
||||
.isEqualTo(
|
||||
addBoilerplate(jsonFileBuilder().load("rdap_domain_explicit_renew_grace_period.json")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransferGracePeriod() {
|
||||
Domain domain =
|
||||
persistActiveDomainWithHost(
|
||||
"transfer", "lol", clock.nowUtc().minusMonths(6), clock.nowUtc().plusYears(1));
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.TRANSFER,
|
||||
domain.getRepoId(),
|
||||
clock.nowUtc().plusDays(1),
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.build());
|
||||
assertAboutJson()
|
||||
.that(generateActualJson("transfer.lol"))
|
||||
.isEqualTo(
|
||||
addBoilerplate(jsonFileBuilder().load("rdap_domain_transfer_grace_period.json")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMetrics() {
|
||||
generateActualJson("cat.lol");
|
||||
@@ -511,4 +607,14 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
|
||||
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE)
|
||||
.build());
|
||||
}
|
||||
|
||||
private Domain persistActiveDomainWithHost(
|
||||
String label, String tld, DateTime creationTime, DateTime expirationTime) {
|
||||
return persistResource(
|
||||
persistDomainWithDependentResources(
|
||||
label, tld, registrantLol, clock.nowUtc(), creationTime, expirationTime)
|
||||
.asBuilder()
|
||||
.addNameserver(host1.createVKey())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,13 @@ import static org.mockito.Mockito.when;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
|
||||
import com.google.api.client.json.webtoken.JsonWebSignature;
|
||||
import com.google.api.client.json.webtoken.JsonWebSignature.Header;
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.auth.oauth2.TokenVerifier.VerificationException;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import dagger.Component;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.ApplicationDefaultCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.User;
|
||||
@@ -40,8 +41,8 @@ import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.OidcTokenAuthenticationMechanism.IapOidcAuthenticationMechanism;
|
||||
import google.registry.request.auth.OidcTokenAuthenticationMechanism.RegularOidcAuthenticationMechanism;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
import javax.inject.Singleton;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -228,9 +229,9 @@ public class OidcTokenAuthenticationMechanismTest {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Config("backendServiceIds")
|
||||
Map<String, Long> provideBackendServiceIds() {
|
||||
return ImmutableMap.of();
|
||||
@ApplicationDefaultCredential
|
||||
GoogleCredentialsBundle provideGoogleCredentialBundle() {
|
||||
return GoogleCredentialsBundle.create(GoogleCredentials.newBuilder().build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static org.mockito.Mockito.when;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.groups.GmailClient;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.request.RequestModule;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
import google.registry.ui.server.SendEmailUtils;
|
||||
@@ -45,7 +46,13 @@ public final class ConsoleApiParamsUtils {
|
||||
xsrfTokenManager.generateToken(
|
||||
authResult.user().map(User::getEmailAddress).orElse("")))
|
||||
});
|
||||
when(request.getRequestURI()).thenReturn("/console/fake-url");
|
||||
return ConsoleApiParams.create(
|
||||
request, new FakeResponse(), authResult, sendEmailUtils, xsrfTokenManager);
|
||||
request,
|
||||
new FakeResponse(),
|
||||
authResult,
|
||||
sendEmailUtils,
|
||||
xsrfTokenManager,
|
||||
RequestModule.provideGson());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Static utils for setting up test resources. */
|
||||
public final class DatabaseHelper {
|
||||
@@ -593,30 +594,36 @@ public final class DatabaseHelper {
|
||||
DateTime expirationTime) {
|
||||
String domainName = String.format("%s.%s", label, tld);
|
||||
String repoId = generateNewDomainRoid(tld);
|
||||
Domain domain =
|
||||
persistResource(
|
||||
new Domain.Builder()
|
||||
.setRepoId(repoId)
|
||||
.setDomainName(domainName)
|
||||
.setPersistedCurrentSponsorRegistrarId("TheRegistrar")
|
||||
.setCreationRegistrarId("TheRegistrar")
|
||||
.setCreationTimeForTest(creationTime)
|
||||
.setRegistrationExpirationTime(expirationTime)
|
||||
.setRegistrant(Optional.of(contact.createVKey()))
|
||||
.setContacts(
|
||||
ImmutableSet.of(
|
||||
DesignatedContact.create(Type.ADMIN, contact.createVKey()),
|
||||
DesignatedContact.create(Type.TECH, contact.createVKey())))
|
||||
.setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("fooBAR")))
|
||||
.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.ADD, repoId, now.plusDays(10), "TheRegistrar", null))
|
||||
.build());
|
||||
Domain.Builder domainBuilder =
|
||||
new Domain.Builder()
|
||||
.setRepoId(repoId)
|
||||
.setDomainName(domainName)
|
||||
.setPersistedCurrentSponsorRegistrarId("TheRegistrar")
|
||||
.setCreationRegistrarId("TheRegistrar")
|
||||
.setCreationTimeForTest(creationTime)
|
||||
.setRegistrationExpirationTime(expirationTime)
|
||||
.setRegistrant(Optional.of(contact.createVKey()))
|
||||
.setContacts(
|
||||
ImmutableSet.of(
|
||||
DesignatedContact.create(Type.ADMIN, contact.createVKey()),
|
||||
DesignatedContact.create(Type.TECH, contact.createVKey())))
|
||||
.setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("fooBAR")));
|
||||
Duration addGracePeriodLength = Tld.get(tld).getAddGracePeriodLength();
|
||||
if (creationTime.plus(addGracePeriodLength).isAfter(now)) {
|
||||
domainBuilder.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.ADD,
|
||||
repoId,
|
||||
creationTime.plus(addGracePeriodLength),
|
||||
"TheRegistrar",
|
||||
null));
|
||||
}
|
||||
Domain domain = persistResource(domainBuilder.build());
|
||||
DomainHistory historyEntryDomainCreate =
|
||||
persistResource(
|
||||
new DomainHistory.Builder()
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.setModificationTime(now)
|
||||
.setModificationTime(creationTime)
|
||||
.setDomain(domain)
|
||||
.setRegistrarId(domain.getCreationRegistrarId())
|
||||
.build());
|
||||
@@ -1168,6 +1175,10 @@ public final class DatabaseHelper {
|
||||
tm().transact(() -> tm().delete(resource));
|
||||
}
|
||||
|
||||
public static void deleteByKey(VKey<?> key) {
|
||||
tm().transact(() -> tm().delete(key));
|
||||
}
|
||||
|
||||
/** Force the create and update timestamps to get written into the resource. */
|
||||
public static <R> R cloneAndSetAutoTimestamps(final R resource) {
|
||||
// We have to separate the read and write operation into different transactions otherwise JPA
|
||||
@@ -1294,6 +1305,11 @@ public final class DatabaseHelper {
|
||||
return tm().transact(() -> tm().loadByEntitiesIfPresent(entities));
|
||||
}
|
||||
|
||||
/** Loads the only instance of this particular class, or empty if none exists. */
|
||||
public static <T> Optional<T> loadSingleton(Class<T> clazz) {
|
||||
return tm().transact(() -> tm().loadSingleton(clazz));
|
||||
}
|
||||
|
||||
/** Returns whether or not the given entity exists in Cloud SQL. */
|
||||
public static boolean existsInDb(ImmutableObject object) {
|
||||
return tm().transact(() -> tm().exists(object));
|
||||
|
||||
@@ -56,6 +56,8 @@ public final class FakeKeyringModule {
|
||||
private static final String MARKSDB_LORDN_PASSWORD = "yolo";
|
||||
private static final String MARKSDB_SMDRL_LOGIN_AND_PASSWORD = "smdrl:yolo";
|
||||
private static final String BSA_API_KEY = "bsaapikey";
|
||||
private static final String SQL_PRIMARY_CONNECTION = "project:primary-region:primary-name";
|
||||
private static final String SQL_REPLICA_CONNECTION = "project:replica-region:replica-name";
|
||||
|
||||
@Provides
|
||||
public Keyring get() {
|
||||
@@ -151,6 +153,16 @@ public final class FakeKeyringModule {
|
||||
return rdeReceiverKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlPrimaryConnectionName() {
|
||||
return SQL_PRIMARY_CONNECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlReplicaConnectionName() {
|
||||
return SQL_REPLICA_CONNECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
};
|
||||
|
||||
@@ -91,10 +91,16 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
||||
runCommandForced(
|
||||
"--email",
|
||||
"user@example.test",
|
||||
"--registrar_roles",
|
||||
"TheRegistrar=PRIMARY_CONTACT",
|
||||
"--registry_lock_email_address",
|
||||
"registrylockemail@otherexample.test");
|
||||
assertThat(loadExistingUser("user@example.test").getRegistryLockEmailAddress())
|
||||
.hasValue("registrylockemail@otherexample.test");
|
||||
"registrylockemail@otherexample.test",
|
||||
"--registry_lock_password",
|
||||
"password");
|
||||
User user = loadExistingUser("user@example.test");
|
||||
assertThat(user.getRegistryLockEmailAddress()).hasValue("registrylockemail@otherexample.test");
|
||||
assertThat(user.verifyRegistryLockPassword("password")).isTrue();
|
||||
assertThat(user.verifyRegistryLockPassword("foobar")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -174,4 +180,18 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Provided email this is not valid is not a valid email address");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_registryLockPassword_withoutEmail() {
|
||||
assertThat(
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
runCommandForced(
|
||||
"--email", "user@example.test", "--registry_lock_password", "password")))
|
||||
.hasMessageThat()
|
||||
.isEqualTo(
|
||||
"Cannot set/remove registry lock password on a user without a registry lock email"
|
||||
+ " address");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,19 +157,6 @@ class CurlCommandTest extends CommandTestCase<CurlCommand> {
|
||||
eq("".getBytes(UTF_8)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCanaryInvocation() throws Exception {
|
||||
runCommand("--path=/foo/bar?a=1&b=2", "--request=POST", "--service=TOOLS", "--canary");
|
||||
verify(connection).withService(eq(TOOLS), eq(true));
|
||||
verifyNoMoreInteractions(connection);
|
||||
verify(connectionForService)
|
||||
.sendPostRequest(
|
||||
eq("/foo/bar?a=1&b=2"),
|
||||
eq(ImmutableMap.<String, String>of()),
|
||||
eq(MediaType.PLAIN_TEXT_UTF_8),
|
||||
eq("".getBytes(UTF_8)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
void testGetWithBody() {
|
||||
|
||||
@@ -85,7 +85,7 @@ final class GcpProjectConnectionTest {
|
||||
when(lowLevelHttpResponse.getStatusCode()).thenReturn(200);
|
||||
|
||||
httpTransport = new TestHttpTransport();
|
||||
connection = new ServiceConnection(false, httpTransport.createRequestFactory());
|
||||
connection = new ServiceConnection(false, false, httpTransport.createRequestFactory());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -25,8 +25,12 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.util.DateTimeUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -41,10 +45,49 @@ class GetAllocationTokenCommandTest extends CommandTestCase<GetAllocationTokenCo
|
||||
new AllocationToken.Builder()
|
||||
.setToken("foo")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setAllowedEppActions(
|
||||
ImmutableSet.of(FeeQueryCommandExtensionItem.CommandName.CREATE))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("bar"))
|
||||
.setDiscountFraction(0.5)
|
||||
.setDiscountYears(2)
|
||||
.setTokenStatusTransitions(
|
||||
ImmutableSortedMap.of(
|
||||
DateTimeUtils.START_OF_TIME,
|
||||
AllocationToken.TokenStatus.NOT_STARTED,
|
||||
fakeClock.nowUtc(),
|
||||
AllocationToken.TokenStatus.VALID))
|
||||
.setDomainName("foo.bar")
|
||||
.build());
|
||||
runCommand("foo");
|
||||
assertInStdout(token.toString(), "Token foo was not redeemed.");
|
||||
assertStdoutIs(
|
||||
"""
|
||||
AllocationToken: {
|
||||
allowedClientIds=[TheRegistrar]
|
||||
allowedEppActions=[CREATE]
|
||||
allowedTlds=[bar]
|
||||
creationTime=CreateAutoTimestamp: {
|
||||
creationTime=2022-09-01T00:00:00.000Z
|
||||
}
|
||||
discountFraction=0.5
|
||||
discountPremiums=false
|
||||
discountPrice=null
|
||||
discountYears=2
|
||||
domainName=foo.bar
|
||||
redemptionHistoryId=null
|
||||
registrationBehavior=DEFAULT
|
||||
renewalPrice=null
|
||||
renewalPriceBehavior=DEFAULT
|
||||
token=foo
|
||||
tokenStatusTransitions={1970-01-01T00:00:00.000Z=NOT_STARTED, 2022-09-01T00:00:00.000Z=VALID}
|
||||
tokenType=SINGLE_USE
|
||||
updateTimestamp=UpdateAutoTimestamp: {
|
||||
lastUpdateTime=2022-09-01T00:00:00.000Z
|
||||
}
|
||||
}
|
||||
Token foo was not redeemed.
|
||||
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -37,7 +37,8 @@ public class ServiceConnectionTest {
|
||||
|
||||
@Test
|
||||
void testSuccess_serverUrl_notCanary() {
|
||||
ServiceConnection connection = new ServiceConnection(false, null).withService(DEFAULT, false);
|
||||
ServiceConnection connection =
|
||||
new ServiceConnection(false, false, null).withService(DEFAULT, false);
|
||||
String serverUrl = connection.getServer().toString();
|
||||
assertThat(serverUrl).isEqualTo("https://default.example.com"); // See default-config.yaml
|
||||
}
|
||||
@@ -48,14 +49,15 @@ public class ServiceConnectionTest {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> {
|
||||
new ServiceConnection(true, null).withService(DEFAULT, true);
|
||||
new ServiceConnection(true, false, null).withService(DEFAULT, true);
|
||||
});
|
||||
assertThat(thrown).hasMessageThat().contains("Cannot switch from GkeService to GaeService");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_serverUrl_gae_canary() {
|
||||
ServiceConnection connection = new ServiceConnection(false, null).withService(DEFAULT, true);
|
||||
ServiceConnection connection =
|
||||
new ServiceConnection(false, false, null).withService(DEFAULT, true);
|
||||
String serverUrl = connection.getServer().toString();
|
||||
assertThat(serverUrl).isEqualTo("https://nomulus-dot-default.example.com");
|
||||
}
|
||||
@@ -71,7 +73,7 @@ public class ServiceConnectionTest {
|
||||
when(request.execute()).thenReturn(response);
|
||||
when(response.getContent()).thenReturn(ByteArrayInputStream.nullInputStream());
|
||||
ServiceConnection connection =
|
||||
new ServiceConnection(true, factory).withService(GkeService.PUBAPI, true);
|
||||
new ServiceConnection(true, false, factory).withService(GkeService.PUBAPI, true);
|
||||
String serverUrl = connection.getServer().toString();
|
||||
assertThat(serverUrl).isEqualTo("https://pubapi.registry.test");
|
||||
connection.sendGetRequest("/path", ImmutableMap.of());
|
||||
|
||||
@@ -33,6 +33,8 @@ import google.registry.model.billing.BillingRecurrence;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
@@ -121,6 +123,25 @@ public class UpdateRecurrenceCommandTest extends CommandTestCase<UpdateRecurrenc
|
||||
Money.of(CurrencyUnit.USD, 9001));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_completedTransfer() throws Exception {
|
||||
Domain domain = persistDomain();
|
||||
domain =
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.setTransferData(
|
||||
new DomainTransferData.Builder()
|
||||
.setTransferStatus(TransferStatus.CLIENT_APPROVED)
|
||||
.setPendingTransferExpirationTime(fakeClock.nowUtc().minusDays(8))
|
||||
.build())
|
||||
.build());
|
||||
BillingRecurrence billingRecurrence = loadByKey(domain.getAutorenewBillingEvent());
|
||||
runCommandForced("domain.tld", "--renewal_price_behavior", "NONPREMIUM");
|
||||
assertNewBillingEventAndHistory(
|
||||
billingRecurrence.getId(), RenewalPriceBehavior.NONPREMIUM, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_nonexistentDomain() {
|
||||
assertThrows(
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.tools;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.DatabaseHelper.loadExistingUser;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.testing.DatabaseHelper.putInDb;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
@@ -98,6 +99,44 @@ public class UpdateUserCommandTest extends CommandTestCase<UpdateUserCommand> {
|
||||
.isEqualTo(GlobalRole.FTE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_removePassword() throws Exception {
|
||||
// Empty password value removes the password
|
||||
persistResource(
|
||||
loadExistingUser("user@example.test")
|
||||
.asBuilder()
|
||||
.setUserRoles(
|
||||
new UserRoles.Builder()
|
||||
.setRegistrarRoles(ImmutableMap.of("TheRegistrar", RegistrarRole.TECH_CONTACT))
|
||||
.build())
|
||||
.setRegistryLockEmailAddress("registrylock@example.test")
|
||||
.setRegistryLockPassword("password")
|
||||
.build());
|
||||
assertThat(loadExistingUser("user@example.test").hasRegistryLockPassword()).isTrue();
|
||||
runCommandForced("--email", "user@example.test", "--registry_lock_password", "");
|
||||
assertThat(loadExistingUser("user@example.test").hasRegistryLockPassword()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_setsPassword() throws Exception {
|
||||
persistResource(
|
||||
loadExistingUser("user@example.test")
|
||||
.asBuilder()
|
||||
.setUserRoles(
|
||||
new UserRoles.Builder()
|
||||
.setRegistrarRoles(ImmutableMap.of("TheRegistrar", RegistrarRole.TECH_CONTACT))
|
||||
.build())
|
||||
.setRegistryLockEmailAddress("registrylock@example.test")
|
||||
.setRegistryLockPassword("password")
|
||||
.build());
|
||||
assertThat(loadExistingUser("user@example.test").verifyRegistryLockPassword("password"))
|
||||
.isTrue();
|
||||
runCommandForced("--email", "user@example.test", "--registry_lock_password", "foobar");
|
||||
assertThat(loadExistingUser("user@example.test").verifyRegistryLockPassword("password"))
|
||||
.isFalse();
|
||||
assertThat(loadExistingUser("user@example.test").verifyRegistryLockPassword("foobar")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_doesntExist() {
|
||||
assertThat(
|
||||
@@ -122,4 +161,18 @@ public class UpdateUserCommandTest extends CommandTestCase<UpdateUserCommand> {
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Provided email this is not valid is not a valid email address");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_setPassword_noEmail() {
|
||||
assertThat(
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
runCommandForced(
|
||||
"--email", "user@example.test", "--registry_lock_password", "foobar")))
|
||||
.hasMessageThat()
|
||||
.isEqualTo(
|
||||
"Cannot set/remove registry lock password on a user without a registry lock email"
|
||||
+ " address");
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user