2

I have a function which validates a password.

CustomValidators.patternValidator(/[A-Z]{2,}/, {
              hasCapitalCase: true
 }),

right now it is hard coded to 2 upper Case letters but I would like to load the password requirments based on a user profile via variables in my case it would be this.paswdProfile.upperCase but if I replace the 2 with the variable it no longer works. Here is my CustomValidator Code

export class CustomValidators {
static patternValidator(regex: RegExp, error: ValidationErrors): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
  if (!control.value) {
    // if control is empty return no error
    return null;
  }

  // test the value of the control against the regexp supplied
  const valid = regex.test(control.value);

  // if true, return no error (no error), else return error passed in the second parameter
  return valid ? null : error;
};
}

here is how i use it

paswdProfile = {minChar: 10, numbers: 2, upperCase: 4, lowerCase: 3, specialChar: 2}

 CustomValidators.patternValidator(/[A-Z]{ paswdProfile.upperCase ,}/, {
              hasCapitalCase: true
            }),

i know that i can access the value because in my template i print

Must contain at least {{ paswdProfile.upperCase }} in Capital Case!

and that shows correct value

9
  • when you arre going to update the number , and how you get the value of this.paswdProfile.upperCase Commented Jan 3, 2020 at 0:30
  • can you share the formgroup code and put the code with point wherer it start not working Commented Jan 3, 2020 at 0:31
  • for now i use just some static nbrs like this paswdProfile = {minChar: 10, numbers: 2, upperCase: 4, lowerCase: 3, specialChar: 2} Commented Jan 3, 2020 at 0:32
  • is it working when u have static values? Commented Jan 3, 2020 at 1:25
  • 1
    when i use CustomValidators.patternValidator(new RegExp([A-Z]{ 4 ,}), { it doesnt work either Commented Jan 3, 2020 at 1:27

2 Answers 2

2

you can create a regex pattern to test number of lower case , upper with spical characters but this will consider as a pattern and it's hard for the user to know that he must enter 4 of more lower or upper and I 'm not expert regex 😶 so my idea is to create a validation funtion test the value and base of the test I will give to the user different validation messages.

interface PasswordProfile {
  upperCase: number;
  lowerCase: number;
  numbers: number;
  minChar: number;
  specialChar: number;
}
export class CustomValidators {
  static passwordValidator(passwordProfile: PasswordProfile): ValidatorFn {

    function patternTest(value, pattern: RegExp): string[] {
      return (value.match(pattern) || []).length;
    }

    return (control: AbstractControl): { [key: string]: any } => {
      if (!control.value) {
        return null;
      }
      const value: string = control.value;

      if ((value.match(/[A-Z]/g) || []).length < passwordProfile.upperCase) {
        return {
          passwordStrength: {
            message: `the password must containe ${
              passwordProfile.upperCase
            } upper case`
          }
        };
      }

      if (patternTest(value, /[a-z]/g).length < passwordProfile.lowerCase) {
        return {
          passwordStrength: {
            message: `the password must containe ${
              passwordProfile.lowerCase
            } lowercase case`
          }
        };
      }

      if (patternTest(value, /[0-9]/g).length < passwordProfile.numbers) {
        return {
          passwordStrength: {
            message: `the password must containe ${
              passwordProfile.numbers
            } numbers`
          }
        };
      }

      if (
        patternTest(value, /[!@#\$%\^&]/g).length < passwordProfile.specialChar
      ) {
        return {
          passwordStrength: {
            message: `the password must containe ${
              passwordProfile.specialChar
            } specialChar`
          }
        };
      }

      return null;
    };
  }
}

demo 🚀🚀

Sign up to request clarification or add additional context in comments.

Comments

1

Based om Muhammed's answer i was able to come up wit a bit more flexible solution. This way the patternValidator just checks how often the pattern is matched and if the number is equal or bigger then the number in required password profile. Also with leaving all the validation patterns in the Form Group its cleaner and more flexible as well.

  static patternValidator(regex: RegExp, requiredTimes: number, error: ValidationErrors): ValidatorFn {
    return (control: AbstractControl): { [key: string]: any } => {
      if (!control.value) {
        // if control is empty return no error
        return null;
      }
      const value: string = control.value;
       // test the value of the control against the regexp supplied
      const valid =  ((value.match(regex) || []).length >= requiredTimes)
      // if true, return no error (no error), else return error passed in the second parameter
      return valid ? null : error;
    };
  } 

    newPassword: [
      null,
      Validators.compose([
        Validators.required,
        // check whether the entered password has a number
        CustomValidators.patternValidator(/\d/g, this.paswdProfile.numbers , {
          hasNumber: true
        }),
        // check whether the entered password has upper case letter
        CustomValidators.patternValidator(/[A-Z]/g, this.paswdProfile.uperCase, {
          hasCapitalCase: true
        }),
        // check whether the entered password has a lower case letter
        CustomValidators.patternValidator(/[a-z]/g, this.paswdProfile.lowerCase,  {
          hasSmallCase: true
        }),
        // check whether the entered password has a special character
        CustomValidators.patternValidator(
          /[ !@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/g, this.paswdProfile.specialChar ,
          {
            hasSpecialCharacters: true
          }
        ),
        Validators.minLength(this.paswdProfile.minChar)
      ])
    ],

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.