问题
I have reviewed many discussions on this matter but none seems helpful to me.
I am using mongoose 5.5 to save user data as shown below:
My schema looks like this:
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;
My registration code looks like this:
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);
}
};
Login code looks like this:
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);
}
};
Registration and login works well, my challenge is updating a password. I would like to compare current password with what user provides (like in login), if it is valid then update new password.
something like this:
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();
}
}
Kindly advice
回答1:
If you're using findOneAndUpdate() to update, try using the pre("findOneAndUpdate") middleware to modify the password similar to your pre("save"). The pre("findOneAndUpdate") middleware will be called everytime you use Model.findOndAndUpate() to update your models.
You can do the same with updateOne() with pre("updateOne")
Sample:
// 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 }
);
}
来源:https://stackoverflow.com/questions/62066921/hashed-password-update-with-mongoose-express