Skip to content

Instantly share code, notes, and snippets.

@unicornware
Last active May 13, 2021 14:47
Show Gist options
  • Save unicornware/5717b081d5f4ccf0817c494024de8865 to your computer and use it in GitHub Desktop.
Save unicornware/5717b081d5f4ccf0817c494024de8865 to your computer and use it in GitHub Desktop.
Custom Decorators - IsStrongPassword - https://github.com/typestack/class-validator
import type { ValidationArguments } from 'class-validator'
import merge from 'lodash.merge'
import TestSubject from '../is-strong-password.constraint'
/**
* @file Unit Tests - IsStrongPasswordConstraint
* @module constraints/tests/IsStrongPasswordConstraint
*/
describe('unit:constraints/IsStrongPasswordConstraint', () => {
const Subject = new TestSubject()
/**
* Returns a mock `ValidationArguments` object.
*
* @param {any} [value] - Value being validated
* @return {ValidationArguments} Mock `ValidationArguments` object
*/
const mockArgs = (value: any = null): ValidationArguments => {
const property = 'test'
const args_base: Partial<ValidationArguments> = {
constraints: [],
property,
targetName: 'Foo'
}
const args = merge({}, args_base, { object: { [property]: value }, value })
return args as ValidationArguments
}
describe('#defaultMessage', () => {
it('should return default error message', () => {
const expected = '$property is not strong enough; received null'
expect(Subject.defaultMessage(mockArgs())).toBe(expected)
})
})
describe('#validate', () => {
it('should return false if value is not strong password', () => {
const value = 'password'
expect(Subject.validate(value, mockArgs(value))).toBeFalsy()
})
it('should return true if value is strong password', () => {
const value = 'Strongpassword12345678!'
expect(Subject.validate(value, mockArgs(value))).toBeTruthy()
})
})
})
import type { ValidatorConstraintOptions } from '@flex-development/dreepo'
import type {
ValidationArguments,
ValidatorConstraintInterface as IConstraint
} from 'class-validator'
import { ValidatorConstraint as Constraint } from 'class-validator'
import isStrongPassword from 'validator/lib/isStrongPassword'
/**
* @file Constraints - IsStrongPasswordConstraint
* @module constraints/IsStrongPasswordConstraint
* @see https://github.com/typestack/class-validator#custom-validation-classes
*/
@Constraint(IsStrongPasswordConstraint.options)
export default class IsStrongPasswordConstraint implements IConstraint {
/**
* @static
* @readonly
* @property {ValidatorConstraintOptions} options - Custom constraint options
*/
static readonly options: ValidatorConstraintOptions = {
async: false,
name: 'isStrongPassword'
}
/**
* Returns the default error message if constraint validation fails.
*
* @param {ValidationArguments} args - Arguments sent to message builders
* @return {string} Default error message
*/
defaultMessage(args: ValidationArguments): string {
return `$property is not strong enough; received ${args.value}`
}
/**
* Returns `true` if {@param value} is a strong password.
*
* If defined, {@param args.constraints[0]} can be used to pass additional
* password validation options.
*
* @param {any} value - Value to test against constraint
* @param {ValidationArguments} args - Arguments sent to message builders
* @return {boolean} Boolean indicating value is strong password
*/
validate(value: any, args: ValidationArguments): boolean {
if (typeof value !== 'string') return false
return isStrongPassword(value, args.constraints[0])
}
}
import type { ValidateByOptions, ValidationOptions } from 'class-validator'
import { ValidateBy } from 'class-validator'
import type v from 'validator'
import validator from '../constraints/is-strong-password.constraint'
/**
* @file Decorator - IsStrongPassword
* @module decorators/IsStrongPassword
*/
/**
* Custom decorator that ensures a value is a [strong password][1].
*
* [1]: https://github.com/validatorjs/validator.js#validators
*
* @param {v.strongPasswordOptions} [options] - Strong password options
* @param {ValidationOptions} [validationOptions] - Validation options
* @return {PropertyDecorator} Property decorator
*/
const IsStrongPassword = (
options?: v.strongPasswordOptions,
validationOptions?: ValidationOptions
): PropertyDecorator => {
const validateByOptions: ValidateByOptions = {
async: validator.options?.async,
constraints: [options],
name: validator.options?.name as string,
validator
}
return ValidateBy(validateByOptions, validationOptions)
}
export default IsStrongPassword
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment