Skip to content

Commit 7e4e1b5

Browse files
minor #48080 [Security] Make request always available to #[IsGranted] (HypeMC)
This PR was merged into the 6.2 branch. Discussion ---------- [Security] Make request always available to `#[IsGranted]` | Q | A | ------------- | --- | Branch? | 6.2 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix symfony/symfony#48071 (comment) | License | MIT | Doc PR | - Currently, the request is only available to the `#[IsGranted]` attribute when it's a controller argument, eg: ```php #[IsGranted(attribute: 'SOME_ATTRIBUTE', subject: 'request')] public function index(Request $request) { } #[IsGranted( attribute: 'SOME_ATTRIBUTE', subject: new Expression('args["request"].query.get("foo")'), )] public function index(Request $request) { } ``` However, since the `$request` variable might not always be needed in the controller itself, it seems kind of weird to have to add it as an argument just so the `#[IsGranted]` attribute could work. With this PR, the request will always be available to the attribute: ```php #[IsGranted(attribute: 'SOME_ATTRIBUTE', subject: 'request')] public function index() { } #[IsGranted( attribute: 'SOME_ATTRIBUTE', subject: new Expression('request.query.get("foo")'), )] public function index() { } ``` Don't know if this qualifies as a tweak for 6.2 or feature for 6.3. Commits ------- 3b6865295e [Security] Make request always available to #[IsGranted]
2 parents a6859b8 + b0f14eb commit 7e4e1b5

File tree

3 files changed

+72
-8
lines changed

3 files changed

+72
-8
lines changed

EventListener/IsGrantedAttributeListener.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
1515
use Symfony\Component\ExpressionLanguage\Expression;
1616
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
17+
use Symfony\Component\HttpFoundation\Request;
1718
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
1819
use Symfony\Component\HttpKernel\Exception\HttpException;
1920
use Symfony\Component\HttpKernel\KernelEvents;
@@ -42,6 +43,7 @@ public function onKernelControllerArguments(ControllerArgumentsEvent $event)
4243
return;
4344
}
4445

46+
$request = $event->getRequest();
4547
$arguments = $event->getNamedArguments();
4648

4749
foreach ($attributes as $attribute) {
@@ -50,10 +52,10 @@ public function onKernelControllerArguments(ControllerArgumentsEvent $event)
5052
if ($subjectRef = $attribute->subject) {
5153
if (\is_array($subjectRef)) {
5254
foreach ($subjectRef as $refKey => $ref) {
53-
$subject[\is_string($refKey) ? $refKey : (string) $ref] = $this->getIsGrantedSubject($ref, $arguments);
55+
$subject[\is_string($refKey) ? $refKey : (string) $ref] = $this->getIsGrantedSubject($ref, $request, $arguments);
5456
}
5557
} else {
56-
$subject = $this->getIsGrantedSubject($subjectRef, $arguments);
58+
$subject = $this->getIsGrantedSubject($subjectRef, $request, $arguments);
5759
}
5860
}
5961

@@ -78,17 +80,21 @@ public static function getSubscribedEvents(): array
7880
return [KernelEvents::CONTROLLER_ARGUMENTS => ['onKernelControllerArguments', 10]];
7981
}
8082

81-
private function getIsGrantedSubject(string|Expression $subjectRef, array $arguments): mixed
83+
private function getIsGrantedSubject(string|Expression $subjectRef, Request $request, array $arguments): mixed
8284
{
8385
if ($subjectRef instanceof Expression) {
8486
$this->expressionLanguage ??= new ExpressionLanguage();
8587

8688
return $this->expressionLanguage->evaluate($subjectRef, [
89+
'request' => $request,
8790
'args' => $arguments,
8891
]);
8992
}
9093

9194
if (!\array_key_exists($subjectRef, $arguments)) {
95+
if ('request' === $subjectRef) {
96+
return $request;
97+
}
9298
throw new RuntimeException(sprintf('Could not find the subject "%s" for the #[IsGranted] attribute. Try adding a "$%s" argument to your controller method.', $subjectRef, $subjectRef));
9399
}
94100

Tests/EventListener/IsGrantedAttributeListenerTest.php

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ public function testNotFoundHttpException()
281281
$listener->onKernelControllerArguments($event);
282282
}
283283

284-
public function testIsGrantedwithExpressionInAttribute()
284+
public function testIsGrantedWithExpressionInAttribute()
285285
{
286286
$authChecker = $this->createMock(AuthorizationCheckerInterface::class);
287287
$authChecker->expects($this->once())
@@ -301,8 +301,10 @@ public function testIsGrantedwithExpressionInAttribute()
301301
$listener->onKernelControllerArguments($event);
302302
}
303303

304-
public function testIsGrantedwithExpressionInSubject()
304+
public function testIsGrantedWithExpressionInSubject()
305305
{
306+
$request = new Request();
307+
306308
$authChecker = $this->createMock(AuthorizationCheckerInterface::class);
307309
$authChecker->expects($this->once())
308310
->method('isGranted')
@@ -314,23 +316,26 @@ public function testIsGrantedwithExpressionInSubject()
314316
->method('evaluate')
315317
->with(new Expression('args["post"].getAuthor()'), [
316318
'args' => ['post' => 'postVal'],
319+
'request' => $request,
317320
])
318321
->willReturn('author');
319322

320323
$event = new ControllerArgumentsEvent(
321324
$this->createMock(HttpKernelInterface::class),
322325
[new IsGrantedAttributeMethodsController(), 'withExpressionInSubject'],
323326
['postVal'],
324-
new Request(),
327+
$request,
325328
null
326329
);
327330

328331
$listener = new IsGrantedAttributeListener($authChecker, $expressionLanguage);
329332
$listener->onKernelControllerArguments($event);
330333
}
331334

332-
public function testIsGrantedwithNestedExpressionInSubject()
335+
public function testIsGrantedWithNestedExpressionInSubject()
333336
{
337+
$request = new Request();
338+
334339
$authChecker = $this->createMock(AuthorizationCheckerInterface::class);
335340
$authChecker->expects($this->once())
336341
->method('isGranted')
@@ -342,18 +347,61 @@ public function testIsGrantedwithNestedExpressionInSubject()
342347
->method('evaluate')
343348
->with(new Expression('args["post"].getAuthor()'), [
344349
'args' => ['post' => 'postVal', 'arg2Name' => 'arg2Val'],
350+
'request' => $request,
345351
])
346352
->willReturn('author');
347353

348354
$event = new ControllerArgumentsEvent(
349355
$this->createMock(HttpKernelInterface::class),
350356
[new IsGrantedAttributeMethodsController(), 'withNestedExpressionInSubject'],
351357
['postVal', 'arg2Val'],
352-
new Request(),
358+
$request,
353359
null
354360
);
355361

356362
$listener = new IsGrantedAttributeListener($authChecker, $expressionLanguage);
357363
$listener->onKernelControllerArguments($event);
358364
}
365+
366+
public function testIsGrantedWithRequestAsSubjectAndNoArgument()
367+
{
368+
$request = new Request();
369+
370+
$authChecker = $this->createMock(AuthorizationCheckerInterface::class);
371+
$authChecker->expects($this->once())
372+
->method('isGranted')
373+
->with('SOME_VOTER', $request)
374+
->willReturn(true);
375+
376+
$event = new ControllerArgumentsEvent(
377+
$this->createMock(HttpKernelInterface::class),
378+
[new IsGrantedAttributeMethodsController(), 'withRequestAsSubjectAndNoArgument'],
379+
[],
380+
$request,
381+
null
382+
);
383+
384+
$listener = new IsGrantedAttributeListener($authChecker);
385+
$listener->onKernelControllerArguments($event);
386+
}
387+
388+
public function testIsGrantedWithRequestAsSubjectAndArgument()
389+
{
390+
$authChecker = $this->createMock(AuthorizationCheckerInterface::class);
391+
$authChecker->expects($this->once())
392+
->method('isGranted')
393+
->with('SOME_VOTER', 'foobar')
394+
->willReturn(true);
395+
396+
$event = new ControllerArgumentsEvent(
397+
$this->createMock(HttpKernelInterface::class),
398+
[new IsGrantedAttributeMethodsController(), 'withRequestAsSubjectAndArgument'],
399+
['foobar'],
400+
new Request(),
401+
null
402+
);
403+
404+
$listener = new IsGrantedAttributeListener($authChecker);
405+
$listener->onKernelControllerArguments($event);
406+
}
359407
}

Tests/Fixtures/IsGrantedAttributeMethodsController.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,14 @@ public function withExpressionInSubject($post)
6262
public function withNestedExpressionInSubject($post, $arg2Name)
6363
{
6464
}
65+
66+
#[IsGranted(attribute: 'SOME_VOTER', subject: 'request')]
67+
public function withRequestAsSubjectAndNoArgument()
68+
{
69+
}
70+
71+
#[IsGranted(attribute: 'SOME_VOTER', subject: 'request')]
72+
public function withRequestAsSubjectAndArgument($request)
73+
{
74+
}
6575
}

0 commit comments

Comments
 (0)