mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-07 22:07:40 +00:00
fix: disable user action if viewer (#2737)
This commit is contained in:
parent
f7743834b0
commit
a9035def0f
@ -1,7 +1,8 @@
|
|||||||
<form [formGroup]="profileForm" *ngIf="profileForm" (ngSubmit)="submitForm()">
|
<form [formGroup]="profileForm" *ngIf="profileForm" (ngSubmit)="submitForm()">
|
||||||
<div class="user-form-content">
|
<div class="user-form-content">
|
||||||
<div class="user-form-content inner">
|
<div class="user-form-content inner">
|
||||||
<button class="camera-wrapper" type="button" (click)="showEditImage ? openUploadDialog() : null">
|
<button [disabled]="user && disabled" class="camera-wrapper" type="button"
|
||||||
|
(click)="showEditImage ? openUploadDialog() : null">
|
||||||
<div class="i-wrapper" *ngIf="showEditImage">
|
<div class="i-wrapper" *ngIf="showEditImage">
|
||||||
<i class="las la-camera"></i>
|
<i class="las la-camera"></i>
|
||||||
</div>
|
</div>
|
||||||
@ -16,7 +17,7 @@
|
|||||||
<cnsl-label>{{ 'USER.PROFILE.USERNAME' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.USERNAME' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="userName" />
|
<input cnslInput formControlName="userName" />
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<button type="button" color="primary" mat-stroked-button class="edit"
|
<button [disabled]="user && disabled" type="button" color="primary" mat-stroked-button class="edit"
|
||||||
(click)="changeUsername()">{{'USER.PROFILE.CHANGEUSERNAME' |
|
(click)="changeUsername()">{{'USER.PROFILE.CHANGEUSERNAME' |
|
||||||
translate}}</button>
|
translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,25 +16,20 @@ export class DetailFormComponent implements OnDestroy, OnChanges {
|
|||||||
@Input() public preferredLoginName: string = '';
|
@Input() public preferredLoginName: string = '';
|
||||||
@Input() public username!: string;
|
@Input() public username!: string;
|
||||||
@Input() public user!: Human.AsObject;
|
@Input() public user!: Human.AsObject;
|
||||||
@Input() public disabled: boolean = false;
|
@Input() public disabled: boolean = true;
|
||||||
@Input() public genders: Gender[] = [];
|
@Input() public genders: Gender[] = [];
|
||||||
@Input() public languages: string[] = ['de', 'en'];
|
@Input() public languages: string[] = ['de', 'en'];
|
||||||
@Output() public submitData: EventEmitter<Profile.AsObject> = new EventEmitter<Profile.AsObject>();
|
@Output() public submitData: EventEmitter<Profile.AsObject> = new EventEmitter<Profile.AsObject>();
|
||||||
@Output() public changedLanguage: EventEmitter<string> = new EventEmitter<string>();
|
@Output() public changedLanguage: EventEmitter<string> = new EventEmitter<string>();
|
||||||
@Output() public changeUsernameClicked: EventEmitter<void> = new EventEmitter();
|
@Output() public changeUsernameClicked: EventEmitter<void> = new EventEmitter();
|
||||||
|
|
||||||
public profileForm!: FormGroup;
|
public profileForm!: FormGroup;
|
||||||
|
|
||||||
private sub: Subscription = new Subscription();
|
private sub: Subscription = new Subscription();
|
||||||
|
|
||||||
constructor(
|
constructor(private fb: FormBuilder, private dialog: MatDialog) {
|
||||||
private fb: FormBuilder,
|
|
||||||
private dialog: MatDialog,
|
|
||||||
) {
|
|
||||||
this.profileForm = this.fb.group({
|
this.profileForm = this.fb.group({
|
||||||
userName: [{ value: '', disabled: true }, [
|
userName: [{ value: '', disabled: true }, [Validators.required]],
|
||||||
Validators.required,
|
|
||||||
]],
|
|
||||||
firstName: [{ value: '', disabled: this.disabled }, Validators.required],
|
firstName: [{ value: '', disabled: this.disabled }, Validators.required],
|
||||||
lastName: [{ value: '', disabled: this.disabled }, Validators.required],
|
lastName: [{ value: '', disabled: this.disabled }, Validators.required],
|
||||||
nickName: [{ value: '', disabled: this.disabled }],
|
nickName: [{ value: '', disabled: this.disabled }],
|
||||||
@ -46,9 +41,7 @@ export class DetailFormComponent implements OnDestroy, OnChanges {
|
|||||||
|
|
||||||
public ngOnChanges(): void {
|
public ngOnChanges(): void {
|
||||||
this.profileForm = this.fb.group({
|
this.profileForm = this.fb.group({
|
||||||
userName: [{ value: '', disabled: true }, [
|
userName: [{ value: '', disabled: true }, [Validators.required]],
|
||||||
Validators.required,
|
|
||||||
]],
|
|
||||||
firstName: [{ value: '', disabled: this.disabled }, Validators.required],
|
firstName: [{ value: '', disabled: this.disabled }, Validators.required],
|
||||||
lastName: [{ value: '', disabled: this.disabled }, Validators.required],
|
lastName: [{ value: '', disabled: this.disabled }, Validators.required],
|
||||||
nickName: [{ value: '', disabled: this.disabled }],
|
nickName: [{ value: '', disabled: this.disabled }],
|
||||||
@ -60,7 +53,7 @@ export class DetailFormComponent implements OnDestroy, OnChanges {
|
|||||||
this.profileForm.patchValue({ userName: this.username, ...this.user.profile });
|
this.profileForm.patchValue({ userName: this.username, ...this.user.profile });
|
||||||
|
|
||||||
if (this.preferredLanguage) {
|
if (this.preferredLanguage) {
|
||||||
this.sub = this.preferredLanguage.valueChanges.subscribe(value => {
|
this.sub = this.preferredLanguage.valueChanges.subscribe((value) => {
|
||||||
this.changedLanguage.emit(value);
|
this.changedLanguage.emit(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -86,7 +79,7 @@ export class DetailFormComponent implements OnDestroy, OnChanges {
|
|||||||
width: '400px',
|
width: '400px',
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe(resp => {
|
dialogRef.afterClosed().subscribe((resp) => {
|
||||||
if (resp) {
|
if (resp) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -114,5 +107,4 @@ export class DetailFormComponent implements OnDestroy, OnChanges {
|
|||||||
public get preferredLanguage(): AbstractControl | null {
|
public get preferredLanguage(): AbstractControl | null {
|
||||||
return this.profileForm.get('preferredLanguage');
|
return this.profileForm.get('preferredLanguage');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,53 +1,53 @@
|
|||||||
<cnsl-card title="{{'USER.PASSWORDLESS.TITLE' | translate}}"
|
<cnsl-card title="{{'USER.PASSWORDLESS.TITLE' | translate}}"
|
||||||
description="{{'USER.PASSWORDLESS.DESCRIPTION' | translate}}">
|
description="{{'USER.PASSWORDLESS.DESCRIPTION' | translate}}">
|
||||||
<button card-actions mat-icon-button (click)="getPasswordless()" class="icon-button" matTooltip="{{'ACTIONS.REFRESH' | translate}}">
|
<button card-actions mat-icon-button (click)="getPasswordless()" class="icon-button"
|
||||||
<mat-icon class="icon">refresh</mat-icon>
|
matTooltip="{{'ACTIONS.REFRESH' | translate}}">
|
||||||
|
<mat-icon class="icon">refresh</mat-icon>
|
||||||
|
</button>
|
||||||
|
<cnsl-refresh-table [hideRefresh]="true" [loading]="loading$ | async" [dataSize]="dataSource?.data?.length ?? 0">
|
||||||
|
<table class="table" mat-table [dataSource]="dataSource">
|
||||||
|
<ng-container matColumnDef="name">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> {{ 'USER.PASSWORDLESS.NAME' | translate }} </th>
|
||||||
|
<td mat-cell *matCellDef="let mfa"><span *ngIf="mfa?.name" class="centered">
|
||||||
|
{{ mfa?.name }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="state">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> {{ 'USER.PASSWORDLESS.TABLESTATE' | translate }} </th>
|
||||||
|
<td mat-cell *matCellDef="let mfa"><span class="centered">
|
||||||
|
{{'USER.PASSWORDLESS.STATE.'+ mfa.state | translate}}
|
||||||
|
<i matTooltip="verified" *ngIf="mfa.state === AuthFactorState.AUTH_FACTOR_STATE_READY"
|
||||||
|
class="verified las la-check-circle"></i>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="actions">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> {{ 'USER.PASSWORDLESS.TABLEACTIONS' | translate }} </th>
|
||||||
|
<td mat-cell *matCellDef="let mfa">
|
||||||
|
<button matTooltip="{{'ACTIONS.REMOVE' | translate}}" color="warn" mat-icon-button
|
||||||
|
(click)="deletePasswordless(mfa.id)">
|
||||||
|
<i class="las la-trash"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
|
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||||
|
</table>
|
||||||
|
</cnsl-refresh-table>
|
||||||
|
<div class="add-row">
|
||||||
|
<button [disabled]="user && disabled" class="button" (click)="sendPasswordlessRegistration()" mat-raised-button
|
||||||
|
color="primary" matTooltip="{{'ACTIONS.NEW' | translate}}">
|
||||||
|
{{'USER.PASSWORDLESS.SEND' | translate}}
|
||||||
|
<i class="icon las la-paper-plane"></i>
|
||||||
</button>
|
</button>
|
||||||
<cnsl-refresh-table [hideRefresh]="true" [loading]="loading$ | async"
|
|
||||||
[dataSize]="dataSource?.data?.length ?? 0">
|
|
||||||
<table class="table" mat-table [dataSource]="dataSource">
|
|
||||||
<ng-container matColumnDef="name">
|
|
||||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.PASSWORDLESS.NAME' | translate }} </th>
|
|
||||||
<td mat-cell *matCellDef="let mfa"><span *ngIf="mfa?.name" class="centered">
|
|
||||||
{{ mfa?.name }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="state">
|
|
||||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.PASSWORDLESS.TABLESTATE' | translate }} </th>
|
|
||||||
<td mat-cell *matCellDef="let mfa"><span class="centered">
|
|
||||||
{{'USER.PASSWORDLESS.STATE.'+ mfa.state | translate}}
|
|
||||||
<i matTooltip="verified" *ngIf="mfa.state === AuthFactorState.AUTH_FACTOR_STATE_READY"
|
|
||||||
class="verified las la-check-circle"></i>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="actions">
|
|
||||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.PASSWORDLESS.TABLEACTIONS' | translate }} </th>
|
|
||||||
<td mat-cell *matCellDef="let mfa">
|
|
||||||
<button matTooltip="{{'ACTIONS.REMOVE' | translate}}" color="warn" mat-icon-button
|
|
||||||
(click)="deletePasswordless(mfa.id)">
|
|
||||||
<i class="las la-trash"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
|
||||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
|
||||||
</table>
|
|
||||||
</cnsl-refresh-table>
|
|
||||||
<div class="add-row">
|
|
||||||
<button class="button" (click)="sendPasswordlessRegistration()" mat-raised-button color="primary"
|
|
||||||
matTooltip="{{'ACTIONS.NEW' | translate}}">
|
|
||||||
{{'USER.PASSWORDLESS.SEND' | translate}}
|
|
||||||
<i class="icon las la-paper-plane"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="table-wrapper">
|
<div class="table-wrapper">
|
||||||
<div class="spinner-container" *ngIf="loading$ | async">
|
<div class="spinner-container" *ngIf="loading$ | async">
|
||||||
<mat-spinner diameter="50"></mat-spinner>
|
<mat-spinner diameter="50"></mat-spinner>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</cnsl-card>
|
</cnsl-card>
|
@ -10,10 +10,10 @@ import { ToastService } from 'src/app/services/toast.service';
|
|||||||
|
|
||||||
export interface WebAuthNOptions {
|
export interface WebAuthNOptions {
|
||||||
challenge: string;
|
challenge: string;
|
||||||
rp: { name: string, id: string; };
|
rp: { name: string; id: string };
|
||||||
user: { name: string, id: string, displayName: string; };
|
user: { name: string; id: string; displayName: string };
|
||||||
pubKeyCredParams: any;
|
pubKeyCredParams: any;
|
||||||
authenticatorSelection: { userVerification: string; };
|
authenticatorSelection: { userVerification: string };
|
||||||
timeout: number;
|
timeout: number;
|
||||||
attestation: string;
|
attestation: string;
|
||||||
}
|
}
|
||||||
@ -25,6 +25,7 @@ export interface WebAuthNOptions {
|
|||||||
})
|
})
|
||||||
export class PasswordlessComponent implements OnInit, OnDestroy {
|
export class PasswordlessComponent implements OnInit, OnDestroy {
|
||||||
@Input() public user!: User.AsObject;
|
@Input() public user!: User.AsObject;
|
||||||
|
@Input() public disabled: boolean = true;
|
||||||
public displayedColumns: string[] = ['name', 'state', 'actions'];
|
public displayedColumns: string[] = ['name', 'state', 'actions'];
|
||||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||||
@ -36,9 +37,7 @@ export class PasswordlessComponent implements OnInit, OnDestroy {
|
|||||||
public AuthFactorState: any = AuthFactorState;
|
public AuthFactorState: any = AuthFactorState;
|
||||||
public error: string = '';
|
public error: string = '';
|
||||||
|
|
||||||
constructor(private service: ManagementService,
|
constructor(private service: ManagementService, private toast: ToastService, private dialog: MatDialog) {}
|
||||||
private toast: ToastService,
|
|
||||||
private dialog: MatDialog) { }
|
|
||||||
|
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
this.getPasswordless();
|
this.getPasswordless();
|
||||||
@ -49,12 +48,15 @@ export class PasswordlessComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getPasswordless(): void {
|
public getPasswordless(): void {
|
||||||
this.service.listHumanPasswordless(this.user.id).then(passwordless => {
|
this.service
|
||||||
this.dataSource = new MatTableDataSource(passwordless.resultList);
|
.listHumanPasswordless(this.user.id)
|
||||||
this.dataSource.sort = this.sort;
|
.then((passwordless) => {
|
||||||
}).catch(error => {
|
this.dataSource = new MatTableDataSource(passwordless.resultList);
|
||||||
this.error = error.message;
|
this.dataSource.sort = this.sort;
|
||||||
});
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.error = error.message;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public deletePasswordless(id?: string): void {
|
public deletePasswordless(id?: string): void {
|
||||||
@ -68,23 +70,29 @@ export class PasswordlessComponent implements OnInit, OnDestroy {
|
|||||||
width: '400px',
|
width: '400px',
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe(resp => {
|
dialogRef.afterClosed().subscribe((resp) => {
|
||||||
if (resp && id) {
|
if (resp && id) {
|
||||||
this.service.removeHumanPasswordless(id, this.user.id).then(() => {
|
this.service
|
||||||
this.toast.showInfo('USER.TOAST.PASSWORDLESSREMOVED', true);
|
.removeHumanPasswordless(id, this.user.id)
|
||||||
this.getPasswordless();
|
.then(() => {
|
||||||
}).catch(error => {
|
this.toast.showInfo('USER.TOAST.PASSWORDLESSREMOVED', true);
|
||||||
this.toast.showError(error);
|
this.getPasswordless();
|
||||||
});
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public sendPasswordlessRegistration(): void {
|
public sendPasswordlessRegistration(): void {
|
||||||
this.service.sendPasswordlessRegistration(this.user.id).then(() => {
|
this.service
|
||||||
this.toast.showInfo('USER.TOAST.PASSWORDLESSREGISTRATIONSENT');
|
.sendPasswordlessRegistration(this.user.id)
|
||||||
}).catch(error => {
|
.then(() => {
|
||||||
this.toast.showError(error);
|
this.toast.showInfo('USER.TOAST.PASSWORDLESSREGISTRATIONSENT');
|
||||||
});
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.toast.showError(error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,8 @@
|
|||||||
</cnsl-card>
|
</cnsl-card>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<cnsl-passwordless *ngIf="user && user.human" [user]="user"></cnsl-passwordless>
|
<cnsl-passwordless *ngIf="user && user.human" [user]="user" [disabled]="(canWrite$ | async) === false">
|
||||||
|
</cnsl-passwordless>
|
||||||
|
|
||||||
<cnsl-user-mfa *ngIf="user && user.human" [user]="user"></cnsl-user-mfa>
|
<cnsl-user-mfa *ngIf="user && user.human" [user]="user"></cnsl-user-mfa>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user