Skip to content

Instantly share code, notes, and snippets.

@mphasize
Last active December 21, 2020 16:58
Show Gist options
  • Save mphasize/d62ad412e85bda06377c to your computer and use it in GitHub Desktop.
Save mphasize/d62ad412e85bda06377c to your computer and use it in GitHub Desktop.
A naive implementation of custom hooks to enable access control (extending the Sails blueprints).
// https://github.com/balderdashy/sails/blob/master/lib/hooks/blueprints/actionUtil.js
/**
* AccessControl proxy function, expects a Waterline query object for before* hooks and an array of records for after* hooks.
* @param {Collection} model Waterline collectio, from parseModel
* @param {String} action blueprint or hook, e.g. beforeFind, afterFind, beforeCreate, afterCreate --> translates to accessControlBeforeFind, etc.
* @param {Object} options Options: query {Query} Waterline query object for before* hooks, records: {Array} records for after* hooks, {Model} current user record
* @return {Query|Array} returns the modified query (with altered criteria) for before* or the filtered/extended record array for after*.
*/
accessControl: function ( model, action, options, callback ) {
var primaryArgument = null;
var capitaliseFirstLetter = function ( string ) {
return string.charAt( 0 ).toUpperCase() + string.slice( 1 );
};
if ( action.indexOf( "before" ) === 0 ) {
if ( !options.query ) throw new Error( "accessControl before* hook needs option: query!" );
primaryArgument = options.query;
} else if ( action.indexOf( "after" ) === 0 ) {
if ( !options.records ) throw new Error( "accessControl after* hook needs option: records!" );
primaryArgument = options.records;
} else {
throw new Error( "accessControl action '" + action + "' doesn't fit into before/after pattern." );
}
action = capitaliseFirstLetter( action );
if ( typeof model[ "control" + action ] === "function" ) {
primaryArgument = model[ "control" + action ]( primaryArgument, options, callback );
} else {
console.log( "Dev: Model " + model.identity + " is missing control " + action + "!" );
if ( callback ) {
callback( null, primaryArgument );
}
}
return primaryArgument;
}
// https://github.com/balderdashy/sails/blob/master/lib/hooks/blueprints/actions/find.js
// Before the query is executed
query = actionUtil.accessControl( Model, "beforeFind", {
query: query,
user: req.user
} );
// After the query is executed, with the results in "matchingRecords"
actionUtil.accessControl( Model, "afterFind", {
query: query,
user: req.user,
records: matchingRecords
}, function ( err, controlledRecords ) {
if ( err ) return res.serverError( err );
// wrapping:
// pubsub / subscribe
// res ... return the data
} );
// in any of the model files
controlBeforeFind: function ( query, options ) {
// modify the query criteria according to your needs
return query;
},
controlAfterFind: function ( records, options, callback ) {
// modify the records result set according to your needs
callback( err, records );
},
// controlBefore* ...
// controlAfter* ...
@demiro
Copy link

demiro commented Jun 12, 2016

how do I install/implement this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment