Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Password confirmation in TypeScript with `class-validator`

Tags:

Today, I am trying to figure out how to validate a Sign Up form in the backend side (NestJS) of the app. I am just wondering if exists a way to validate password and passwordConfirm matching, using class-validator package to build up a custom validator or exploit provided ones. I am thinking about a class validator, not a field one.

// Maybe validator here export class SignUpDto {     @IsString()     @MinLength(4)     @MaxLength(20)     username: string;      @IsString()     @MinLength(4)     @MaxLength(20)     @Matches(/((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/, {message: 'password too weak'})     password: string;      @IsString()     @MinLength(4)     @MaxLength(20)     passwordConfirm: string; } 

What do you suggest?

like image 553
Piero Macaluso Avatar asked Feb 28 '20 12:02

Piero Macaluso


1 Answers

Finally I managed to solve the password matching problem thanks to the suggestion of @ChristopheGeers in the comments of my question:

@piero: It's not supported yet as mentioned. But here's an example decorator (@IsLongerThan): LINK .... it checks if a property is longer than another one. So it's possible to compare one property against another. You can use this example to create a decorator that does what you want.

Here it is the solution I propose:

sign-up.dto.ts

export class SignUpDto {     @IsString()     @MinLength(4)     @MaxLength(20)     username: string;      @IsString()     @MinLength(4)     @MaxLength(20)     @Matches(/((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/, {message: 'password too weak'})     password: string;      @IsString()     @MinLength(4)     @MaxLength(20)     @Match('password')     passwordConfirm: string; } 

match.decorator.ts

import {registerDecorator, ValidationArguments, ValidationOptions, ValidatorConstraint, ValidatorConstraintInterface} from 'class-validator';  export function Match(property: string, validationOptions?: ValidationOptions) {     return (object: any, propertyName: string) => {         registerDecorator({             target: object.constructor,             propertyName,             options: validationOptions,             constraints: [property],             validator: MatchConstraint,         });     }; }  @ValidatorConstraint({name: 'Match'}) export class MatchConstraint implements ValidatorConstraintInterface {      validate(value: any, args: ValidationArguments) {         const [relatedPropertyName] = args.constraints;         const relatedValue = (args.object as any)[relatedPropertyName];         return value === relatedValue;     }  } 
like image 115
Piero Macaluso Avatar answered Sep 20 '22 15:09

Piero Macaluso