How to check if the incoming request value is unique or not with the help of Joi
package.
exports.createUser = {
body: Joi.object().keys({
email: Joi.string().required().email(),
password: Joi.string().required().custom(password),
phoneNumber: Joi.string().min(10).required(),
}),
};
Here I want to check if email is unique or not. I am aware that I can do this in the mongoose(Schema) but I want to do it with joi package.
The API endpoint:
router
.route("/register")
.post(validate(userValidation.createUser), User.register);
The register controller:
exports.register = catchAsync(async (req, res) => {
try {
var isValidated = await userService.validateInDatabase(req);
if (!isValidated)
return res
.status(409)
.json({ error: "Phone number or email is already registered" });
var user = await userService.create(req.body);
var token = await sendVerification(user);
return res.status(201).json({ user, token });
} catch (error) {
return res.status(400).json({ message: error });
}
});
I have a function called validateInDatabase but I do not want to use it.
The userService.create service function:
exports.create = async (user) => {
const hashedPassword = passwordHash.generate(user.password);
let new_user = new User({
phoneNumber: user.phoneNumber,
email: user.email,
password: hashedPassword,
});
const payload = {
id: new_user._id,
};
let JWToken = jwt.sign(payload, keys.JWToken, { expiresIn: 31556926 });
const userData = await new_user.save();
return { userData, JWToken };
};
The validate function:
const validate = (schema) => (req, res, next) => {
const validSchema = pick(schema, ["params", "query", "body"]);
const object = pick(req, Object.keys(validSchema));
const { value, error } = Joi.compile(validSchema)
.prefs({ errors: { label: "key" }, abortEarly: false })
.validate(object);
if (error) {
const errorMessage = error.details
.map((details) => details.message)
.join(", ");
return res.status(400).json({ error: errorMessage });
}
Object.assign(req, value);
return next();
};
CodePudding user response:
You can use custom
(for sync) or external
validation(for async) and check the email into the database.
Something like this:
exports.createUser = {
body: Joi.object().keys({
email: Joi.string().required().email().external(async (email) => {
// You have to create `checkEmailInUse` funciton somewhere in your code and call it here
const isEmailInUse = await checkEmailInUse(email);
if(isEmailInUse) {
throw new Error('email in use');
}
return email;
}),
password: Joi.string().required().custom(password),
phoneNumber: Joi.string().min(10).required(),
}),
};
and here use validateAsync
instead of validate
const validate = (schema) => (req, res, next) => {
const validSchema = pick(schema, ["params", "query", "body"]);
const object = pick(req, Object.keys(validSchema));
try {
const value = await Joi.compile(validSchema)
.prefs({ errors: { label: "key" }, abortEarly: false })
.validateAsync(object);
Object.assign(req, value);
return next();
}
catch(error) {
const errorMessage = error.details
.map((details) => details.message)
.join(", ");
return res.status(400).json({ error: errorMessage });
}
};