feat: DSC enrollment + MFA controls, user CRUD UX, auth error hardening
- DSC module: list/enroll/revoke dialogs and dsc.service (m_bank_user_dsc API) - Access control: DSC + MFA toggles via disable-confirm-dialog - Two-factor auth: expanded UX (DSC + OTP flows) - Users: create/edit form polish, success snackbar on edit, DSC widget retained only inside dsc/ (removed from view-user) - Auth: X-Requested-With added globally; error handler null-safe on empty 500 bodies Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
3b752dc6ae
commit
09fab88451
@@ -0,0 +1,27 @@
|
||||
<!--
|
||||
Copyright since 2025 Mifos Initiative
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<h2 mat-dialog-title class="dcd-title">
|
||||
<fa-icon icon="ban" class="dcd-title__icon"></fa-icon>
|
||||
<span class="dcd-title__text">{{ data.title }}</span>
|
||||
</h2>
|
||||
|
||||
<mat-dialog-content class="dcd-content">
|
||||
<p class="dcd-msg">{{ data.message }}</p>
|
||||
@if (data.detail) {
|
||||
<p class="dcd-detail">{{ data.detail }}</p>
|
||||
}
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions align="end" class="dcd-actions">
|
||||
<button mat-stroked-button type="button" (click)="cancel()">Cancel</button>
|
||||
<button mat-flat-button color="warn" type="button" (click)="confirm()">
|
||||
<fa-icon icon="ban" class="dcd-btn-icon"></fa-icon>
|
||||
<span>Disable</span>
|
||||
</button>
|
||||
</mat-dialog-actions>
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright since 2025 Mifos Initiative
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
min-width: 380px;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.dcd-title {
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin: 0 !important;
|
||||
padding: 16px 24px 4px !important;
|
||||
font-size: 1.05rem !important;
|
||||
font-weight: 600 !important;
|
||||
color: #b91c1c !important;
|
||||
|
||||
&__icon {
|
||||
color: #dc2626;
|
||||
font-size: 18px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&__text {
|
||||
color: #b91c1c;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.dcd-content {
|
||||
padding: 8px 24px 16px !important;
|
||||
color: #334155 !important;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.dcd-msg {
|
||||
margin: 0 0 8px !important;
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.5;
|
||||
color: #334155;
|
||||
}
|
||||
|
||||
.dcd-detail {
|
||||
margin: 0 !important;
|
||||
font-size: 0.85rem;
|
||||
color: #64748b;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.dcd-actions {
|
||||
padding: 8px 20px 16px !important;
|
||||
gap: 8px;
|
||||
|
||||
button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.dcd-btn-icon {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright since 2025 Mifos Initiative
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { Component, inject } from '@angular/core';
|
||||
import {
|
||||
MAT_DIALOG_DATA,
|
||||
MatDialogRef,
|
||||
MatDialogTitle,
|
||||
MatDialogContent,
|
||||
MatDialogActions
|
||||
} from '@angular/material/dialog';
|
||||
import { MatButton } from '@angular/material/button';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
|
||||
export interface DisableConfirmDialogData {
|
||||
/** Heading shown at the top, e.g. "Disable SMS OTP". */
|
||||
title: string;
|
||||
/** Body paragraph explaining the impact. */
|
||||
message: string;
|
||||
/** Optional muted line shown below the message (the destination being disabled). */
|
||||
detail?: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-disable-confirm-dialog',
|
||||
templateUrl: './disable-confirm-dialog.component.html',
|
||||
styleUrls: ['./disable-confirm-dialog.component.scss'],
|
||||
imports: [
|
||||
MatDialogTitle,
|
||||
MatDialogContent,
|
||||
MatDialogActions,
|
||||
MatButton,
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class DisableConfirmDialogComponent {
|
||||
data = inject<DisableConfirmDialogData>(MAT_DIALOG_DATA);
|
||||
private dialogRef = inject<MatDialogRef<DisableConfirmDialogComponent>>(MatDialogRef);
|
||||
|
||||
cancel(): void {
|
||||
this.dialogRef.close({ confirmed: false });
|
||||
}
|
||||
|
||||
confirm(): void {
|
||||
this.dialogRef.close({ confirmed: true });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user