Home > Back-end >  Validate if user email already exists express validator
Validate if user email already exists express validator

Time:06-18

I have the following route setup in my node js api app:

const { body } = require("express-validator");
router.post(
  "/user/signup",
  [
    body("firstName").not().isEmpty().withMessage("First name is required"),
    body("lastName").not().isEmpty().withMessage("Last name is required"),
    body("email")
      .isEmail()
      .withMessage("Email is required")
      .custom((value, { req }) => {
        return User.findOne({ email: value }).then(userDoc => {
          if (userDoc) {
            return Promise.reject('E-Mail address already exists!');
          }
        });
      }),
    body("mobile").not().isEmpty().withMessage("Mobile is required"),
    body("password").not().isEmpty().withMessage("Password is required"),
    body("confirmPassword")
      .not()
      .isEmpty()
      .withMessage("Confirm password is required"),
  ],
  UserController.signup
);

signup method in UserController

const { validationResult } = require("express-validator");
exports.signup = async (req, res, next) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    const error = new Error('Validation failed.');
    error.statusCode = 422;
    error.data = errors.array();
    throw error;
  }
  const {
    firstName,
    lastName,
    email,
    mobile,
    password,
    confirmPassword
  } = req.body;

  try {
    if (password !== confirmPassword) {
      res
        .status(422)
        .json({ message: "Password and confirm password must be same" });
    }

    //save user and return response to front end
  } catch (err) {
    if (!err.statusCode) {
      err.statusCode = 500;
    }
    next(err);
  }
};

Code block at the end of app.js to catch error:

  /** Catch and return custom errors */
  app.use((error, req, res, next) => {
    const status = error.statusCode || 500;
    const message = error.message;
    const data = error.data;
    res.status(status).json({ message: message, data: data });
  });

In this route I'm checking if user has already registered with same email or not. If user has been registered with same email return error message.

Error message returned by server before crash:

/storage/node/Jeevan-Api/controllers/UserController.js:10

const error = new Error('Validation failed.');                  ^

Error: Validation failed.
    at exports.signup (/storage/node/Jeevan-Api/controllers/UserController.js:10:19)
    at Layer.handle [as handle_request] (/storage/node/Jeevan-Api/node_modules/express/lib/router/layer.js:95:5)
    at next (/storage/node/Jeevan-Api/node_modules/express/lib/router/route.js:144:13)
    at middleware (/storage/node/Jeevan-Api/node_modules/express-validator/src/middlewares/check.js:16:13)
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  statusCode: 422,
  data: [
    {
      value: '[email protected]',
      msg: 'E-Mail address already exists!',
      param: 'email',
      location: 'body'
    }
  ]
}
[nodemon] app crashed - waiting for file changes before starting...

The above code does the job but the server crashes after it returns the error message. This is happening in both local server and my development server.

How can I return validation message and

CodePudding user response:

You are throwing error which makes the app to stop processing to the next request or response / middleware. What you could do is doing next(error) so it will catch in the last catch block.

Or you could also look into this to set up error handling in express; https://expressjs.com/en/guide/error-handling.html#:~:text=Writing error handlers

CodePudding user response:

This is happening because your middleware is throwing an async error and your node app has no way of handling it.

Even if you have an error handler in place you need to explicitly call the next function with the error object. E.g.

try{
    // Your code...
}catch(error){
    console.log(error)
    next(error)
}

When express sees next(error) i.e. next function being called with an argument it passes it to the error handler that you have written at the end of app.js

/** Catch and return custom errors */
app.use((error, req, res, next) => {
    const status = error.statusCode || 500;
    const message = error.message;
    const data = error.data;
    res.status(status).json({ message: message, data: data });
});

Solution:

You can make use of an npm package express-async-errors

Link for the npm package: https://www.npmjs.com/package/express-async-errors

And in your app.js file just add require('express-async-errors') on the very top. This will direct all the async errors to the error handler middleware in your application.

  • Related