mirror of
https://github.com/google/nomulus
synced 2025-12-23 06:15:42 +00:00
Add console user role update and minor fixes to delete (#2610)
This commit is contained in:
@@ -172,14 +172,20 @@ export class BackendService {
|
|||||||
.pipe(catchError((err) => this.errorCatcher<User>(err)));
|
.pipe(catchError((err) => this.errorCatcher<User>(err)));
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteUser(registrarId: string, emailAddress: string): Observable<any> {
|
deleteUser(registrarId: string, user: User): Observable<any> {
|
||||||
return this.http
|
return this.http
|
||||||
.delete<any>(`/console-api/users?registrarId=${registrarId}`, {
|
.delete<any>(`/console-api/users?registrarId=${registrarId}`, {
|
||||||
body: JSON.stringify({ emailAddress }),
|
body: JSON.stringify(user),
|
||||||
})
|
})
|
||||||
.pipe(catchError((err) => this.errorCatcher<any>(err)));
|
.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> {
|
getUserData(): Observable<UserData> {
|
||||||
return this.http
|
return this.http
|
||||||
.get<UserData>('/console-api/userdata')
|
.get<UserData>('/console-api/userdata')
|
||||||
|
|||||||
@@ -1,32 +1,77 @@
|
|||||||
<div class="console-app__user-details">
|
<div class="console-app__user-details">
|
||||||
@if(isNewUser) {
|
@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>
|
||||||
|
<form (ngSubmit)="saveEdit()">
|
||||||
|
<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)]="userRole" 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>
|
||||||
|
} @else { @if(isNewUser) {
|
||||||
<h1 class="mat-headline-4">
|
<h1 class="mat-headline-4">
|
||||||
{{ userDetails.emailAddress + " succesfully created" }}
|
{{ userDetails().emailAddress + " successfully created" }}
|
||||||
</h1>
|
</h1>
|
||||||
} @else {
|
} @else {
|
||||||
<h1 class="mat-headline-4">User details</h1>
|
<h1 class="mat-headline-4">User details</h1>
|
||||||
}
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<div>
|
<div class="console-app__user-details-controls">
|
||||||
<div class="console-app__user-details-controls">
|
<button mat-icon-button aria-label="Back to users list" (click)="goBack()">
|
||||||
<button
|
<mat-icon>arrow_back</mat-icon>
|
||||||
mat-icon-button
|
</button>
|
||||||
aria-label="Back to users list"
|
<div class="spacer"></div>
|
||||||
(click)="goBack()"
|
<button
|
||||||
>
|
mat-flat-button
|
||||||
<mat-icon>arrow_back</mat-icon>
|
color="primary"
|
||||||
</button>
|
aria-label="Edit User"
|
||||||
<div class="spacer"></div>
|
(click)="userRole = userDetails().role; isEditing = true"
|
||||||
<button
|
>
|
||||||
mat-icon-button
|
<mat-icon>edit</mat-icon>
|
||||||
aria-label="Delete User"
|
Edit
|
||||||
(click)="deleteUser()"
|
</button>
|
||||||
[disabled]="isLoading"
|
<button
|
||||||
>
|
mat-icon-button
|
||||||
<mat-icon>delete</mat-icon>
|
aria-label="Delete User"
|
||||||
</button>
|
(click)="deleteUser()"
|
||||||
</div>
|
[disabled]="isLoading"
|
||||||
|
>
|
||||||
|
<mat-icon>delete</mat-icon>
|
||||||
|
</button>
|
||||||
</div>
|
</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">
|
<p *ngIf="isLoading">
|
||||||
<mat-progress-bar mode="query"></mat-progress-bar>
|
<mat-progress-bar mode="query"></mat-progress-bar>
|
||||||
</p>
|
</p>
|
||||||
@@ -41,17 +86,17 @@
|
|||||||
<mat-list-item role="listitem">
|
<mat-list-item role="listitem">
|
||||||
<span class="console-app__list-key">User email</span>
|
<span class="console-app__list-key">User email</span>
|
||||||
<span class="console-app__list-value">{{
|
<span class="console-app__list-value">{{
|
||||||
userDetails.emailAddress
|
userDetails().emailAddress
|
||||||
}}</span>
|
}}</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<mat-list-item role="listitem">
|
<mat-list-item role="listitem">
|
||||||
<span class="console-app__list-key">User role</span>
|
<span class="console-app__list-key">User role</span>
|
||||||
<span class="console-app__list-value">{{
|
<span class="console-app__list-value">{{
|
||||||
roleToDescription(userDetails.role)
|
roleToDescription(userDetails().role)
|
||||||
}}</span>
|
}}</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
@if (userDetails.password) {
|
@if (userDetails().password) {
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<mat-list-item role="listitem">
|
<mat-list-item role="listitem">
|
||||||
<span class="console-app__list-key">Password</span>
|
<span class="console-app__list-key">Password</span>
|
||||||
@@ -60,7 +105,7 @@
|
|||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
[type]="isPasswordVisible ? 'text' : 'password'"
|
[type]="isPasswordVisible ? 'text' : 'password'"
|
||||||
[value]="userDetails.password"
|
[value]="userDetails().password"
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
@@ -76,4 +121,5 @@
|
|||||||
</mat-list>
|
</mat-list>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,6 +25,15 @@
|
|||||||
background: transparent;
|
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;
|
max-width: 616px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,13 +13,14 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component } from '@angular/core';
|
import { Component, computed } from '@angular/core';
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
import { SelectedRegistrarModule } from '../app.module';
|
import { SelectedRegistrarModule } from '../app.module';
|
||||||
import { MaterialModule } from '../material.module';
|
import { MaterialModule } from '../material.module';
|
||||||
import { RegistrarService } from '../registrar/registrar.service';
|
import { RegistrarService } from '../registrar/registrar.service';
|
||||||
import { SnackBarModule } from '../snackbar.module';
|
import { SnackBarModule } from '../snackbar.module';
|
||||||
import { User, UsersService, roleToDescription } from './users.service';
|
import { User, UsersService, roleToDescription } from './users.service';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-user-edit',
|
selector: 'app-user-edit',
|
||||||
@@ -27,6 +28,7 @@ import { User, UsersService, roleToDescription } from './users.service';
|
|||||||
styleUrls: ['./userEdit.component.scss'],
|
styleUrls: ['./userEdit.component.scss'],
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
|
FormsModule,
|
||||||
MaterialModule,
|
MaterialModule,
|
||||||
SnackBarModule,
|
SnackBarModule,
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@@ -35,22 +37,25 @@ import { User, UsersService, roleToDescription } from './users.service';
|
|||||||
providers: [],
|
providers: [],
|
||||||
})
|
})
|
||||||
export class UserEditComponent {
|
export class UserEditComponent {
|
||||||
inEdit = false;
|
isEditing = false;
|
||||||
isPasswordVisible = false;
|
isPasswordVisible = false;
|
||||||
isNewUser = false;
|
isNewUser = false;
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
userDetails: User;
|
userRole = '';
|
||||||
|
|
||||||
|
userDetails = computed(() => {
|
||||||
|
return this.usersService
|
||||||
|
.users()
|
||||||
|
.filter(
|
||||||
|
(u) => u.emailAddress === this.usersService.currentlyOpenUserEmail()
|
||||||
|
)[0];
|
||||||
|
});
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected registrarService: RegistrarService,
|
protected registrarService: RegistrarService,
|
||||||
protected usersService: UsersService,
|
protected usersService: UsersService,
|
||||||
private _snackBar: MatSnackBar
|
private _snackBar: MatSnackBar
|
||||||
) {
|
) {
|
||||||
this.userDetails = this.usersService
|
|
||||||
.users()
|
|
||||||
.filter(
|
|
||||||
(u) => u.emailAddress === this.usersService.currentlyOpenUserEmail()
|
|
||||||
)[0];
|
|
||||||
if (this.usersService.isNewUser) {
|
if (this.usersService.isNewUser) {
|
||||||
this.isNewUser = true;
|
this.isNewUser = true;
|
||||||
this.usersService.isNewUser = false;
|
this.usersService.isNewUser = false;
|
||||||
@@ -63,7 +68,7 @@ export class UserEditComponent {
|
|||||||
|
|
||||||
deleteUser() {
|
deleteUser() {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.usersService.deleteUser(this.userDetails.emailAddress).subscribe({
|
this.usersService.deleteUser(this.userDetails()).subscribe({
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
this._snackBar.open(err.error || err.message);
|
this._snackBar.open(err.error || err.message);
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
@@ -78,4 +83,23 @@ export class UserEditComponent {
|
|||||||
goBack() {
|
goBack() {
|
||||||
this.usersService.currentlyOpenUserEmail.set('');
|
this.usersService.currentlyOpenUserEmail.set('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saveEdit() {
|
||||||
|
this.isLoading = true;
|
||||||
|
this.usersService
|
||||||
|
.updateUser({
|
||||||
|
role: this.userRole,
|
||||||
|
emailAddress: this.userDetails().emailAddress,
|
||||||
|
})
|
||||||
|
.subscribe({
|
||||||
|
error: (err) => {
|
||||||
|
this._snackBar.open(err.error || err.message);
|
||||||
|
this.isLoading = false;
|
||||||
|
},
|
||||||
|
complete: () => {
|
||||||
|
this.isLoading = false;
|
||||||
|
this.isEditing = false;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,13 +13,13 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable, signal } from '@angular/core';
|
import { Injectable, signal } from '@angular/core';
|
||||||
import { tap } from 'rxjs';
|
import { switchMap, tap } from 'rxjs';
|
||||||
import { RegistrarService } from '../registrar/registrar.service';
|
import { RegistrarService } from '../registrar/registrar.service';
|
||||||
import { BackendService } from '../shared/services/backend.service';
|
import { BackendService } from '../shared/services/backend.service';
|
||||||
|
|
||||||
export const roleToDescription = (role: string) => {
|
export const roleToDescription = (role: string) => {
|
||||||
if (!role) return 'N/A';
|
if (!role) return 'N/A';
|
||||||
else if (role.toLowerCase().startsWith('account_manager')) {
|
else if (role === 'ACCOUNT_MANAGER') {
|
||||||
return 'Viewer';
|
return 'Viewer';
|
||||||
}
|
}
|
||||||
return 'Editor';
|
return 'Editor';
|
||||||
@@ -68,9 +68,15 @@ export class UsersService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteUser(emailAddress: string) {
|
deleteUser(user: User) {
|
||||||
return this.backendService
|
return this.backendService
|
||||||
.deleteUser(this.registrarService.registrarId(), emailAddress)
|
.deleteUser(this.registrarService.registrarId(), user)
|
||||||
.pipe(tap((_) => this.fetchUsers()));
|
.pipe(switchMap((_) => this.fetchUsers()));
|
||||||
|
}
|
||||||
|
|
||||||
|
updateUser(updatedUser: User) {
|
||||||
|
return this.backendService
|
||||||
|
.updateUser(this.registrarService.registrarId(), updatedUser)
|
||||||
|
.pipe(switchMap((_) => this.fetchUsers()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public @interface Action {
|
|||||||
GET,
|
GET,
|
||||||
HEAD,
|
HEAD,
|
||||||
POST,
|
POST,
|
||||||
|
PUT,
|
||||||
DELETE
|
DELETE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static google.registry.request.Action.Method.DELETE;
|
|||||||
import static google.registry.request.Action.Method.GET;
|
import static google.registry.request.Action.Method.GET;
|
||||||
import static google.registry.request.Action.Method.HEAD;
|
import static google.registry.request.Action.Method.HEAD;
|
||||||
import static google.registry.request.Action.Method.POST;
|
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_BAD_REQUEST;
|
||||||
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
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_INTERNAL_SERVER_ERROR;
|
||||||
@@ -87,6 +88,8 @@ public abstract class ConsoleApiAction implements Runnable {
|
|||||||
if (verifyXSRF(user)) {
|
if (verifyXSRF(user)) {
|
||||||
if (requestMethod.equals(DELETE.toString())) {
|
if (requestMethod.equals(DELETE.toString())) {
|
||||||
deleteHandler(user);
|
deleteHandler(user);
|
||||||
|
} else if (requestMethod.equals(PUT.toString())) {
|
||||||
|
putHandler(user);
|
||||||
} else {
|
} else {
|
||||||
postHandler(user);
|
postHandler(user);
|
||||||
}
|
}
|
||||||
@@ -117,6 +120,10 @@ public abstract class ConsoleApiAction implements Runnable {
|
|||||||
throw new UnsupportedOperationException("Console API POST handler not implemented");
|
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) {
|
protected void getHandler(User user) {
|
||||||
throw new UnsupportedOperationException("Console API GET handler not implemented");
|
throw new UnsupportedOperationException("Console API GET handler not implemented");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import google.registry.ui.server.SendEmailUtils;
|
|||||||
import google.registry.ui.server.console.ConsoleEppPasswordAction.EppPasswordData;
|
import google.registry.ui.server.console.ConsoleEppPasswordAction.EppPasswordData;
|
||||||
import google.registry.ui.server.console.ConsoleOteAction.OteCreateData;
|
import google.registry.ui.server.console.ConsoleOteAction.OteCreateData;
|
||||||
import google.registry.ui.server.console.ConsoleRegistryLockAction.ConsoleRegistryLockPostInput;
|
import google.registry.ui.server.console.ConsoleRegistryLockAction.ConsoleRegistryLockPostInput;
|
||||||
import google.registry.ui.server.console.ConsoleUsersAction.UserDeleteData;
|
import google.registry.ui.server.console.ConsoleUsersAction.UserData;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
@@ -247,10 +247,10 @@ public final class ConsoleModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Parameter("userDeleteData")
|
@Parameter("userData")
|
||||||
public static Optional<UserDeleteData> provideUserDeleteData(
|
public static Optional<UserData> provideUserData(
|
||||||
Gson gson, @OptionalJsonPayload Optional<JsonElement> payload) {
|
Gson gson, @OptionalJsonPayload Optional<JsonElement> payload) {
|
||||||
return payload.map(s -> gson.fromJson(s, UserDeleteData.class));
|
return payload.map(s -> gson.fromJson(s, UserData.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
|||||||
import static google.registry.request.Action.Method.DELETE;
|
import static google.registry.request.Action.Method.DELETE;
|
||||||
import static google.registry.request.Action.Method.GET;
|
import static google.registry.request.Action.Method.GET;
|
||||||
import static google.registry.request.Action.Method.POST;
|
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_CREATED;
|
||||||
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
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_INTERNAL_SERVER_ERROR;
|
||||||
@@ -35,6 +36,7 @@ import com.google.gson.Gson;
|
|||||||
import com.google.gson.annotations.Expose;
|
import com.google.gson.annotations.Expose;
|
||||||
import google.registry.config.RegistryConfig.Config;
|
import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.model.console.ConsolePermission;
|
import google.registry.model.console.ConsolePermission;
|
||||||
|
import google.registry.model.console.RegistrarRole;
|
||||||
import google.registry.model.console.User;
|
import google.registry.model.console.User;
|
||||||
import google.registry.model.console.UserRoles;
|
import google.registry.model.console.UserRoles;
|
||||||
import google.registry.persistence.VKey;
|
import google.registry.persistence.VKey;
|
||||||
@@ -50,6 +52,7 @@ import java.util.List;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
@@ -57,7 +60,7 @@ import javax.inject.Named;
|
|||||||
service = Action.GaeService.DEFAULT,
|
service = Action.GaeService.DEFAULT,
|
||||||
gkeService = GkeService.CONSOLE,
|
gkeService = GkeService.CONSOLE,
|
||||||
path = ConsoleUsersAction.PATH,
|
path = ConsoleUsersAction.PATH,
|
||||||
method = {GET, POST, DELETE},
|
method = {GET, POST, DELETE, PUT},
|
||||||
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
||||||
public class ConsoleUsersAction extends ConsoleApiAction {
|
public class ConsoleUsersAction extends ConsoleApiAction {
|
||||||
static final String PATH = "/console-api/users";
|
static final String PATH = "/console-api/users";
|
||||||
@@ -68,7 +71,7 @@ public class ConsoleUsersAction extends ConsoleApiAction {
|
|||||||
private final String registrarId;
|
private final String registrarId;
|
||||||
private final Directory directory;
|
private final Directory directory;
|
||||||
private final StringGenerator passwordGenerator;
|
private final StringGenerator passwordGenerator;
|
||||||
private final Optional<UserDeleteData> userDeleteData;
|
private final Optional<UserData> userData;
|
||||||
private final Optional<String> maybeGroupEmailAddress;
|
private final Optional<String> maybeGroupEmailAddress;
|
||||||
private final IamClient iamClient;
|
private final IamClient iamClient;
|
||||||
private final String gSuiteDomainName;
|
private final String gSuiteDomainName;
|
||||||
@@ -82,14 +85,14 @@ public class ConsoleUsersAction extends ConsoleApiAction {
|
|||||||
@Config("gSuiteDomainName") String gSuiteDomainName,
|
@Config("gSuiteDomainName") String gSuiteDomainName,
|
||||||
@Config("gSuiteConsoleUserGroupEmailAddress") Optional<String> maybeGroupEmailAddress,
|
@Config("gSuiteConsoleUserGroupEmailAddress") Optional<String> maybeGroupEmailAddress,
|
||||||
@Named("base58StringGenerator") StringGenerator passwordGenerator,
|
@Named("base58StringGenerator") StringGenerator passwordGenerator,
|
||||||
@Parameter("userDeleteData") Optional<UserDeleteData> userDeleteData,
|
@Parameter("userData") Optional<UserData> userData,
|
||||||
@Parameter("registrarId") String registrarId) {
|
@Parameter("registrarId") String registrarId) {
|
||||||
super(consoleApiParams);
|
super(consoleApiParams);
|
||||||
this.gson = gson;
|
this.gson = gson;
|
||||||
this.registrarId = registrarId;
|
this.registrarId = registrarId;
|
||||||
this.directory = directory;
|
this.directory = directory;
|
||||||
this.passwordGenerator = passwordGenerator;
|
this.passwordGenerator = passwordGenerator;
|
||||||
this.userDeleteData = userDeleteData;
|
this.userData = userData;
|
||||||
this.maybeGroupEmailAddress = maybeGroupEmailAddress;
|
this.maybeGroupEmailAddress = maybeGroupEmailAddress;
|
||||||
this.iamClient = iamClient;
|
this.iamClient = iamClient;
|
||||||
this.gSuiteDomainName = gSuiteDomainName;
|
this.gSuiteDomainName = gSuiteDomainName;
|
||||||
@@ -106,18 +109,28 @@ public class ConsoleUsersAction extends ConsoleApiAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void putHandler(User user) {
|
||||||
|
// Temporary flag while testing
|
||||||
|
if (user.getUserRoles().isAdmin()) {
|
||||||
|
checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
|
||||||
|
tm().transact(() -> runUpdateInTransaction());
|
||||||
|
} else {
|
||||||
|
consoleApiParams.response().setStatus(SC_FORBIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void getHandler(User user) {
|
protected void getHandler(User user) {
|
||||||
checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
|
checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
|
||||||
List<ImmutableMap> users =
|
List<UserData> users =
|
||||||
getAllRegistrarUsers(registrarId).stream()
|
getAllRegistrarUsers(registrarId).stream()
|
||||||
.map(
|
.map(
|
||||||
u ->
|
u ->
|
||||||
ImmutableMap.of(
|
new UserData(
|
||||||
"emailAddress",
|
|
||||||
u.getEmailAddress(),
|
u.getEmailAddress(),
|
||||||
"role",
|
u.getUserRoles().getRegistrarRoles().get(registrarId).toString(),
|
||||||
u.getUserRoles().getRegistrarRoles().get(registrarId)))
|
null))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
consoleApiParams.response().setPayload(gson.toJson(users));
|
consoleApiParams.response().setPayload(gson.toJson(users));
|
||||||
@@ -136,22 +149,10 @@ public class ConsoleUsersAction extends ConsoleApiAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void runDeleteInTransaction() throws IOException {
|
private void runDeleteInTransaction() throws IOException {
|
||||||
if (userDeleteData.isEmpty() || isNullOrEmpty(userDeleteData.get().userEmail)) {
|
if (!isModifyingRequestValid()) {
|
||||||
throw new BadRequestException("Missing user data param");
|
|
||||||
}
|
|
||||||
String email = userDeleteData.get().userEmail;
|
|
||||||
User userToDelete =
|
|
||||||
tm().loadByKeyIfPresent(VKey.create(User.class, email))
|
|
||||||
.orElseThrow(
|
|
||||||
() -> new BadRequestException(String.format("User %s doesn't exist", email)));
|
|
||||||
|
|
||||||
if (!userToDelete.getUserRoles().getRegistrarRoles().containsKey(registrarId)) {
|
|
||||||
setFailedResponse(
|
|
||||||
String.format("Can't delete user not associated with registrarId %s", registrarId),
|
|
||||||
SC_FORBIDDEN);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
String email = this.userData.get().emailAddress;
|
||||||
try {
|
try {
|
||||||
directory.users().delete(email).execute();
|
directory.users().delete(email).execute();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -213,13 +214,50 @@ public class ConsoleUsersAction extends ConsoleApiAction {
|
|||||||
.response()
|
.response()
|
||||||
.setPayload(
|
.setPayload(
|
||||||
gson.toJson(
|
gson.toJson(
|
||||||
ImmutableMap.of(
|
new UserData(
|
||||||
"password",
|
newUser.getPrimaryEmail(), ACCOUNT_MANAGER.toString(), newUser.getPassword())));
|
||||||
newUser.getPassword(),
|
}
|
||||||
"emailAddress",
|
|
||||||
newUser.getPrimaryEmail(),
|
private void runUpdateInTransaction() {
|
||||||
"role",
|
if (!isModifyingRequestValid()) {
|
||||||
ACCOUNT_MANAGER)));
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserData userData = this.userData.get();
|
||||||
|
UserRoles userRoles =
|
||||||
|
new UserRoles.Builder()
|
||||||
|
.setRegistrarRoles(ImmutableMap.of(registrarId, RegistrarRole.valueOf(userData.role)))
|
||||||
|
.build();
|
||||||
|
User updatedUser =
|
||||||
|
tm().loadByKeyIfPresent(VKey.create(User.class, userData.emailAddress))
|
||||||
|
.get()
|
||||||
|
.asBuilder()
|
||||||
|
.setUserRoles(userRoles)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
tm().put(updatedUser);
|
||||||
|
consoleApiParams.response().setStatus(SC_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isModifyingRequestValid() {
|
||||||
|
if (userData.isEmpty()
|
||||||
|
|| isNullOrEmpty(userData.get().emailAddress)
|
||||||
|
|| isNullOrEmpty(userData.get().role)) {
|
||||||
|
throw new BadRequestException("User data is missing or incomplete");
|
||||||
|
}
|
||||||
|
String email = userData.get().emailAddress;
|
||||||
|
User userToUpdate =
|
||||||
|
tm().loadByKeyIfPresent(VKey.create(User.class, email))
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new BadRequestException(String.format("User %s doesn't exist", email)));
|
||||||
|
|
||||||
|
if (!userToUpdate.getUserRoles().getRegistrarRoles().containsKey(registrarId)) {
|
||||||
|
setFailedResponse(
|
||||||
|
String.format("Can't update user not associated with registrarId %s", registrarId),
|
||||||
|
SC_FORBIDDEN);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImmutableList<User> getAllRegistrarUsers(String registrarId) {
|
private ImmutableList<User> getAllRegistrarUsers(String registrarId) {
|
||||||
@@ -230,5 +268,6 @@ public class ConsoleUsersAction extends ConsoleApiAction {
|
|||||||
.collect(toImmutableList()));
|
.collect(toImmutableList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public record UserDeleteData(@Expose String userEmail) {}
|
public record UserData(
|
||||||
|
@Expose String emailAddress, @Expose String role, @Expose @Nullable String password) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ import google.registry.testing.DatabaseHelper;
|
|||||||
import google.registry.testing.DeterministicStringGenerator;
|
import google.registry.testing.DeterministicStringGenerator;
|
||||||
import google.registry.testing.FakeResponse;
|
import google.registry.testing.FakeResponse;
|
||||||
import google.registry.tools.IamClient;
|
import google.registry.tools.IamClient;
|
||||||
import google.registry.ui.server.console.ConsoleUsersAction.UserDeleteData;
|
import google.registry.ui.server.console.ConsoleUsersAction.UserData;
|
||||||
import google.registry.util.StringGenerator;
|
import google.registry.util.StringGenerator;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -176,7 +176,7 @@ class ConsoleUsersActionTest {
|
|||||||
assertThat(response.getStatus()).isEqualTo(SC_CREATED);
|
assertThat(response.getStatus()).isEqualTo(SC_CREATED);
|
||||||
assertThat(response.getPayload())
|
assertThat(response.getPayload())
|
||||||
.contains(
|
.contains(
|
||||||
"{\"password\":\"abcdefghijklmnop\",\"emailAddress\":\"TheRegistrar-user1@email.com\",\"role\":\"ACCOUNT_MANAGER\"}");
|
"{\"emailAddress\":\"TheRegistrar-user1@email.com\",\"role\":\"ACCOUNT_MANAGER\",\"password\":\"abcdefghijklmnop\"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -192,14 +192,15 @@ class ConsoleUsersActionTest {
|
|||||||
createAction(
|
createAction(
|
||||||
Optional.of(ConsoleApiParamsUtils.createFake(authResult)),
|
Optional.of(ConsoleApiParamsUtils.createFake(authResult)),
|
||||||
Optional.of("DELETE"),
|
Optional.of("DELETE"),
|
||||||
Optional.of(new UserDeleteData("test3@test.com")));
|
Optional.of(
|
||||||
|
new UserData("test3@test.com", RegistrarRole.ACCOUNT_MANAGER.toString(), null)));
|
||||||
when(directory.users()).thenReturn(users);
|
when(directory.users()).thenReturn(users);
|
||||||
when(users.delete(any(String.class))).thenReturn(delete);
|
when(users.delete(any(String.class))).thenReturn(delete);
|
||||||
action.run();
|
action.run();
|
||||||
var response = ((FakeResponse) consoleApiParams.response());
|
var response = ((FakeResponse) consoleApiParams.response());
|
||||||
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
|
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
|
||||||
assertThat(response.getPayload())
|
assertThat(response.getPayload())
|
||||||
.contains("Can't delete user not associated with registrarId TheRegistrar");
|
.contains("Can't update user not associated with registrarId TheRegistrar");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -210,7 +211,8 @@ class ConsoleUsersActionTest {
|
|||||||
createAction(
|
createAction(
|
||||||
Optional.of(ConsoleApiParamsUtils.createFake(authResult)),
|
Optional.of(ConsoleApiParamsUtils.createFake(authResult)),
|
||||||
Optional.of("DELETE"),
|
Optional.of("DELETE"),
|
||||||
Optional.of(new UserDeleteData("email-1@email.com")));
|
Optional.of(
|
||||||
|
new UserData("email-1@email.com", RegistrarRole.ACCOUNT_MANAGER.toString(), null)));
|
||||||
when(directory.users()).thenReturn(users);
|
when(directory.users()).thenReturn(users);
|
||||||
when(users.delete(any(String.class))).thenReturn(delete);
|
when(users.delete(any(String.class))).thenReturn(delete);
|
||||||
action.run();
|
action.run();
|
||||||
@@ -232,7 +234,8 @@ class ConsoleUsersActionTest {
|
|||||||
createAction(
|
createAction(
|
||||||
Optional.of(ConsoleApiParamsUtils.createFake(authResult)),
|
Optional.of(ConsoleApiParamsUtils.createFake(authResult)),
|
||||||
Optional.of("DELETE"),
|
Optional.of("DELETE"),
|
||||||
Optional.of(new UserDeleteData("test2@test.com")));
|
Optional.of(
|
||||||
|
new UserData("test2@test.com", RegistrarRole.ACCOUNT_MANAGER.toString(), null)));
|
||||||
action.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
action.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||||
when(directory.users()).thenReturn(users);
|
when(directory.users()).thenReturn(users);
|
||||||
when(users.delete(any(String.class))).thenReturn(delete);
|
when(users.delete(any(String.class))).thenReturn(delete);
|
||||||
@@ -282,10 +285,66 @@ class ConsoleUsersActionTest {
|
|||||||
assertThat(response.getPayload()).contains("Total users amount per registrar is limited to 4");
|
assertThat(response.getPayload()).contains("Total users amount per registrar is limited to 4");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSuccess_updatesUserRole() throws IOException {
|
||||||
|
User user1 = DatabaseHelper.loadByKey(VKey.create(User.class, "test1@test.com"));
|
||||||
|
AuthResult authResult =
|
||||||
|
AuthResult.createUser(
|
||||||
|
user1
|
||||||
|
.asBuilder()
|
||||||
|
.setUserRoles(user1.getUserRoles().asBuilder().setIsAdmin(true).build())
|
||||||
|
.build());
|
||||||
|
|
||||||
|
assertThat(
|
||||||
|
DatabaseHelper.loadByKey(VKey.create(User.class, "test2@test.com"))
|
||||||
|
.getUserRoles()
|
||||||
|
.getRegistrarRoles()
|
||||||
|
.get("TheRegistrar"))
|
||||||
|
.isEqualTo(RegistrarRole.PRIMARY_CONTACT);
|
||||||
|
ConsoleUsersAction action =
|
||||||
|
createAction(
|
||||||
|
Optional.of(ConsoleApiParamsUtils.createFake(authResult)),
|
||||||
|
Optional.of("PUT"),
|
||||||
|
Optional.of(
|
||||||
|
new UserData("test2@test.com", RegistrarRole.ACCOUNT_MANAGER.toString(), null)));
|
||||||
|
action.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||||
|
action.run();
|
||||||
|
var response = ((FakeResponse) consoleApiParams.response());
|
||||||
|
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||||
|
assertThat(
|
||||||
|
DatabaseHelper.loadByKey(VKey.create(User.class, "test2@test.com"))
|
||||||
|
.getUserRoles()
|
||||||
|
.getRegistrarRoles()
|
||||||
|
.get("TheRegistrar"))
|
||||||
|
.isEqualTo(RegistrarRole.ACCOUNT_MANAGER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFailure_noPermissionToUpdateUser() throws IOException {
|
||||||
|
User user1 = DatabaseHelper.loadByKey(VKey.create(User.class, "test1@test.com"));
|
||||||
|
AuthResult authResult =
|
||||||
|
AuthResult.createUser(
|
||||||
|
user1
|
||||||
|
.asBuilder()
|
||||||
|
.setUserRoles(user1.getUserRoles().asBuilder().setIsAdmin(true).build())
|
||||||
|
.build());
|
||||||
|
ConsoleUsersAction action =
|
||||||
|
createAction(
|
||||||
|
Optional.of(ConsoleApiParamsUtils.createFake(authResult)),
|
||||||
|
Optional.of("PUT"),
|
||||||
|
Optional.of(
|
||||||
|
new UserData("test3@test.com", RegistrarRole.ACCOUNT_MANAGER.toString(), null)));
|
||||||
|
action.run();
|
||||||
|
var response = ((FakeResponse) consoleApiParams.response());
|
||||||
|
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
|
||||||
|
assertThat(response.getPayload())
|
||||||
|
.contains("Can't update user not associated with registrarId TheRegistrar");
|
||||||
|
}
|
||||||
|
|
||||||
private ConsoleUsersAction createAction(
|
private ConsoleUsersAction createAction(
|
||||||
Optional<ConsoleApiParams> maybeConsoleApiParams,
|
Optional<ConsoleApiParams> maybeConsoleApiParams,
|
||||||
Optional<String> method,
|
Optional<String> method,
|
||||||
Optional<UserDeleteData> userDeleteData)
|
Optional<UserData> userData)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
consoleApiParams =
|
consoleApiParams =
|
||||||
maybeConsoleApiParams.orElseGet(
|
maybeConsoleApiParams.orElseGet(
|
||||||
@@ -299,7 +358,7 @@ class ConsoleUsersActionTest {
|
|||||||
"email.com",
|
"email.com",
|
||||||
Optional.of("someRandomString"),
|
Optional.of("someRandomString"),
|
||||||
passwordGenerator,
|
passwordGenerator,
|
||||||
userDeleteData,
|
userData,
|
||||||
"TheRegistrar");
|
"TheRegistrar");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
SERVICE PATH CLASS METHODS OK MIN USER_POLICY
|
SERVICE PATH CLASS METHODS OK MIN USER_POLICY
|
||||||
FRONTEND /_dr/epp EppTlsAction POST n APP ADMIN
|
FRONTEND /_dr/epp EppTlsAction POST n APP ADMIN
|
||||||
CONSOLE /console-api/domain ConsoleDomainGetAction GET n USER PUBLIC
|
CONSOLE /console-api/domain ConsoleDomainGetAction GET n USER PUBLIC
|
||||||
CONSOLE /console-api/domain-list ConsoleDomainListAction GET n USER PUBLIC
|
CONSOLE /console-api/domain-list ConsoleDomainListAction GET n USER PUBLIC
|
||||||
CONSOLE /console-api/dum-download ConsoleDumDownloadAction GET n USER PUBLIC
|
CONSOLE /console-api/dum-download ConsoleDumDownloadAction GET n USER PUBLIC
|
||||||
CONSOLE /console-api/eppPassword ConsoleEppPasswordAction POST n USER PUBLIC
|
CONSOLE /console-api/eppPassword ConsoleEppPasswordAction POST n USER PUBLIC
|
||||||
CONSOLE /console-api/ote ConsoleOteAction GET,POST n USER PUBLIC
|
CONSOLE /console-api/ote ConsoleOteAction GET,POST n USER PUBLIC
|
||||||
CONSOLE /console-api/registrar ConsoleUpdateRegistrarAction POST n USER PUBLIC
|
CONSOLE /console-api/registrar ConsoleUpdateRegistrarAction POST n USER PUBLIC
|
||||||
CONSOLE /console-api/registrars RegistrarsAction GET,POST n USER PUBLIC
|
CONSOLE /console-api/registrars RegistrarsAction GET,POST n USER PUBLIC
|
||||||
CONSOLE /console-api/registry-lock ConsoleRegistryLockAction GET,POST n USER PUBLIC
|
CONSOLE /console-api/registry-lock ConsoleRegistryLockAction GET,POST n USER PUBLIC
|
||||||
CONSOLE /console-api/registry-lock-verify ConsoleRegistryLockVerifyAction GET n USER PUBLIC
|
CONSOLE /console-api/registry-lock-verify ConsoleRegistryLockVerifyAction GET n USER PUBLIC
|
||||||
CONSOLE /console-api/settings/contacts ContactAction GET,POST n USER PUBLIC
|
CONSOLE /console-api/settings/contacts ContactAction GET,POST n USER PUBLIC
|
||||||
CONSOLE /console-api/settings/security SecurityAction POST n USER PUBLIC
|
CONSOLE /console-api/settings/security SecurityAction POST n USER PUBLIC
|
||||||
CONSOLE /console-api/settings/whois-fields WhoisRegistrarFieldsAction POST n USER PUBLIC
|
CONSOLE /console-api/settings/whois-fields WhoisRegistrarFieldsAction POST n USER PUBLIC
|
||||||
CONSOLE /console-api/userdata ConsoleUserDataAction GET n USER PUBLIC
|
CONSOLE /console-api/userdata ConsoleUserDataAction GET n USER PUBLIC
|
||||||
CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE n USER PUBLIC
|
CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE,PUT n USER PUBLIC
|
||||||
@@ -1,82 +1,82 @@
|
|||||||
SERVICE PATH CLASS METHODS OK MIN USER_POLICY
|
SERVICE PATH CLASS METHODS OK MIN USER_POLICY
|
||||||
FRONTEND /_dr/epp EppTlsAction POST n APP ADMIN
|
FRONTEND /_dr/epp EppTlsAction POST n APP ADMIN
|
||||||
BACKEND /_dr/admin/createGroups CreateGroupsAction POST n APP ADMIN
|
BACKEND /_dr/admin/createGroups CreateGroupsAction POST n APP ADMIN
|
||||||
BACKEND /_dr/admin/list/domains ListDomainsAction GET,POST n APP ADMIN
|
BACKEND /_dr/admin/list/domains ListDomainsAction GET,POST n APP ADMIN
|
||||||
BACKEND /_dr/admin/list/hosts ListHostsAction GET,POST n APP ADMIN
|
BACKEND /_dr/admin/list/hosts ListHostsAction GET,POST n APP ADMIN
|
||||||
BACKEND /_dr/admin/list/premiumLists ListPremiumListsAction GET,POST n APP ADMIN
|
BACKEND /_dr/admin/list/premiumLists ListPremiumListsAction GET,POST n APP ADMIN
|
||||||
BACKEND /_dr/admin/list/registrars ListRegistrarsAction GET,POST n APP ADMIN
|
BACKEND /_dr/admin/list/registrars ListRegistrarsAction GET,POST n APP ADMIN
|
||||||
BACKEND /_dr/admin/list/reservedLists ListReservedListsAction GET,POST n APP ADMIN
|
BACKEND /_dr/admin/list/reservedLists ListReservedListsAction GET,POST n APP ADMIN
|
||||||
BACKEND /_dr/admin/list/tlds ListTldsAction GET,POST n APP ADMIN
|
BACKEND /_dr/admin/list/tlds ListTldsAction GET,POST n APP ADMIN
|
||||||
BACKEND /_dr/admin/updateUserGroup UpdateUserGroupAction POST n APP ADMIN
|
BACKEND /_dr/admin/updateUserGroup UpdateUserGroupAction POST n APP ADMIN
|
||||||
BACKEND /_dr/admin/verifyOte VerifyOteAction POST n APP ADMIN
|
BACKEND /_dr/admin/verifyOte VerifyOteAction POST n APP ADMIN
|
||||||
BACKEND /_dr/cron/fanout TldFanoutAction GET y APP ADMIN
|
BACKEND /_dr/cron/fanout TldFanoutAction GET y APP ADMIN
|
||||||
BACKEND /_dr/epptool EppToolAction POST n APP ADMIN
|
BACKEND /_dr/epptool EppToolAction POST n APP ADMIN
|
||||||
BACKEND /_dr/loadtest LoadTestAction POST y APP ADMIN
|
BACKEND /_dr/loadtest LoadTestAction POST y APP ADMIN
|
||||||
BACKEND /_dr/task/brdaCopy BrdaCopyAction POST y APP ADMIN
|
BACKEND /_dr/task/brdaCopy BrdaCopyAction POST y APP ADMIN
|
||||||
BACKEND /_dr/task/bsaDownload BsaDownloadAction GET,POST n APP ADMIN
|
BACKEND /_dr/task/bsaDownload BsaDownloadAction GET,POST n APP ADMIN
|
||||||
BACKEND /_dr/task/bsaRefresh BsaRefreshAction GET,POST n APP ADMIN
|
BACKEND /_dr/task/bsaRefresh BsaRefreshAction GET,POST n APP ADMIN
|
||||||
BACKEND /_dr/task/bsaValidate BsaValidateAction GET,POST n APP ADMIN
|
BACKEND /_dr/task/bsaValidate BsaValidateAction GET,POST n APP ADMIN
|
||||||
BACKEND /_dr/task/copyDetailReports CopyDetailReportsAction POST n APP ADMIN
|
BACKEND /_dr/task/copyDetailReports CopyDetailReportsAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/deleteExpiredDomains DeleteExpiredDomainsAction GET n APP ADMIN
|
BACKEND /_dr/task/deleteExpiredDomains DeleteExpiredDomainsAction GET n APP ADMIN
|
||||||
BACKEND /_dr/task/deleteLoadTestData DeleteLoadTestDataAction POST n APP ADMIN
|
BACKEND /_dr/task/deleteLoadTestData DeleteLoadTestDataAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/deleteProberData DeleteProberDataAction POST n APP ADMIN
|
BACKEND /_dr/task/deleteProberData DeleteProberDataAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/dnsRefresh RefreshDnsAction GET y APP ADMIN
|
BACKEND /_dr/task/dnsRefresh RefreshDnsAction GET y APP ADMIN
|
||||||
BACKEND /_dr/task/executeCannedScript CannedScriptExecutionAction POST,GET y APP ADMIN
|
BACKEND /_dr/task/executeCannedScript CannedScriptExecutionAction POST,GET y APP ADMIN
|
||||||
BACKEND /_dr/task/expandBillingRecurrences ExpandBillingRecurrencesAction GET n APP ADMIN
|
BACKEND /_dr/task/expandBillingRecurrences ExpandBillingRecurrencesAction GET n APP ADMIN
|
||||||
BACKEND /_dr/task/exportDomainLists ExportDomainListsAction POST n APP ADMIN
|
BACKEND /_dr/task/exportDomainLists ExportDomainListsAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/exportPremiumTerms ExportPremiumTermsAction POST n APP ADMIN
|
BACKEND /_dr/task/exportPremiumTerms ExportPremiumTermsAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/exportReservedTerms ExportReservedTermsAction POST n APP ADMIN
|
BACKEND /_dr/task/exportReservedTerms ExportReservedTermsAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/generateInvoices GenerateInvoicesAction POST n APP ADMIN
|
BACKEND /_dr/task/generateInvoices GenerateInvoicesAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/generateSpec11 GenerateSpec11ReportAction POST n APP ADMIN
|
BACKEND /_dr/task/generateSpec11 GenerateSpec11ReportAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/generateZoneFiles GenerateZoneFilesAction POST n APP ADMIN
|
BACKEND /_dr/task/generateZoneFiles GenerateZoneFilesAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/icannReportingStaging IcannReportingStagingAction POST n APP ADMIN
|
BACKEND /_dr/task/icannReportingStaging IcannReportingStagingAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/icannReportingUpload IcannReportingUploadAction POST n APP ADMIN
|
BACKEND /_dr/task/icannReportingUpload IcannReportingUploadAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/nordnUpload NordnUploadAction POST y APP ADMIN
|
BACKEND /_dr/task/nordnUpload NordnUploadAction POST y APP ADMIN
|
||||||
BACKEND /_dr/task/nordnVerify NordnVerifyAction POST y APP ADMIN
|
BACKEND /_dr/task/nordnVerify NordnVerifyAction POST y APP ADMIN
|
||||||
BACKEND /_dr/task/publishDnsUpdates PublishDnsUpdatesAction POST y APP ADMIN
|
BACKEND /_dr/task/publishDnsUpdates PublishDnsUpdatesAction POST y APP ADMIN
|
||||||
BACKEND /_dr/task/publishInvoices PublishInvoicesAction POST n APP ADMIN
|
BACKEND /_dr/task/publishInvoices PublishInvoicesAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/publishSpec11 PublishSpec11ReportAction POST n APP ADMIN
|
BACKEND /_dr/task/publishSpec11 PublishSpec11ReportAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/rdeReport RdeReportAction POST n APP ADMIN
|
BACKEND /_dr/task/rdeReport RdeReportAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/rdeStaging RdeStagingAction GET,POST n APP ADMIN
|
BACKEND /_dr/task/rdeStaging RdeStagingAction GET,POST n APP ADMIN
|
||||||
BACKEND /_dr/task/rdeUpload RdeUploadAction POST n APP ADMIN
|
BACKEND /_dr/task/rdeUpload RdeUploadAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/readDnsRefreshRequests ReadDnsRefreshRequestsAction POST y APP ADMIN
|
BACKEND /_dr/task/readDnsRefreshRequests ReadDnsRefreshRequestsAction POST y APP ADMIN
|
||||||
BACKEND /_dr/task/refreshDnsForAllDomains RefreshDnsForAllDomainsAction GET n APP ADMIN
|
BACKEND /_dr/task/refreshDnsForAllDomains RefreshDnsForAllDomainsAction GET n APP ADMIN
|
||||||
BACKEND /_dr/task/refreshDnsOnHostRename RefreshDnsOnHostRenameAction POST n APP ADMIN
|
BACKEND /_dr/task/refreshDnsOnHostRename RefreshDnsOnHostRenameAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/relockDomain RelockDomainAction POST y APP ADMIN
|
BACKEND /_dr/task/relockDomain RelockDomainAction POST y APP ADMIN
|
||||||
BACKEND /_dr/task/resaveAllEppResourcesPipeline ResaveAllEppResourcesPipelineAction GET n APP ADMIN
|
BACKEND /_dr/task/resaveAllEppResourcesPipeline ResaveAllEppResourcesPipelineAction GET n APP ADMIN
|
||||||
BACKEND /_dr/task/resaveEntity ResaveEntityAction POST n APP ADMIN
|
BACKEND /_dr/task/resaveEntity ResaveEntityAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/sendExpiringCertificateNotificationEmail SendExpiringCertificateNotificationEmailAction GET n APP ADMIN
|
BACKEND /_dr/task/sendExpiringCertificateNotificationEmail SendExpiringCertificateNotificationEmailAction GET n APP ADMIN
|
||||||
BACKEND /_dr/task/syncGroupMembers SyncGroupMembersAction POST n APP ADMIN
|
BACKEND /_dr/task/syncGroupMembers SyncGroupMembersAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/syncRegistrarsSheet SyncRegistrarsSheetAction POST n APP ADMIN
|
BACKEND /_dr/task/syncRegistrarsSheet SyncRegistrarsSheetAction POST n APP ADMIN
|
||||||
BACKEND /_dr/task/tmchCrl TmchCrlAction POST y APP ADMIN
|
BACKEND /_dr/task/tmchCrl TmchCrlAction POST y APP ADMIN
|
||||||
BACKEND /_dr/task/tmchDnl TmchDnlAction POST y APP ADMIN
|
BACKEND /_dr/task/tmchDnl TmchDnlAction POST y APP ADMIN
|
||||||
BACKEND /_dr/task/tmchSmdrl TmchSmdrlAction POST y APP ADMIN
|
BACKEND /_dr/task/tmchSmdrl TmchSmdrlAction POST y APP ADMIN
|
||||||
BACKEND /_dr/task/updateRegistrarRdapBaseUrls UpdateRegistrarRdapBaseUrlsAction GET y APP ADMIN
|
BACKEND /_dr/task/updateRegistrarRdapBaseUrls UpdateRegistrarRdapBaseUrlsAction GET y APP ADMIN
|
||||||
BACKEND /_dr/task/uploadBsaUnavailableNames UploadBsaUnavailableDomainsAction GET,POST n APP ADMIN
|
BACKEND /_dr/task/uploadBsaUnavailableNames UploadBsaUnavailableDomainsAction GET,POST n APP ADMIN
|
||||||
BACKEND /_dr/task/wipeOutContactHistoryPii WipeOutContactHistoryPiiAction GET n APP ADMIN
|
BACKEND /_dr/task/wipeOutContactHistoryPii WipeOutContactHistoryPiiAction GET n APP ADMIN
|
||||||
PUBAPI /_dr/whois WhoisAction POST n APP ADMIN
|
PUBAPI /_dr/whois WhoisAction POST n APP ADMIN
|
||||||
PUBAPI /check CheckApiAction GET n NONE PUBLIC
|
PUBAPI /check CheckApiAction GET n NONE PUBLIC
|
||||||
PUBAPI /rdap/autnum/(*) RdapAutnumAction GET,HEAD n NONE PUBLIC
|
PUBAPI /rdap/autnum/(*) RdapAutnumAction GET,HEAD n NONE PUBLIC
|
||||||
PUBAPI /rdap/domain/(*) RdapDomainAction GET,HEAD n NONE PUBLIC
|
PUBAPI /rdap/domain/(*) RdapDomainAction GET,HEAD n NONE PUBLIC
|
||||||
PUBAPI /rdap/domains RdapDomainSearchAction GET,HEAD n NONE PUBLIC
|
PUBAPI /rdap/domains RdapDomainSearchAction GET,HEAD n NONE PUBLIC
|
||||||
PUBAPI /rdap/entities RdapEntitySearchAction GET,HEAD n NONE PUBLIC
|
PUBAPI /rdap/entities RdapEntitySearchAction GET,HEAD n NONE PUBLIC
|
||||||
PUBAPI /rdap/entity/(*) RdapEntityAction GET,HEAD n NONE PUBLIC
|
PUBAPI /rdap/entity/(*) RdapEntityAction GET,HEAD n NONE PUBLIC
|
||||||
PUBAPI /rdap/help(*) RdapHelpAction GET,HEAD n NONE PUBLIC
|
PUBAPI /rdap/help(*) RdapHelpAction GET,HEAD n NONE PUBLIC
|
||||||
PUBAPI /rdap/ip/(*) RdapIpAction GET,HEAD n NONE PUBLIC
|
PUBAPI /rdap/ip/(*) RdapIpAction GET,HEAD n NONE PUBLIC
|
||||||
PUBAPI /rdap/nameserver/(*) RdapNameserverAction GET,HEAD n NONE PUBLIC
|
PUBAPI /rdap/nameserver/(*) RdapNameserverAction GET,HEAD n NONE PUBLIC
|
||||||
PUBAPI /rdap/nameservers RdapNameserverSearchAction GET,HEAD n NONE PUBLIC
|
PUBAPI /rdap/nameservers RdapNameserverSearchAction GET,HEAD n NONE PUBLIC
|
||||||
PUBAPI /whois/(*) WhoisHttpAction GET n NONE PUBLIC
|
PUBAPI /whois/(*) WhoisHttpAction GET n NONE PUBLIC
|
||||||
CONSOLE /console-api/domain ConsoleDomainGetAction GET n USER PUBLIC
|
CONSOLE /console-api/domain ConsoleDomainGetAction GET n USER PUBLIC
|
||||||
CONSOLE /console-api/domain-list ConsoleDomainListAction GET n USER PUBLIC
|
CONSOLE /console-api/domain-list ConsoleDomainListAction GET n USER PUBLIC
|
||||||
CONSOLE /console-api/dum-download ConsoleDumDownloadAction GET n USER PUBLIC
|
CONSOLE /console-api/dum-download ConsoleDumDownloadAction GET n USER PUBLIC
|
||||||
CONSOLE /console-api/eppPassword ConsoleEppPasswordAction POST n USER PUBLIC
|
CONSOLE /console-api/eppPassword ConsoleEppPasswordAction POST n USER PUBLIC
|
||||||
CONSOLE /console-api/ote ConsoleOteAction GET,POST n USER PUBLIC
|
CONSOLE /console-api/ote ConsoleOteAction GET,POST n USER PUBLIC
|
||||||
CONSOLE /console-api/registrar ConsoleUpdateRegistrarAction POST n USER PUBLIC
|
CONSOLE /console-api/registrar ConsoleUpdateRegistrarAction POST n USER PUBLIC
|
||||||
CONSOLE /console-api/registrars RegistrarsAction GET,POST n USER PUBLIC
|
CONSOLE /console-api/registrars RegistrarsAction GET,POST n USER PUBLIC
|
||||||
CONSOLE /console-api/registry-lock ConsoleRegistryLockAction GET,POST n USER PUBLIC
|
CONSOLE /console-api/registry-lock ConsoleRegistryLockAction GET,POST n USER PUBLIC
|
||||||
CONSOLE /console-api/registry-lock-verify ConsoleRegistryLockVerifyAction GET n USER PUBLIC
|
CONSOLE /console-api/registry-lock-verify ConsoleRegistryLockVerifyAction GET n USER PUBLIC
|
||||||
CONSOLE /console-api/settings/contacts ContactAction GET,POST n USER PUBLIC
|
CONSOLE /console-api/settings/contacts ContactAction GET,POST n USER PUBLIC
|
||||||
CONSOLE /console-api/settings/security SecurityAction POST n USER PUBLIC
|
CONSOLE /console-api/settings/security SecurityAction POST n USER PUBLIC
|
||||||
CONSOLE /console-api/settings/whois-fields WhoisRegistrarFieldsAction POST n USER PUBLIC
|
CONSOLE /console-api/settings/whois-fields WhoisRegistrarFieldsAction POST n USER PUBLIC
|
||||||
CONSOLE /console-api/userdata ConsoleUserDataAction GET n USER PUBLIC
|
CONSOLE /console-api/userdata ConsoleUserDataAction GET n USER PUBLIC
|
||||||
CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE n USER PUBLIC
|
CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE,PUT n USER PUBLIC
|
||||||
Reference in New Issue
Block a user