Password confirmation in TypeScript with `class-validator`

Issue

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?

Solution

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;
    }

}

Answered By – Piero Macaluso

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published