feat: MFA/2FA, OTP audit logs, KYC + client/user enhancements
- Access Control module: SMS/Email/TOTP/Hardware-token MFA factor management - OTP Audit Logs module under Admin menu (list + detail) with 401/403 handling - Two-factor authentication login flow updates - Client KYC, India address, family-members, ckyc, nominee enhancements - New shared KYC helpers (kyc-proof-types, kyc-upload-helper.service) - User create/edit/view enhancements - Shell navigation: OTP Audit Logs entry under real Admin menu
This commit is contained in:
@@ -43,6 +43,7 @@ import { TenantSelectorComponent } from '../shared/tenant-selector/tenant-select
|
||||
import { LoginFormComponent } from './login-form/login-form.component';
|
||||
import { ResetPasswordComponent } from './reset-password/reset-password.component';
|
||||
import { TwoFactorAuthenticationComponent } from './two-factor-authentication/two-factor-authentication.component';
|
||||
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||
import { MatMenuTrigger, MatMenu, MatMenuItem } from '@angular/material/menu';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
@@ -216,6 +217,8 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
private alertService = inject(AlertService);
|
||||
private settingsService = inject(SettingsService);
|
||||
private themingService = inject(ThemingService);
|
||||
private dialog = inject(MatDialog);
|
||||
private twoFactorDialogRef: MatDialogRef<TwoFactorAuthenticationComponent> | null = null;
|
||||
private router = inject(Router);
|
||||
|
||||
private versionService = inject(VersionService);
|
||||
@@ -270,13 +273,16 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
const alertType = alertEvent.type;
|
||||
if (alertType === 'Password Expired') {
|
||||
this.twoFactorAuthenticationRequired = false;
|
||||
this.closeTwoFactorDialog();
|
||||
this.resetPassword = true;
|
||||
} else if (alertType === 'Two Factor Authentication Required') {
|
||||
this.resetPassword = false;
|
||||
this.twoFactorAuthenticationRequired = true;
|
||||
this.openTwoFactorDialog();
|
||||
} else if (alertType === 'Authentication Success') {
|
||||
this.resetPassword = false;
|
||||
this.twoFactorAuthenticationRequired = false;
|
||||
this.closeTwoFactorDialog();
|
||||
this.router.navigate(['/'], { replaceUrl: true });
|
||||
} else if (alertType === 'Tenant Changed') {
|
||||
this.updateLogo();
|
||||
@@ -323,9 +329,34 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
if (this.theme$) {
|
||||
this.theme$.unsubscribe();
|
||||
}
|
||||
this.closeTwoFactorDialog();
|
||||
clearInterval(this.slideTimer);
|
||||
}
|
||||
|
||||
/** Open the 2FA challenge as a non-dismissable modal */
|
||||
private openTwoFactorDialog(): void {
|
||||
if (this.twoFactorDialogRef) return;
|
||||
this.twoFactorDialogRef = this.dialog.open(TwoFactorAuthenticationComponent, {
|
||||
width: '440px',
|
||||
maxWidth: '95vw',
|
||||
panelClass: 'tfa-dialog-panel',
|
||||
backdropClass: 'tfa-dialog-backdrop',
|
||||
disableClose: true,
|
||||
autoFocus: 'first-tabbable',
|
||||
restoreFocus: true
|
||||
});
|
||||
this.twoFactorDialogRef.afterClosed().subscribe(() => {
|
||||
this.twoFactorDialogRef = null;
|
||||
});
|
||||
}
|
||||
|
||||
private closeTwoFactorDialog(): void {
|
||||
if (this.twoFactorDialogRef) {
|
||||
this.twoFactorDialogRef.close();
|
||||
this.twoFactorDialogRef = null;
|
||||
}
|
||||
}
|
||||
|
||||
goToSlide(index: number): void {
|
||||
this.currentSlide = index;
|
||||
this.restartSlider();
|
||||
|
||||
Reference in New Issue
Block a user