I am registering a user I need a name
, email
and a password
.
When there is no name
given the backend does not need to check if the email is valid.
To my knowledge this is where the .bail()
functionality comes in of the express-validator
. This functionality unfortunately does nothing in my case all validations run anyway.
The route: app.post('/register', validate(createUserSchema), createUser)
;
The validate()
function:
export const validate = (schemas: ValidationChain[]) => async (req: Request, res: Response, next: NextFunction) => {
await Promise.all(schemas.map(async (schema) => await schema.run(req)));
const result = validationResult(req);
if (result.isEmpty()) {
return next();
}
const errors = result.array();
return res.status(422).json(errors);
};
The createUserSchema
:
export const createUserSchema = [
body('name', 'Name is required').notEmpty().bail(),
body('email', 'Email is required').notEmpty().bail(),
body('email').isEmail().withMessage('Email is not valid').bail(),
body('email')
.custom((value) => {
if (!value) return true;
return prisma.user
.findUnique({
where: {
email: value
}
})
.then(async (user) => {
if (user) {
return await Promise.reject(new Error('E-mail already in use'));
}
return await Promise.resolve();
});
}).bail(),
body('password', 'Password is required').notEmpty().bail()
.isLength({min: 6}).withMessage('Password must be longer than 6 characters')
.matches(/[A-Z]/).withMessage('Password does not contain an uppercase character')
.matches(/\W/).withMessage('Password does not contain any non-word characters')
];
my request payload:
{
name: "",
email: "",
password: ""
}
The response I get:
[
{
"value":"",
"msg":"Name is required",
"param":"name",
"location":"body"
},
{
"value":"",
"msg":"Email is required",
"param":"email",
"location":"body"
},
{
"value":"",
"msg":"Email is not valid",
"param":"email",
"location":"body"
},
{
"value":"",
"msg":"Password is required",
"param":"password",
"location":"body"
}
]
The response I expect (because it should bail on the first validation):
[
{
"value":"",
"msg":"Name is required",
"param":"name",
"location":"body"
}
]
Am I doing something wrong?
Here to answer my own question -_-
So I misunderstood what a Validation Chain
is in express-validator
.
I was under the impression that different validations rows formed one validation chain (so an array woud form a chain). This is not the case. A chain is formed by the separate validation rules.
For example
export const createUserSchema = [
body('name').notEmpty().withMessage('Name is required').bail(), //<--- this is a validation chain
body('email').notEmpty().withMessage('Email is required').bail()
.isEmail().withMessage('Email is not valid').bail()
]; // <--- The whole array does not form a chain (which is what I thought)
Gustavo Henke explained it here.
So to achieve what I want I needed to use the .if(condition)
validation.