feat(core) : RBAC Task 2 - repositories Permission et Role

- PermissionRepositoryInterface avec findByCode et findAllCodes (pour le sync
  command et le futur PermissionVoter)
- RoleRepositoryInterface avec findByCode
- Implementations Doctrine alignees sur DoctrineUserRepository
- Alias DI dans config/services.yaml
- Rebranchement de repositoryClass sur les entites Permission et Role

Ticket #343 - 2/7 : couche persistence RBAC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-04-14 16:40:44 +02:00
parent 0fc0b57e37
commit 3b34d00872
8 changed files with 179 additions and 5 deletions

View File

@@ -6,6 +6,7 @@ namespace App\Module\Core\Infrastructure\ApiPlatform\State\Provider;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use Symfony\Bundle\SecurityBundle\Security;
/**
* @implements ProviderInterface<object>
@@ -13,7 +14,7 @@ use ApiPlatform\State\ProviderInterface;
class MeProvider implements ProviderInterface
{
public function __construct(
private readonly \Symfony\Bundle\SecurityBundle\Security $security,
private readonly Security $security,
) {}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?object

View File

@@ -0,0 +1,62 @@
<?php
declare(strict_types=1);
namespace App\Module\Core\Infrastructure\Doctrine;
use App\Module\Core\Domain\Entity\Permission;
use App\Module\Core\Domain\Repository\PermissionRepositoryInterface;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Permission>
*/
class DoctrinePermissionRepository extends ServiceEntityRepository implements PermissionRepositoryInterface
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Permission::class);
}
public function findById(int $id): ?Permission
{
return $this->find($id);
}
public function findByCode(string $code): ?Permission
{
return $this->findOneBy(['code' => $code]);
}
/**
* @return array<int, Permission>
*/
public function findAll(): array
{
return parent::findAll();
}
/**
* @return array<int, string>
*/
public function findAllCodes(): array
{
// Requete legere : on ne selectionne que la colonne code (pas d'hydratation
// d'entites Permission) car findAllCodes() est appelee par la commande de
// sync et le futur voter qui n'ont besoin que des chaines.
$rows = $this->createQueryBuilder('p')
->select('p.code')
->getQuery()
->getArrayResult()
;
return array_column($rows, 'code');
}
public function save(Permission $permission): void
{
$this->getEntityManager()->persist($permission);
$this->getEntityManager()->flush();
}
}

View File

@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace App\Module\Core\Infrastructure\Doctrine;
use App\Module\Core\Domain\Entity\Role;
use App\Module\Core\Domain\Repository\RoleRepositoryInterface;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Role>
*/
class DoctrineRoleRepository extends ServiceEntityRepository implements RoleRepositoryInterface
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Role::class);
}
public function findById(int $id): ?Role
{
return $this->find($id);
}
public function findByCode(string $code): ?Role
{
return $this->findOneBy(['code' => $code]);
}
/**
* @return array<int, Role>
*/
public function findAll(): array
{
return parent::findAll();
}
public function save(Role $role): void
{
$this->getEntityManager()->persist($role);
$this->getEntityManager()->flush();
}
}