I am validating a login form with express-validator and passport.js, using a local strategy:
login: function() {
passport.use('local-login', new LocalStrategy({
passReqToCallback: true
},
function(req, username, password, done) {
req.check('username', 'Incorrect user and/or password.').doesUserExists(password);
req.check('password', 'Password cannot be empty.').notEmpty();
req.asyncValidationErrors(true)
.then(function(user) {
return done(null, user);
})
.catch(function(errors) {
if (errors) return done(null, false, req.flash('error', errors));
});
}
));
}
The function doesUserExists() is a custom asynchronous validation, which query for the user, compare the password provided with the hashed password in the database, and resolves it:
doesUserExists: function(username, password) {
return new Promise(function(resolve, reject) {
User.findOne({ username: username })
.then(function(user) {
if (user) return user;
if (!user) reject(user);
})
.then(function(user) {
user.comparePassword(password, function(error, isMatch) {
if (isMatch) return user;
else reject(user);
});
resolve(user);
})
.catch(function(error) {
if (error) reject(error);
});
});
}
So far it is working perfectly, except when the user and the password are matched, and the promise is resolved, no object (user) is returned to the req.asyncValidationErrors() function, preventing its .then() block to redirect to the user profile.
I must add that I'm pretty new to promises, and not sure if what I'm expecting should happen. Perhaps some misunderstanding about how it works is leading me to think erroneous.
Update
For now, I decided to make another database query for the validated user/password:
req.asyncValidationErrors(true)
.then(function() {
User.findOne({ username: username })
.then(function(user) {
return done(null, user);
});
})
.catch(function(errors) {
if (errors) {
return done(null, false, req.flash('error', errors));
}
});
Extra database queries are not elegant, but...