fix(console): Display MFA Name and Type correctly (#10586)

# Which Problems Are Solved
On the user detail page the mfa names and types where not displayed
correctly.

# How the Problems Are Solved
Switched to our internal TypeSafeCellDef and correctly parse the
@zitadel/proto types.

# Additional Context
- Closes #10493

Co-authored-by: Max Peintner <[email protected]>
This commit is contained in:
Ramon
2025-09-03 09:33:04 +02:00
committed by GitHub
co-authored by Max Peintner
parent ded0adffd1
commit d9554d483c
3 changed files with 27 additions and 19 deletions
@@ -27,32 +27,32 @@
<table class="table" mat-table [dataSource]="dataSource">
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef>{{ 'USER.MFA.TABLETYPE' | translate }}</th>
<td mat-cell *matCellDef="let mfa">
<span *ngIf="mfa.otp !== undefined">TOTP (Time-based One-Time Password)</span>
<span *ngIf="mfa.u2f !== undefined">U2F (Universal 2nd Factor)</span>
<span *ngIf="mfa.otpSms !== undefined">One-Time Password SMS</span>
<span *ngIf="mfa.otpEmail !== undefined">One-Time Password Email</span>
<td mat-cell *cnslCellDef="let mfa; dataSource: dataSource" [ngSwitch]="mfa.type.case">
<span *ngSwitchCase="'otp'">TOTP (Time-based One-Time Password)</span>
<span *ngSwitchCase="'u2f'">U2F (Universal 2nd Factor)</span>
<span *ngSwitchCase="'otpSms'">One-Time Password SMS</span>
<span *ngSwitchCase="'otpEmail'">One-Time Password Email</span>
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'USER.MFA.NAME' | translate }}</th>
<td mat-cell *matCellDef="let mfa">
<span *ngIf="mfa?.u2f?.name" class="centered">
{{ mfa.u2f.name }}
<td mat-cell *cnslCellDef="let mfa; dataSource: dataSource">
<span *ngIf="mfaName(mfa) as name" class="centered">
{{ name }}
</span>
</td>
</ng-container>
<ng-container matColumnDef="state">
<th mat-header-cell *matHeaderCellDef>{{ 'USER.MFA.TABLESTATE' | translate }}</th>
<td mat-cell *matCellDef="let mfa">
<td mat-cell *cnslCellDef="let mfa; dataSource: dataSource">
<span class="centered">
<span
class="state"
[ngClass]="{
active: mfa.state === AuthFactorState.AUTH_FACTOR_STATE_READY,
inactive: mfa.state === AuthFactorState.AUTH_FACTOR_STATE_NOT_READY,
active: mfa.state === AuthFactorState.READY,
inactive: mfa.state === AuthFactorState.NOT_READY,
}"
>{{ 'USER.MFA.STATE.' + mfa.state | translate }}</span
>
@@ -62,7 +62,7 @@
<ng-container matColumnDef="actions" stickyEnd>
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let mfa">
<td mat-cell *cnslCellDef="let mfa; dataSource: dataSource">
<cnsl-table-actions>
<button
actions
@@ -4,12 +4,12 @@ import { MatSort } from '@angular/material/sort';
import { MatTable, MatTableDataSource } from '@angular/material/table';
import { BehaviorSubject, Observable } from 'rxjs';
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
import { AuthFactorState } from 'src/app/proto/generated/zitadel/user_pb';
import { NewAuthService } from 'src/app/services/new-auth.service';
import { ToastService } from 'src/app/services/toast.service';
import { AddAuthFactorDialogData, AuthFactorDialogComponent } from '../auth-factor-dialog/auth-factor-dialog.component';
import { AuthFactor } from '@zitadel/proto/zitadel/user_pb';
import { AuthFactor, AuthFactorState } from '@zitadel/proto/zitadel/user_pb';
import { SecondFactorType } from '@zitadel/proto/zitadel/policy_pb';
export interface WebAuthNOptions {
challenge: string;
rp: { name: string; id: string };
@@ -33,8 +33,8 @@ export class AuthUserMfaComponent implements OnInit, OnDestroy {
@ViewChild(MatTable) public table!: MatTable<AuthFactor>;
@ViewChild(MatSort) public sort!: MatSort;
@Input() public phoneVerified: boolean = false;
public AuthFactorState: any = AuthFactorState;
public dataSource: MatTableDataSource<AuthFactor> = new MatTableDataSource<AuthFactor>([]);
protected readonly AuthFactorState = AuthFactorState;
protected dataSource: MatTableDataSource<AuthFactor> = new MatTableDataSource<AuthFactor>([]);
protected error: string = '';
@@ -194,4 +194,11 @@ export class AuthUserMfaComponent implements OnInit, OnDestroy {
): void {
subject.next(factors.some((f) => f === factor));
}
protected mfaName(factor: AuthFactor): string | undefined {
if (factor.type.value && 'name' in factor.type.value) {
return factor.type.value.name;
}
return undefined;
}
}
@@ -9,6 +9,7 @@ import { MatMenuModule } from '@angular/material/menu';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatTableModule } from '@angular/material/table';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatSelectModule } from '@angular/material/select';
import { RouterModule } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { CopyToClipboardModule } from 'src/app/directives/copy-to-clipboard/copy-to-clipboard.module';
@@ -35,13 +36,12 @@ import { WarnDialogModule } from 'src/app/modules/warn-dialog/warn-dialog.module
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
import { MatSelectModule } from '@angular/material/select';
import { QRCodeModule } from 'angularx-qrcode';
import { InfoDialogModule } from 'src/app/modules/info-dialog/info-dialog.module';
import { MetadataModule } from 'src/app/modules/metadata/metadata.module';
import { CountryCallingCodesService } from 'src/app/services/country-calling-codes.service';
import { InfoRowModule } from '../../../modules/info-row/info-row.module';
import { InfoRowModule } from 'src/app/modules/info-row/info-row.module';
import { TypeSafeCellDefModule } from 'src/app/directives/type-safe-cell-def/type-safe-cell-def.module';
import { AuthFactorDialogComponent } from './auth-user-detail/auth-factor-dialog/auth-factor-dialog.component';
import { AuthPasswordlessComponent } from './auth-user-detail/auth-passwordless/auth-passwordless.component';
import { DialogPasswordlessComponent } from './auth-user-detail/auth-passwordless/dialog-passwordless/dialog-passwordless.component';
@@ -128,6 +128,7 @@ import { UserMfaComponent } from './user-detail/user-mfa/user-mfa.component';
MachineKeysModule,
InfoSectionModule,
MatSelectModule,
TypeSafeCellDefModule,
],
})
export class UserDetailModule {}