diff --git a/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts b/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts index 463a7b01dc..65b759a21e 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts @@ -13,4 +13,8 @@ export const DEFAULT_VALIDATION_BLUEPRINTS = { range: 'AbpValidation::ThisFieldMustBeBetween{0}And{1}[{{ min }},{{ max }}]', required: 'AbpValidation::ThisFieldIsRequired.', url: 'AbpValidation::ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl', + passwordRequiresLower: 'AbpIdentity::Volo.Abp.Identity:PasswordRequiresLower', + passwordRequiresUpper: 'AbpIdentity::Volo.Abp.Identity:PasswordRequiresUpper', + passwordRequiresDigit: 'AbpIdentity::Volo.Abp.Identity:PasswordRequiresDigit', + passwordRequiresNonAlphanumeric: 'AbpIdentity::Volo.Abp.Identity:PasswordRequiresNonAlphanumeric', }; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/utils/validation-utils.ts b/npm/ng-packs/packages/theme-shared/src/lib/utils/validation-utils.ts index a9ec1d4270..b7d8d23376 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/utils/validation-utils.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/utils/validation-utils.ts @@ -1,7 +1,7 @@ import { ABP, ConfigStateService } from '@abp/ng.core'; import { Injector } from '@angular/core'; -import { ValidatorFn, Validators } from '@angular/forms'; -import { PasswordRules, validatePassword } from '@ngx-validate/core'; +import { AbstractControl, ValidatorFn, Validators } from '@angular/forms'; +import { PasswordRules, normalizeDiacritics } from '@ngx-validate/core'; const { minLength, maxLength } = Validators; @@ -31,7 +31,8 @@ export function getPasswordValidators(injector: Injector): ValidatorFn[] { requiredLength = +getRule('RequiredLength'); } - return [validatePassword(passwordRulesArr), minLength(requiredLength), maxLength(128)]; + const passwordValidators = passwordRulesArr.map(rule => validatePassword(rule)); + return [...passwordValidators, minLength(requiredLength), maxLength(128)]; } function getRuleFn(injector: Injector) { @@ -43,3 +44,37 @@ function getRuleFn(injector: Injector) { return (passwordRules[`Abp.Identity.Password.${key}`] || '').toLowerCase(); }; } +const errorMessageMap = { + small: 'passwordRequiresLower', + capital: 'passwordRequiresUpper', + number: 'passwordRequiresDigit', + special: 'passwordRequiresNonAlphanumeric', +}; + +function validatePassword(shouldContain: 'small' | 'capital' | 'number' | 'special'): ValidatorFn { + return (control: AbstractControl) => { + if (!control.value) return null; + + const value = normalizeDiacritics(control.value); + + const regexMap = { + small: /.*[a-z].*/, + capital: /.*[A-Z].*/, + number: /.*[0-9].*/, + special: /.*[^0-9a-zA-Z].*/, + }; + const regex = regexMap[shouldContain]; + + const hasError = regex[shouldContain].test(value); + + if (!hasError) { + return null; + } + + const error = errorMessageMap[shouldContain]; + + return { + [error]: true, + }; + }; +}