rasco22862
rasco22862

Reputation: 137

How can I throw a custom error with express-validator?

I am validating a form through the POST method. I want to push an error into express-validator when an email address is already registered, so when I do req.validationErrors() it is included. Something like this:

req.checkBody('inputFirstName', 'First name empty').notEmpty();
req.checkBody('inputLastName', 'Last name empty').notEmpty();
db.User.find({email: req.body.inputEmail}, function (err, user){
        if(user){
            var error = {param: "inputEmail", msg: "Email address already registered", value: ''};
            expressValidator._errors.push(error);
        }
    });

Thanks.

Upvotes: 6

Views: 15828

Answers (5)

Nebojsa
Nebojsa

Reputation: 153

Here is one example that you should put in your validator:

   // Validates data when registering new user.
   exports.registerNewUser = [        
     body('email').
       exists().withMessage("Email is required").
       isEmail().withMessage("Not a valid email").bail().
       // bail() is important so that in case some of previous validations fail, you don't call db function
       custom(async (val) => {
        // Check if the email is already taken
        try {
            const user = await User.getOneUserByEmail({email: val});
            // check for example if user exists or that it is not closed
            if(user && user.status!=="closed") return false;
            else return true;
        } catch(error) {
            // if there is an error, always return false
            console.log(error);
            return false;
        }
    }).withMessage("Email already taken")
  ]

You should also import:

const { body } = require('express-validator/check');

Upvotes: 3

Neil Cooper
Neil Cooper

Reputation: 102

Looks like the express-validator already show this as a use case of custom validators:

https://express-validator.github.io/docs/custom-validators-sanitizers.html

const { body } = require('express-validator/check');

app.post('/user', body('email').custom(value => {
  return User.findUserByEmail(value).then(user => {
    if (user) {
      return Promise.reject('E-mail already in use');
    }
  });
}), (req, res) => {
  // Handle the request
});

Upvotes: 0

Elaine Bertoni
Elaine Bertoni

Reputation: 11

req.checkBody('inputFirstName', 'First name empty').notEmpty();
req.checkBody('inputLastName', 'Last name empty').notEmpty();
req.checkBody('inputEmail','Email address already registered').custom(inputEmail => {
    db.User.find({email: inputEmail}, function (err, user) {
        if(!user) return true;
    });
});

Upvotes: 0

Dũng IT
Dũng IT

Reputation: 2999

Following:

In app.js:

...
var session = require('express-session');
var passport = require('passport');
var flash = require('connect-flash');
var validator = require('express-validator');
...
var app = express();
require('./config/passport');
...
app.use(bodyParser.urlencoded({ extended: false }));
app.use(validator());
...
app.use(session({ secret: settings.session_key, resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());

In Router/index.js:

router.get('/register', function (req, res, next) {
    var messages = req.flash('error');
    res.render('customers/register', {
        messages: messages,
        hasErrors: messages.length > 0
    }
}

router.post('/register', passport.authenticate('local.register', {
    successRedirect: '/customer/dasdboard',
    failureRedirect: '/customer/register',
    failureFlash: true //required
}));

In Views/customers/signup.hbs:

{{#if hasErrors}}
    <div class="alert alert-danger">
         {{#each messages}}
              <p>{{this}}</p>
         {{/each}}
    </div>
{{/if}}

In config/passport.js:

passport.use('local.register', new LocalStrategy({
    usernameField: 'email',
    passwordField: 'password',
    passReqToCallback: true //required
}, function(req, email, password, done) {

    req.checkBody('inputFirstName', 'First name empty').notEmpty();
    req.checkBody('inputLastName', 'Last name empty').notEmpty();
    req.checkBody('inputEmail', 'Invalid email').notEmpty().isEmail();
    req.checkBody('password','Confirm password does not match.').equals(req.body.confirmpassword);

    var errors = req.validationErrors();
    if (errors) {
        var messages = [];
        errors.forEach(function(error){
            messages.push(error.msg);
        });
        return done(null, false, req.flash('error', messages));
    }

    db.User.find({email: req.body.inputEmail}, function (err, user) {
        if (err) {
            return done(err);
        }
        if (user) {
            return done(null, false, {message: 'Email address already registered!'});
        }

        //Save new data here
        ....
    });
}));

working for my solution.

Upvotes: 1

Krzysztof Wilczek
Krzysztof Wilczek

Reputation: 67

You can do something like this:

req.checkBody('inputFirstName', 'First name empty').notEmpty();
req.checkBody('inputLastName', 'Last name empty').notEmpty();
var errors = req.validationErrors();
db.User.find({email: req.body.inputEmail}, function (err, user){
        if(user){
            var error = {param: "inputEmail", msg: "Email address already registered", value: req.body.email};
            if (!errors) {
                errors = [];
            }
            errors.push(error);
        }

        // Here need  to be next part of action - not outside find callback!
    });

But I think it's a bad idea to put some mongoose validation on request side validation. You can use some schema methods, e.g. pre save, make validation there.

Upvotes: 7

Related Questions