File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 88final class Security extends Attribute
99{
1010 /**
11- * @param array<string>|string|null $handlers
11+ * @param array<string>|string|null $handlers
12+ * @param array<string>|null $roles
1213 * @param class-string<\RuntimeException> $exception
1314 */
1415 public function __construct (
15- public readonly ?string $ expression = null ,
16+ public readonly ?string $ expression = null ,
1617 public array |string |null $ handlers = null ,
17- public ?string $ message = null ,
18- public ?string $ exception = null ,
18+ public ?string $ message = null ,
19+ public ?string $ exception = null ,
20+ public ?array $ roles = null ,
1921 ) {
2022 parent ::__construct ();
2123 $ this ->setHandlers ($ handlers );
Original file line number Diff line number Diff line change @@ -51,10 +51,25 @@ public function prefix(Instance $instance): Response
5151 return new Response ();
5252 }
5353
54+ $ rolesExpressions = null ;
55+ if ($ attribute ->roles !== null ) {
56+ if ($ attribute ->expression !== null ) {
57+ throw new \RuntimeException ('You cannot use both roles and expression in the Security attribute. ' );
58+ }
59+ $ rolesExpressions = array_map (
60+ static fn (string $ role ) => "is_granted(' {$ role }') " ,
61+ $ attribute ->roles
62+ );
63+ }
64+
5465 $ expression = $ attribute ->expression ;
5566 if ($ expression === null ) {
56- $ role = $ this ->guessRoleName ($ instance );
57- $ expression = "is_granted(' {$ role }') " ;
67+ if ($ rolesExpressions !== null ) {
68+ $ expression = implode (' or ' , $ rolesExpressions );
69+ } else {
70+ $ role = $ this ->guessRoleName ($ instance );
71+ $ expression = "is_granted(' {$ role }') " ;
72+ }
5873 }
5974 $ handlers = $ this ->getHandlers (SecurityHandler::class, $ attribute );
6075 foreach ($ handlers as $ handler ) {
Original file line number Diff line number Diff line change @@ -61,4 +61,19 @@ public function accessDeniedWithMessage(): void
6161 public function accessDeniedWithException (): void
6262 {
6363 }
64+
65+ #[Security(roles: ['ROLE_1 ' ])]
66+ public function rolesParamOne (): void
67+ {
68+ }
69+
70+ #[Security(roles: ['ROLE_3 ' , 'ROLE_1 ' ])]
71+ public function rolesParamMultiple (): void
72+ {
73+ }
74+
75+ #[Security("is_granted('ROLE_1') " , roles: ['ROLE_1 ' , 'ROLE_2 ' ])]
76+ public function conflict (): void
77+ {
78+ }
6479}
Original file line number Diff line number Diff line change @@ -111,4 +111,22 @@ public function testAccessDeniedWithException(): void
111111 $ this ->expectExceptionMessage ('Invalid argument. ' );
112112 $ this ->proxy ->accessDeniedWithException ();
113113 }
114+
115+ public function testWithRolesParamOne (): void
116+ {
117+ $ this ->proxy ->rolesParamOne ();
118+ $ this ->assertSame (['ROLE_1 ' ], $ this ->handler ->attributes );
119+ }
120+
121+ public function testWithRolesParamMultiple (): void
122+ {
123+ $ this ->proxy ->rolesParamMultiple ();
124+ $ this ->assertSame (['ROLE_3 ' , 'ROLE_1 ' ], $ this ->handler ->attributes );
125+ }
126+
127+ public function testWithRolesAndExpressionShouldThrow (): void
128+ {
129+ $ this ->expectException (\RuntimeException::class);
130+ $ this ->proxy ->conflict ();
131+ }
114132}
You can’t perform that action at this time.
0 commit comments