Skip to content

Commit 4b0293c

Browse files
committedJan 28, 2025
feat(security): add roles param to simplfy migration
1 parent 3fb67c4 commit 4b0293c

File tree

4 files changed

+56
-6
lines changed

4 files changed

+56
-6
lines changed
 

‎src/Attribute/Security.php

+6-4
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@
88
final 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);

‎src/Interceptor/Impl/SecurityInterceptor.php

+17-2
Original file line numberDiff line numberDiff 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) {

‎tests/Double/Stub/Security/SecurityAnnotatedClass.php

+15
Original file line numberDiff line numberDiff 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
}

‎tests/Interceptor/SecurityInterceptorTest.php

+18
Original file line numberDiff line numberDiff 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
}

0 commit comments

Comments
 (0)