Skip to content

Commit 7c7d2de

Browse files
alexandre-dauboisnicolas-grekas
authored andcommitted
[Security] Allow using a callable with #[IsGranted]
1 parent 5d6d6ee commit 7c7d2de

File tree

6 files changed

+512
-8
lines changed

6 files changed

+512
-8
lines changed

Attribute/IsGranted.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
namespace Symfony\Component\Security\Http\Attribute;
1313

1414
use Symfony\Component\ExpressionLanguage\Expression;
15+
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
17+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
18+
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
1519

1620
/**
1721
* Checks if user has permission to access to some resource using security roles and voters.
@@ -24,15 +28,15 @@
2428
final class IsGranted
2529
{
2630
/**
27-
* @param string|Expression $attribute The attribute that will be checked against a given authentication token and optional subject
28-
* @param array|string|Expression|null $subject An optional subject - e.g. the current object being voted on
29-
* @param string|null $message A custom message when access is not granted
30-
* @param int|null $statusCode If set, will throw HttpKernel's HttpException with the given $statusCode; if null, Security\Core's AccessDeniedException will be used
31-
* @param int|null $exceptionCode If set, will add the exception code to thrown exception
31+
* @param string|Expression|(\Closure(TokenInterface $token, mixed $subject, AccessDecisionManagerInterface $accessDecisionManager, AuthenticationTrustResolverInterface $trustResolver): bool) $attribute The attribute that will be checked against a given authentication token and optional subject
32+
* @param array|string|Expression|(\Closure(array<string, mixed>, Request): mixed)|null $subject An optional subject - e.g. the current object being voted on
33+
* @param string|null $message A custom message when access is not granted
34+
* @param int|null $statusCode If set, will throw HttpKernel's HttpException with the given $statusCode; if null, Security\Core's AccessDeniedException will be used
35+
* @param int|null $exceptionCode If set, will add the exception code to thrown exception
3236
*/
3337
public function __construct(
34-
public string|Expression $attribute,
35-
public array|string|Expression|null $subject = null,
38+
public string|Expression|\Closure $attribute,
39+
public array|string|Expression|\Closure|null $subject = null,
3640
public ?string $message = null,
3741
public ?int $statusCode = null,
3842
public ?int $exceptionCode = null,

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ CHANGELOG
88
* Replace `$hideAccountStatusExceptions` argument with `$exposeSecurityErrors` in `AuthenticatorManager` constructor
99
* Add argument `$identifierNormalizer` to `UserBadge::__construct()` to allow normalizing the identifier
1010
* Support hashing the hashed password using crc32c when putting the user in the session
11+
* Add support for closures in `#[IsGranted]`
1112

1213
7.2
1314
---

EventListener/IsGrantedAttributeListener.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ public function onKernelControllerArguments(ControllerArgumentsEvent $event): vo
5555
foreach ($subjectRef as $refKey => $ref) {
5656
$subject[\is_string($refKey) ? $refKey : (string) $ref] = $this->getIsGrantedSubject($ref, $request, $arguments);
5757
}
58+
} elseif ($subjectRef instanceof \Closure) {
59+
$subject = $subjectRef($arguments, $request);
5860
} else {
5961
$subject = $this->getIsGrantedSubject($subjectRef, $request, $arguments);
6062
}
@@ -69,7 +71,7 @@ public function onKernelControllerArguments(ControllerArgumentsEvent $event): vo
6971
}
7072

7173
$e = new AccessDeniedException($message, code: $attribute->exceptionCode ?? 403);
72-
$e->setAttributes($attribute->attribute);
74+
$e->setAttributes([$attribute->attribute]);
7375
$e->setSubject($subject);
7476
$e->setAccessDecision($accessDecision);
7577

0 commit comments

Comments
 (0)