sethetter/j-app

How would you change the User model to allow for a password to be updated?

Opened this issue · 4 comments

Your User model is fine for a very simple case but in the real-world people will need to be able to change their passwords.

Given you can't access model methods from within the beforeCreate and beforeSave methods, and with a view to maintaining DRYness as much as possible, what changes would you make to your User model such that when a user's password is updated it's properly hashed. Obviously just changing beforeCreate to beforeSave is not going to work as then the password will be rehashed every time it's saved.

There are a number of ways to do this but I'm wondering what the best-practice, DRY way would be.

@davesag I imagine using a beforeSave hook would work if you just check if a password is provided in the body of the request. If the password is sent with it then we can assume an update is being attempted, otherwise do nothing.

@davesag Also, I'll apologize for having little activity on this project for awhile. I should be getting back to the article series soon as time permits.

Here's how I ended up doing it

var bcrypt = require('bcrypt');

function hashPassword(password, errCallback, successCallback) {
  bcrypt.genSalt(10, function(err, salt) {
    if (err) return errCallback(err);

    bcrypt.hash(password, salt, function(err, hash) {
      if (err) return errCallback(err);
      return successCallback(hash);
    });
  });
}

module.exports = {

  beforeCreate: function (attrs, next) {
    // ensure the password is properly encrypted
    hashPassword(attrs.password, function(err){
      sails.log.error('Caught error while hashing password', err);
      return next(err);
    }, function(hash){
      attrs.password = hash;
      return next();
    });
  },

  attributes: {

    email: {
      type: 'string',
      unique: true,
      required: true
    },

    password: {
      type: 'string',
      required: true,
      minLength: 6
    },

    updatePassword: function(password, next) {
      var attrs = this;
      hashPassword(attrs.password, function(err){
        sails.log.error('Caught error while hashing password', err);
        return next(err);
      }, function(hash){
        attrs.password = hash;
        return next();
      });
    },

    // strip out password from JSON representation of the User
    toJSON: function() {
      var obj = this.toObject();
      delete obj.password;
      return obj;
    }    
  }

};

Very nice. Thanks for sharing :)
On May 12, 2014 5:05 PM, "Dave Sag" notifications@github.com wrote:

Here's how I ended up doing it

var bcrypt = require('bcrypt');

function hashPassword(password, errCallback, successCallback) {
bcrypt.genSalt(10, function(err, salt) {
if (err) return errCallback(err);

bcrypt.hash(password, salt, function(err, hash) {
  if (err) return errCallback(err);
  return successCallback(hash);
});

});
}

module.exports = {

beforeCreate: function (attrs, next) {
// ensure the password is properly encrypted
hashPassword(attrs.password, function(err){
sails.log.error('Caught error while hashing password', err);
return next(err);
}, function(hash){
attrs.password = hash;
return next();
});
},

attributes: {

email: {
  type: 'string',
  unique: true,
  required: true
},

password: {
  type: 'string',
  required: true,
  minLength: 6
},

updatePassword: function(password, next) {
  var attrs = this;
  hashPassword(attrs.password, function(err){
    sails.log.error('Caught error while hashing password', err);
    return next(err);
  }, function(hash){
    attrs.password = hash;
    return next();
  });
},

// strip out password from JSON representation of the User
toJSON: function() {
  var obj = this.toObject();
  delete obj.password;
  return obj;
}

}

};


Reply to this email directly or view it on GitHubhttps://github.com//issues/3#issuecomment-42894569
.