Skip to content
Snippets Groups Projects
Commit 02dc9068 authored by Reiter, Christoph's avatar Reiter, Christoph :snake:
Browse files

authz: split the authz classes up for easier testing

One class for muxing the attribute data, one for evaluating the
expression and one for the user.
parent 996fc7d4
No related branches found
No related tags found
No related merge requests found
......@@ -10,7 +10,7 @@ use Symfony\Component\HttpFoundation\Response;
abstract class AbstractAuthorizationService
{
/** @var UserAuthorizationChecker */
/** @var AuthorizationExpressionChecker */
private $userAuthorizationChecker;
/** @var AuthorizationUser|null */
......@@ -18,8 +18,9 @@ abstract class AbstractAuthorizationService
public function __construct(UserSessionInterface $userSession, AuthorizationDataProviderProvider $authorizationDataProviderProvider)
{
$this->userAuthorizationChecker = new UserAuthorizationChecker($userSession->getUserIdentifier(), $authorizationDataProviderProvider);
$this->currentAuthorizationUser = new AuthorizationUser($this->userAuthorizationChecker);
$muxer = new AuthorizationDataMuxer($authorizationDataProviderProvider->getAuthorizationDataProviders());
$this->userAuthorizationChecker = new AuthorizationExpressionChecker($muxer);
$this->currentAuthorizationUser = new AuthorizationUser($userSession->getUserIdentifier(), $this->userAuthorizationChecker);
}
public function setConfig(array $config)
......
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\Authorization;
class AuthorizationDataMuxer
{
/** @var iterable */
private $authorizationDataProviders;
/** @var array */
private $customAttributes;
/**
* @param iterable<AuthorizationDataProviderInterface> $authorizationDataProviders
*/
public function __construct(iterable $authorizationDataProviders)
{
$this->authorizationDataProviders = $authorizationDataProviders;
$this->customAttributes = [];
}
private function loadUserAttributesFromAuthorizationProvider(?string $userIdentifier, AuthorizationDataProviderInterface $authorizationDataProvider): void
{
$userAttributes = [];
if ($userIdentifier !== null) {
$userAttributes = $authorizationDataProvider->getUserAttributes($userIdentifier);
}
foreach ($authorizationDataProvider->getAvailableAttributes() as $availableAttribute) {
$this->customAttributes[$availableAttribute] = $userAttributes[$availableAttribute] ?? null;
}
}
/**
* @param mixed|null $defaultValue
*
* @return mixed|null
*
* @throws AuthorizationException
*/
public function getCustomAttribute(?string $userIdentifier, string $attributeName, $defaultValue = null)
{
if (array_key_exists($attributeName, $this->customAttributes) === false) {
$this->loadCustomAttribute($userIdentifier, $attributeName);
}
return $this->customAttributes[$attributeName] ?? $defaultValue;
}
/**
* @throws AuthorizationException
*/
private function loadCustomAttribute(?string $userIdentifier, string $attributeName): void
{
$wasFound = false;
foreach ($this->authorizationDataProviders as $authorizationDataProvider) {
$availableAttributes = $authorizationDataProvider->getAvailableAttributes();
if (in_array($attributeName, $availableAttributes, true)) {
$this->loadUserAttributesFromAuthorizationProvider($userIdentifier, $authorizationDataProvider);
$wasFound = true;
break;
}
}
if ($wasFound === false) {
throw new AuthorizationException(sprintf('custom attribute \'%s\' undefined', $attributeName), AuthorizationException::ATTRIBUTE_UNDEFINED);
}
}
}
......@@ -5,27 +5,17 @@ declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\Authorization;
use Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage\ExpressionLanguage;
use Dbp\Relay\CoreBundle\Helpers\Tools;
class UserAuthorizationChecker
class AuthorizationExpressionChecker
{
public const RIGHTS_CONFIG_ATTRIBUTE = 'rights';
public const ATTRIBUTES_CONFIG_ATTRIBUTE = 'attributes';
private const MAX_NUM_CALLS = 16;
/** @var ?string */
private $currentUserIdentifier;
/** @var iterable */
private $authorizationDataProviders;
/** @var ExpressionLanguage */
private $expressionLanguage;
/** @var array */
private $customAttributes;
/** @var array */
private $rightExpressions;
......@@ -35,16 +25,16 @@ class UserAuthorizationChecker
/** @var int */
private $callCounter;
public function __construct(?string $userIdentifier, AuthorizationDataProviderProvider $authorizationDataProviderProvider)
/** @var AuthorizationDataMuxer */
private $dataMux;
public function __construct(AuthorizationDataMuxer $dataMux)
{
$this->currentUserIdentifier = $userIdentifier;
$this->authorizationDataProviders = $authorizationDataProviderProvider->getAuthorizationDataProviders();
$this->expressionLanguage = new ExpressionLanguage();
$this->customAttributes = [];
$this->rightExpressions = [];
$this->attributeExpressions = [];
$this->dataMux = $dataMux;
}
public function setConfig(array $config)
......@@ -58,11 +48,6 @@ class UserAuthorizationChecker
$this->callCounter = 0;
}
public function getCurrentUserIdentifier(): ?string
{
return $this->currentUserIdentifier;
}
/**
* @param mixed|null $defaultValue
*
......@@ -92,11 +77,7 @@ class UserAuthorizationChecker
*/
public function getCustomAttribute(AuthorizationUser $currentAuthorizationUser, string $attributeName, $defaultValue = null)
{
if (array_key_exists($attributeName, $this->customAttributes) === false) {
$this->loadCustomAttribute($attributeName);
}
return $this->customAttributes[$attributeName] ?? $defaultValue;
return $this->dataMux->getCustomAttribute($currentAuthorizationUser->getIdentifier(), $attributeName, $defaultValue);
}
/**
......@@ -127,39 +108,6 @@ class UserAuthorizationChecker
}
}
/**
* @throws AuthorizationException
*/
private function loadCustomAttribute(string $attributeName): void
{
$wasFound = false;
foreach ($this->authorizationDataProviders as $authorizationDataProvider) {
$availableAttributes = $authorizationDataProvider->getAvailableAttributes();
if (in_array($attributeName, $availableAttributes, true)) {
$this->loadUserAttributesFromAuthorizationProvider($authorizationDataProvider);
$wasFound = true;
break;
}
}
if ($wasFound === false) {
throw new AuthorizationException(sprintf('custom attribute \'%s\' undefined', $attributeName), AuthorizationException::ATTRIBUTE_UNDEFINED);
}
}
private function loadUserAttributesFromAuthorizationProvider(AuthorizationDataProviderInterface $authorizationDataProvider): void
{
$userAttributes = [];
if (Tools::isNullOrEmpty($this->currentUserIdentifier) === false) {
$userAttributes = $authorizationDataProvider->getUserAttributes($this->currentUserIdentifier);
}
foreach ($authorizationDataProvider->getAvailableAttributes() as $availableAttribute) {
$this->customAttributes[$availableAttribute] = $userAttributes[$availableAttribute] ?? null;
}
}
/**
* @throws AuthorizationException
*/
......
......@@ -9,17 +9,23 @@ namespace Dbp\Relay\CoreBundle\Authorization;
*/
class AuthorizationUser
{
/** @var UserAuthorizationChecker */
/** @var AuthorizationExpressionChecker */
private $authorizationChecker;
public function __construct(UserAuthorizationChecker $authorizationChecker)
/**
* @var string|null
*/
private $identifier;
public function __construct(?string $identifier, AuthorizationExpressionChecker $authorizationChecker)
{
$this->authorizationChecker = $authorizationChecker;
$this->identifier = $identifier;
}
public function getIdentifier(): ?string
{
return $this->authorizationChecker->getCurrentUserIdentifier();
return $this->identifier;
}
/**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment