Skip to content

Instantly share code, notes, and snippets.

@mrvisser
Created September 21, 2012 21:50
Show Gist options
  • Save mrvisser/3764153 to your computer and use it in GitHub Desktop.
Save mrvisser/3764153 to your computer and use it in GitHub Desktop.
Manually monitoring parallel permission checks
/**
* Determine whether or not one of the principals in the array of principalUuids is able to perform the action on the
* resource specified. If the action is null, then we will determine if the user can perform *any* action on the
* resource specified.
*
* @param {Array<String>} principalUuids The array of principals to check
* @param {String} action The action to check. If null, check for any action.
* @param {String} resourceUuid The resource to check
* @param {Function(err, isAllowed)} callback A function invoked when the process is complete.
* @param {Object} callback.err An error that occured, if any
* @param {Boolean} callback.isAllowed Whether or not one of the principals is authorized to perform the action
*/
var _isAllowed = function(principalUuids, action, resourceUuid, callback) {
// variables for monitoring the progress of permissions checks
var returned = false;
var handleEach = function(principaUuid, forEachCallback) {
var handleRole = function(err, isAllowed) {
if (err) {
return forEachCallback(err);
} else if (!returned && isAllowed) {
returned = true;
// short circuit
callback(null, true);
return forEachCallback(null);
} else {
return forEachCallback(null);
}
}
if (action !== null) {
hasRole(principalUuid, resourceUuid, action, handleRole);
} else {
getRole(principalUuid, resourceUuid, handleRole);
}
};
async.forEachLimit(principalUuids, 10, handleEach, function(err) {
if (err && !returned) {
return callback(err);
}
if (!returned) {
return callback(null, false);
}
});
}
/**
* Determine whether or not one of the principals in the array of principalUuids is able to perform the action on the
* resource specified. If the action is null, then we will determine if the user can perform *any* action on the
* resource specified.
*
* @param {Array<String>} principalUuids The array of principals to check
* @param {String} action The action to check. If null, check for any action.
* @param {String} resourceUuid The resource to check
* @param {Function(err, isAllowed)} callback A function invoked when the process is complete.
* @param {Object} callback.err An error that occured, if any
* @param {Boolean} callback.isAllowed Whether or not one of the principals is authorized to perform the action
*/
var _isAllowed = function(principalUuids, action, resourceUuid, callback) {
// short circuit if there is no ancestry
if (principalUuids.length === 0) {
return callback(null, false);
}
// variables for monitoring the progress of permissions checks
var index = 0;
var isAllowedResult = false;
var errResult = false;
// this function monitors the progress of asynchronous permissions checks, calling back to the caller when appropriate
var checkStatus = function(err, isAllowed) {
if (errResult || isAllowedResult) {
// do nothing, because we've already finished executing and called the callback
} else if (err) {
// we got an error while executing, call back with the error
errResult = err;
return callback(errResult);
} else if (isAllowed) {
// one of the principals is allowed to perform the action, short circuit
isAllowedResult = isAllowed;
return callback(null, isAllowedResult);
} else {
index++;
if (index >= principalUuids.length) {
// we've reached the end of the check and none are allowed, return false
return callback(null, false);
}
}
}
// invoke the entire ancestry asynchronously. checkStatus will determine the result and when it is possible to call back.
principalUuids.forEach(function(principalUuid) {
if (action !== null) {
hasRole(principalUuid, resourceUuid, action, checkStatus);
} else {
// we pass checkStatus directly here on the basis that the 'isAllowed' parameter is a duck-check and not strictly typed.
getRole(principalUuid, resourceUuid, checkStatus);
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment