Skip to content

Commit

Permalink
Enable security information mapping for RoleSecurityHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
core23 committed Jul 5, 2024
1 parent cc6adb5 commit c57d8ba
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 6 deletions.
24 changes: 18 additions & 6 deletions src/Security/Handler/RoleSecurityHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,26 @@ private function hasOnlyAdminRules(mixed $attributes): bool
*/
private function mapAttributes(mixed $attributes, AdminInterface $admin): array
{
// NEXT_MAJOR: Change the foreach to a single check.
foreach ($attributes as $pos => $attribute) {
// If the attribute is not already a ROLE_ we generate the related role.
if (\is_string($attribute) && !str_starts_with($attribute, 'ROLE_')) {
$attributes[$pos] = sprintf($this->getBaseRole($admin), $attribute);
$mappedAttributes = [];

foreach ($attributes as $attribute) {
if (!\is_string($attribute) || str_starts_with($attribute, 'ROLE_')) {
$mappedAttributes[] = $attribute;

continue;
}

$baseRole = $this->getBaseRole($admin);

$mappedAttributes[] = sprintf($baseRole, $attribute);

foreach ($admin->getSecurityInformation() as $role => $permissions) {
if (\in_array($attribute, $permissions, true)) {
$mappedAttributes[] = sprintf($baseRole, $role);
}
}
}

return $attributes;
return array_unique($mappedAttributes);
}
}
48 changes: 48 additions & 0 deletions tests/Security/Handler/RoleSecurityHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,54 @@ public function provideGetBaseRoleCases(): iterable
yield ['ROLE_FOO_BAR_%s', 'FOO.BAR'];
}

/**
* @dataProvider provideIsGrantedWithSecurityInformationCases
*
* @param array<string, string[]> $informationMapping
* @param string[] $userRoles
*/
public function testIsGrantedWithSecurityInformation(array $informationMapping, array $userRoles, bool $expected): void
{
$handler = new RoleSecurityHandler($this->authorizationChecker, 'ROLE_SUPER_ADMIN');

$subject = new \stdClass();

$this->admin
->method('getCode')
->willReturn('test');
$this->admin->expects(static::once())
->method('getSecurityInformation')
->willReturn($informationMapping);

$this->authorizationChecker
->method('isGranted')
->willReturnCallback(static function (mixed $attribute, mixed $subject = null) use ($userRoles): bool {
if ($attribute instanceof Expression) {
$attribute = (string) $attribute;
}

if (\in_array($attribute, $userRoles, true)) {
return $subject instanceof \stdClass;
}

return false;
});

static::assertSame($expected, $handler->isGranted($this->admin, 'EDIT', $subject));
}

/**
* @phpstan-return iterable<array{array<string, string[]>, string[], bool}>
*/
public function provideIsGrantedWithSecurityInformationCases(): iterable
{
yield 'default mapping' => [[], ['ROLE_TEST_EDIT'], true];
yield 'with single mapping' => [['VIEW' => ['EDIT', 'SHOW']], ['ROLE_TEST_VIEW'], true];
yield 'with multiple mappings' => [['WRITE' => ['EDIT', 'SHOW'], 'MANAGE' => ['EDIT', 'SHOW', 'DELETE']], ['ROLE_TEST_MANAGE'], true];
yield 'with all mapping' => [['ADMIN' => ['ALL']], ['ROLE_TEST_ALL'], true];
yield 'with missing permission' => [['SHOW' => ['VIEW', 'SHOW']], ['ROLE_TEST_VIEW'], false];
}

/**
* NEXT_MAJOR: Remove the group legacy and only keep string $superAdminRoles and string|Expression $operation in dataProvider.
*
Expand Down

0 comments on commit c57d8ba

Please sign in to comment.