diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c19891d..b9de155 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -13,9 +13,7 @@ jobs: strategy: matrix: version: - - 8.2 - - 8.3 - - 8.4 + - 8.5 steps: - uses: shivammathur/setup-php@v2 with: diff --git a/composer.json b/composer.json index 54dccc5..684643e 100644 --- a/composer.json +++ b/composer.json @@ -6,15 +6,15 @@ "homepage": "https://www.alchemy.fr/", "license": "MIT", "require": { - "php": "^8.2", + "php": "^8.5", "ext-json": "*", - "doctrine/orm": "^2.6", - "ramsey/uuid-doctrine": "^1.5", - "symfony/event-dispatcher": "^4.0|^5.4|^6.1", - "symfony/framework-bundle": "^4.0|^5.4|^6.1", - "symfony/security-bundle": "^4.0|^5.4|^6.1", - "symfony/validator": "^6.3", - "symfony/yaml": "^4.4|^5.4|^6.1" + "doctrine/orm": "^2.6|^3.6.1", + "ramsey/uuid-doctrine": "^1.5|^2.1.0", + "symfony/event-dispatcher": "^6.4|^7.4", + "symfony/framework-bundle": "^6.4|^7.4", + "symfony/security-bundle": "^6.4|^7.4", + "symfony/validator": "^6.4|^7.4", + "symfony/yaml": "6.4|^7.4" }, "config": { "sort-packages": true diff --git a/rector.php b/rector.php index 494266d..46c7a24 100644 --- a/rector.php +++ b/rector.php @@ -13,6 +13,7 @@ ->withPhpSets( php84: true, ) + ->withAttributesSets(all: true) ->withTypeCoverageLevel(0) ->withDeadCodeLevel(0) ->withCodeQualityLevel(0); diff --git a/src/Admin/PermissionView.php b/src/Admin/PermissionView.php index 66f1614..31b265d 100644 --- a/src/Admin/PermissionView.php +++ b/src/Admin/PermissionView.php @@ -47,7 +47,7 @@ public function getViewParameters(string $objectKey, ?string $id): array 'userId' => $ace->getUserId() ?? AccessControlEntryInterface::USER_WILDCARD, 'name' => $this->resolveUserName($ace), 'objectId' => $ace->getObjectId(), - 'permissions' => array_map(fn (int $p): bool => $ace->hasPermission($p), $permissions), + 'permissions' => array_map($ace->hasPermission(...), $permissions), ], $aces); $objectTitle = null; diff --git a/src/Controller/PermissionController.php b/src/Controller/PermissionController.php index 20f4ba0..89b72bd 100644 --- a/src/Controller/PermissionController.php +++ b/src/Controller/PermissionController.php @@ -23,7 +23,11 @@ class PermissionController extends AbstractController { - public function __construct(private readonly PermissionManager $permissionManager, private readonly EntityManagerInterface $em, private readonly ObjectMapping $objectMapping) + public function __construct( + private readonly PermissionManager $permissionManager, + private readonly EntityManagerInterface $em, + private readonly ObjectMapping $objectMapping, + ) { } @@ -95,7 +99,7 @@ public function indexAces( $aces = $repository->findAcesByParams($params); - return new JsonResponse(array_map(fn (AccessControlEntryInterface $ace): array => $aceSerializer->serialize($ace), $aces)); + return new JsonResponse(array_map($aceSerializer->serialize(...), $aces)); } #[Route(path: '/ace', name: 'ace_delete', methods: ['DELETE'])] @@ -118,7 +122,7 @@ public function deleteAce(Request $request): Response private function getRequestData(Request $request): array { - if ('json' !== $request->getContentType() || empty($request->getContent())) { + if ('json' !== $request->getContentTypeFormat() || empty($request->getContent())) { if ('GET' === $request->getMethod()) { return $request->query->all(); } diff --git a/src/Entity/AccessControlEntry.php b/src/Entity/AccessControlEntry.php index 4381c3e..f01c5f2 100644 --- a/src/Entity/AccessControlEntry.php +++ b/src/Entity/AccessControlEntry.php @@ -9,70 +9,52 @@ use Ramsey\Uuid\Uuid; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Table( - * uniqueConstraints={@ORM\UniqueConstraint(name="uniq_ace", columns={"user_type", "user_id", "object_type", "object_id", "parent_id"})}, - * indexes={ - * @ORM\Index(name="user_idx", columns={"user_type", "user_id"}), - * @ORM\Index(name="object_idx", columns={"object_type", "object_id"}), - * @ORM\Index(name="user_type_idx", columns={"user_type"}), - * @ORM\Index(name="object_type_idx", columns={"object_type"}), - * @ORM\Index(name="parent_idx", columns={"parent_id"}), - * } - * ) - * @ORM\Entity(repositoryClass="AccessControlEntryRepository") - */ +#[ORM\Entity(repositoryClass: AccessControlEntryRepository::class)] +#[ORM\Table] +#[ORM\Index(name: 'user_idx', columns: ['user_type', 'user_id'])] +#[ORM\Index(name: 'object_idx', columns: ['object_type', 'object_id'])] +#[ORM\Index(name: 'user_type_idx', columns: ['user_type'])] +#[ORM\Index(name: 'object_type_idx', columns: ['object_type'])] +#[ORM\Index(name: 'parent_idx', columns: ['parent_id'])] +#[ORM\UniqueConstraint(name: 'uniq_ace', columns: ['user_type', 'user_id', 'object_type', 'object_id', 'parent_id'])] class AccessControlEntry implements AccessControlEntryInterface { /** * @var Uuid - * - * @ORM\Id - * @ORM\Column(type="uuid", unique=true) - * @ORM\GeneratedValue(strategy="CUSTOM") - * @ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator") */ + #[ORM\Id] + #[ORM\Column(type: 'uuid', unique: true)] + #[ORM\GeneratedValue(strategy: 'CUSTOM')] + #[ORM\CustomIdGenerator(class: \Ramsey\Uuid\Doctrine\UuidGenerator::class)] protected $id; - /** - * @ORM\Column(type="smallint") - */ + #[ORM\Column(type: 'smallint')] protected int $userType = self::TYPE_USER_VALUE; - /** - * @ORM\Column(type="string", length=36, nullable=true) - */ + #[ORM\Column(type: 'string', length: 36, nullable: true)] protected ?string $userId = null; /** * The object type name (i.e. publication). - * - * @ORM\Column(type="string", length=20) */ #[Assert\NotNull] + #[ORM\Column(type: 'string', length: 20)] protected ?string $objectType = null; - /** - * @ORM\Column(type="uuid", nullable=true) - */ + #[ORM\Column(type: 'uuid', nullable: true)] protected ?string $objectId = null; - /** - * @ORM\Column(type="integer") - */ + #[ORM\Column(type: 'integer')] protected int $mask = 0; /** * i.e. "p:b9ccf60e-9f08-4388-b703-2953c40cb0a7". - * - * @ORM\Column(type="string", length=39, nullable=true) */ + #[ORM\Column(type: 'string', length: 39, nullable: true)] protected ?string $parentId = null; - /** - * @ORM\Column(type="datetime") - */ - private \DateTime $createdAt; + #[ORM\Column(type: 'datetime')] + private readonly \DateTime $createdAt; public function __construct() { diff --git a/src/Security/Voter/AclVoter.php b/src/Security/Voter/AclVoter.php index 52d0b46..2be7018 100644 --- a/src/Security/Voter/AclVoter.php +++ b/src/Security/Voter/AclVoter.php @@ -9,6 +9,7 @@ use Alchemy\AclBundle\Security\PermissionManager; use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Authorization\Voter\Vote; use Symfony\Component\Security\Core\Authorization\Voter\Voter; #[AutoconfigureTag(name: 'security.voter')] @@ -33,7 +34,7 @@ public function supportsType(string $subjectType): bool return is_a($subjectType, AclObjectInterface::class, true); } - protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool + protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool { $user = $token->getUser(); if ($user instanceof AclUserInterface) { diff --git a/src/Security/Voter/SetPermissionVoter.php b/src/Security/Voter/SetPermissionVoter.php index 7d15d29..9c2ae60 100644 --- a/src/Security/Voter/SetPermissionVoter.php +++ b/src/Security/Voter/SetPermissionVoter.php @@ -51,7 +51,7 @@ public function supportsType(string $subjectType): bool /** * @param AclObjectInterface $subject */ - protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool + protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool { if ($this->security->isGranted('ROLE_ADMIN')) { return true; diff --git a/tests/PermissionTest.php b/tests/PermissionTest.php index 9a6c195..958f975 100644 --- a/tests/PermissionTest.php +++ b/tests/PermissionTest.php @@ -12,14 +12,13 @@ use Alchemy\AclBundle\Security\PermissionManager; use Alchemy\AclBundle\Tests\Mock\AclUserMock; use Alchemy\AclBundle\Tests\Mock\ObjectMock; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcherInterface; class PermissionTest extends TestCase { - /** - * @dataProvider permissionProvider - */ + #[DataProvider('permissionProvider')] public function testPermissionsWithUser(array $acePermissions, int $permissionToTest, bool $expectedResult) { $ace = $this->createAce(AccessControlEntry::TYPE_USER_VALUE, '123', 'pub', '42', $acePermissions); @@ -53,9 +52,7 @@ public function testPermissionsWithUser(array $acePermissions, int $permissionTo $this->assertEquals($expectedResult, $permissionManager->isGranted($user, $object, $permissionToTest)); } - /** - * @dataProvider permissionProvider - */ + #[DataProvider('permissionProvider')] public function testPermissionsWithGroup(array $acePermissions, int $permissionToTest, bool $expectedResult) { $userAce = $this->createAce(AccessControlEntry::TYPE_USER_VALUE, '123', 'pub', '42', []);