Created
March 8, 2017 21:00
-
-
Save skleeschulte/1fc47b51863b922041bda9bb99be65da to your computer and use it in GitHub Desktop.
LoopBack 3 boot script for protecting userId properties on custom models
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
/** | |
* Add before safe hook and validation to all custom models with an userId property to prevent changing userId | |
* properties by non-admin users. | |
*/ | |
const USER_ID_PROPERTY = 'userId'; | |
const INVALID_USER_ID = -1; | |
function getBeforeSaveHook(app) { | |
return (ctx, next) => { | |
const accessToken = ctx.options.accessToken; | |
const userId = accessToken && accessToken.userId; | |
const data = ctx.instance || ctx.data; | |
if (data.hasOwnProperty(USER_ID_PROPERTY) && data.userId !== userId) { | |
const Role = app.models.Role; | |
const RoleMapping = app.models.RoleMapping; | |
Role.isInRole('admin', { principalType: RoleMapping.USER, principalId: userId }, (err, isInRole) => { | |
if (err) return next(err); | |
if (!isInRole) data.userId = INVALID_USER_ID; | |
next(); | |
}); | |
} else { | |
next(); | |
} | |
}; | |
} | |
module.exports = function(app) { | |
const builtInModels = ['User', 'AccessToken', 'ACL', 'RoleMapping', 'Role']; | |
const patchedModels = []; | |
for (let model in app.models) { | |
if (!app.models.hasOwnProperty(model)) continue; | |
// Don't patch in-built models. | |
if (builtInModels.indexOf(model) !== -1) continue; | |
model = app.models[model]; | |
// Patch models only once. | |
if (patchedModels.indexOf(model) !== -1) continue; | |
if (model.definition.properties[USER_ID_PROPERTY]) { | |
model.observe('before save', getBeforeSaveHook(app)); | |
model.validatesExclusionOf(USER_ID_PROPERTY, { in: [INVALID_USER_ID], message: 'Invalid userId.' }); | |
patchedModels.push(model); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment