javascript - 如何执行 Mongoose 验证功能仅用于创建用户页面而不编辑用户页面?

标签 javascript node.js mongodb express mongoose

背景
我目前正在使用 Node.js、Express 和 MongoDB 构建一个网站。我正在使用 mongoose 来处理我的 MongoDB 服务器。 现在,我的 Mongoose 架构中有一个函数,用于检查用户输入的电子邮件地址是否已存在于数据库中。我希望仅在创建帐户页面上调用此函数。任何帮助将不胜感激!谢谢!

问题
该功能运行良好,但在编辑用户个人资料页面和创建用户页面上被调用。这意味着,如果用户未在编辑个人资料页面上更改其电子邮件,则他们无法更新其个人资料。我只想为创建用户页面调用此验证唯一电子邮件功能,这样我就可以避免此问题。如何根据用户所在的页面运行函数?

代码
在我的用户架构中检查电子邮件是否已存在

UserSchema.path('email').validate(function(value, done) {
    this.model('User').count({ email: value }, function(err, count) {
        if (err) {
            return done(err);
        } 
        // If `count` is greater than zero, "invalidate"
        done(!count);
    });
}, 'Email already exists');

整个用户架构(文件名为 user.server.model.js)

'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    crypto = require('crypto');

/**
 * A Validation function for local strategy properties
 */
var validateLocalStrategyProperty = function(property) {
    return ((this.provider !== 'local' && !this.updated) || property.length);
};

/**
 * A Validation function for local strategy password
 */
var validateLocalStrategyPassword = function(password) {
    return (this.provider !== 'local' || (password && password.length > 6));
};

/**
 * User Schema
 */
var UserSchema = new Schema({
    firstName: {
        type: String,
        trim: true,
        default: '',
        validate: [validateLocalStrategyProperty, 'Please fill in your first name']
    },
    lastName: {
        type: String,
        trim: true,
        default: '',
        validate: [validateLocalStrategyProperty, 'Please fill in your last name']
    },
    displayName: {
        type: String,
        trim: true
    },
    companyName: {
        type: String,
        trim: true,
        default: ''
    },
    companyWebsite: {
        type: String,
        trim: true,
        default: ''
    },
    companyAddress1: {
        type: String,
        trim: true,
        default: ''
    },
    companyAddress2: {
        type: String,
        trim: true,
        default: ''
    },
    companyCity: {
        type: String,
        trim: true,
        default: ''
    },
    companyState: {
        type: String,
        trim: true,
        default: ''
    },
    companyZip: {
        type: String,
        trim: true,
        default: ''
    },
    phone: {
        type: String,
        trim: true,
        default: ''
    },
    email: {
        type: String,
        trim: true,
        default: '',
        unique: true,
        validate: [validateLocalStrategyProperty, 'Please fill in your email'],
        match: [/.+\@.+\..+/, 'Please fill a valid email address']
    },
    username: {
        type: String,
        unique: 'testing error message',
        required: 'Please fill in a username',
        trim: true
    },
    password: {
        type: String,
        default: '',
        validate: [validateLocalStrategyPassword, 'Password should be longer']
    },
    salt: {
        type: String
    },
    provider: {
        type: String,
        required: 'Provider is required'
    },
    providerData: {},
    additionalProvidersData: {},
    roles: {
        type: [{
            type: String,
            enum: ['user', 'admin']
        }],
        default: ['user']
    },
    updated: {
        type: Date
    },
    created: {
        type: Date,
        default: Date.now
    },
    /* For reset password */
    resetPasswordToken: {
        type: String
    },
    resetPasswordExpires: {
        type: Date
    }
});

/**
 * Hook a pre save method to hash the password
 */
UserSchema.pre('save', function(next) {
    if (this.password && this.password.length > 6) {
        this.salt = new Buffer(crypto.randomBytes(16).toString('base64'), 'base64');
        this.password = this.hashPassword(this.password);
    }

    next();
});

/**
 * Check if email already exists in database
 */
UserSchema.path('email').validate(function(value, done) {
    this.model('User').count({ email: value }, function(err, count) {
        if (err) {
            return done(err);
        } 
        // If `count` is greater than zero, "invalidate"
        done(!count);
    });
}, 'Email already exists');

/**
 * Create instance method for hashing a password
 */
UserSchema.methods.hashPassword = function(password) {
    if (this.salt && password) {
        return crypto.pbkdf2Sync(password, this.salt, 10000, 64).toString('base64');
    } else {
        return password;
    }
};

/**
 * Create instance method for authenticating user
 */
UserSchema.methods.authenticate = function(password) {
    return this.password === this.hashPassword(password);
};

/**
 * Find possible not used username
 */
UserSchema.statics.findUniqueUsername = function(username, suffix, callback) {
    var _this = this;
    var possibleUsername = username + (suffix || '');

    _this.findOne({
        username: possibleUsername
    }, function(err, user) {
        if (!err) {
            if (!user) {
                callback(possibleUsername);
            } else {
                return _this.findUniqueUsername(username, (suffix || 0) + 1, callback);
            }
        } else {
            callback(null);
        }
    });
};

mongoose.model('User', UserSchema);

users.server.routes.js 文件

'use strict';

/**
 * Module dependencies.
 */
var passport = require('passport');

module.exports = function(app) {
    // User Routes
    var users = require('../../app/controllers/users.server.controller');

    // Setting up the users profile api
    app.route('/users/me').get(users.me);
    app.route('/users').put(users.update);
    app.route('/users/accounts').delete(users.removeOAuthProvider);

    // Setting up the users password api
    app.route('/users/password').post(users.changePassword);
    app.route('/auth/forgot').post(users.forgot);
    app.route('/auth/reset/:token').get(users.validateResetToken);
    app.route('/auth/reset/:token').post(users.reset);

    // Setting up the users authentication api
    app.route('/auth/signup').post(users.signup);
    app.route('/auth/signin').post(users.signin);
    app.route('/auth/signout').get(users.signout);

    // Finish by binding the user middleware
    app.param('userId', users.userByID);
};  

最佳答案

您可以使用 Document.isNew 标志仅在创建时运行检查。像这样:

UserSchema.pre('save', function(next) {
    if (this.isNew) {
        // Enforce constraints here
    }

    if (this.password && this.password.length > 6) {
        this.salt = new Buffer(crypto.randomBytes(16).toString('base64'), 'base64');
        this.password = this.hashPassword(this.password);
    }

    next();
});

您还可以使用 Document.isModified,因此在保存 Hook 中您也可以检查 this.isModified('email')

关于javascript - 如何执行 Mongoose 验证功能仅用于创建用户页面而不编辑用户页面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30416170/

相关文章:

Node.js 取消设置环境变量

javascript - 使用聚合框架或 MapReduce 将事件数据中的文档嵌入到 MongoDB 中

javascript - 灯箱无法正常工作

c# - 如何使用 C# 在 Asp.net 中创建编辑缩略图功能(同时上传显示图像)?

node.js - Hapi.js Bell/Auth-Cookie 重定向循环

javascript - 将对象传递给 sails.js 中的views/layout.ejs

scala - 从 scala 将文档插入 mongodb 时出错

java - 使用 Spring 3.1 的 Java 配置来配置 spring-data-mongodb 存储库

使用函数构造函数创建对象时javascript双重相等比较

javascript - 单击时运行 CSS 关键帧