Luja Shrestha
Luja Shrestha

Reputation: 2847

conditional beforeUpdate in sails

I need to encrypt the password only if some criteria is fullfilled.

beforeUpdate: function (value, cb) {
User.findOne(value.id)
  .exec(function (err, originalUser) {
    if (err || !originalUser) {
      return cb();
    }
    //encrypt the password only if the password is not previously encrypted
    if (value.password != originalUser.password) {
       //encrypt the Pwd
    } else {
      cb();
    }
  });

} The problem is that, the value object only contains the update params, how can I get the whole user object in the value object?

Upvotes: 3

Views: 3450

Answers (6)

hasan3050
hasan3050

Reputation: 195

After the update of async, this method does not work anymore.

You can not get the whole object inside beforeUpdate. You can try this to get the id. var id= this.update.arguments[0]

Upvotes: 5

GeekLad
GeekLad

Reputation: 478

I was also trying to do something similar: save the password to the associated passport record. I'm using the sails-auth and sails-permissions modules, which includes passport.

I was finally able to do it by using the afterValidate lifecycle callback instead of beforeUpdate callback. In the afterValidate callback, you can access the user model using this.user.

Here's the code I put into my afterValidate callback where I save the password passed in using the Passport model:

afterValidate: function(updates, next) {
  // Update the passport password if it was passed in
  if(updates.password) {
    Passport.update({user: this.user.id}, {password: updates.password}).exec(function(err, passport) {
      next(err);
    });
  }
  else {
    next();
  }
}

Upvotes: 1

Telgin
Telgin

Reputation: 1604

To expand on what user3036010 suggested, I ended up creating a new policy like this:

In api/policies/propagateId.js:

module.exports = function(req, res, next) {
    var id = req.param('id');
    if (id && req.body) {
        req.body.id = id;
    }

    next();
};

Then set up your api/config/policies.js file to apply the policy by default to all controllers and actions:

module.exports.policies = {
    '*': 'propagateId'
};

What this does is it forces the id property to be set on the document body, which tricks the update action into thinking that the id was manually specified. For whatever reason, there is a block of code in the update action that checks for this, and if the id is not manually specified it will remove it from the values.

This is sort of an abuse of policies, but it seems to work fine for me. If you don't want to do it this way, it looks like manually specifying id in your request body every time you make an update API request should work too.

Upvotes: 2

Vijay Rajasekaran
Vijay Rajasekaran

Reputation: 613

Now, only if you send password: password in the Update method, it will update the password (hash and store) else it will only update the provided user fields.

Controller(UserController.js):

updateDisplayName: function(req, res) {

var userid = req.token;
var newDisplayName = req.param('newdisplayname');

User.update({id: userid},{displayname: newDisplayName}).exec(function afterwards(err,updated){

if (err) {
res.json(err);
} else {
res.json("Success");
}
});

},

Model(User.js):

beforeUpdate: function(values, next) {
if(values.password) {
hashPassword(values, next);
} else {
next();
}
},

Upvotes: 1

Meeker
Meeker

Reputation: 5979

Just use lodash to extend value with originalUser. Or for this use case you can always just check if the pasword is already hashed if you using node bcrypt or something

Upvotes: 1

Darkest
Darkest

Reputation: 49

I'm not sure why you need this in the value object here, but you may create a custom policy that will get the whole user object and send in 'next()' callback to update;

Upvotes: 1

Related Questions