@inspire-platform/sails-hook-permissions
Version:
Comprehensive user permissions and entitlements system for sails.js and Waterline. Supports user authentication with passport.js, role-based permissioning, object ownership, and row-level security.
81 lines (66 loc) • 2.44 kB
JavaScript
/**
* RolePolicy
* @depends PermissionPolicy
* @depends OwnerPolicy
* @depends ModelPolicy
*
* Verify that User is satisfactorily related to the Object's owner.
* By this point, we know we have some permissions related to the action and object
* If they are 'owner' permissions, verify that the objects that are being accessed are owned by the current user
*/
import _ from 'lodash'
module.exports = function(req, res, next) {
// can't apply policy to unknown model
if (req.options.unknownModel) {
return next();
}
var action = PermissionService.getMethod(req.method);
var relations = _.groupBy(req.permissions, 'relation');
// do any role or user permissions exist which grant the asserted privilege?
if (
false === _.isEmpty(relations.role) ||
false === _.isEmpty(relations.user)
) {
// yes, continue
return next();
}
//
// If we made it this far, we are dealing with object owner permissions
//
if (true === _.has(req.options, 'modelDefinition.attributes.owner')) {
// are we creating?
if ('create' === action) {
// owner permission never allows create
return res.send(403, {
error: 'Cannot perform action [create] without role or user based permission'
});
}
// are we mutating?
if (true === _.contains(['update', 'delete'], action)) {
// yes, find objects that would be modified/deleted.
return PermissionService.findTargetObjects(req)
.then(function (objects) {
if (PermissionService.hasForeignObjects(objects, req.user)) {
return res.send(403, {
error: 'Cannot perform action [' + action + ']. Authenticated user does not own one or more target objects.'
});
} else {
return next();
}
}).catch(next);
}
// This block allows us to filter reads by the owner attribute, rather than failing an entire request
// if some of the results are not owned by the user.
req.params.all().where = req.params.all().where || {};
req.params.all().where.owner = req.user.id;
req.query.owner = req.user.id;
_.isObject(req.body) && (req.body.owner = req.user.id);
// not mutating
return next();
} else {
// no owner attribute on model!
return res.send(403, {
error: `Cannot apply owner permission policy to model ${req.method} due to missing "owner" attribute.`
});
}
};