feat(users): OTP delivery method picker on user creation + post-login agreement
build-run / Run Lint, Build and Deploy (push) Canceled after 0s
Publish Image in Docker Hub / build (push) Canceled after 0s
Playwright E2E Tests / Run Playwright Tests (push) Canceled after 0s
Tests / testRigor (push) Canceled after 0s

Create User dialog now has a mandatory Email/Mobile OTP delivery method
picker (styled as a pill toggle) alongside the existing fields.

Adds a new post-login agreement acceptance dialog: right after the existing
2FA flow (TwoFactorAuthenticationComponent) succeeds, or immediately after
login for users without 2FA, the user must accept the bank's current
agreement/disclaimer at least once before reaching the app.

Also adds a "Manage User Agreement" admin screen (System section) to publish
versioned agreement text without a code deploy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-24 16:20:46 +05:30
co-authored by Claude Sonnet 5
parent d0536dbb11
commit d334dd1669
18 changed files with 1356 additions and 16 deletions
@@ -124,6 +124,19 @@
<mat-error>Enter a valid <strong>10-digit mobile number</strong></mat-error>
}
</mat-form-field>
<div class="cu-checkbox-row cu-field--full">
<div>
<label class="cu-radio-label">OTP Delivery Method *</label>
<mat-radio-group formControlName="otpDeliveryMethod">
<mat-radio-button value="EMAIL">Email</mat-radio-button>
<mat-radio-button value="SMS">Mobile</mat-radio-button>
</mat-radio-group>
@if (userForm.controls.otpDeliveryMethod.hasError('required')) {
<mat-error>Choose how this user will receive their first-login OTP.</mat-error>
}
</div>
</div>
</div>
</div>
@@ -166,6 +166,14 @@ $gray-900: #202124;
}
}
.cu-radio-label {
display: block;
font-size: 12px;
font-weight: 500;
color: $gray-700;
margin-bottom: 6px;
}
.cu-error {
grid-column: 1 / -1;
color: #dc2626;
@@ -29,6 +29,7 @@ import { ConfigurationWizardService } from 'app/configuration-wizard/configurati
import { ContinueSetupDialogComponent } from 'app/configuration-wizard/continue-setup-dialog/continue-setup-dialog.component';
import { MatCheckbox } from '@angular/material/checkbox';
import { MatIcon } from '@angular/material/icon';
import { MatRadioGroup, MatRadioButton } from '@angular/material/radio';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
/**
@@ -41,7 +42,9 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
imports: [
...STANDALONE_SHARED_IMPORTS,
MatCheckbox,
MatIcon
MatIcon,
MatRadioGroup,
MatRadioButton
]
})
export class CreateUserComponent implements OnInit, AfterViewInit {
@@ -142,6 +145,10 @@ export class CreateUserComponent implements OnInit, AfterViewInit {
roles: [
'',
Validators.required
],
otpDeliveryMethod: [
'',
Validators.required
]
},
{ validator: confirmPasswordValidator }