diff --git a/src/Authorize/AuthorizationManager.php b/src/Authorize/AuthorizationManager.php new file mode 100644 index 0000000..5f8ca44 --- /dev/null +++ b/src/Authorize/AuthorizationManager.php @@ -0,0 +1,94 @@ +ci->config['debug.auth']; + $logger = $this->ci->authLogger; + + if (is_null($user) || !($user instanceof UserInterface)) { + if ($debug) { + $this->ci->authLogger->debug('No user defined. 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; + } + + 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}') against check '$name'..."); + } + + if (!array_key_exists($name, $this->callbacks) || !isset($this->callbacks[$name])) { + if ($debug) { + $this->ci->authLogger->debug('No matching callback found. Access denied.'); + } + + return false; + } + + try { + if ($debug) { + $this->ci->authLogger->debug("Calling check '{$name}' with arguments:", $args); + } + + $result = call_user_func_array($this->callbacks[$name], $args); + + if ($result === true) { + if ($debug) { + $this->ci->authLogger->debug("User passed check '{$name}'. Access granted."); + } + + return true; + } + + return $result; + } catch (Exception $e) { + if ($this->debug) { + $this->logger->debug("Error running check '$name':" . $e->getMessage() . ". Access denied."); + } + + return false; + } + } +} diff --git a/src/ServicesProvider/ServicesProvider.php b/src/ServicesProvider/ServicesProvider.php index 8d80a81..2adf14b 100644 --- a/src/ServicesProvider/ServicesProvider.php +++ b/src/ServicesProvider/ServicesProvider.php @@ -14,6 +14,7 @@ use Psr\Container\ContainerInterface; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use UserFrosting\Sprinkle\Organisations\Database\Models\Interfaces\OrganisationInterface as OrganisationInterface; +use UserFrosting\Sprinkle\Organisations\Authorize\AuthorizationManager; /** * Registers services for the organisation sprinkle. @@ -51,6 +52,9 @@ class ServicesProvider * @return \UserFrosting\Sprinkle\Core\Util\ClassMapper */ $container->extend('authorizer', function ($authorizer, $c) { + + $new_authorizer = new AuthorizationManager($c, $authorizer->getCallbacks()); + /* * Check if all $user is a member of $organisation. * @@ -58,7 +62,7 @@ class ServicesProvider * @param int $organisation_id the id of the target organisation. * @return bool true if $user is a member of $organisation. */ - $authorizer->addCallback('is_organisation_member', function ($user_id, $organisation_id) { + $new_authorizer->addCallback('is_organisation_member', function ($user_id, $organisation_id) { return Capsule::table('organisation_members') ->where('user_id', $user_id) ->where('organisation_id', $organisation_id) @@ -72,15 +76,15 @@ class ServicesProvider * @param int $organisation_id the id of the target organisation. * @return bool true if $user is an administrator of $organisation. */ - $authorizer->addCallback('is_organisation_admin', function ($user_id, $organisation_id) { + $new_authorizer->addCallback('is_organisation_admin', function ($user_id, $organisation_id) { return Capsule::table('organisation_members') ->where('user_id', $user_id) ->where('organisation_id', $organisation_id) ->where('flag_admin', true) ->count() > 0; }); - - return $authorizer; + + return $new_authorizer; }); /*