1313
1414use Symfony \Component \Security \Acl \Voter \FieldVote ;
1515use Symfony \Component \Security \Core \Authorization \AuthorizationCheckerInterface ;
16+ use Symfony \Component \Security \Core \Authorization \UserAuthorizationCheckerInterface ;
1617use Symfony \Component \Security \Core \Exception \AuthenticationCredentialsNotFoundException ;
18+ use Symfony \Component \Security \Core \User \UserInterface ;
1719use Symfony \Component \Security \Http \Impersonate \ImpersonateUrlGenerator ;
1820use Twig \Extension \AbstractExtension ;
1921use Twig \TwigFunction ;
@@ -28,6 +30,7 @@ final class SecurityExtension extends AbstractExtension
2830 public function __construct (
2931 private ?AuthorizationCheckerInterface $ securityChecker = null ,
3032 private ?ImpersonateUrlGenerator $ impersonateUrlGenerator = null ,
33+ private ?UserAuthorizationCheckerInterface $ userSecurityChecker = null ,
3134 ) {
3235 }
3336
@@ -48,6 +51,19 @@ public function isGranted(mixed $role, mixed $object = null, ?string $field = nu
4851 }
4952 }
5053
54+ public function isGrantedForUser (UserInterface $ user , mixed $ attribute , mixed $ subject = null , ?string $ field = null ): bool
55+ {
56+ if (!$ this ->userSecurityChecker ) {
57+ throw new \LogicException (\sprintf ('An instance of "%s" must be provided to use "%s()". ' , UserAuthorizationCheckerInterface::class, __METHOD__ ));
58+ }
59+
60+ if ($ field ) {
61+ $ subject = new FieldVote ($ subject , $ field );
62+ }
63+
64+ return $ this ->userSecurityChecker ->isGrantedForUser ($ user , $ attribute , $ subject );
65+ }
66+
5167 public function getImpersonateExitUrl (?string $ exitTo = null ): string
5268 {
5369 if (null === $ this ->impersonateUrlGenerator ) {
@@ -86,12 +102,18 @@ public function getImpersonatePath(string $identifier): string
86102
87103 public function getFunctions (): array
88104 {
89- return [
105+ $ functions = [
90106 new TwigFunction ('is_granted ' , $ this ->isGranted (...)),
91107 new TwigFunction ('impersonation_exit_url ' , $ this ->getImpersonateExitUrl (...)),
92108 new TwigFunction ('impersonation_exit_path ' , $ this ->getImpersonateExitPath (...)),
93109 new TwigFunction ('impersonation_url ' , $ this ->getImpersonateUrl (...)),
94110 new TwigFunction ('impersonation_path ' , $ this ->getImpersonatePath (...)),
95111 ];
112+
113+ if ($ this ->userSecurityChecker ) {
114+ $ functions [] = new TwigFunction ('is_granted_for_user ' , $ this ->isGrantedForUser (...));
115+ }
116+
117+ return $ functions ;
96118 }
97119}
0 commit comments