diff options
Diffstat (limited to 'main/app/sprinkles/account/src/Authorize')
4 files changed, 0 insertions, 504 deletions
diff --git a/main/app/sprinkles/account/src/Authorize/AccessConditionExpression.php b/main/app/sprinkles/account/src/Authorize/AccessConditionExpression.php deleted file mode 100644 index 8a8225e..0000000 --- a/main/app/sprinkles/account/src/Authorize/AccessConditionExpression.php +++ /dev/null @@ -1,138 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authorize;
-
-use Monolog\Logger;
-use PhpParser\Lexer\Emulative as EmulativeLexer;
-use PhpParser\Node;
-use PhpParser\NodeTraverser;
-use PhpParser\Parser as Parser;
-use PhpParser\PrettyPrinter\Standard as StandardPrettyPrinter;
-use PhpParser\Error as PhpParserException;
-use Psr\Http\Message\ServerRequestInterface as Request;
-use UserFrosting\Sprinkle\Account\Database\Models\User;
-
-/**
- * AccessConditionExpression class
- *
- * This class models the evaluation of an authorization condition expression, as associated with permissions.
- * A condition is built as a boolean expression composed of AccessCondition method calls.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AccessConditionExpression
-{
- /**
- * @var User A user object, which for convenience can be referenced as 'self' in access conditions.
- */
- protected $user;
-
- /**
- * @var ParserNodeFunctionEvaluator The node visitor, which evaluates access condition callbacks used in a permission condition.
- */
- protected $nodeVisitor;
-
- /**
- * @var \PhpParser\Parser The PhpParser object to use (initialized in the ctor)
- */
- protected $parser;
-
- /**
- * @var NodeTraverser The NodeTraverser object to use (initialized in the ctor)
- */
- protected $traverser;
-
- /**
- * @var StandardPrettyPrinter The PrettyPrinter object to use (initialized in the ctor)
- */
- protected $prettyPrinter;
-
- /**
- * @var Logger
- */
- protected $logger;
-
- /**
- * @var bool Set to true if you want debugging information printed to the auth log.
- */
- protected $debug;
-
- /**
- * Create a new AccessConditionExpression object.
- *
- * @param User $user A user object, which for convenience can be referenced as 'self' in access conditions.
- * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations.
- * @param bool $debug Set to true if you want debugging information printed to the auth log.
- */
- public function __construct(ParserNodeFunctionEvaluator $nodeVisitor, User $user, Logger $logger, $debug = FALSE) {
- $this->nodeVisitor = $nodeVisitor;
- $this->user = $user;
- $this->parser = new Parser(new EmulativeLexer);
- $this->traverser = new NodeTraverser;
- $this->traverser->addVisitor($nodeVisitor);
- $this->prettyPrinter = new StandardPrettyPrinter;
- $this->logger = $logger;
- $this->debug = $debug;
- }
-
- /**
- * Evaluates a condition expression, based on the given parameters.
- *
- * The special parameter `self` is an array of the current user's data.
- * This get included automatically, and so does not need to be passed in.
- * @param string $condition a boolean expression composed of calls to AccessCondition functions.
- * @param array[mixed] $params the parameters to be used when evaluating the expression.
- * @return bool true if the condition is passed for the given parameters, otherwise returns false.
- */
- public function evaluateCondition($condition, $params) {
- // Set the reserved `self` parameters.
- // This replaces any values of `self` specified in the arguments, thus preventing them from being overridden in malicious user input.
- // (For example, from an unfiltered request body).
- $params['self'] = $this->user->export();
-
- $this->nodeVisitor->setParams($params);
-
- $code = "<?php $condition;";
-
- if ($this->debug) {
- $this->logger->debug("Evaluating access condition '$condition' with parameters:", $params);
- }
-
- // Traverse the parse tree, and execute any callbacks found using the supplied parameters.
- // Replace the function node with the return value of the callback.
- try {
- // parse
- $stmts = $this->parser->parse($code);
-
- // traverse
- $stmts = $this->traverser->traverse($stmts);
-
- // Evaluate boolean statement. It is safe to use eval() here, because our expression has been reduced entirely to a boolean expression.
- $expr = $this->prettyPrinter->prettyPrintExpr($stmts[0]);
- $expr_eval = "return " . $expr . ";\n";
- $result = eval($expr_eval);
-
- if ($this->debug) {
- $this->logger->debug("Expression '$expr' evaluates to " . ($result == TRUE ? "true" : "false"));
- }
-
- return $result;
- } catch (PhpParserException $e) {
- if ($this->debug) {
- $this->logger->debug("Error parsing access condition '$condition':" . $e->getMessage());
- }
- return FALSE; // Access fails if the access condition can't be parsed.
- } catch (AuthorizationException $e) {
- if ($this->debug) {
- $this->logger->debug("Error parsing access condition '$condition':" . $e->getMessage());
- }
- return FALSE;
- }
- }
-}
diff --git a/main/app/sprinkles/account/src/Authorize/AuthorizationException.php b/main/app/sprinkles/account/src/Authorize/AuthorizationException.php deleted file mode 100644 index f93e847..0000000 --- a/main/app/sprinkles/account/src/Authorize/AuthorizationException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authorize;
-
-use UserFrosting\Support\Exception\ForbiddenException;
-
-/**
- * AuthorizationException class
- *
- * Exception for AccessConditionExpression.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- * @see http://www.userfrosting.com/components/#authorization
- */
-class AuthorizationException extends ForbiddenException
-{
-
-}
diff --git a/main/app/sprinkles/account/src/Authorize/AuthorizationManager.php b/main/app/sprinkles/account/src/Authorize/AuthorizationManager.php deleted file mode 100644 index 487881f..0000000 --- a/main/app/sprinkles/account/src/Authorize/AuthorizationManager.php +++ /dev/null @@ -1,153 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authorize;
-
-use Interop\Container\ContainerInterface;
-use UserFrosting\Sprinkle\Account\Database\Models\User;
-
-/**
- * AuthorizationManager class.
- *
- * Manages a collection of access condition callbacks, and uses them to perform access control checks on user objects.
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AuthorizationManager
-{
- /**
- * @var ContainerInterface The global container object, which holds all your services.
- */
- protected $ci;
-
- /**
- * @var array[callable] An array of callbacks that accept some parameters and evaluate to true or false.
- */
- protected $callbacks = [];
-
- /**
- * Create a new AuthorizationManager object.
- *
- * @param ContainerInterface $ci The global container object, which holds all your services.
- */
- public function __construct(ContainerInterface $ci, array $callbacks = []) {
- $this->ci = $ci;
- $this->callbacks = $callbacks;
- }
-
- /**
- * Register an authorization callback, which can then be used in permission conditions.
- *
- * To add additional callbacks, simply extend the `authorizer` service in your Sprinkle's service provider.
- * @param string $name
- * @param callable $callback
- */
- public function addCallback($name, $callback) {
- $this->callbacks[$name] = $callback;
- return $this;
- }
-
- /**
- * Get all authorization callbacks.
- *
- * @return callable[]
- */
- public function getCallbacks() {
- return $this->callbacks;
- }
-
- /**
- * Checks whether or not a user has access on a particular permission slug.
- *
- * Determine if this user has access to the given $slug under the given $params.
- *
- * @param UserFrosting\Sprinkle\Account\Database\Models\User $user
- * @param string $slug The permission slug to check for access.
- * @param array $params [optional] An array of field names => values, specifying any additional data to provide the authorization module
- * when determining whether or not this user has access.
- * @return boolean True if the user has access, false otherwise.
- */
- public function checkAccess(User $user, $slug, array $params = []) {
- $debug = $this->ci->config['debug.auth'];
-
- if ($debug) {
- $trace = array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), 1);
- $this->ci->authLogger->debug("Authorization check requested at: ", $trace);
- $this->ci->authLogger->debug("Checking authorization for user {$user->id} ('{$user->user_name}') on permission '$slug'...");
- }
-
- if ($this->ci->authenticator->guest()) {
- if ($debug) {
- $this->ci->authLogger->debug("User is not logged in. Access denied.");
- }
- return FALSE;
- }
-
- // The master (root) account has access to everything.
- // Need to use loose comparison for now, because some DBs return `id` as a string.
-
- if ($user->id == $this->ci->config['reserved_user_ids.master']) {
- if ($debug) {
- $this->ci->authLogger->debug("User is the master (root) user. Access granted.");
- }
- return TRUE;
- }
-
- // Find all permissions that apply to this user (via roles), and check if any evaluate to true.
- $permissions = $user->getCachedPermissions();
-
- if (empty($permissions) || !isset($permissions[$slug])) {
- if ($debug) {
- $this->ci->authLogger->debug("No matching permissions found. Access denied.");
- }
- return FALSE;
- }
-
- $permissions = $permissions[$slug];
-
- if ($debug) {
- $this->ci->authLogger->debug("Found matching permissions: \n" . print_r($this->getPermissionsArrayDebugInfo($permissions), TRUE));
- }
-
- $nodeVisitor = new ParserNodeFunctionEvaluator($this->callbacks, $this->ci->authLogger, $debug);
- $ace = new AccessConditionExpression($nodeVisitor, $user, $this->ci->authLogger, $debug);
-
- foreach ($permissions as $permission) {
- $pass = $ace->evaluateCondition($permission->conditions, $params);
- if ($pass) {
- if ($debug) {
- $this->ci->authLogger->debug("User passed conditions '{$permission->conditions}' . Access granted.");
- }
- return TRUE;
- }
- }
-
- if ($debug) {
- $this->ci->authLogger->debug("User failed to pass any of the matched permissions. Access denied.");
- }
-
- return FALSE;
- }
-
- /**
- * Remove extraneous information from the permission to reduce verbosity.
- *
- * @param array
- * @return array
- */
- protected function getPermissionsArrayDebugInfo($permissions) {
- $permissionsInfo = [];
- foreach ($permissions as $permission) {
- $permissionData = array_only($permission->toArray(), ['id', 'slug', 'name', 'conditions', 'description']);
- // Remove this until we can find an efficient way to only load these once during debugging
- //$permissionData['roles_via'] = $permission->roles_via->pluck('id')->all();
- $permissionsInfo[] = $permissionData;
- }
-
- return $permissionsInfo;
- }
-}
diff --git a/main/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php b/main/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php deleted file mode 100644 index af26d9a..0000000 --- a/main/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php +++ /dev/null @@ -1,189 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authorize;
-
-use Monolog\Logger;
-use PhpParser\Node;
-use PhpParser\NodeVisitorAbstract;
-use PhpParser\PrettyPrinter\Standard as StandardPrettyPrinter;
-
-/**
- * ParserNodeFunctionEvaluator class
- *
- * This class parses access control condition expressions.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- * @see http://www.userfrosting.com/components/#authorization
- */
-class ParserNodeFunctionEvaluator extends NodeVisitorAbstract
-{
-
- /**
- * @var array[callable] An array of callback functions to be used when evaluating a condition expression.
- */
- protected $callbacks;
- /**
- * @var \PhpParser\PrettyPrinter\Standard The PrettyPrinter object to use (initialized in the ctor)
- */
- protected $prettyPrinter;
- /**
- * @var array The parameters to be used when evaluating the methods in the condition expression, as an array.
- */
- protected $params = [];
-
- /**
- * @var Logger
- */
- protected $logger;
-
- /**
- * @var bool Set to true if you want debugging information printed to the auth log.
- */
- protected $debug;
-
- /**
- * Create a new ParserNodeFunctionEvaluator object.
- *
- * @param array $params The parameters to be used when evaluating the methods in the condition expression, as an array.
- * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations.
- * @param bool $debug Set to true if you want debugging information printed to the auth log.
- */
- public function __construct($callbacks, $logger, $debug = FALSE) {
- $this->callbacks = $callbacks;
- $this->prettyPrinter = new StandardPrettyPrinter;
- $this->logger = $logger;
- $this->debug = $debug;
- $this->params = [];
- }
-
- public function leaveNode(Node $node) {
- // Look for function calls
- if ($node instanceof \PhpParser\Node\Expr\FuncCall) {
- $eval = new \PhpParser\Node\Scalar\LNumber;
-
- // Get the method name
- $callbackName = $node->name->toString();
- // Get the method arguments
- $argNodes = $node->args;
-
- $args = [];
- $argsInfo = [];
- foreach ($argNodes as $arg) {
- $argString = $this->prettyPrinter->prettyPrintExpr($arg->value);
-
- // Debugger info
- $currentArgInfo = [
- 'expression' => $argString
- ];
- // Resolve parameter placeholders ('variable' names (either single-word or array-dot identifiers))
- if (($arg->value instanceof \PhpParser\Node\Expr\BinaryOp\Concat) || ($arg->value instanceof \PhpParser\Node\Expr\ConstFetch)) {
- $value = $this->resolveParamPath($argString);
- $currentArgInfo['type'] = "parameter";
- $currentArgInfo['resolved_value'] = $value;
- // Resolve arrays
- } else if ($arg->value instanceof \PhpParser\Node\Expr\Array_) {
- $value = $this->resolveArray($arg);
- $currentArgInfo['type'] = "array";
- $currentArgInfo['resolved_value'] = print_r($value, TRUE);
- // Resolve strings
- } else if ($arg->value instanceof \PhpParser\Node\Scalar\String_) {
- $value = $arg->value->value;
- $currentArgInfo['type'] = "string";
- $currentArgInfo['resolved_value'] = $value;
- // Resolve numbers
- } else if ($arg->value instanceof \PhpParser\Node\Scalar\DNumber) {
- $value = $arg->value->value;
- $currentArgInfo['type'] = "float";
- $currentArgInfo['resolved_value'] = $value;
- } else if ($arg->value instanceof \PhpParser\Node\Scalar\LNumber) {
- $value = $arg->value->value;
- $currentArgInfo['type'] = "integer";
- $currentArgInfo['resolved_value'] = $value;
- // Anything else is simply interpreted as its literal string value
- } else {
- $value = $argString;
- $currentArgInfo['type'] = "unknown";
- $currentArgInfo['resolved_value'] = $value;
- }
-
- $args[] = $value;
- $argsInfo[] = $currentArgInfo;
- }
-
- if ($this->debug) {
- if (count($args)) {
- $this->logger->debug("Evaluating callback '$callbackName' on: ", $argsInfo);
- } else {
- $this->logger->debug("Evaluating callback '$callbackName'...");
- }
- }
-
- // Call the specified access condition callback with the specified arguments.
- if (isset($this->callbacks[$callbackName]) && is_callable($this->callbacks[$callbackName])) {
- $result = call_user_func_array($this->callbacks[$callbackName], $args);
- } else {
- throw new AuthorizationException("Authorization failed: Access condition method '$callbackName' does not exist.");
- }
-
- if ($this->debug) {
- $this->logger->debug("Result: " . ($result ? "1" : "0"));
- }
-
- return new \PhpParser\Node\Scalar\LNumber($result ? "1" : "0");
- }
- }
-
- public function setParams($params) {
- $this->params = $params;
- }
-
- /**
- * Resolve an array expression in a condition expression into an actual array.
- *
- * @param string $arg the array, represented as a string.
- * @return array[mixed] the array, as a plain ol' PHP array.
- */
- private function resolveArray($arg) {
- $arr = [];
- $items = (array)$arg->value->items;
- foreach ($items as $item) {
- if ($item->key) {
- $arr[$item->key] = $item->value->value;
- } else {
- $arr[] = $item->value->value;
- }
- }
- return $arr;
- }
-
- /**
- * Resolve a parameter path (e.g. "user.id", "post", etc) into its value.
- *
- * @param string $path the name of the parameter to resolve, based on the parameters set in this object.
- * @throws Exception the path could not be resolved. Path is malformed or key does not exist.
- * @return mixed the value of the specified parameter.
- */
- private function resolveParamPath($path) {
- $pathTokens = explode(".", $path);
- $value = $this->params;
- foreach ($pathTokens as $token) {
- $token = trim($token);
- if (is_array($value) && isset($value[$token])) {
- $value = $value[$token];
- continue;
- } else if (is_object($value) && isset($value->$token)) {
- $value = $value->$token;
- continue;
- } else {
- throw new AuthorizationException("Cannot resolve the path \"$path\". Error at token \"$token\".");
- }
- }
- return $value;
- }
-}
|