Skip to content

Commit

Permalink
add user/group resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
4rthem committed Jan 9, 2024
1 parent 5a0316c commit c8fd609
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 28 deletions.
45 changes: 29 additions & 16 deletions Admin/PermissionView.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Alchemy\AclBundle\Mapping\ObjectMapping;
use Alchemy\AclBundle\Model\AccessControlEntryInterface;
use Alchemy\AclBundle\Repository\AclUserRepositoryInterface;
use Alchemy\AclBundle\Repository\UserRepositoryInterface;
use Alchemy\AclBundle\Repository\GroupRepositoryInterface;
use Alchemy\AclBundle\Repository\PermissionRepositoryInterface;
use Alchemy\AclBundle\Security\PermissionInterface;
Expand All @@ -16,15 +16,15 @@ class PermissionView
{
private ObjectMapping $objectMapping;
private PermissionRepositoryInterface $repository;
private AclUserRepositoryInterface $userRepository;
private UserRepositoryInterface $userRepository;
private GroupRepositoryInterface $groupRepository;
private EntityManagerInterface $em;
private ?array $enabledPermissions;

public function __construct(
ObjectMapping $objectMapping,
PermissionRepositoryInterface $repository,
AclUserRepositoryInterface $userRepository,
UserRepositoryInterface $userRepository,
GroupRepositoryInterface $groupRepository,
EntityManagerInterface $em,
?array $enabledPermissions
Expand Down Expand Up @@ -53,29 +53,19 @@ public function getViewParameters(string $objectKey, ?string $id): array
$users = [
AccessControlEntryInterface::USER_WILDCARD => 'All users',
];
foreach ($this->userRepository->getAclUsers() as $user) {
foreach ($this->userRepository->getUsers() as $user) {
$users[$user['id']] = $user['username'];
}
$groups = [];
foreach ($this->groupRepository->getGroups() as $group) {
$groups[$group['id']] = $group['name'];
}

$aces = array_map(function (AccessControlEntryInterface $ace) use ($users, $groups, $permissions): array {
$name = $ace->getUserId();
switch ($ace->getUserType()) {
case AccessControlEntryInterface::TYPE_USER_VALUE:
$name = $ace->getUserId() ? ($users[$ace->getUserId()] ?? $name) : AccessControlEntryInterface::USER_WILDCARD;
break;
case AccessControlEntryInterface::TYPE_GROUP_VALUE:
$name = $groups[$ace->getUserId()] ?? $name;
break;
}

$aces = array_map(function (AccessControlEntryInterface $ace) use ($permissions): array {
return [
'userType' => $ace->getUserTypeString(),
'userId' => $ace->getUserId() ?? AccessControlEntryInterface::USER_WILDCARD,
'name' => $name,
'name' => $this->resolveUserName($ace),
'objectId' => $ace->getObjectId(),
'permissions' => array_map(fn (int $p): bool => $ace->hasPermission($p), $permissions),
];
Expand Down Expand Up @@ -105,4 +95,27 @@ public function getViewParameters(string $objectKey, ?string $id): array

return $params;
}

private function resolveUserName(AccessControlEntryInterface $ace): string
{
$userId = $ace->getUserId();

if (null !== $userId) {
switch ($ace->getUserType()) {
case AccessControlEntryInterface::TYPE_USER_VALUE:
if (null !== $user = $this->userRepository->getUser($userId)) {
return $user['username'];
}

return 'User not found';
case AccessControlEntryInterface::TYPE_GROUP_VALUE:
if (null !== $group = $this->groupRepository->getGroup($userId)) {
return $group['name'];
}
return 'Group not found';
}
}

return AccessControlEntryInterface::USER_WILDCARD;
}
}
6 changes: 3 additions & 3 deletions Controller/PermissionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private function validateAuthorization(string $attribute, Request $request): arr
/**
* @Route("/ace", methods={"PUT"}, name="ace")
*/
public function setAce(Request $request): Response
public function setAce(Request $request, AceSerializer $aceSerializer): Response
{
$data = $this->validateAuthorization(SetPermissionVoter::ACL_WRITE, $request);

Expand All @@ -72,9 +72,9 @@ public function setAce(Request $request): Response

$userType = AccessControlEntry::getUserTypeFromString($userType);

$this->permissionManager->updateOrCreateAce($userType, $userId, $objectType, $objectId, $mask);
$ace = $this->permissionManager->updateOrCreateAce($userType, $userId, $objectType, $objectId, $mask);

return new JsonResponse(true);
return new JsonResponse($aceSerializer->serialize($ace));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Then you must alias your UserRepository service:
```yaml
# config/services.yaml
services:
Alchemy\AclBundle\Repository\AclUserRepositoryInterface: '@App\Repository\UserRepository'
Alchemy\AclBundle\Repository\UserRepositoryInterface: '@App\Repository\UserRepository'
```
Add redis cache for access token:
Expand Down
2 changes: 2 additions & 0 deletions Repository/GroupRepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
interface GroupRepositoryInterface
{
public function getGroups(int $limit = null, int $offset = 0): array;

public function getGroup(string $groupId): ?array;
}
2 changes: 2 additions & 0 deletions Repository/UserRepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
interface UserRepositoryInterface
{
public function getUsers(int $limit, int $offset = 0): array;

public function getUser(string $userId): ?array;
}
6 changes: 3 additions & 3 deletions Security/PermissionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Alchemy\AclBundle\Mapping\ObjectMapping;
use Alchemy\AclBundle\Model\AccessControlEntryInterface;
use Alchemy\AclBundle\Model\AclUserInterface;
use Alchemy\AclBundle\Repository\AclUserRepositoryInterface;
use Alchemy\AclBundle\Repository\UserRepositoryInterface;
use Alchemy\AclBundle\Repository\PermissionRepositoryInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

Expand All @@ -19,14 +19,14 @@ class PermissionManager
private ObjectMapping $objectMapper;
private PermissionRepositoryInterface $repository;
private EventDispatcherInterface $eventDispatcher;
private AclUserRepositoryInterface $userRepository;
private UserRepositoryInterface $userRepository;
private array $cache = [];

public function __construct(
ObjectMapping $objectMapper,
PermissionRepositoryInterface $repository,
EventDispatcherInterface $eventDispatcher,
AclUserRepositoryInterface $userRepository
UserRepositoryInterface $userRepository
) {
$this->objectMapper = $objectMapper;
$this->repository = $repository;
Expand Down
22 changes: 20 additions & 2 deletions Serializer/AceSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@
namespace Alchemy\AclBundle\Serializer;

use Alchemy\AclBundle\Model\AccessControlEntryInterface;
use Alchemy\AclBundle\Repository\GroupRepositoryInterface;
use Alchemy\AclBundle\Repository\UserRepositoryInterface;

class AceSerializer
readonly class AceSerializer
{
public function __construct(
private UserRepositoryInterface $userRepository,
private GroupRepositoryInterface $groupRepository,
)
{
}

public function serialize(AccessControlEntryInterface $ace): array
{
return [
$payload = [
'id' => $ace->getId(),
'userType' => array_search($ace->getUserType(), AccessControlEntryInterface::USER_TYPES, true),
'userId' => $ace->getUserId(),
Expand All @@ -19,5 +28,14 @@ public function serialize(AccessControlEntryInterface $ace): array
'mask' => $ace->getMask(),
'parentId' => $ace->getParentId(),
];

$id = $ace->getUserId();
if ($ace->getUserType() === AccessControlEntryInterface::TYPE_USER_VALUE) {
$payload['user'] = $this->userRepository->getUser($id);
} elseif ($ace->getUserType() === AccessControlEntryInterface::TYPE_GROUP_VALUE) {
$payload['group'] = $this->groupRepository->getGroup($id);
}

return $payload;
}
}
6 changes: 3 additions & 3 deletions Tests/PermissionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Alchemy\AclBundle\Entity\AccessControlEntry;
use Alchemy\AclBundle\Mapping\ObjectMapping;
use Alchemy\AclBundle\Repository\AclUserRepositoryInterface;
use Alchemy\AclBundle\Repository\UserRepositoryInterface;
use Alchemy\AclBundle\Repository\PermissionRepositoryInterface;
use Alchemy\AclBundle\Security\PermissionInterface;
use Alchemy\AclBundle\Security\PermissionManager;
Expand Down Expand Up @@ -38,7 +38,7 @@ public function testPermissionsWithUser(array $acePermissions, int $permissionTo

$user = new AclUserMock('123');

$userRepo = $this->createMock(AclUserRepositoryInterface::class);
$userRepo = $this->createMock(UserRepositoryInterface::class);
$userRepo
->expects($this->once())
->method('getAclGroupsId')
Expand Down Expand Up @@ -80,7 +80,7 @@ public function testPermissionsWithGroup(array $acePermissions, int $permissionT

$user = new AclUserMock('123');

$userRepo = $this->createMock(AclUserRepositoryInterface::class);
$userRepo = $this->createMock(UserRepositoryInterface::class);
$userRepo
->expects($this->once())
->method('getAclGroupsId')
Expand Down

0 comments on commit c8fd609

Please sign in to comment.