Mongoose 预保存挂钩不会在 findOneAndUpdate 上加密密码

问题描述 投票:0回答:1

我正在节点应用程序上运行猫鼬。我有一组用户文档,非常简单。我有 .pre 中间件,当它是新记录或更新密码时,应该使用 bcrypt 加密密码。然而,虽然它可以很好地处理新的用户文档,但在执行 findOneAndUpdate 时它不会加密。

我确实意识到这个问题已经被问过并且表面上得到了回答,但是我在这里或其他地方找到的解决方案都不起作用。

这是架构:

const bcrypt = require("bcrypt");
const { Schema, model } = require("mongoose");
const uniqueValidator = require("mongoose-unique-validator");

const userSchema = new Schema({
  userName: {
    type: String,
    required: true,
    unique: true,
  },
  email: {
    type: String,
    required: true,
    unique: true,
  },
  password: {
    type: String,
    required: true,
  }
});

...这是我的中间件:

userSchema.pre("save", function (next) {
  if (!this.isModified("password")) {
    return next();
  }

  try {
    // Hash the password synchronously
    const saltRounds = 10;
    const hashedPassword = bcrypt.hashSync(this.password, saltRounds);

    // Override the cleartext password with the hashed one
    this.password = hashedPassword;

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

这个中间件实际上是从 ChatGPT 中出来的,但本质上与我之前的完全一样,除了使用 hashSync 而不是 hash(加上 async/await)。

这是我的 findOneAndUpdate 调用:

const user = await User.updateOne(
        { _id: conf.user_id },
        { password: newPwd },
        { new: true, upsert: false, runValidators: true }
      );

runValidators: true
是我在这里学到的我应该添加的内容,添加它并没有影响任何东西。我还尝试过使用第二个专门针对
findOneAndUpdate
的预中间件,但没有成功。

我在 .pre 函数中使用 console.log 运行了一些测试,并确认在新用户上可以访问 console.log...但在 findOneAndUpdate 上却不能。因此,该钩子被完全绕过,而不仅仅是无法工作。

使用此解决方案是否缺少某些内容?

mongoose mongoose-schema
1个回答
0
投票

有时会出现这种情况,发布问题意味着我会在五分钟后找到答案。第 1 部分是一个错误:我没有使用

findOneAndUpdate
,但因为脑痉挛而使用了
updateOne
。我还了解到
.isModified()
不再是该钩子中的函数。我得知答案是这样的:

userSchema.pre("findOneAndUpdate", async function (next) {
  const update = this.getUpdate();

  if (update.$set && update.$set.password) {
    const saltRounds = 10;
    const hashedPassword = await bcrypt.hash(update.$set.password, saltRounds);

    update.$set.password = hashedPassword;
  }

  next();
});

所以我必须使用

$set
方法,然后在钩子内引用它。

© www.soinside.com 2019 - 2024. All rights reserved.