From 654c887f0e3ce9264c8fb36f27bb4b5bc0db6b55 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Thu, 7 Dec 2023 12:52:13 +0200 Subject: [PATCH] UI: Add max password length with validation --- .../admin/security-settings.component.html | 59 ++++++++++++------- .../admin/security-settings.component.ts | 27 ++++++++- .../pages/security/security.component.html | 7 +++ .../home/pages/security/security.component.ts | 5 ++ .../src/app/shared/models/settings.models.ts | 2 + .../assets/locale/locale.constant-en_US.json | 9 ++- 6 files changed, 83 insertions(+), 26 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html index ef29248767..f49b2b25e8 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html +++ b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html @@ -51,24 +51,36 @@
admin.password-policy
- - admin.minimum-password-length - - - {{ 'admin.minimum-password-length-required' | translate }} - - - {{ 'admin.minimum-password-length-range' | translate }} - - - {{ 'admin.minimum-password-length-range' | translate }} - - +
+ + admin.minimum-password-length + + + {{ 'admin.minimum-password-length-required' | translate }} + + + {{ 'admin.minimum-password-length-range' | translate }} + + + {{ 'admin.minimum-password-length-range' | translate }} + + + + admin.maximum-password-length + + + {{ 'admin.maximum-password-length-min' | translate }} + + + {{ 'admin.maximum-password-length-less-min' | translate }} + + +
admin.minimum-uppercase-letters @@ -140,9 +152,14 @@
- - admin.allow-whitespace - +
+ + admin.allow-whitespace + + + admin.force-reset-password-if-no-valid + +
diff --git a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts index cdaf0747af..9e969bf8e0 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts @@ -19,7 +19,14 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { PageComponent } from '@shared/components/page.component'; import { Router } from '@angular/router'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; +import { + AbstractControl, + UntypedFormBuilder, + UntypedFormControl, + UntypedFormGroup, ValidationErrors, + ValidatorFn, + Validators +} from '@angular/forms'; import { JwtSettings, SecuritySettings } from '@shared/models/settings.models'; import { AdminService } from '@core/http/admin.service'; import { HasConfirmForm } from '@core/guards/confirm-on-exit.guard'; @@ -67,14 +74,16 @@ export class SecuritySettingsComponent extends PageComponent implements HasConfi userLockoutNotificationEmail: ['', []], passwordPolicy: this.fb.group( { - minimumLength: [null, [Validators.required, Validators.min(5), Validators.max(50)]], + minimumLength: [null, [Validators.required, Validators.min(6), Validators.max(50)]], + maximumLength: [null, [Validators.min(6), this.maxPasswordValidation()]], minimumUppercaseLetters: [null, Validators.min(0)], minimumLowercaseLetters: [null, Validators.min(0)], minimumDigits: [null, Validators.min(0)], minimumSpecialCharacters: [null, Validators.min(0)], passwordExpirationPeriodDays: [null, Validators.min(0)], passwordReuseFrequencyDays: [null, Validators.min(0)], - allowWhitespaces: [true] + allowWhitespaces: [true], + forceUserToResetPasswordIfNotValid: [false] } ) }); @@ -113,6 +122,18 @@ export class SecuritySettingsComponent extends PageComponent implements HasConfi })).subscribe(() => {}); } + private maxPasswordValidation(): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + const value: string = control.value; + if (value) { + if (value < this.securitySettingsFormGroup.get('passwordPolicy.minimumLength').value) { + return {lessMin: true}; + } + } + return null; + }; + } + discardSetting() { this.securitySettingsFormGroup.reset(this.securitySettings); } diff --git a/ui-ngx/src/app/modules/home/pages/security/security.component.html b/ui-ngx/src/app/modules/home/pages/security/security.component.html index 45460e086d..9d40e0786b 100644 --- a/ui-ngx/src/app/modules/home/pages/security/security.component.html +++ b/ui-ngx/src/app/modules/home/pages/security/security.component.html @@ -105,6 +105,13 @@ {{ 'security.password-requirement.character' | translate : {count: passwordPolicy.minimumLength} }}

+
+

security.password-requirement.at-most

+

+ + {{ 'security.password-requirement.character' | translate : {count: passwordPolicy.maximumLength} }} +

+
diff --git a/ui-ngx/src/app/modules/home/pages/security/security.component.ts b/ui-ngx/src/app/modules/home/pages/security/security.component.ts index 9a99e7d6d4..d79a6c59b4 100644 --- a/ui-ngx/src/app/modules/home/pages/security/security.component.ts +++ b/ui-ngx/src/app/modules/home/pages/security/security.component.ts @@ -213,6 +213,11 @@ export class SecurityComponent extends PageComponent implements OnInit, OnDestro errors.minLength = true; } + if (this.passwordPolicy?.maximumLength > 0 && + (value.length > this.passwordPolicy?.maximumLength || value.length < this.passwordPolicy.minimumLength)) { + errors.maxLength = true; + } + return isEqual(errors, {}) ? null : errors; }; } diff --git a/ui-ngx/src/app/shared/models/settings.models.ts b/ui-ngx/src/app/shared/models/settings.models.ts index 9238dae197..9dd599d49b 100644 --- a/ui-ngx/src/app/shared/models/settings.models.ts +++ b/ui-ngx/src/app/shared/models/settings.models.ts @@ -99,12 +99,14 @@ export type DeviceConnectivitySettings = Record