我正在节点应用程序上运行猫鼬。我有一组用户文档,非常简单。我有 .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 上却不能。因此,该钩子被完全绕过,而不仅仅是无法工作。
使用此解决方案是否缺少某些内容?
有时会出现这种情况,发布问题意味着我会在五分钟后找到答案。第 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
方法,然后在钩子内引用它。