Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
No results found
Select Git revision
Show changes
Commits on Source (4)
......@@ -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 = $authorizationDataProvider->getUserAttributes($userIdentifier);
foreach ($authorizationDataProvider->getAvailableAttributes() as $availableAttribute) {
if (array_key_exists($availableAttribute, $userAttributes)) {
$this->customAttributes[$availableAttribute] = $userAttributes[$availableAttribute];
}
}
}
/**
* Returns an array of available attributes.
*
* @return string[]
*/
public function getAvailableAttributes(): array
{
$res = [];
foreach ($this->authorizationDataProviders as $authorizationDataProvider) {
$availableAttributes = $authorizationDataProvider->getAvailableAttributes();
$res = array_merge($res, $availableAttributes);
}
return $res;
}
/**
* @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);
}
}
}
......@@ -7,9 +7,20 @@ namespace Dbp\Relay\CoreBundle\Authorization;
interface AuthorizationDataProviderInterface
{
/**
* Returns a list of available attributes.
*
* @return string[]
*/
public function getAvailableAttributes(): array;
public function getUserAttributes(string $userIdentifier): array;
/**
* Returns an array of attribute names and values.
* In case an attribute has no value then it isn't contained.
*
* In case $userIdentifier is null then there is no active user and
* only globally available attributes shold be returned.
*
* @return array<string, mixed>
*/
public function getUserAttributes(?string $userIdentifier): array;
}
......@@ -6,7 +6,6 @@ namespace Dbp\Relay\CoreBundle\Authorization;
class AuthorizationException extends \RuntimeException
{
public const ROLE_UNDEFINED = 1;
public const PRIVILEGE_UNDEFINED = 2;
public const ATTRIBUTE_UNDEFINED = 3;
public const INFINITE_LOOP_DETECTED = 4;
......
......@@ -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;
}
/**
......
......@@ -37,32 +37,26 @@ class DebugCommand extends Command implements LoggerAwareInterface
protected function execute(InputInterface $input, OutputInterface $output): int
{
$username = $input->getArgument('username');
if ($username === null) {
// No username, list all providers
$output->writeln("<fg=blue;options=bold>Attributes available for all provider</>\n");
$providers = $this->provider->getAuthorizationDataProviders();
foreach ($providers as $provider) {
$output->writeln('<fg=green;options=bold>['.get_class($provider).']</>');
foreach ($provider->getAvailableAttributes() as $attr) {
$output->writeln($attr);
}
$output->writeln('');
}
// TODO: list all attributes
} else {
// get all available attributes for a user per provider
$output->writeln('<fg=blue;options=bold>Attributes for user "'.$username."\":</>\n");
$providers = $this->provider->getAuthorizationDataProviders();
foreach ($providers as $provider) {
$output->writeln('<fg=green;options=bold>['.get_class($provider).']</>');
foreach ($provider->getUserAttributes($username) as $attr => $value) {
$output->writeln($attr.'='.json_encode($value));
}
$output->writeln('');
}
// Fetch all attributes first (to get potential log spam first)
$providers = $this->provider->getAuthorizationDataProviders();
$mux = new AuthorizationDataMuxer($providers);
$attrs = $mux->getAvailableAttributes();
$all = [];
$default = new \stdClass();
sort($attrs, SORT_STRING | SORT_FLAG_CASE);
foreach ($attrs as $attr) {
$all[$attr] = $mux->getCustomAttribute($username, $attr, $default);
}
// TODO: list all attributes
// Now print them out
$output->writeln('<fg=blue;options=bold>[Authorization attributes]</>');
foreach ($all as $attr => $value) {
if ($value === $default) {
$output->writeln('<fg=green;options=bold>'.$attr.'</> = <fg=magenta;options=bold>\<N/A\></>');
} else {
$output->writeln('<fg=green;options=bold>'.$attr.'</> = '.json_encode($value));
}
}
return 0;
......