Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9cc8b11

Browse files
authored
Merge pull request #286 from cakephp/3.next
3.2.0
2 parents 819b496 + 5c41fc4 commit 9cc8b11

File tree

9 files changed

+200
-6
lines changed

9 files changed

+200
-6
lines changed

src/Middleware/AuthorizationMiddleware.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
use ArrayAccess;
2020
use Authentication\IdentityInterface as AuthenIdentityInterface;
21+
use Authorization\AuthorizationService;
2122
use Authorization\AuthorizationServiceInterface;
2223
use Authorization\AuthorizationServiceProviderInterface;
2324
use Authorization\Exception\AuthorizationRequiredException;
@@ -26,6 +27,8 @@
2627
use Authorization\IdentityDecorator;
2728
use Authorization\IdentityInterface;
2829
use Authorization\Middleware\UnauthorizedHandler\UnauthorizedHandlerTrait;
30+
use Cake\Core\ContainerApplicationInterface;
31+
use Cake\Core\ContainerInterface;
2932
use Cake\Core\InstanceConfigTrait;
3033
use Psr\Http\Message\ResponseInterface;
3134
use Psr\Http\Message\ServerRequestInterface;
@@ -71,16 +74,25 @@ class AuthorizationMiddleware implements MiddlewareInterface
7174
*/
7275
protected AuthorizationServiceInterface|AuthorizationServiceProviderInterface $subject;
7376

77+
/**
78+
* The container instance from the application
79+
*
80+
* @var \Cake\Core\ContainerInterface|null
81+
*/
82+
protected ?ContainerInterface $container = null;
83+
7484
/**
7585
* Constructor.
7686
*
7787
* @param \Authorization\AuthorizationServiceInterface|\Authorization\AuthorizationServiceProviderInterface $subject Authorization service or provider instance.
7888
* @param array $config Config array.
89+
* @param \Cake\Core\ContainerInterface|null $container The container instance from the application
7990
* @throws \InvalidArgumentException
8091
*/
8192
public function __construct(
8293
AuthorizationServiceInterface|AuthorizationServiceProviderInterface $subject,
83-
array $config = []
94+
array $config = [],
95+
?ContainerInterface $container = null
8496
) {
8597
if ($this->_defaultConfig['identityDecorator'] === null) {
8698
$this->_defaultConfig['identityDecorator'] = interface_exists(AuthenIdentityInterface::class)
@@ -89,6 +101,7 @@ public function __construct(
89101
}
90102

91103
$this->subject = $subject;
104+
$this->container = $container;
92105
$this->setConfig($config);
93106
}
94107

@@ -104,6 +117,13 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
104117
$service = $this->getAuthorizationService($request);
105118
$request = $request->withAttribute('authorization', $service);
106119

120+
if ($this->subject instanceof ContainerApplicationInterface) {
121+
$container = $this->subject->getContainer();
122+
$container->add(AuthorizationService::class, $service);
123+
} elseif ($this->container) {
124+
$this->container->add(AuthorizationService::class, $service);
125+
}
126+
107127
$attribute = $this->getConfig('identityAttribute');
108128
$identity = $request->getAttribute($attribute);
109129

src/Policy/MapResolver.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
namespace Authorization\Policy;
1818

1919
use Authorization\Policy\Exception\MissingPolicyException;
20+
use Cake\Core\ContainerInterface;
2021
use InvalidArgumentException;
2122

2223
/**
@@ -32,6 +33,13 @@ class MapResolver implements ResolverInterface
3233
*/
3334
protected array $map = [];
3435

36+
/**
37+
* The DIC instance from the application
38+
*
39+
* @var \Cake\Core\ContainerInterface|null
40+
*/
41+
protected ?ContainerInterface $container;
42+
3543
/**
3644
* Constructor.
3745
*
@@ -45,9 +53,11 @@ class MapResolver implements ResolverInterface
4553
* ```
4654
*
4755
* @param array $map Resource class name to policy map.
56+
* @param \Cake\Core\ContainerInterface|null $container The DIC instance from the application
4857
*/
49-
public function __construct(array $map = [])
58+
public function __construct(array $map = [], ?ContainerInterface $container = null)
5059
{
60+
$this->container = $container;
5161
foreach ($map as $resourceClass => $policy) {
5262
$this->map($resourceClass, $policy);
5363
}
@@ -107,6 +117,10 @@ public function getPolicy($resource): mixed
107117
return $policy;
108118
}
109119

120+
if ($this->container && $this->container->has($policy)) {
121+
return $this->container->get($policy);
122+
}
123+
110124
return new $policy();
111125
}
112126
}

src/Policy/OrmResolver.php

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
use Authorization\Policy\Exception\MissingPolicyException;
2020
use Cake\Core\App;
21+
use Cake\Core\ContainerInterface;
2122
use Cake\Datasource\EntityInterface;
2223
use Cake\Datasource\QueryInterface;
2324
use Cake\Datasource\RepositoryInterface;
@@ -43,16 +44,28 @@ class OrmResolver implements ResolverInterface
4344
*/
4445
protected array $overrides = [];
4546

47+
/**
48+
* The DIC instance from the application
49+
*
50+
* @var \Cake\Core\ContainerInterface|null
51+
*/
52+
protected ?ContainerInterface $container;
53+
4654
/**
4755
* Constructor
4856
*
4957
* @param string $appNamespace The application namespace
5058
* @param array<string, string> $overrides A list of plugin name overrides.
59+
* @param \Cake\Core\ContainerInterface|null $container The DIC instance from the application
5160
*/
52-
public function __construct(string $appNamespace = 'App', array $overrides = [])
53-
{
61+
public function __construct(
62+
string $appNamespace = 'App',
63+
array $overrides = [],
64+
?ContainerInterface $container = null
65+
) {
5466
$this->appNamespace = $appNamespace;
5567
$this->overrides = $overrides;
68+
$this->container = $container;
5669
}
5770

5871
/**
@@ -146,7 +159,13 @@ protected function findPolicy(string $class, string $name, string $namespace): m
146159
throw new MissingPolicyException([$class]);
147160
}
148161

149-
return new $policyClass();
162+
if ($this->container && $this->container->has($policyClass)) {
163+
$policy = $this->container->get($policyClass);
164+
} else {
165+
$policy = new $policyClass();
166+
}
167+
168+
return $policy;
150169
}
151170

152171
/**

tests/TestCase/Middleware/AuthorizationMiddlewareTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,25 @@
1616
*/
1717
namespace Authorization\Test\TestCase\Middleware;
1818

19+
use Authorization\AuthorizationService;
1920
use Authorization\AuthorizationServiceInterface;
2021
use Authorization\AuthorizationServiceProviderInterface;
2122
use Authorization\Exception\AuthorizationRequiredException;
2223
use Authorization\Exception\Exception;
2324
use Authorization\IdentityDecorator;
2425
use Authorization\IdentityInterface;
2526
use Authorization\Middleware\AuthorizationMiddleware;
27+
use Cake\Core\Container;
2628
use Cake\Http\Response;
2729
use Cake\Http\ServerRequest;
30+
use Cake\Http\ServerRequestFactory;
2831
use Cake\TestSuite\TestCase;
2932
use Psr\Http\Message\RequestInterface;
3033
use Psr\Http\Message\ResponseInterface;
3134
use Psr\Http\Message\ServerRequestInterface;
3235
use RuntimeException;
3336
use stdClass;
37+
use TestApp\Application;
3438
use TestApp\Http\TestRequestHandler;
3539
use TestApp\Identity;
3640

@@ -270,4 +274,46 @@ public function testUnauthorizedHandlerRequireAuthz()
270274
$result = $middleware->process($request, $handler);
271275
$this->assertSame(200, $result->getStatusCode());
272276
}
277+
278+
public function testMiddlewareInjectsServiceIntoDIC()
279+
{
280+
$request = ServerRequestFactory::fromGlobals(
281+
['REQUEST_URI' => '/testpath'],
282+
[],
283+
['username' => 'mariano', 'password' => 'password']
284+
);
285+
$handler = new TestRequestHandler();
286+
$application = new Application('config');
287+
288+
$middleware = new AuthorizationMiddleware($application, ['requireAuthorizationCheck' => false]);
289+
$middleware->process($request, $handler);
290+
291+
$container = $application->getContainer();
292+
$this->assertInstanceOf(AuthorizationService::class, $container->get(AuthorizationService::class));
293+
}
294+
295+
public function testMiddlewareInjectsServiceIntoDICViaCustomContainerInstance()
296+
{
297+
$request = ServerRequestFactory::fromGlobals(
298+
['REQUEST_URI' => '/testpath'],
299+
[],
300+
['username' => 'mariano', 'password' => 'password']
301+
);
302+
$handler = new TestRequestHandler();
303+
304+
$service = $this->createMock(AuthorizationServiceInterface::class);
305+
$provider = $this->createMock(AuthorizationServiceProviderInterface::class);
306+
$provider
307+
->expects($this->once())
308+
->method('getAuthorizationService')
309+
->with($this->isInstanceOf(ServerRequestInterface::class))
310+
->willReturn($service);
311+
312+
$container = new Container();
313+
314+
$middleware = new AuthorizationMiddleware($provider, ['requireAuthorizationCheck' => false], $container);
315+
$middleware->process($request, $handler);
316+
317+
$this->assertEquals($service, $container->get(AuthorizationService::class));
318+
}
273319
}

tests/TestCase/Policy/MapResolverTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@
1616
*/
1717
namespace Authorization\Test\TestCase\Policy;
1818

19+
use Authorization\AuthorizationService;
20+
use Authorization\IdentityDecorator;
1921
use Authorization\Policy\Exception\MissingPolicyException;
2022
use Authorization\Policy\MapResolver;
23+
use Cake\Core\Container;
2124
use Cake\TestSuite\TestCase;
2225
use InvalidArgumentException;
2326
use TestApp\Model\Entity\Article;
2427
use TestApp\Policy\ArticlePolicy;
28+
use TestApp\Service\TestService;
2529

2630
class MapResolverTest extends TestCase
2731
{
@@ -102,4 +106,25 @@ public function testGetPolicyMissing()
102106

103107
$resolver->getPolicy(new Article());
104108
}
109+
110+
public function testGetPolicyViaDIC()
111+
{
112+
$container = new Container();
113+
$container->add(TestService::class);
114+
$container->add(ArticlePolicy::class)
115+
->addArgument(TestService::class);
116+
117+
$article = new Article();
118+
$resolver = new MapResolver([], $container);
119+
$resolver->map(Article::class, ArticlePolicy::class);
120+
121+
$service = new AuthorizationService($resolver);
122+
$user = new IdentityDecorator($service, [
123+
'role' => 'admin',
124+
]);
125+
126+
$policy = $resolver->getPolicy($article);
127+
$this->assertInstanceOf(ArticlePolicy::class, $policy);
128+
$this->assertTrue($policy->canWithInjectedService($user, $article));
129+
}
105130
}

tests/TestCase/Policy/OrmResolverTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
*/
1717
namespace Authorization\Test\TestCase\Policy;
1818

19+
use Authorization\AuthorizationService;
20+
use Authorization\IdentityDecorator;
1921
use Authorization\Policy\Exception\MissingPolicyException;
2022
use Authorization\Policy\OrmResolver;
23+
use Cake\Core\Container;
2124
use Cake\ORM\Entity;
2225
use Cake\ORM\Locator\LocatorAwareTrait;
2326
use Cake\TestSuite\TestCase;
@@ -27,6 +30,7 @@
2730
use TestApp\Policy\ArticlePolicy;
2831
use TestApp\Policy\ArticlesTablePolicy;
2932
use TestApp\Policy\TestPlugin\BookmarkPolicy;
33+
use TestApp\Service\TestService;
3034
use TestPlugin\Model\Entity\Bookmark;
3135
use TestPlugin\Model\Entity\Tag;
3236
use TestPlugin\Policy\TagPolicy;
@@ -119,4 +123,24 @@ public function testGetPolicyUnknownTable()
119123
$resolver = new OrmResolver('TestApp');
120124
$resolver->getPolicy($articles);
121125
}
126+
127+
public function testGetPolicyViaDIC()
128+
{
129+
$container = new Container();
130+
$container->add(TestService::class);
131+
$container->add(ArticlePolicy::class)
132+
->addArgument(TestService::class);
133+
134+
$article = new Article();
135+
$resolver = new OrmResolver('TestApp', [], $container);
136+
137+
$service = new AuthorizationService($resolver);
138+
$user = new IdentityDecorator($service, [
139+
'role' => 'admin',
140+
]);
141+
142+
$policy = $resolver->getPolicy($article);
143+
$this->assertInstanceOf(ArticlePolicy::class, $policy);
144+
$this->assertTrue($policy->canWithInjectedService($user, $article));
145+
}
122146
}

tests/test_app/TestApp/Application.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@
33

44
namespace TestApp;
55

6+
use Authorization\AuthorizationService;
7+
use Authorization\AuthorizationServiceInterface;
8+
use Authorization\AuthorizationServiceProviderInterface;
9+
use Authorization\Policy\MapResolver;
610
use Cake\Http\BaseApplication;
711
use Cake\Http\MiddlewareQueue;
812
use Cake\Routing\RouteBuilder;
13+
use Psr\Http\Message\ServerRequestInterface;
14+
use TestApp\Model\Entity\Article;
15+
use TestApp\Policy\ArticlePolicy;
916

10-
class Application extends BaseApplication
17+
class Application extends BaseApplication implements AuthorizationServiceProviderInterface
1118
{
1219
public function middleware(MiddlewareQueue $middleware): MiddlewareQueue
1320
{
@@ -23,4 +30,13 @@ public function bootstrap(): void
2330
$this->addPlugin('Authorization');
2431
$this->addPlugin('Bake');
2532
}
33+
34+
public function getAuthorizationService(ServerRequestInterface $request): AuthorizationServiceInterface
35+
{
36+
$resolver = new MapResolver([
37+
Article::class => ArticlePolicy::class,
38+
]);
39+
40+
return new AuthorizationService($resolver);
41+
}
2642
}

tests/test_app/TestApp/Policy/ArticlePolicy.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,22 @@
66
use Authorization\Policy\Result;
77
use Closure;
88
use TestApp\Model\Entity\Article;
9+
use TestApp\Service\TestService;
910

1011
class ArticlePolicy
1112
{
13+
/**
14+
* A service class injected via DIC
15+
*
16+
* @var \TestApp\Service\TestService|null
17+
*/
18+
protected ?TestService $service;
19+
20+
public function __construct(?TestService $service = null)
21+
{
22+
$this->service = $service;
23+
}
24+
1225
/**
1326
* Create articles if you're an admin or author
1427
*
@@ -131,4 +144,9 @@ public function canWithMultipleServices($user, Article $article, Closure $servic
131144
{
132145
return $service1() && $service2();
133146
}
147+
148+
public function canWithInjectedService($user, Article $article)
149+
{
150+
return $this->service->serviceLogic();
151+
}
134152
}

0 commit comments

Comments
 (0)