Fix registration of operation hooks in User model

Operation hooks are inherited by subclassed models, therefore they must
be registered outside of `Model.setup()` function.

This commit fixes this problem in the built-in User model.

There are not tests verifying this change, as writing a test would be
too cumbersome and not worth the cost IMO.
This commit is contained in:
Miroslav Bajtoš 2016-12-09 13:16:42 +01:00
parent 63beaa21fe
commit 4edce47b24
1 changed files with 48 additions and 43 deletions

View File

@ -700,49 +700,6 @@ module.exports = function(User) {
next(); next();
}); });
// Delete old sessions once email is updated
UserModel.observe('before save', function beforeEmailUpdate(ctx, next) {
if (ctx.isNewInstance) return next();
if (!ctx.where && !ctx.instance) return next();
var where = ctx.where || {id: ctx.instance.id};
ctx.Model.find({where: where}, function(err, userInstances) {
if (err) return next(err);
ctx.hookState.originalUserData = userInstances.map(function(u) {
return {id: u.id, email: u.email};
});
if (ctx.instance) {
var emailChanged = ctx.instance.email !== ctx.hookState.originalUserData[0].email;
if (emailChanged && ctx.Model.settings.emailVerificationRequired) {
ctx.instance.emailVerified = false;
}
} else {
var emailChanged = ctx.hookState.originalUserData.some(function(data) {
return data.email != ctx.data.email;
});
if (emailChanged && ctx.Model.settings.emailVerificationRequired) {
ctx.data.emailVerified = false;
}
}
next();
});
});
UserModel.observe('after save', function afterEmailUpdate(ctx, next) {
if (!ctx.Model.relations.accessTokens) return next();
var AccessToken = ctx.Model.relations.accessTokens.modelTo;
if (!ctx.instance && !ctx.data) return next();
var newEmail = (ctx.instance || ctx.data).email;
if (!newEmail) return next();
if (!ctx.hookState.originalUserData) return next();
var idsToExpire = ctx.hookState.originalUserData.filter(function(u) {
return u.email !== newEmail;
}).map(function(u) {
return u.id;
});
if (!idsToExpire.length) return next();
AccessToken.deleteAll({userId: {inq: idsToExpire}}, next);
});
UserModel.remoteMethod( UserModel.remoteMethod(
'login', 'login',
{ {
@ -855,6 +812,54 @@ module.exports = function(User) {
*/ */
User.setup(); User.setup();
// --- OPERATION HOOKS ---
//
// Important: Operation hooks are inherited by subclassed models,
// therefore they must be registered outside of setup() function
// Delete old sessions once email is updated
User.observe('before save', function beforeEmailUpdate(ctx, next) {
if (ctx.isNewInstance) return next();
if (!ctx.where && !ctx.instance) return next();
var where = ctx.where || {id: ctx.instance.id};
ctx.Model.find({where: where}, function(err, userInstances) {
if (err) return next(err);
ctx.hookState.originalUserData = userInstances.map(function(u) {
return {id: u.id, email: u.email};
});
if (ctx.instance) {
var emailChanged = ctx.instance.email !== ctx.hookState.originalUserData[0].email;
if (emailChanged && ctx.Model.settings.emailVerificationRequired) {
ctx.instance.emailVerified = false;
}
} else {
var emailChanged = ctx.hookState.originalUserData.some(function(data) {
return data.email != ctx.data.email;
});
if (emailChanged && ctx.Model.settings.emailVerificationRequired) {
ctx.data.emailVerified = false;
}
}
next();
});
});
User.observe('after save', function afterEmailUpdate(ctx, next) {
if (!ctx.Model.relations.accessTokens) return next();
var AccessToken = ctx.Model.relations.accessTokens.modelTo;
if (!ctx.instance && !ctx.data) return next();
var newEmail = (ctx.instance || ctx.data).email;
if (!newEmail) return next();
if (!ctx.hookState.originalUserData) return next();
var idsToExpire = ctx.hookState.originalUserData.filter(function(u) {
return u.email !== newEmail;
}).map(function(u) {
return u.id;
});
if (!idsToExpire.length) return next();
AccessToken.deleteAll({userId: {inq: idsToExpire}}, next);
});
}; };
function emailValidator(err, done) { function emailValidator(err, done) {