Is there a way to do this using Joi?
For example:
Joi.string()
.required()
.min(8)
.max(16)
.pattern(/(?=(?:.*[a-z]){2,16}).+/)
.pattern(/(?=(?:.*[A-Z]){2,16}).+/)
.pattern(/(?=(?:.*[0-9]){2,16}).+/)
.pattern(/(?=(?:.*[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]){2,16}).+/)
.messages({
'string.base': 'Username must be of type string',
'string.regex': 'Username must contain at least two lower-case letters',
'string.regex2': 'Username must contain at least two upper-case letters',
'string.regex3': 'Username must contain at least two numbers',
'string.regex4': 'Username must contain at least two special characters',
'string.min': 'Username must be at least 8 characters long',
'string.max': 'Username must be no more than 16 characters long',
'string.empty': 'Username is a required field',
}),
})
});
The only problem I seem to be running into is getting back a good error message for the regular expressions. What should the keys be for messages? I would also like to see all failed validations, not just the first one that fails? Is there a better approach to this?
const passwordSchema: ObjectSchema = Joi.object().keys({
password: Joi.string()
.min(8)
.max(16)
.pattern(/(?=(?:.*[a-z]){2,16}).+/, 'lowercase')
.pattern(/(?=(?:.*[A-Z]){2,16}).+/, 'uppercase')
.pattern(/(?=(?:.*[0-9]){2,16}).+/, 'number')
.pattern(/(?=(?:.*[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]){2,16}).+/, 'special')
.required()
.error((errors) => {
errors.forEach((err) => {
switch (err.code) {
case 'string.base':
case 'string.empty':
case 'any.required':
default:
err.message = defaultErrorMessage;
break;
case 'string.min':
err.message = minLengthMessage;
break;
case 'string.max':
err.message = maxLengthMessage;
break;
case 'string.pattern.name':
switch (err.local.name) {
case 'lowercase':
err.message = 'must contain at least two lower-case letters';
break;
case 'uppercase':
err.message = 'must contain at least two lower-case letters';
break;
case 'number':
err.message = 'must contain at least two numbers';
break;
case 'special':
err.message = 'must contain at least two special characters';
break;
}
break;
}
});
return errors;
}),
Then to get all messages:
passwordSchema.validate(data, { abortEarly: false });