diff --git a/src/Authorization/AuthorizationDataMuxer.php b/src/Authorization/AuthorizationDataMuxer.php index e6e811af2d9462d93b249b178c6cd5efdee9206f..984580e8064838e172463404562d38aab2165225 100644 --- a/src/Authorization/AuthorizationDataMuxer.php +++ b/src/Authorization/AuthorizationDataMuxer.php @@ -16,10 +16,10 @@ class AuthorizationDataMuxer /** @var iterable<AuthorizationDataProviderInterface> */ private $authorizationDataProviders; - /** @var array<string, array> */ + /** @var array<int, array> */ private $providerCache; - /** @var array<string, string[]> */ + /** @var array<int, string[]> */ private $availableCache; /** @var EventDispatcherInterface */ @@ -73,7 +73,7 @@ class AuthorizationDataMuxer private function getProviderAvailableAttributes(AuthorizationDataProviderInterface $prov): array { // Caches getAvailableAttributes for each provider - $provKey = get_class($prov); + $provKey = spl_object_id($prov); if (!array_key_exists($provKey, $this->availableCache)) { $this->availableCache[$provKey] = $prov->getAvailableAttributes(); } @@ -89,7 +89,7 @@ class AuthorizationDataMuxer private function getProviderUserAttributes(AuthorizationDataProviderInterface $prov, ?string $userIdentifier): array { // We cache the attributes for each provider, but only for the last userIdentifier - $provKey = get_class($prov); + $provKey = spl_object_id($prov); if (!array_key_exists($provKey, $this->providerCache) || $this->providerCache[$provKey][0] !== $userIdentifier) { $this->providerCache[$provKey] = [$userIdentifier, $prov->getUserAttributes($userIdentifier)]; } @@ -112,7 +112,7 @@ class AuthorizationDataMuxer throw new AuthorizationException(sprintf('attribute \'%s\' undefined', $attributeName), AuthorizationException::ATTRIBUTE_UNDEFINED); } - $value = $defaultValue; + $value = null; foreach ($this->authorizationDataProviders as $authorizationDataProvider) { $availableAttributes = $this->getProviderAvailableAttributes($authorizationDataProvider); if (!in_array($attributeName, $availableAttributes, true)) { @@ -140,6 +140,6 @@ class AuthorizationDataMuxer array_pop($this->attributeStack); } - return $event->getAttributeValue(); + return $event->getAttributeValue() ?? $defaultValue; } } diff --git a/tests/Authorization/AuthorizationDataMuxerTest.php b/tests/Authorization/AuthorizationDataMuxerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..53d938bdd76439559a4e491ac8900f5d3bd53317 --- /dev/null +++ b/tests/Authorization/AuthorizationDataMuxerTest.php @@ -0,0 +1,103 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CoreBundle\Tests\Authorization; + +use Dbp\Relay\CoreBundle\Authorization\AuthorizationDataMuxer; +use Dbp\Relay\CoreBundle\Authorization\AuthorizationDataProviderProvider; +use Dbp\Relay\CoreBundle\Authorization\Event\GetAttributeEvent; +use Dbp\Relay\CoreBundle\Authorization\Event\GetAvailableAttributesEvent; +use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; + +class AuthorizationDataMuxerTest extends TestCase +{ + public function testBasics() + { + $dummy = new DummyAuthorizationDataProvider(['foo' => 42], ['foo', 'bar']); + $mux = new AuthorizationDataMuxer(new AuthorizationDataProviderProvider([$dummy]), new EventDispatcher()); + $this->assertSame(['foo', 'bar'], $mux->getAvailableAttributes()); + $this->assertSame(42, $mux->getAttribute(null, 'foo')); + $this->assertSame(24, $mux->getAttribute(null, 'bar', 24)); + } + + public function testMultiple() + { + $dummy = new DummyAuthorizationDataProvider(['foo' => 42], ['foo', 'qux']); + $dummy2 = new DummyAuthorizationDataProvider(['bar' => 24], ['bar', 'baz']); + + $mux = new AuthorizationDataMuxer(new AuthorizationDataProviderProvider([$dummy, $dummy2]), new EventDispatcher()); + $this->assertSame(['foo', 'qux', 'bar', 'baz'], $mux->getAvailableAttributes()); + $this->assertSame(42, $mux->getAttribute(null, 'foo')); + $this->assertSame('default', $mux->getAttribute(null, 'qux', 'default')); + $this->assertSame(24, $mux->getAttribute(null, 'bar')); + $this->assertSame(12, $mux->getAttribute(null, 'baz', 12)); + $this->assertNull($mux->getAttribute(null, 'baz')); + } + + public function testAvailEvent() + { + $dummy = new DummyAuthorizationDataProvider(['foo' => 42], ['foo', 'bar']); + $dispatched = new EventDispatcher(); + $getAvail = function (GetAvailableAttributesEvent $event) { + $this->assertSame(['foo', 'bar'], $event->getAttributes()); + $event->addAttributes(['new']); + }; + $dispatched->addListener(GetAvailableAttributesEvent::class, $getAvail); + $getAvail2 = function (GetAvailableAttributesEvent $event) { + $event->addAttributes(['new2']); + }; + $dispatched->addListener(GetAvailableAttributesEvent::class, $getAvail2); + $mux = new AuthorizationDataMuxer(new AuthorizationDataProviderProvider([$dummy]), $dispatched); + $this->assertSame(['foo', 'bar', 'new', 'new2'], $mux->getAvailableAttributes()); + } + + public function testGetAttrEvent() + { + $dummy = new DummyAuthorizationDataProvider(['foo' => 42], ['foo', 'bar']); + $dispatched = new EventDispatcher(); + $getAttr = function (GetAttributeEvent $event) { + $this->assertSame('myuser', $event->getUserIdentifier()); + $this->assertSame('bar', $event->getAttributeName()); + $this->assertNull($event->getAttributeValue()); + $event->setAttributeValue('OK'); + }; + $dispatched->addListener(GetAttributeEvent::class, $getAttr); + $mux = new AuthorizationDataMuxer(new AuthorizationDataProviderProvider([$dummy]), $dispatched); + $this->assertSame('OK', $mux->getAttribute('myuser', 'bar')); + } + + public function testGetAttrEventDefault() + { + $dummy = new DummyAuthorizationDataProvider([], []); + $dispatched = new EventDispatcher(); + $getAvail = function (GetAvailableAttributesEvent $event) { + $event->addAttributes(['bar']); + }; + $dispatched->addListener(GetAvailableAttributesEvent::class, $getAvail); + $getAttr = function (GetAttributeEvent $event) { + $this->assertNull($event->getAttributeValue()); + }; + $dispatched->addListener(GetAttributeEvent::class, $getAttr); + $mux = new AuthorizationDataMuxer(new AuthorizationDataProviderProvider([$dummy]), $dispatched); + $this->assertSame('Default', $mux->getAttribute('myuser', 'bar', 'Default')); + } + + public function testGetAttrMultipleEvents() + { + $dummy = new DummyAuthorizationDataProvider(['foo' => 42], ['foo', 'bar']); + $dispatched = new EventDispatcher(); + $getAttr = function (GetAttributeEvent $event) { + $event->setAttributeValue('OK'); + }; + $dispatched->addListener(GetAttributeEvent::class, $getAttr); + $getAttr2 = function (GetAttributeEvent $event) { + $this->assertSame('OK', $event->getAttributeValue()); + $event->setAttributeValue('OK2'); + }; + $dispatched->addListener(GetAttributeEvent::class, $getAttr2); + $mux = new AuthorizationDataMuxer(new AuthorizationDataProviderProvider([$dummy]), $dispatched); + $this->assertSame('OK2', $mux->getAttribute('myuser', 'bar')); + } +} diff --git a/tests/Authorization/DummyAuthorizationDataProvider.php b/tests/Authorization/DummyAuthorizationDataProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..af4252a76644149c64656b5220967d2160e8e8ae --- /dev/null +++ b/tests/Authorization/DummyAuthorizationDataProvider.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CoreBundle\Tests\Authorization; + +use Dbp\Relay\CoreBundle\Authorization\AuthorizationDataProviderInterface; + +class DummyAuthorizationDataProvider implements AuthorizationDataProviderInterface +{ + /** + * @var array + */ + private $attributes; + + /** + * @var array + */ + private $available; + + public function __construct(array $attributes, array $available = null) + { + $this->attributes = $attributes; + $this->available = $available ?? array_keys($attributes); + } + + /** + * @return string[] + */ + public function getAvailableAttributes(): array + { + return $this->available; + } + + public function getUserAttributes(?string $userIdentifier): array + { + return $this->attributes; + } +}