Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with mongoose .findByIdAndUpdate and pre-update hook

I have mongoose-schema called UserSchema, which stores information about all users. I want to enable the user to change his information, which I try by using .findByIdAndUpdate. This is the relevant code:

router.post("/updateprofile", function(req,res,next) {
    const {id, org, tel, email, firstName, lastName} = req.body;
    Users.findByIdAndUpdate(id, {org : org, tel : tel, email : email, firstName : firstName , lastName : lastName}, function (err, response) {
        if (err) throw err
        res.json(response);
    });

});

However, when trying to change the info, I get the following error-message: Cannot read property 'password' of undefined. I'm pretty sure this is caused by a pre-update hook, but I can not remove it because I need it for my "forgot-password"-functionality. Here's the code:

UserSchema.pre('findOneAndUpdate', function (next) {
    this.update({},{ $set: { password: 
    bcrypt.hashSync(this.getUpdate().$set.password, 10)}} )
    next();
});

I'm confused by why it used that prehook anyway, since in the hook it's looking for findOneandUpdate and when I try to change the data I'm using findByIdAndUpdate.

I tried using .update() instead but that doesn't work either. Does anyone know what I'm doing wrong and how to fix it?

like image 435
A.S.J Avatar asked Dec 08 '22 15:12

A.S.J


1 Answers

Looks like getUpdate isn't what you want, try it like this:

    UserSchema.pre('findOneAndUpdate', function (next) {
    this._update.password = bcrypt.hashSync(this._update.password, 10)
    next();
});

With regards to your second question, findByIdAndUpdate is a wrapper around findOneAndUpdate. Here's the code straight from Mongoose's source code for your reference

Model.findByIdAndUpdate = function(id, update, options, callback) {
  if (callback) {
    callback = this.$wrapCallback(callback);
  }
  if (arguments.length === 1) {
    if (typeof id === 'function') {
      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n'
          + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)\n'
          + '  ' + this.modelName + '.findByIdAndUpdate(id)\n'
          + '  ' + this.modelName + '.findByIdAndUpdate()\n';
      throw new TypeError(msg);
    }
    return this.findOneAndUpdate({_id: id}, undefined);
  }

The comments in the code read:

/**
 * Issues a mongodb findAndModify update command by a document's _id field.
 * `findByIdAndUpdate(id, ...)` is equivalent to `findOneAndUpdate({ _id: id }, ...)`.
 *

You can read the source code for yourself here: https://github.com/Automattic/mongoose/blob/9ec32419fb38b74b240280aaba162f9ee4416674/lib/model.js

like image 99
Daniel Gary Avatar answered Dec 26 '22 00:12

Daniel Gary