Skip to content

Commit fb4bc2f

Browse files
authored
Merge pull request #236 from cakephp/3.x-can-params
3.x: add ability to add multiple optional parameters to can and canResult
2 parents a47a948 + cab8c55 commit fb4bc2f

File tree

5 files changed

+128
-14
lines changed

5 files changed

+128
-14
lines changed

docs/en/3-0-migration-guide.rst

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ The following interfaces now have appropriate parameter and return types added:
1414
- ``RequestPolicyInterface.php``
1515
- ``ResolverInterface``
1616

17-
Multiple optional arguments for ``applyScope``
18-
----------------------------------------------
19-
20-
``IdentityInterface::applyScope`` as well as ``AuthorizationServiceInterface::applyScope``
21-
allow multiple optional arguments to be added.
17+
Multiple optional arguments for ``applyScope``, ``can`` and ``canResult``
18+
-------------------------------------------------------------------------
19+
20+
The following interface methods have been adjusted to pass on multiple optional arguments.
21+
- ``IdentityInterface::applyScope``
22+
- ``AuthorizationServiceInterface::applyScope``
23+
- ``AuthorizationServiceInterface::can``
24+
- ``AuthorizationServiceInterface::canResult``
2225

2326
Removed methods
2427
---------------

src/AuthorizationService.php

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,19 @@ public function __construct(ResolverInterface $resolver)
5151
/**
5252
* @inheritDoc
5353
*/
54-
public function can(?IdentityInterface $user, string $action, $resource): bool
54+
public function can(?IdentityInterface $user, string $action, $resource, ...$optionalArgs): bool
5555
{
56-
$result = $this->performCheck($user, $action, $resource);
56+
$result = $this->performCheck($user, $action, $resource, ...$optionalArgs);
5757

5858
return is_bool($result) ? $result : $result->getStatus();
5959
}
6060

6161
/**
6262
* @inheritDoc
6363
*/
64-
public function canResult(?IdentityInterface $user, string $action, $resource): ResultInterface
64+
public function canResult(?IdentityInterface $user, string $action, $resource, ...$optionalArgs): ResultInterface
6565
{
66-
$result = $this->performCheck($user, $action, $resource);
66+
$result = $this->performCheck($user, $action, $resource, ...$optionalArgs);
6767

6868
return is_bool($result) ? new Result($result) : $result;
6969
}
@@ -74,10 +74,15 @@ public function canResult(?IdentityInterface $user, string $action, $resource):
7474
* @param \Authorization\IdentityInterface|null $user The user to check permissions for.
7575
* @param string $action The action/operation being performed.
7676
* @param mixed $resource The resource being operated on.
77+
* @param mixed $optionalArgs Multiple additional arguments which are passed on
7778
* @return \Authorization\Policy\ResultInterface|bool
7879
*/
79-
protected function performCheck(?IdentityInterface $user, string $action, mixed $resource): bool|ResultInterface
80-
{
80+
protected function performCheck(
81+
?IdentityInterface $user,
82+
string $action,
83+
mixed $resource,
84+
mixed ...$optionalArgs
85+
): bool|ResultInterface {
8186
$this->authorizationChecked = true;
8287
$policy = $this->resolver->getPolicy($resource);
8388

@@ -90,7 +95,7 @@ protected function performCheck(?IdentityInterface $user, string $action, mixed
9095
}
9196

9297
$handler = $this->getCanHandler($policy, $action);
93-
$result = $handler($user, $resource);
98+
$result = $handler($user, $resource, ...$optionalArgs);
9499

95100
assert(
96101
is_bool($result) || $result instanceof ResultInterface,

src/AuthorizationServiceInterface.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ interface AuthorizationServiceInterface
3232
* @param \Authorization\IdentityInterface|null $user The user to check permissions for.
3333
* @param string $action The action/operation being performed.
3434
* @param mixed $resource The resource being operated on.
35+
* @param mixed $optionalArgs Multiple additional arguments which are passed to the scope
3536
* @return bool
3637
*/
37-
public function can(?IdentityInterface $user, string $action, mixed $resource): bool;
38+
public function can(?IdentityInterface $user, string $action, mixed $resource, mixed ...$optionalArgs): bool;
3839

3940
/**
4041
* Check whether the provided user can perform an action on a resource.
@@ -45,9 +46,15 @@ public function can(?IdentityInterface $user, string $action, mixed $resource):
4546
* @param \Authorization\IdentityInterface|null $user The user to check permissions for.
4647
* @param string $action The action/operation being performed.
4748
* @param mixed $resource The resource being operated on.
49+
* @param mixed $optionalArgs Multiple additional arguments which are passed to the scope
4850
* @return \Authorization\Policy\ResultInterface
4951
*/
50-
public function canResult(?IdentityInterface $user, string $action, mixed $resource): ResultInterface;
52+
public function canResult(
53+
?IdentityInterface $user,
54+
string $action,
55+
mixed $resource,
56+
mixed ...$optionalArgs
57+
): ResultInterface;
5158

5259
/**
5360
* Apply authorization scope conditions/restrictions.

tests/TestCase/AuthorizationServiceTest.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,50 @@ public function testCan()
6666
$this->assertTrue($result);
6767
}
6868

69+
public function testCanWithAdditionalParams()
70+
{
71+
$resolver = new MapResolver([
72+
Article::class => ArticlePolicy::class,
73+
]);
74+
75+
$service = new AuthorizationService($resolver);
76+
77+
$user = new IdentityDecorator($service, [
78+
'role' => 'admin',
79+
]);
80+
81+
$innerService = function () {
82+
return true;
83+
};
84+
85+
$result = $service->can($user, 'withService', new Article(), $innerService);
86+
$this->assertTrue($result);
87+
}
88+
89+
public function testCanWithAdditionalNamedParams()
90+
{
91+
$resolver = new MapResolver([
92+
Article::class => ArticlePolicy::class,
93+
]);
94+
95+
$service = new AuthorizationService($resolver);
96+
97+
$user = new IdentityDecorator($service, [
98+
'role' => 'admin',
99+
]);
100+
101+
$innerService1 = function () {
102+
return true;
103+
};
104+
105+
$innerService2 = function () {
106+
return false;
107+
};
108+
109+
$result = $service->can(user: $user, action: 'withMultipleServices', resource: new Article(), service2: $innerService2, service1: $innerService1);
110+
$this->assertFalse($result);
111+
}
112+
69113
public function testCanWithResult()
70114
{
71115
$resolver = new MapResolver([
@@ -82,6 +126,50 @@ public function testCanWithResult()
82126
$this->assertInstanceOf(ResultInterface::class, $result);
83127
}
84128

129+
public function testCanWithResultAndAdditionalParams()
130+
{
131+
$resolver = new MapResolver([
132+
Article::class => ArticlePolicy::class,
133+
]);
134+
135+
$service = new AuthorizationService($resolver);
136+
137+
$user = new IdentityDecorator($service, [
138+
'role' => 'admin',
139+
]);
140+
141+
$innerService = function () {
142+
return true;
143+
};
144+
145+
$result = $service->canResult($user, 'withService', new Article(), $innerService);
146+
$this->assertInstanceOf(ResultInterface::class, $result);
147+
}
148+
149+
public function testCanWithResultAndAdditionalNamedParams()
150+
{
151+
$resolver = new MapResolver([
152+
Article::class => ArticlePolicy::class,
153+
]);
154+
155+
$service = new AuthorizationService($resolver);
156+
157+
$user = new IdentityDecorator($service, [
158+
'role' => 'admin',
159+
]);
160+
161+
$innerService1 = function () {
162+
return true;
163+
};
164+
165+
$innerService2 = function () {
166+
return false;
167+
};
168+
169+
$result = $service->canResult(user: $user, action: 'withMultipleServices', resource: new Article(), service2: $innerService2, service1: $innerService1);
170+
$this->assertInstanceOf(ResultInterface::class, $result);
171+
}
172+
85173
public function testAuthorizationCheckedWithCan()
86174
{
87175
$resolver = new MapResolver([

tests/test_app/TestApp/Policy/ArticlePolicy.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace TestApp\Policy;
55

66
use Authorization\Policy\Result;
7+
use Closure;
78
use TestApp\Model\Entity\Article;
89

910
class ArticlePolicy
@@ -116,4 +117,14 @@ public function canPublish($user, Article $article)
116117

117118
return new Result($article->get('user_id') === $user['id']);
118119
}
120+
121+
public function canWithService($user, Article $article, Closure $service)
122+
{
123+
return $service();
124+
}
125+
126+
public function canWithMultipleServices($user, Article $article, Closure $service1, Closure $service2)
127+
{
128+
return $service1() && $service2();
129+
}
119130
}

0 commit comments

Comments
 (0)