class-validator icon indicating copy to clipboard operation
class-validator copied to clipboard

@matches with my regex shows true sometimes while false sometimes

Open rubiin opened this issue 5 years ago • 14 comments

I am using class-validator with nestjs. I have a password field like this:

  @Matches(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).{6,64}$/gm, {
    message:
      'Password must be between 6 and 64 characters long with 1 special character and capital character each',
  })

but sometimes the password passes this while sometimes it doesnt

rubiin avatar Dec 06 '19 07:12 rubiin

@vlapo also when is the release of next version. I like to use the uuid fix

rubiin avatar Dec 06 '19 07:12 rubiin

I've also encountered this with @Matches.

Here's my user class:

import {
  IsEmail,
  Matches,
  IsOptional,
  IsPhoneNumber,
  IsDefined,
  validateSync
} from "class-validator";

export class User {
  @IsDefined()
  @IsEmail()
  public email: string;

  @IsDefined()
  @Matches(/[a-zA-Z0-9_-]{2,20}/)
  public username: string;

  @IsDefined()
  @Matches(/^\$2[ayb]\$[\d]{2}\$[./A-Za-z0-9]{53}$/)
  private _password: string;

  @IsOptional()
  @IsPhoneNumber(null)
  public phoneNumber?: string;

  constructor(
    email: string,
    username: string,
    password: string,
    phoneNumber?: string
  ) {
    this.email = email;
    this.username = username;
    this.password = password;
    if (phoneNumber) {
      this.phoneNumber = phoneNumber;
    }
  }
}

The test I've run:

console.log(
  validateSync(
    new User(
      "[email protected]",
      "I'm way too long to be a username, much too long",
      "$2y$12$E6I8o3kUs8CsSs0WnyYiGOmBeVxfhvaEbxPGgJ334jfpB//gEwFYO"
    )
  )
);

This yields no errors: []

EDIT: My RegEx was wrong. Adding ^ at the beginning and $ at the end fixed it.

yardenshoham avatar Dec 23 '19 15:12 yardenshoham

Same here

I'm trying to use class validator for validating my inputtype in type-graphql but the @matches decorator, is not working, All other decorators with suffix 'Is' are working, but not this one.

``

const mobileNumberRegex = /^(\+[0-9]{1,3}[- ]?)?[0-9]{9,10}$/;

@Field()
@Matches(mobileNumberRegex)
mobileNumber!: string;

`` I'm expecting error when the mobile number is not matching, but it's not there. Validate method also doesn't pass as expected

insanebaba avatar Jan 01 '20 10:01 insanebaba

@insanebaba

Same here

I'm trying to use class validator for validating my inputtype in type-graphql but the @matches decorator, is not working, All other decorators with suffix 'Is' are working, but not this one.

``

const mobileNumberRegex = /^(\+[0-9]{1,3}[- ]?)?[0-9]{9,10}$/;

@Field()
@Matches(mobileNumberRegex)
mobileNumber!: string;

`` I'm expecting error when the mobile number is not matching, but it's not there. Validate method also doesn't pass as expected

For your use case I'd recommend the @IsPhoneNumber(null) decorator.

yardenshoham avatar Jan 01 '20 10:01 yardenshoham

@insanebaba

Same here I'm trying to use class validator for validating my inputtype in type-graphql but the @matches decorator, is not working, All other decorators with suffix 'Is' are working, but not this one. ``

const mobileNumberRegex = /^(\+[0-9]{1,3}[- ]?)?[0-9]{9,10}$/;

@Field()
@Matches(mobileNumberRegex)
mobileNumber!: string;

`` I'm expecting error when the mobile number is not matching, but it's not there. Validate method also doesn't pass as expected

For your use case I'd recommend the @IsPhoneNumber(null) decorator.

Thanks for suggestion, @IsPhoneNumber(null) works, but I want to have more control over the pattern.

I solved my issue by stepping down to version 0.10.2

Thank you everyone, I hope this issue gets addressed in later versions.

insanebaba avatar Jan 01 '20 14:01 insanebaba

@vlapo do you know how can i resolve this

rubiin avatar Jan 23 '20 15:01 rubiin

@rubiin Please provide an example of an input that fails.

yardenshoham avatar Jan 23 '20 16:01 yardenshoham

Facing the same issue with class-validator package version 0.11.0

import {  IsArray,  IsOptional,  Matches } from 'class-validator';

export class MyDto {
  @IsArray()
  @IsOptional()
  @Matches( /^[\w .,-]+$/gi, { each: true })
  readonly rangeFilters?: string[];
}

values that pass only each second time: price, price.amountToPay,500,600

        {
            "target": {
                "rangeFilters": [
                    "price.amountToPay,500,600"
                ]
            },
            "value": [
                "price.amountToPay,500,600"
            ],
            "property": "rangeFilters",
            "children": [],
            "constraints": {
                "matches": "each value in rangeFilters must match /^[\\w .,-]+$/gi regular expression"
            }
        }

windok avatar Feb 28 '20 16:02 windok

@windok , @rubiin Please read the following thread on the use of g flag. It makes the regex object stateful, which explains this bug.

I guess you'll have to avoid that flag to fix the issue.

https://stackoverflow.com/questions/6739136/consecutive-calls-to-regexp-test-fail-for-pattern-with-global-option

aozisik avatar Mar 06 '20 15:03 aozisik

@rubiin Did you resolve your issue?

vlapo avatar Mar 16 '20 20:03 vlapo

I have the same problem

@IsString()
 @MinLength(8)
 @MaxLength(20)
 @Matches(/((?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[@$!%*?&])[A-Za-z0-9@$!%*?&]+)+/g)
 password: string;

response sometime true, sometime false with same request

DUDY206 avatar Sep 15 '21 03:09 DUDY206

I have the same problem

@IsString()
 @MinLength(8)
 @MaxLength(20)
 @Matches(/((?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[@$!%*?&])[A-Za-z0-9@$!%*?&]+)+/g)
 password: string;

@Matches('^09[0-9]{9}',"",{"message":"phone is incorrect"}) phone: string;

after regex pattern we need pass empty string and third argument be our message

kazemimorteza68 avatar Jan 22 '22 12:01 kazemimorteza68

Hm, issue opened from 2019. Got the same issue.

https://user-images.githubusercontent.com/3227120/174649929-ee1309d6-f427-4702-9721-880fdd4228c8.mp4

IMAGE 2022-06-20 20:03:58

I fixed it by removing /g flag from regular expression

bezenson avatar Jun 20 '22 17:06 bezenson

Got the same issue I want to validate time format '/^(?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$/' but it fails on 08:30

ibrahimwithi avatar Jun 29 '22 07:06 ibrahimwithi

Hm, issue opened from 2019. Got the same issue.

wtf.mp4 IMAGE 2022-06-20 20:03:58

I fixed it by removing /g flag from regular expression

Thank you! It worked for me.

lublot avatar Nov 11 '22 18:11 lublot

As @aozisik explained correctly this is how the g flag works with Regexes. From MDN - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test:

JavaScript RegExp objects are stateful when they have the global or sticky flags set (e.g., /foo/g or /foo/y). They store a lastIndex from the previous match. Using this internally, test() can be used to iterate over multiple matches in a string of text (with capture groups).

Closing this as there is no action to take from our side.

NoNameProvided avatar Dec 16 '22 00:12 NoNameProvided

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

github-actions[bot] avatar Jan 16 '23 00:01 github-actions[bot]