以干净的方式验证电子邮件和用户名

时间:2016-03-06 12:14:22

标签: node.js mongodb express mongoose

我需要在保存到数据库之前验证用户名(如果提供了用户名)和电子邮件(如果提供了一个)。我正在使用MongooseJS,但是,我不确定如何构建我的代码

这是我到目前为止所做的:

var user = new User();
if(req.body.email) {
    User.findOne({"email" : req.body.email}, function(err, found){
        if(err) return next(err);
        if(found) return res.status(200).send({"error_code" : "INVALID_REQUEST_ERROR", "message" : "Email address already exists"});
    });
}

if(req.body.username) {
    User.findOne({"username" : req.body.username}, function(err, found){
        if(err) return next(err);
        if(found) return res.status(200).send({"error_code" : "INVALID_REQUEST_ERROR", "message" : "Username already exists"});
    });
}

user.save(function(err){
    if(err) return next(err);
    res.status(200).send(user);
});

但当然这不起作用,因为user.save将在任一验证块执行之前执行。我意识到我可以将user.save置于回调中,但之后我会重复我想要避免的代码。

2 个答案:

答案 0 :(得分:0)

另一种简单的方法可能

var user = new User();
var email = req.body.email || '';
var username = req.body.username || '';

User.find({
          $or: [{"email": email}, {"username": username}]}, 
          function(err, users){
             if(err) return next(err);
             if(users && users.length == 0) {
                // save new user if none is matched
                user.save(function(err){
                       if(err) return next(err);
                       res.status(200).send(user);
                });
             } else if (users && users.length > 0) {
                // check users returned to determine which of following two error codes should be returned
                //return res.status(200).send({"error_code" : "INVALID_REQUEST_ERROR", "message" : "Email address already exists"});
                //return res.status(200).send({"error_code" : "INVALID_REQUEST_ERROR", "message" : "Username already exists"});
             }
});

您可以通过Promise执行此操作,以下是使用Q.js

的一个示例代码
function findUserByEmail() {
    var deferred = Q.defer();
    if(req.body.email) {
        User.findOne({"email" : req.body.email}, function(err, found){
            if(err) return deferred.reject(err);
            if(found) {
               res.status(200).send({"error_code" : "INVALID_REQUEST_ERROR", "message" : "Email address already exists"});
               deferred.reject();   
            }else {
               // no user is found, resolve it
               deferred.resolve();
            }
        });
    } else {
       deferred.reject();
    }
    return deferred.promise;
}

function findUserByName() {
    var deferred = Q.defer();
    if(req.body.username) {
        User.findOne({"username" : req.body.username}, function(err, found){
            if(err) return deferred.reject(err);
            if(found) {
                res.status(200).send({"error_code" : "INVALID_REQUEST_ERROR", "message" : "Username already exists"});
                deferred.reject();
            } else {
                // no user is found, resolve it
                deferred.resolve();
            }
        });
    } else {
        deferred.reject();
    }
    return deferred.promise;
}

Q.all([findUserByName(), findUserByEmail()]).then (function() {
    // in the resolve function, namely, no exist username and email 
    user.save(function(err){
        if(err) return next(err);
        res.status(200).send(user);
    });
});

答案 1 :(得分:0)

最好的办法是添加validation on to your mongoose Schema并让它在您尝试保存模型时自动执行(或者您可以在之前调用验证函数)。像这样:

var userSchema = new Schema({
    email: {
        type: String,
        required: true,
        validate: {
            validator: function(v) {
                var emailRegexp = /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i;

                return emailRegexp.test(v);
            },
            message: "{VALUE} does not appear to be a valid email address."
        }
    }
});

然后当您尝试使用不正确的数据保存时:

var user = new User({ email: "this_isnt_a_proper_email" });

user.save(function(err) {
    if (err.name === "ValidationError") { // check that it comes from mongoose validation
        console.log(err.errors.email.message)
        res.status(400).send({ validationError: err }); // send "Bad Request" HTTP header
    } else {
        res.send(user) // status 200 is implicit when not set
    }
});

为了更好地组织检查用户名或电子邮件是否已在数据库中设置的代码,我建议查找Bluebird(或类似的)Promises,以便您可以拥有流程的逻辑流程。 / p>