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)));
|
||||
}
|
||||
|
||||
deleteUser(registrarId: string, emailAddress: string): Observable<any> {
|
||||
deleteUser(registrarId: string, user: User): Observable<any> {
|
||||
return this.http
|
||||
.delete<any>(`/console-api/users?registrarId=${registrarId}`, {
|
||||
body: JSON.stringify({ emailAddress }),
|
||||
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')
|
||||
|
||||
@@ -1,32 +1,77 @@
|
||||
<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">
|
||||
{{ userDetails.emailAddress + " succesfully created" }}
|
||||
{{ userDetails().emailAddress + " successfully created" }}
|
||||
</h1>
|
||||
} @else {
|
||||
<h1 class="mat-headline-4">User details</h1>
|
||||
}
|
||||
<mat-divider></mat-divider>
|
||||
<div>
|
||||
<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-icon-button
|
||||
aria-label="Delete User"
|
||||
(click)="deleteUser()"
|
||||
[disabled]="isLoading"
|
||||
>
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<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)="userRole = userDetails().role; 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>
|
||||
@@ -41,17 +86,17 @@
|
||||
<mat-list-item role="listitem">
|
||||
<span class="console-app__list-key">User email</span>
|
||||
<span class="console-app__list-value">{{
|
||||
userDetails.emailAddress
|
||||
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)
|
||||
roleToDescription(userDetails().role)
|
||||
}}</span>
|
||||
</mat-list-item>
|
||||
@if (userDetails.password) {
|
||||
@if (userDetails().password) {
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item role="listitem">
|
||||
<span class="console-app__list-key">Password</span>
|
||||
@@ -60,7 +105,7 @@
|
||||
>
|
||||
<input
|
||||
[type]="isPasswordVisible ? 'text' : 'password'"
|
||||
[value]="userDetails.password"
|
||||
[value]="userDetails().password"
|
||||
disabled
|
||||
/>
|
||||
<button
|
||||
@@ -76,4 +121,5 @@
|
||||
</mat-list>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
}}
|
||||
</div>
|
||||
|
||||
@@ -25,6 +25,15 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
// limitations under the License.
|
||||
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
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 { User, UsersService, roleToDescription } from './users.service';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-user-edit',
|
||||
@@ -27,6 +28,7 @@ import { User, UsersService, roleToDescription } from './users.service';
|
||||
styleUrls: ['./userEdit.component.scss'],
|
||||
standalone: true,
|
||||
imports: [
|
||||
FormsModule,
|
||||
MaterialModule,
|
||||
SnackBarModule,
|
||||
CommonModule,
|
||||
@@ -35,22 +37,25 @@ import { User, UsersService, roleToDescription } from './users.service';
|
||||
providers: [],
|
||||
})
|
||||
export class UserEditComponent {
|
||||
inEdit = false;
|
||||
isEditing = false;
|
||||
isPasswordVisible = false;
|
||||
isNewUser = false;
|
||||
isLoading = false;
|
||||
userDetails: User;
|
||||
userRole = '';
|
||||
|
||||
userDetails = computed(() => {
|
||||
return this.usersService
|
||||
.users()
|
||||
.filter(
|
||||
(u) => u.emailAddress === this.usersService.currentlyOpenUserEmail()
|
||||
)[0];
|
||||
});
|
||||
|
||||
constructor(
|
||||
protected registrarService: RegistrarService,
|
||||
protected usersService: UsersService,
|
||||
private _snackBar: MatSnackBar
|
||||
) {
|
||||
this.userDetails = this.usersService
|
||||
.users()
|
||||
.filter(
|
||||
(u) => u.emailAddress === this.usersService.currentlyOpenUserEmail()
|
||||
)[0];
|
||||
if (this.usersService.isNewUser) {
|
||||
this.isNewUser = true;
|
||||
this.usersService.isNewUser = false;
|
||||
@@ -63,7 +68,7 @@ export class UserEditComponent {
|
||||
|
||||
deleteUser() {
|
||||
this.isLoading = true;
|
||||
this.usersService.deleteUser(this.userDetails.emailAddress).subscribe({
|
||||
this.usersService.deleteUser(this.userDetails()).subscribe({
|
||||
error: (err) => {
|
||||
this._snackBar.open(err.error || err.message);
|
||||
this.isLoading = false;
|
||||
@@ -78,4 +83,23 @@ export class UserEditComponent {
|
||||
goBack() {
|
||||
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.
|
||||
|
||||
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.toLowerCase().startsWith('account_manager')) {
|
||||
else if (role === 'ACCOUNT_MANAGER') {
|
||||
return 'Viewer';
|
||||
}
|
||||
return 'Editor';
|
||||
@@ -68,9 +68,15 @@ export class UsersService {
|
||||
);
|
||||
}
|
||||
|
||||
deleteUser(emailAddress: string) {
|
||||
deleteUser(user: User) {
|
||||
return this.backendService
|
||||
.deleteUser(this.registrarService.registrarId(), emailAddress)
|
||||
.pipe(tap((_) => this.fetchUsers()));
|
||||
.deleteUser(this.registrarService.registrarId(), user)
|
||||
.pipe(switchMap((_) => this.fetchUsers()));
|
||||
}
|
||||
|
||||
updateUser(updatedUser: User) {
|
||||
return this.backendService
|
||||
.updateUser(this.registrarService.registrarId(), updatedUser)
|
||||
.pipe(switchMap((_) => this.fetchUsers()));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user