TypeError: User.pre is not a function

TypeError: User.pre is not a function

我正在尝试实现一个 Node.js 端点,如果时间戳和 JWT 匹配,它会更新密码。我在这里使用旧语法吗?我的代码如下:

app.put('/changepassword', function (req, res) {
  // 
  // https://www.mongodb.com/blog/post/password-authentication-with-mongoose-part-1
  console.log("Password change endpoint was called by", req.ip);
  User.pre('save', function (next) {
     var user = this;
    // only hash the password if it has been modified (or is new)
    if (!user.isModified('password')) return next();
    
    // generate a salt
    bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
        if (err) return next(err);
    
        // hash the password along with our new salt
        bcrypt.hash(user.password, salt, function(err, hash) {
            if (err) return next(err);
    
            // override the cleartext password with the hashed one
            user.password = hash;
            next();
        });
      });
    });
        
UserSchema.methods.comparePassword = function(candidatePassword, cb) {
  bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
      if (err) return cb(err);
      cb(null, isMatch);
  });
};
});

我的错误是:TypeError: User.pre is not a function

我的 UserSchema 如下。它有名字、姓氏、电子邮件、密码、活动等键:

const mongoose = require('mongoose');
 
const userSchema = mongoose.Schema({
 
    firstname: {
        type: String,
        required: true
    },
    lastname: String,
    eMail: { 
    type: String, 
    required: true,
    unique: true 
    }, 
    password: String,
    active: Boolean,
    lastlogin: Date,
    loginAttempts: { type: Number, required: true, default: 0 },
    lockUntil: { type: Number }
});
 
/* // expose enum on the model
UserSchema.statics.failedLogin = {
    NOT_FOUND: 0,
    PASSWORD_INCORRECT: 1,
    MAX_ATTEMPTS: 2
  }; */

module.exports = mongoose.model("User", userSchema);

您的User是猫鼬模型,没有pre功能。 pre 函数属于中间件。

https://mongoosejs.com/docs/models.html

https://mongoosejs.com/docs/middleware.html#pre

为了执行 pre 操作,您应该将整个 pre 函数调用移动到您声明 userSchema 的文件中。 pre 函数是一个钩子,是您希望在每次调用保存操作时发生的事情。不需要在 put 函数中声明它。

正如 Chris 所说,将以下代码移动到 UserSchema 文件

User.pre('save', function (next) {
     var user = this;
    // only hash the password if it has been modified (or is new)
    if (!user.isModified('password')) return next();
    
    // generate a salt
    bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
        if (err) return next(err);
    
        // hash the password along with our new salt
        bcrypt.hash(user.password, salt, function(err, hash) {
            if (err) return next(err);
    
            // override the cleartext password with the hashed one
            user.password = hash;
            next();
        });
      });
    });
        
UserSchema.methods.comparePassword = function(candidatePassword, cb) {
  bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
      if (err) return cb(err);
      cb(null, isMatch);
  });
};

完成后,您可以像这样在您的方法中访问 comparePassword 函数,

虚拟请求示例

app.get('/comparePasswords', function (req, res) {
  User.findOne(req.id, function (err, user) {
    if (err) throw err;

    
    user.comparePassword(req.password, function (err, isMatch) {
      if (err) throw err;
      console.log(isMatch); // -> Returns True if match
   });
 })

对于 ChangingPassword 我认为您不需要比较密码,但取决于您的用户情况