Skip to content

Commit cabacfa

Browse files
authored
Merge pull request #226 from cakephp/3.x-scope-params
3.x: add ability to add multiple optional parameters to table scopes
2 parents 4259040 + 10051f4 commit cabacfa

File tree

10 files changed

+122
-8
lines changed

10 files changed

+122
-8
lines changed

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
3.0 Migration Guide
2+
###################
3+
4+
Authorization 3.0 contains new features and a few breaking changes.
5+
6+
Breaking Changes
7+
================
8+
9+
The following interfaces now have appropriate parameter and return types added:
10+
11+
- ``AuthorizationServiceInterface``
12+
- ``IdentityInterface``
13+
- ``BeforePolicyInterface``
14+
- ``RequestPolicyInterface.php``
15+
- ``ResolverInterface``
16+
17+
Multiple optional arguments for ``applyScope``
18+
----------------------------------------------
19+
20+
``IdentityInterface::applyScope`` as well as ``AuthorizationServiceInterface::applyScope``
21+
allow multiple optional arguments to be added.
22+
23+
Removed methods
24+
---------------
25+
26+
- ``AuthorizationService::resultTypeCheck`` - has been replaced with an ``assert()`` call
27+

src/AuthorizationService.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,13 @@ protected function performCheck(?IdentityInterface $user, string $action, mixed
106106
/**
107107
* @inheritDoc
108108
*/
109-
public function applyScope(?IdentityInterface $user, string $action, $resource): mixed
109+
public function applyScope(?IdentityInterface $user, string $action, mixed $resource, mixed ...$optionalArgs): mixed
110110
{
111111
$this->authorizationChecked = true;
112112
$policy = $this->resolver->getPolicy($resource);
113113
$handler = $this->getScopeHandler($policy, $action);
114114

115-
return $handler($user, $resource);
115+
return $handler($user, $resource, ...$optionalArgs);
116116
}
117117

118118
/**

src/AuthorizationServiceInterface.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,15 @@ public function canResult(?IdentityInterface $user, string $action, mixed $resou
6060
* @param \Authorization\IdentityInterface|null $user The user to check permissions for.
6161
* @param string $action The action/operation being performed.
6262
* @param mixed $resource The resource being operated on.
63+
* @param mixed $optionalArgs Multiple additional arguments which are passed to the scope
6364
* @return mixed The modified resource.
6465
*/
65-
public function applyScope(?IdentityInterface $user, string $action, mixed $resource): mixed;
66+
public function applyScope(
67+
?IdentityInterface $user,
68+
string $action,
69+
mixed $resource,
70+
mixed ...$optionalArgs
71+
): mixed;
6672

6773
/**
6874
* Return a boolean based on whether or not this object

src/Controller/Component/AuthorizationComponent.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,10 @@ protected function performCheck(
151151
*
152152
* @param mixed $resource The resource to apply a scope to.
153153
* @param string|null $action The action to apply a scope for.
154+
* @param mixed $optionalArgs Multiple additional arguments which are passed to the scope
154155
* @return mixed
155156
*/
156-
public function applyScope(mixed $resource, ?string $action = null): mixed
157+
public function applyScope(mixed $resource, ?string $action = null, mixed ...$optionalArgs): mixed
157158
{
158159
$request = $this->getController()->getRequest();
159160
if ($action === null) {
@@ -164,7 +165,7 @@ public function applyScope(mixed $resource, ?string $action = null): mixed
164165
throw new MissingIdentityException('Identity must exist for applyScope() call.');
165166
}
166167

167-
return $identity->applyScope($action, $resource);
168+
return $identity->applyScope($action, $resource, ...$optionalArgs);
168169
}
169170

170171
/**

src/IdentityDecorator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ public function canResult(string $action, $resource): ResultInterface
7676
/**
7777
* @inheritDoc
7878
*/
79-
public function applyScope(string $action, $resource): mixed
79+
public function applyScope(string $action, mixed $resource, mixed ...$optionalArgs): mixed
8080
{
81-
return $this->authorization->applyScope($this, $action, $resource);
81+
return $this->authorization->applyScope($this, $action, $resource, ...$optionalArgs);
8282
}
8383

8484
/**

src/IdentityInterface.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,10 @@ public function canResult(string $action, mixed $resource): ResultInterface;
5353
*
5454
* @param string $action The action/operation being performed.
5555
* @param mixed $resource The resource being operated on.
56+
* @param mixed $optionalArgs Multiple additional arguments which are passed to the scope
5657
* @return mixed The modified resource.
5758
*/
58-
public function applyScope(string $action, mixed $resource): mixed;
59+
public function applyScope(string $action, mixed $resource, mixed ...$optionalArgs): mixed;
5960

6061
/**
6162
* Get the decorated identity

tests/TestCase/AuthorizationServiceTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@
2121
use Authorization\Policy\BeforePolicyInterface;
2222
use Authorization\Policy\Exception\MissingMethodException;
2323
use Authorization\Policy\MapResolver;
24+
use Authorization\Policy\OrmResolver;
2425
use Authorization\Policy\Result;
2526
use Authorization\Policy\ResultInterface;
27+
use Cake\Datasource\QueryInterface;
2628
use Cake\TestSuite\TestCase;
2729
use TestApp\Model\Entity\Article;
30+
use TestApp\Model\Table\ArticlesTable;
2831
use TestApp\Policy\ArticlePolicy;
2932
use TestApp\Policy\MagicCallPolicy;
3033

@@ -173,6 +176,38 @@ public function testApplyScopeMethodMissing()
173176
$result = $service->applyScope($user, 'nope', $article);
174177
}
175178

179+
public function testApplyScopeAdditionalArguments()
180+
{
181+
$service = new AuthorizationService(new OrmResolver());
182+
$user = new IdentityDecorator($service, [
183+
'id' => 9,
184+
'role' => 'admin',
185+
]);
186+
187+
$articles = new ArticlesTable();
188+
$query = $this->createMock(QueryInterface::class);
189+
$query->method('getRepository')
190+
->willReturn($articles);
191+
192+
$query->expects($this->exactly(2))
193+
->method('where')
194+
->with([
195+
'identity_id' => 9,
196+
'firstArg' => 'first argument',
197+
'secondArg' => false,
198+
])
199+
->willReturn($query);
200+
201+
$result = $service->applyScope($user, 'additionalArguments', $query, 'first argument', false);
202+
$this->assertInstanceOf(QueryInterface::class, $result);
203+
$this->assertSame($query, $result);
204+
205+
// Test with named args as well
206+
$result = $service->applyScope($user, 'additionalArguments', $query, firstArg: 'first argument', secondArg: false);
207+
$this->assertInstanceOf(QueryInterface::class, $result);
208+
$this->assertSame($query, $result);
209+
}
210+
176211
public function testBeforeFalse()
177212
{
178213
$entity = new Article();

tests/TestCase/Controller/Component/AuthorizationComponentTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,28 @@ public function testApplyScopExplicitAction()
284284
$this->assertSame($query, $result);
285285
}
286286

287+
public function testApplyScopeAdditionalArguments()
288+
{
289+
$articles = new ArticlesTable();
290+
$query = $this->createMock(QueryInterface::class);
291+
$query->method('getRepository')
292+
->willReturn($articles);
293+
294+
$query->expects($this->once())
295+
->method('where')
296+
->with([
297+
'identity_id' => 1,
298+
'firstArg' => 'first argument',
299+
'secondArg' => false,
300+
])
301+
->willReturn($query);
302+
303+
$result = $this->Auth->applyScope($query, 'additionalArguments', 'first argument', false);
304+
305+
$this->assertInstanceOf(QueryInterface::class, $result);
306+
$this->assertSame($query, $result);
307+
}
308+
287309
public function testAuthorizeSuccessCheckExplicitAction()
288310
{
289311
$article = new Article(['user_id' => 1]);

tests/TestCase/IdentityDecoratorTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,19 @@ public function testApplyScopeDelegation()
6767
$this->assertTrue($identity->applyScope('update', $resource));
6868
}
6969

70+
public function testApplyScopeAdditionalParams()
71+
{
72+
$resource = new stdClass();
73+
$auth = $this->createMock(AuthorizationServiceInterface::class);
74+
$identity = new IdentityDecorator($auth, ['id' => 1]);
75+
76+
$auth->expects($this->once())
77+
->method('applyScope')
78+
->with($identity, 'update', $resource, 'first argument', false)
79+
->will($this->returnValue(true));
80+
$this->assertTrue($identity->applyScope('update', $resource, 'first argument', false));
81+
}
82+
7083
public function testCall()
7184
{
7285
$data = new Article(['id' => 1]);

tests/test_app/TestApp/Policy/ArticlesTablePolicy.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,13 @@ public function scopeModify(IdentityInterface $user, QueryInterface $query)
3636
'identity_id' => $user['id'],
3737
]);
3838
}
39+
40+
public function scopeAdditionalArguments(IdentityInterface $user, QueryInterface $query, $firstArg, $secondArg)
41+
{
42+
return $query->where([
43+
'identity_id' => $user['id'],
44+
'firstArg' => $firstArg,
45+
'secondArg' => $secondArg,
46+
]);
47+
}
3948
}

0 commit comments

Comments
 (0)