Skip to content

Commit

Permalink
Add instance-level method
Browse files Browse the repository at this point in the history
  • Loading branch information
bajtos committed Mar 23, 2017
1 parent 4e60e62 commit 2c0ab9e
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 18 deletions.
56 changes: 38 additions & 18 deletions common/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -373,10 +373,8 @@ module.exports = function(User) {
cb = cb || utils.createPromiseCallback();

// Make sure to use the constructor of the (sub)class
// where the method is invoked from
const Ctor = this;

Ctor.findById(userId, options, function(err, inst) {
// where the method is invoked from (`this` instead of `User`)
this.findById(userId, options, (err, inst) => {
if (err) return cb(err);

if (!inst) {
Expand All @@ -388,25 +386,47 @@ module.exports = function(User) {
return cb(err);
}

inst.hasPassword(oldPassword, function(err, isMatch) {
if (err) return cb(err);
if (!isMatch) {
const err = new Error('Invalid current password');
Object.assign(err, {
code: 'INVALID_PASSWORD',
statusCode: 400,
});
return cb(err);
}

const delta = {password: newPassword};
inst.patchAttributes(delta, options, (err, updated) => cb(err));
});
inst.changePassword(oldPassword, newPassword, options, cb);
});

return cb.promise;
};

/**
* Change this user's password (prototype/instance version).
*
* @param {string} oldPassword Current password, required in order
* to strongly verify the identity of the requesting user
* @param {string} newPassword The new password to use.
* @param {object} [options]
* @callback {Function} callback
* @param {Error} err Error object
* @promise
*/
User.prototype.changePassword = function(oldPassword, newPassword, options, cb) {
if (cb === undefined && typeof options === 'function') {
cb = options;
options = undefined;
}
cb = cb || utils.createPromiseCallback();

this.hasPassword(oldPassword, (err, isMatch) => {
if (err) return cb(err);
if (!isMatch) {
const err = new Error('Invalid current password');
Object.assign(err, {
code: 'INVALID_PASSWORD',
statusCode: 400,
});
return cb(err);
}

const delta = {password: newPassword};
this.patchAttributes(delta, options, (err, updated) => cb(err));
});
return cb.promise;
};

/**
* Verify a user's identity by sending them a confirmation email.
*
Expand Down
15 changes: 15 additions & 0 deletions test/user.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1303,6 +1303,21 @@ describe('User', function() {
});
});

it('changes the password - instance method', () => {
validCredentialsUser.changePassword(currentPassword, 'new password')
.then(() => {
expect(arguments.length, 'changePassword promise resolution')
.to.equal(0);
return User.findById(userId);
})
.then(user => {
return user.hasPassword('new password');
})
.then(isMatch => {
expect(isMatch, 'user has new password').to.be.true();
});
});

it('fails when current password does not match', () => {
return User.changePassword(userId, 'bad password', 'new password').then(
success => { throw new Error('changePassword should have failed'); },
Expand Down

0 comments on commit 2c0ab9e

Please sign in to comment.