Skip to content

Commit

Permalink
Merge pull request #284 from cakephp/3.next-dic
Browse files Browse the repository at this point in the history
Forward port DIC related changes done in 2.next to 3.next
  • Loading branch information
ADmad authored Mar 18, 2024
2 parents d463e54 + c45771c commit 5c41fc4
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 2 deletions.
22 changes: 21 additions & 1 deletion src/Middleware/AuthorizationMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

use ArrayAccess;
use Authentication\IdentityInterface as AuthenIdentityInterface;
use Authorization\AuthorizationService;
use Authorization\AuthorizationServiceInterface;
use Authorization\AuthorizationServiceProviderInterface;
use Authorization\Exception\AuthorizationRequiredException;
Expand All @@ -26,6 +27,8 @@
use Authorization\IdentityDecorator;
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;
Expand Down Expand Up @@ -71,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)
Expand All @@ -89,6 +101,7 @@ public function __construct(
}

$this->subject = $subject;
$this->container = $container;
$this->setConfig($config);
}

Expand All @@ -104,6 +117,13 @@ 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);
} elseif ($this->container) {
$this->container->add(AuthorizationService::class, $service);
}

$attribute = $this->getConfig('identityAttribute');
$identity = $request->getAttribute($attribute);

Expand Down
46 changes: 46 additions & 0 deletions tests/TestCase/Middleware/AuthorizationMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,25 @@
*/
namespace Authorization\Test\TestCase\Middleware;

use Authorization\AuthorizationService;
use Authorization\AuthorizationServiceInterface;
use Authorization\AuthorizationServiceProviderInterface;
use Authorization\Exception\AuthorizationRequiredException;
use Authorization\Exception\Exception;
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;
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;

Expand Down Expand Up @@ -270,4 +274,46 @@ 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));
}

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));
}
}
18 changes: 17 additions & 1 deletion tests/test_app/TestApp/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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);
}
}

0 comments on commit 5c41fc4

Please sign in to comment.