Created
September 21, 2012 21:50
-
-
Save mrvisser/3764153 to your computer and use it in GitHub Desktop.
Manually monitoring parallel permission checks
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
/** | |
* 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); | |
} | |
}); | |
} |
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
/** | |
* 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