使用 mongooseexpress 更新哈希密码

Den*_*enn 2 mongoose mongodb express

我回顾了有关此问题的许多讨论,但似乎没有一个对我有帮助。

我使用 mongoose 5.5 来保存用户数据,如下所示:

我的架构如下所示:

const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const bcrypt = require("bcryptjs");

const userSchema = Schema({

  userName: {
    type: String
  },
  firstName: {
    type: String
  },
  surName: {
    type: String
  },
  password: {
    type: String,
    required: true
  }
});

userSchema.pre('save', async function(next){

try {
  if(!this.isModified('password')){
      return next();
  }
  const hashed = await bcrypt.hash(this.password, 10);
  this.password = hashed;

} catch (err) {
    return next(err);
  }
});

module.exports = user;
Run Code Online (Sandbox Code Playgroud)

我的注册码如下所示:

exports.register = async (req, res, next) => {

try {
    const user = await db.user.create(req.body);
    const {id, username} = user;
    res.status(201).json({user});
    
} catch (err) {
    if(err.code === 11000){
        err.message ='Sorry, details already taken';
    }
    next(err);
  }
};
Run Code Online (Sandbox Code Playgroud)

登录代码如下所示:

exports.login = async (req, res, next) => {

try {
    const user = await db.user.findOne({username: req.body.username});
    const valid = await user.comparePasswords(req.body.password);

    if(valid){

        const token = jwt.sign({id, username}, process.env.SECRET);
        res.json({id, username, token});
    }
    else{
        throw new Error();
    }        
    
} catch (err) {
    err.message = 'Invalid username/password';
    next(err);
  } 
};
Run Code Online (Sandbox Code Playgroud)

注册和登录效果很好,我的挑战是更新密码。我想将当前密码与用户提供的密码(例如登录时)进行比较,如果有效则更新新密码。

像这样的东西:

exports.changepass = async (req, res, next) => {
    const user = await db.user.findOne({username: req.body.username});
    const valid = await user.comparePasswords(req.body.password);

    if(valid){

           " ?? update password and hash ?? "
    }
    else{
        throw new Error();
    }       

}
Run Code Online (Sandbox Code Playgroud)

Jef*_*eda 5

如果您使用findOneAndUpdate()更新,请尝试使用pre("findOneAndUpdate")中间件修改类似于您的pre("save"). 每次用于更新模型pre("findOneAndUpdate")时都会调用中间件。Model.findOndAndUpate()

你可以用同样的updateOne()方法pre("updateOne")

样本:

// userSchema--------------------
...
userSchema.pre('save', async function (next) {
    try {
        if (!this.isModified('password')) {
            return next();
        }
        const hashed = await bcrypt.hash(this.password, 10);
        this.password = hashed;
    } catch (err) {
        return next(err);
    }
});

userSchema.pre('findOneAndUpdate', async function (next) {
    try {
        if (this._update.password) {
            const hashed = await bcrypt.hash(this._update.password, 10)
            this._update.password = hashed;
        }
        next();
    } catch (err) {
        return next(err);
    }
});

// changepass--------------------
...
if(valid){

    //" ?? update password and hash ?? "
    const result = await db.user.findOneAndUpdate(
        { username: req.body.username },
        { password: req.body.newPassword },
        { useFindAndModify: false }
    ); 
}
Run Code Online (Sandbox Code Playgroud)