Reputation: 2839
I'm trying to hash passwords in an app I'm building and they are hashing fine when I create a user by calling this function(coffeesctipt):
UserSchema.pre 'save', (next) ->
user = this
hashPass(user, next)
hashPass = (user, next) ->
# 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, (err, salt) ->
if err
return next(err)
# hash the password using our new salt
bcrypt.hash user.password, salt, (err, hash) ->
if err
return next(err)
# override the cleartext password with the hashed one
user.password = hash
next()
return
return
but when I do an update and have this pre:
UserSchema.pre 'findOneAndUpdate', (next) ->
user = this
hashPass(user, next)
I get TypeError: user.isModified is not a function
if I console log user in the pres the save pre logs the user I am updating, the findandupdate pre does not,id there to way to access the document in the pre or do I need to do this another way?
Upvotes: 12
Views: 13688
Reputation: 1
Instead of using arrow function use normal function like async function(next){}
Upvotes: 0
Reputation: 19
Don't use the arrow operator for the callback, that'll change the scope this. Define a regular function; it may help you to solve this problem.
Upvotes: 1
Reputation: 65
Be careful when using middleware in mongoose, in that case of "save" or "updateOne", this
refers to a query, not a document. It should look like this
schema.pre(type, { document: true, query: false }, async function (next)
{
if(this.isModified('password')) {
//Do the hash
}
next();
});
Upvotes: 3
Reputation: 437
I know this might be way too late for you, but for any future coders that land on this issue, I think this solution should work. So, since save() is a middleware inside .pre, that overrides some of mongoose's methods, such as findByIDAndUpdate. What you might want to do is instead of using that, break your code up like this if you have patch request firing off somewhere:
const user = await User.findById(req.params.id);
updates.forEach((update) => {
user[update] = req.body[update];
});
Upvotes: 0
Reputation: 467
You get an error because the arrow function changes the scope of 'this.' Just use
UserSchema.pre('save', function(next){})
Upvotes: 28
Reputation: 622
I had a similar issue on typescript and it turns out that is was related to the arrow operator you are also using. Not sure how to change this in coffescript right now but I think that should fix your issue.
you have to change this line:
hashPass = (user, next) ->
Check this out: https://github.com/Automattic/mongoose/issues/4537
Upvotes: 1