From 0065a0802d03ea5ed7bcc43860f86db8b7d69d4d Mon Sep 17 00:00:00 2001 From: Kevin Pfeifer Date: Sat, 11 Nov 2023 11:17:23 +0100 Subject: [PATCH 1/3] 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 911f1a86..e3aea77d 100644 --- a/src/Middleware/AuthorizationMiddleware.php +++ b/src/Middleware/AuthorizationMiddleware.php @@ -17,6 +17,7 @@ namespace Authorization\Middleware; use Authentication\IdentityInterface as AuthenIdentityInterface; +use Authorization\AuthorizationService; use Authorization\AuthorizationServiceInterface; use Authorization\AuthorizationServiceProviderInterface; use Authorization\Exception\AuthorizationRequiredException; @@ -25,6 +26,7 @@ use Authorization\IdentityDecorator; use Authorization\IdentityInterface; use Authorization\Middleware\UnauthorizedHandler\UnauthorizedHandlerTrait; +use Cake\Core\ContainerApplicationInterface; use Cake\Core\InstanceConfigTrait; use InvalidArgumentException; use Psr\Http\Message\ResponseInterface; @@ -117,6 +119,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 f4ea15cb..64af0ea9 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,6 +26,7 @@ use Authorization\Middleware\AuthorizationMiddleware; use Cake\Http\Response; use Cake\Http\ServerRequest; +use Cake\Http\ServerRequestFactory; use Cake\TestSuite\TestCase; use InvalidArgumentException; use Psr\Http\Message\RequestInterface; @@ -32,6 +34,7 @@ use Psr\Http\Message\ServerRequestInterface; use RuntimeException; use stdClass; +use TestApp\Application; use TestApp\Http\TestRequestHandler; use TestApp\Identity; @@ -282,4 +285,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 868e3e5b9207694a27f74ccec2ece8145054ea58 Mon Sep 17 00:00:00 2001 From: Kevin Pfeifer Date: Sun, 12 Nov 2023 17:53:14 +0100 Subject: [PATCH 2/3] require CakePHP 4.2 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 1950f98f..a8f59cd2 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "type": "cakephp-plugin", "require": { "php": ">=7.2", - "cakephp/http": "^4.0", + "cakephp/http": "^4.2", "psr/http-client": "^1.0", "psr/http-message": "^1.0", "psr/http-server-handler": "^1.0", From 183e7f9acd00d92d046fe0fa625bc0e48b505a23 Mon Sep 17 00:00:00 2001 From: Kevin Pfeifer Date: Mon, 22 Jan 2024 21:02:14 +0100 Subject: [PATCH 3/3] add ability to set custom container instance --- src/Middleware/AuthorizationMiddleware.php | 19 ++++++++++++-- .../AuthorizationMiddlewareTest.php | 26 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/Middleware/AuthorizationMiddleware.php b/src/Middleware/AuthorizationMiddleware.php index e3aea77d..d10ed65e 100644 --- a/src/Middleware/AuthorizationMiddleware.php +++ b/src/Middleware/AuthorizationMiddleware.php @@ -27,6 +27,7 @@ use Authorization\IdentityInterface; use Authorization\Middleware\UnauthorizedHandler\UnauthorizedHandlerTrait; use Cake\Core\ContainerApplicationInterface; +use Cake\Core\ContainerInterface; use Cake\Core\InstanceConfigTrait; use InvalidArgumentException; use Psr\Http\Message\ResponseInterface; @@ -73,15 +74,26 @@ class AuthorizationMiddleware implements MiddlewareInterface */ protected $subject; + /** + * The container instance from the application + * + * @var \Cake\Core\ContainerInterface|null + */ + protected $container; + /** * 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($subject, array $config = []) - { + public function __construct( + $subject, + array $config = [], + ?ContainerInterface $container = null + ) { /** @psalm-suppress DocblockTypeContradiction */ if ( !$subject instanceof AuthorizationServiceInterface && @@ -104,6 +116,7 @@ public function __construct($subject, array $config = []) } $this->subject = $subject; + $this->container = $container; $this->setConfig($config); } @@ -122,6 +135,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 64af0ea9..522bea7b 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; @@ -302,4 +303,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)); + } }