Skip to content
Commits on Source (1)
......@@ -10,6 +10,9 @@ use Symfony\Component\HttpFoundation\Response;
abstract class AbstractAuthorizationService
{
public const RIGHTS_CONFIG_ATTRIBUTE = AuthorizationExpressionChecker::RIGHTS_CONFIG_ATTRIBUTE;
public const ATTRIBUTES_CONFIG_ATTRIBUTE = AuthorizationExpressionChecker::ATTRIBUTES_CONFIG_ATTRIBUTE;
/** @var AuthorizationExpressionChecker */
private $userAuthorizationChecker;
......
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\Entity;
/**
* Interface for entities with an identifier and a name.
*/
interface NamedEntityInterface
{
public function getIdentifier();
public function getName();
}
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\LocalData;
use Dbp\Relay\CoreBundle\Authorization\AbstractAuthorizationService;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
abstract class AbstractLocalDataPostEventSubscriber extends AbstractAuthorizationService implements EventSubscriberInterface
{
public const CONFIG_NODE = 'local_data_mapping';
public const SOURCE_ATTRIBUTE_KEY = 'source_attribute';
public const LOCAL_DATA_ATTRIBUTE_KEY = 'local_data_attribute';
public const AUTHORIZATION_EXPRESSION_KEY = 'authorization_expression';
/** @var string[] */
private $attributeMapping;
public function setConfig(array $config)
{
$configNode = $config[self::CONFIG_NODE] ?? [];
$rights = [];
foreach ($configNode as $configMappingEntry) {
if (isset($this->attributeMapping[$configMappingEntry[self::LOCAL_DATA_ATTRIBUTE_KEY]])) {
throw new \RuntimeException(sprintf('multiple mapping entries for local data attribute %s', $configMappingEntry[self::LOCAL_DATA_ATTRIBUTE_KEY]));
}
$this->attributeMapping[$configMappingEntry[self::LOCAL_DATA_ATTRIBUTE_KEY]] = $configMappingEntry[self::SOURCE_ATTRIBUTE_KEY];
// the name of the local data attribute is used as name for the right to view that attribute
// the attribute is visible false by default
$rights[$configMappingEntry[self::LOCAL_DATA_ATTRIBUTE_KEY]] = $configMappingEntry[self::AUTHORIZATION_EXPRESSION_KEY] ?? 'false';
}
if (!empty($rights)) {
parent::setConfig([AbstractAuthorizationService::RIGHTS_CONFIG_ATTRIBUTE => $rights]);
}
}
public static function getSubscribedEvents(): array
{
return [static::getSubscribedEventName() => 'onPost'];
}
public static function getSubscribedEventName(): string
{
throw new \RuntimeException(sprintf('child classes must implement the \'%s\' method', __METHOD__));
}
public function onPost(LocalDataPostEvent $postEvent)
{
$sourceData = $postEvent->getSourceData();
foreach ($this->attributeMapping as $localDataAttributeName => $sourceAttributeName) {
if ($this->isGranted($localDataAttributeName)) {
if ($sourceAttributeValue = $sourceData[$sourceAttributeName] ?? null) {
$postEvent->trySetLocalDataAttribute($localDataAttributeName, $sourceAttributeValue);
} else {
throw new \RuntimeException(sprintf('attribute \'%s\' not available in source data', $sourceAttributeName));
}
}
}
}
public static function getConfigNode()
{
$treeBuilder = new TreeBuilder(self::CONFIG_NODE);
return $treeBuilder->getRootNode()
->arrayPrototype()
->children()
->scalarNode(self::SOURCE_ATTRIBUTE_KEY)->end()
->scalarNode(self::LOCAL_DATA_ATTRIBUTE_KEY)->end()
->scalarNode(self::AUTHORIZATION_EXPRESSION_KEY)
->defaultValue('false')
->end()
->end()
->end()
;
}
}
......@@ -35,4 +35,9 @@ class LocalData
{
return $options[self::QUERY_PARAMETER_NAME] ?? null;
}
public static function toIncludeLocalParameterValue(array $attributeNames): string
{
return implode(LocalDataEventDispatcher::SEPARATOR, $attributeNames);
}
}
......@@ -13,8 +13,10 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\EventDispatcher\Event;
class LocalDataAwareEventDispatcher
class LocalDataEventDispatcher
{
public const SEPARATOR = ',';
/** @var array */
private $queryParameters;
......@@ -79,10 +81,10 @@ class LocalDataAwareEventDispatcher
*/
public function dispatch(Event $event, string $eventName): void
{
if ($event instanceof LocalDataAwarePreEvent) {
if ($event instanceof LocalDataPreEvent) {
$event->setQueryParameters($this->queryParameters);
$this->eventDispatcher->dispatch($event, $eventName);
} elseif ($event instanceof LocalDataAwarePostEvent) {
} elseif ($event instanceof LocalDataPostEvent) {
$event->setRequestedAttributes($this->requestedAttributes);
$this->eventDispatcher->dispatch($event, $eventName);
......@@ -130,7 +132,7 @@ class LocalDataAwareEventDispatcher
$this->requestedAttributes = [];
if (!Tools::isNullOrEmpty($includeParameter)) {
$requestedAttributes = explode(',', $includeParameter);
$requestedAttributes = explode(self::SEPARATOR, $includeParameter);
foreach ($requestedAttributes as $requestedAttribute) {
$requestedAttribute = trim($requestedAttribute);
......@@ -155,7 +157,7 @@ class LocalDataAwareEventDispatcher
$this->queryParameters = [];
if (!Tools::isNullOrEmpty($queryParameter)) {
$localQueryParameters = explode(',', $queryParameter);
$localQueryParameters = explode(self::SEPARATOR, $queryParameter);
foreach ($localQueryParameters as $localQueryParameter) {
$localQueryParameter = trim($localQueryParameter);
......
......@@ -9,22 +9,31 @@ use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Symfony\Contracts\EventDispatcher\Event;
class LocalDataAwarePostEvent extends Event implements LoggerAwareInterface
class LocalDataPostEvent extends Event implements LoggerAwareInterface
{
use LoggerAwareTrait;
/** @var LocalDataAwareInterface */
private $entity;
/** @var array */
private $sourceData;
/** @var array */
private $requestedAttributes;
protected function __construct(LocalDataAwareInterface $entity)
public function __construct(LocalDataAwareInterface $entity, array $sourceData)
{
$this->entity = $entity;
$this->sourceData = $sourceData;
}
public function getSourceData(): array
{
return $this->sourceData;
}
protected function getEntityInternal(): LocalDataAwareInterface
public function getEntity(): LocalDataAwareInterface
{
return $this->entity;
}
......@@ -100,7 +109,7 @@ class LocalDataAwarePostEvent extends Event implements LoggerAwareInterface
if ($arrayKey === false) {
if ($warnfNotFound) {
if ($this->logger !== null) {
$this->logger->warning(sprintf("trying to set local data attribute '%s', which was not requested for entity '%s'", $key, LocalDataAwareEventDispatcher::getUniqueEntityName(get_class($this->entity))));
$this->logger->warning(sprintf("trying to set local data attribute '%s', which was not requested for entity '%s'", $key, LocalDataEventDispatcher::getUniqueEntityName(get_class($this->entity))));
}
assert(false);
} else {
......
......@@ -6,7 +6,7 @@ namespace Dbp\Relay\CoreBundle\LocalData;
use Symfony\Contracts\EventDispatcher\Event;
class LocalDataAwarePreEvent extends Event
class LocalDataPreEvent extends Event
{
public const NAME = 'dbp.relay.relay_core.local_data_aware_event.pre';
......