Skip to content

Commit 05db433

Browse files
committed
Preserve sessions on User.save() making no changes
1 parent 50743e9 commit 05db433

File tree

2 files changed

+19
-23
lines changed

2 files changed

+19
-23
lines changed

common/models/user.js

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -866,30 +866,16 @@ module.exports = function(User) {
866866
next();
867867
});
868868

869-
// Delete old sessions once email is updated
870-
User.observe('before save', function beforeEmailUpdate(ctx, next) {
869+
User.observe('before save', function prepareForTokenInvalidation(ctx, next) {
871870
if (!ctx.Model.app.get('logoutSessionsOnSensitiveChanges')) return next();
872871

873-
var emailChanged;
874872
if (ctx.isNewInstance) return next();
875873
if (!ctx.where && !ctx.instance) return next();
876-
var pkName = ctx.Model.definition.idName() || 'id';
877-
878-
var isPartialUpdateChangingPassword = ctx.data && 'password' in ctx.data;
879-
880-
// Full replace of User instance => assume password change.
881-
// HashPassword returns a different value for each invocation,
882-
// therefore we cannot tell whether ctx.instance.password is the same
883-
// or not.
884-
var isFullReplaceChangingPassword = !!ctx.instance;
885874

886-
ctx.hookState.isPasswordChange = isPartialUpdateChangingPassword ||
887-
isFullReplaceChangingPassword;
875+
var pkName = ctx.Model.definition.idName() || 'id';
888876

889-
var where;
890-
if (ctx.where) {
891-
where = ctx.where;
892-
} else {
877+
var where = ctx.where;
878+
if (!where) {
893879
where = {};
894880
where[pkName] = ctx.instance[pkName];
895881
}
@@ -899,9 +885,11 @@ module.exports = function(User) {
899885
ctx.hookState.originalUserData = userInstances.map(function(u) {
900886
var user = {};
901887
user[pkName] = u[pkName];
902-
user['email'] = u['email'];
888+
user.email = u.email;
889+
user.password = u.password;
903890
return user;
904891
});
892+
var emailChanged;
905893
if (ctx.instance) {
906894
emailChanged = ctx.instance.email !== ctx.hookState.originalUserData[0].email;
907895
if (emailChanged && ctx.Model.settings.emailVerificationRequired) {
@@ -920,20 +908,21 @@ module.exports = function(User) {
920908
});
921909
});
922910

923-
User.observe('after save', function afterEmailUpdate(ctx, next) {
911+
User.observe('after save', function invalidateOtherTokens(ctx, next) {
924912
if (!ctx.Model.app.get('logoutSessionsOnSensitiveChanges')) return next();
925913

926914
if (!ctx.instance && !ctx.data) return next();
927915
if (!ctx.hookState.originalUserData) return next();
928916

929917
var pkName = ctx.Model.definition.idName() || 'id';
930918
var newEmail = (ctx.instance || ctx.data).email;
931-
var isPasswordChange = ctx.hookState.isPasswordChange;
919+
var newPassword = (ctx.instance || ctx.data).password;
932920

933-
if (!newEmail && !isPasswordChange) return next();
921+
if (!newEmail && !newPassword) return next();
934922

935923
var userIdsToExpire = ctx.hookState.originalUserData.filter(function(u) {
936-
return (newEmail && u.email !== newEmail) || isPasswordChange;
924+
return (newEmail && u.email !== newEmail) ||
925+
(newPassword && u.password !== newPassword);
937926
}).map(function(u) {
938927
return u[pkName];
939928
});

test/user.test.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2097,6 +2097,13 @@ describe('User', function() {
20972097
});
20982098
});
20992099

2100+
it('keeps sessions AS IS when calling save() with no changes', function(done) {
2101+
user.save(function(err) {
2102+
if (err) return done(err);
2103+
assertPreservedTokens(done);
2104+
});
2105+
});
2106+
21002107
it('keeps sessions AS IS if firstName is added using `updateOrCreate`', function(done) {
21012108
User.updateOrCreate({
21022109
pk: user.pk,

0 commit comments

Comments
 (0)