From dda8730ff6ff9da14dc2f35d4fd38e3d438d39f7 Mon Sep 17 00:00:00 2001 From: Kevin Pfeifer Date: Sat, 11 Nov 2023 11:17:23 +0100 Subject: [PATCH 1/2] add authorization service to DIC by default --- src/Middleware/AuthorizationMiddleware.php | 7 +++++++ .../AuthorizationMiddlewareTest.php | 20 +++++++++++++++++++ tests/test_app/TestApp/Application.php | 18 ++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/Middleware/AuthorizationMiddleware.php b/src/Middleware/AuthorizationMiddleware.php index 337a050b..5f2f8618 100644 --- a/src/Middleware/AuthorizationMiddleware.php +++ b/src/Middleware/AuthorizationMiddleware.php @@ -18,6 +18,7 @@ use ArrayAccess; use Authentication\IdentityInterface as AuthenIdentityInterface; +use Authorization\AuthorizationService; use Authorization\AuthorizationServiceInterface; use Authorization\AuthorizationServiceProviderInterface; use Authorization\Exception\AuthorizationRequiredException; @@ -26,6 +27,7 @@ use Authorization\IdentityDecorator; use Authorization\IdentityInterface; use Authorization\Middleware\UnauthorizedHandler\UnauthorizedHandlerTrait; +use Cake\Core\ContainerApplicationInterface; use Cake\Core\InstanceConfigTrait; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -104,6 +106,11 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $service = $this->getAuthorizationService($request); $request = $request->withAttribute('authorization', $service); + if ($this->subject instanceof ContainerApplicationInterface) { + $container = $this->subject->getContainer(); + $container->add(AuthorizationService::class, $service); + } + $attribute = $this->getConfig('identityAttribute'); $identity = $request->getAttribute($attribute); diff --git a/tests/TestCase/Middleware/AuthorizationMiddlewareTest.php b/tests/TestCase/Middleware/AuthorizationMiddlewareTest.php index cd1ee0d9..c2d91b02 100644 --- a/tests/TestCase/Middleware/AuthorizationMiddlewareTest.php +++ b/tests/TestCase/Middleware/AuthorizationMiddlewareTest.php @@ -16,6 +16,7 @@ */ namespace Authorization\Test\TestCase\Middleware; +use Authorization\AuthorizationService; use Authorization\AuthorizationServiceInterface; use Authorization\AuthorizationServiceProviderInterface; use Authorization\Exception\AuthorizationRequiredException; @@ -25,12 +26,14 @@ use Authorization\Middleware\AuthorizationMiddleware; use Cake\Http\Response; use Cake\Http\ServerRequest; +use Cake\Http\ServerRequestFactory; use Cake\TestSuite\TestCase; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use RuntimeException; use stdClass; +use TestApp\Application; use TestApp\Http\TestRequestHandler; use TestApp\Identity; @@ -270,4 +273,21 @@ public function testUnauthorizedHandlerRequireAuthz() $result = $middleware->process($request, $handler); $this->assertSame(200, $result->getStatusCode()); } + + public function testMiddlewareInjectsServiceIntoDIC() + { + $request = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/testpath'], + [], + ['username' => 'mariano', 'password' => 'password'] + ); + $handler = new TestRequestHandler(); + $application = new Application('config'); + + $middleware = new AuthorizationMiddleware($application, ['requireAuthorizationCheck' => false]); + $middleware->process($request, $handler); + + $container = $application->getContainer(); + $this->assertInstanceOf(AuthorizationService::class, $container->get(AuthorizationService::class)); + } } diff --git a/tests/test_app/TestApp/Application.php b/tests/test_app/TestApp/Application.php index ed753482..508e75cf 100644 --- a/tests/test_app/TestApp/Application.php +++ b/tests/test_app/TestApp/Application.php @@ -3,11 +3,18 @@ namespace TestApp; +use Authorization\AuthorizationService; +use Authorization\AuthorizationServiceInterface; +use Authorization\AuthorizationServiceProviderInterface; +use Authorization\Policy\MapResolver; use Cake\Http\BaseApplication; use Cake\Http\MiddlewareQueue; use Cake\Routing\RouteBuilder; +use Psr\Http\Message\ServerRequestInterface; +use TestApp\Model\Entity\Article; +use TestApp\Policy\ArticlePolicy; -class Application extends BaseApplication +class Application extends BaseApplication implements AuthorizationServiceProviderInterface { public function middleware(MiddlewareQueue $middleware): MiddlewareQueue { @@ -23,4 +30,13 @@ public function bootstrap(): void $this->addPlugin('Authorization'); $this->addPlugin('Bake'); } + + public function getAuthorizationService(ServerRequestInterface $request): AuthorizationServiceInterface + { + $resolver = new MapResolver([ + Article::class => ArticlePolicy::class, + ]); + + return new AuthorizationService($resolver); + } } From c45771cd5b65b772978f0cff23ab10eba0a310a9 Mon Sep 17 00:00:00 2001 From: Kevin Pfeifer Date: Mon, 22 Jan 2024 21:02:14 +0100 Subject: [PATCH 2/2] add ability to set custom container instance --- src/Middleware/AuthorizationMiddleware.php | 15 ++++++++++- .../AuthorizationMiddlewareTest.php | 26 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/Middleware/AuthorizationMiddleware.php b/src/Middleware/AuthorizationMiddleware.php index 5f2f8618..b3f2213b 100644 --- a/src/Middleware/AuthorizationMiddleware.php +++ b/src/Middleware/AuthorizationMiddleware.php @@ -28,6 +28,7 @@ use Authorization\IdentityInterface; use Authorization\Middleware\UnauthorizedHandler\UnauthorizedHandlerTrait; use Cake\Core\ContainerApplicationInterface; +use Cake\Core\ContainerInterface; use Cake\Core\InstanceConfigTrait; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -73,16 +74,25 @@ class AuthorizationMiddleware implements MiddlewareInterface */ protected AuthorizationServiceInterface|AuthorizationServiceProviderInterface $subject; + /** + * The container instance from the application + * + * @var \Cake\Core\ContainerInterface|null + */ + protected ?ContainerInterface $container = null; + /** * Constructor. * * @param \Authorization\AuthorizationServiceInterface|\Authorization\AuthorizationServiceProviderInterface $subject Authorization service or provider instance. * @param array $config Config array. + * @param \Cake\Core\ContainerInterface|null $container The container instance from the application * @throws \InvalidArgumentException */ public function __construct( AuthorizationServiceInterface|AuthorizationServiceProviderInterface $subject, - array $config = [] + array $config = [], + ?ContainerInterface $container = null ) { if ($this->_defaultConfig['identityDecorator'] === null) { $this->_defaultConfig['identityDecorator'] = interface_exists(AuthenIdentityInterface::class) @@ -91,6 +101,7 @@ public function __construct( } $this->subject = $subject; + $this->container = $container; $this->setConfig($config); } @@ -109,6 +120,8 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface if ($this->subject instanceof ContainerApplicationInterface) { $container = $this->subject->getContainer(); $container->add(AuthorizationService::class, $service); + } elseif ($this->container) { + $this->container->add(AuthorizationService::class, $service); } $attribute = $this->getConfig('identityAttribute'); diff --git a/tests/TestCase/Middleware/AuthorizationMiddlewareTest.php b/tests/TestCase/Middleware/AuthorizationMiddlewareTest.php index c2d91b02..591a1684 100644 --- a/tests/TestCase/Middleware/AuthorizationMiddlewareTest.php +++ b/tests/TestCase/Middleware/AuthorizationMiddlewareTest.php @@ -24,6 +24,7 @@ use Authorization\IdentityDecorator; use Authorization\IdentityInterface; use Authorization\Middleware\AuthorizationMiddleware; +use Cake\Core\Container; use Cake\Http\Response; use Cake\Http\ServerRequest; use Cake\Http\ServerRequestFactory; @@ -290,4 +291,29 @@ public function testMiddlewareInjectsServiceIntoDIC() $container = $application->getContainer(); $this->assertInstanceOf(AuthorizationService::class, $container->get(AuthorizationService::class)); } + + public function testMiddlewareInjectsServiceIntoDICViaCustomContainerInstance() + { + $request = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/testpath'], + [], + ['username' => 'mariano', 'password' => 'password'] + ); + $handler = new TestRequestHandler(); + + $service = $this->createMock(AuthorizationServiceInterface::class); + $provider = $this->createMock(AuthorizationServiceProviderInterface::class); + $provider + ->expects($this->once()) + ->method('getAuthorizationService') + ->with($this->isInstanceOf(ServerRequestInterface::class)) + ->willReturn($service); + + $container = new Container(); + + $middleware = new AuthorizationMiddleware($provider, ['requireAuthorizationCheck' => false], $container); + $middleware->process($request, $handler); + + $this->assertEquals($service, $container->get(AuthorizationService::class)); + } }