Need to check if password field has been modified in pre findOneAndUpdate
See original GitHub issueI ran into a problem last night and still haven’t been able to figure out a solution so hopefully someone can offer some advice. I am allowing users to update their username and password, and whenever the password field has been modified I need to hash it before storing it in mongo.
So far I had been using this code to hash the user’s password:
UserSchema.pre('save', function(next) {
if (this.isModified('password')) // If the pw has been modified, then encrypt it again
this.password = this.encryptPassword(this.password);
next();
});
The encryptPassword
function is a custom one I added to my User Schema
:
// Add custom methods to our User schema
UserSchema.methods = {
// Hash the password
encryptPassword: function(plainTextPassword) {
if (!plainTextPassword) {
return ''
} else {
var salt = bcrypt.genSaltSync(10);
return bcrypt.hashSync(plainTextPassword, salt);
}
}
};
This only works though when the user first signs up and I create a new user instance and then save it. I need the same functionality when updating the user as well.
I was doing research in past issues here and came across this one: pre, post middleware are not executed on findByIdAndUpdate, and came across a comment where another dev was trying to do something very similar to what I am taking about: https://github.com/Automattic/mongoose/issues/964#issuecomment-154332797
@vkarpov15 responded to his question with the following code suggestion:
TodoSchema.pre('findOneAndUpdate', function() {
this.findOneAndUpdate({}, { password: hashPassword(this.getUpdate().$set.password) });
});
The only problem is, that this will cause us to rehash the password every time you update a user, which is wrong. You should only be hashing the password when the user initially signs up, and whenever they send a request up to change their password. If you run the above code every single time the user is updated, you will just end up rehashing the old hash, so when the user enters in their password next time on the client, it wont match with the hash stored in mongo anymore…
Is there any way I can use something like this.isModified('password')
inside of the .pre('findOneAndUpdate'
, so that I only hash the password when the user has updated it?
At this point I’m open to any and all suggestions thanks.
Issue Analytics
- State:
- Created 7 years ago
- Reactions:7
- Comments:24
I’m currently using this solution and it works. You don’t need to execute another query.
@NicolasBlois that works. There’s a potential race condition there but it’ll work for most cases.