【问题标题】:isModified and pre-save mongoose...NodejsisModified 并预先保存 mongoose...Nodejs
【发布时间】:2018-11-07 23:01:55
【问题描述】:

您好,我只想在密码更改时才使用散列密码保存,所以我在预保存中使用了 isModified 函数,但即使我更改了密码,它也总是返回 false。我尝试这样做的原因是因为我不想在更改其他属性时更改并保存我的密码。

router.post('/changepw', isAuthenticated, function (req, res, next) {
    User.findOneAndUpdate({_id: req.user._id}, {$set: req.body},{ new: true }, function (err, user){

        if (err) {
          return err;
        } 
        else {

          if (req.body.password) {
            user.password = req.body.password;
            user.save();
          } else { 

          }

        }
        res.redirect('/profile');
    });
});

像这里一样,当我更改毕业值时,我不想更改密码。

router.post('/edit', isAuthenticated, function (req, res, next) {
    User.findOneAndUpdate({
        _id: req.user._id
    }, {
        $set: {
            name: req.body.name,
            phone: req.body.phone,
            classc: req.body.classc,
            major: req.body.major,
            minor: req.body.minor,
            linkedin: req.body.linkedin,
            bio: req.body.bio
        }
    }, {
        new: true
    }, function (err, user, done) {

        if (err) {
            return err;
        } else {

            if (typeof req.body.graduated == 'undefined') {
                user.graduated = false;


            } else if (typeof req.body.graduated == 'string') {

                user.graduated = true;

            }

            user.save();
        }
        res.redirect('/profile');
    });
});
userSchema.pre('save', function(next) {
console.log(this.isModified('password'));                                                                                                                                        
    if(this.password && this.isModified('password')){                                                                                                                                                                                                                                                                                      
        this.password  = bcrypt.hashSync(this.password, bcrypt.genSaltSync(8),null);                                                                                                             
    }

    next()                                                                                                                                                                     
}); 

有什么建议吗?

【问题讨论】:

    标签: node.js mongoose


    【解决方案1】:

    findOneAndUpdate()已经更新了user,所以在你提供的回调函数中user已经是最新的了。当您在该回调中调用user.save() 时,将调用前save() 挂钩,但isModified('password') 将为false。

    如果您使用req.body 提供新密码,则密码将不经过哈希处理进入数据库,因为“不会在update()findOneAndUpdate() 等上执行save() 之前和之后的挂钩。” (see documentation)。如果你再比较req.bodyuser中的密码,它们将是相同的,你无法决定是否用save()触发哈希函数。

    保留您之前的 save() 钩子,并作为 findById()save() 的组合进行更新:

      User.findById(req.user._id, (err, user) => {
        if (err)
          handleYourErrorAndLeave(err)
      
        // Update all user attributes which are different or missing from user with values from req.body
        Object.assign(user, req.body)
    
        // Save the updated user object.
        // pre save() hook will be triggered and isModified('password') should be correct
        user.save()
          .then(savedUser => {
            res.redirect('/profile')
          }) 
      })
    

    【讨论】:

      【解决方案2】:

      试试这个

      userSchema.pre('save', async function (next) {
        // Only run this function if password was moddified (not on other update functions)
        if (!this.isModified('password')) return next();
        // Hash password with strength of 12
        this.password = await bcrypt.hash(this.password, 12);
        //remove the confirm field 
        this.passwordConfirm = undefined;
      });
      

      【讨论】:

      • 这不会在User.findOneAndUpdate期间被调用。
      • 根据文档,它确实是mongoosejs.com/docs/middleware.html#pre
      • 绝对不是。在您链接到的页面下方,有一章“关于 findAndUpdate() 和查询中间件的说明”。它说“save() 之前和之后的钩子不会在 update()findOneAndUpdate() 等上执行。”此外,“您无法访问pre('updateOne')pre('findOneAndUpdate') 查询中间件中正在更新的文档。” OP 修改了user 两次。也许findById()user.save() 的组合会更好。我将添加一个带有建议的答案。
      【解决方案3】:

      请注意,当您使用findAndUpdate() 方法时,不会触发预保存挂钩。使用新的钩子检查 Mongoose 文档:http://mongoosejs.com/docs/middleware.html#notes

      【讨论】:

        猜你喜欢
        • 2016-02-01
        • 2020-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-14
        • 2013-07-01
        相关资源
        最近更新 更多