feat(core) : add rbac seeder and seed-rbac command for system roles
This commit is contained in:
@@ -25,6 +25,7 @@ use App\Enum\AbsenceType;
|
||||
use App\Enum\ContractType;
|
||||
use App\Enum\RecurrenceType;
|
||||
use App\Enum\StatusCategory;
|
||||
use App\Module\Core\Application\Rbac\RbacSeeder;
|
||||
use App\Module\Core\Domain\Entity\User;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeZone;
|
||||
@@ -36,6 +37,7 @@ class AppFixtures extends Fixture
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UserPasswordHasherInterface $passwordHasher,
|
||||
private readonly RbacSeeder $rbacSeeder,
|
||||
) {}
|
||||
|
||||
public function load(ObjectManager $manager): void
|
||||
@@ -751,5 +753,9 @@ class AppFixtures extends Fixture
|
||||
$manager->persist($pendingMarriage);
|
||||
|
||||
$manager->flush();
|
||||
|
||||
// Seed des rôles système RBAC (admin, user). Idempotent ; aucune matrice
|
||||
// métier attachée (cf. Décision 4 : les modules métier arrivent en 2.x).
|
||||
$this->rbacSeeder->ensureSystemRoles();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Module\Core\Application\Rbac;
|
||||
|
||||
use App\Module\Core\Domain\Entity\Role;
|
||||
use App\Module\Core\Domain\Repository\RoleRepositoryInterface;
|
||||
use App\Module\Core\Domain\Security\SystemRoles;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
final readonly class RbacSeeder
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManagerInterface $em,
|
||||
private RoleRepositoryInterface $roles,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Crée les rôles système s'ils sont absents. Idempotent.
|
||||
*/
|
||||
public function ensureSystemRoles(): void
|
||||
{
|
||||
$this->ensureRole(SystemRoles::ADMIN_CODE, 'Administrateur', 'Accès complet (bypass RBAC).');
|
||||
$this->ensureRole(SystemRoles::USER_CODE, 'Utilisateur', 'Rôle de base sans permission spécifique.');
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
private function ensureRole(string $code, string $label, string $description): void
|
||||
{
|
||||
if (null !== $this->roles->findByCode($code)) {
|
||||
return;
|
||||
}
|
||||
$this->roles->save(new Role($code, $label, $description, true));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Module\Core\Domain\Security;
|
||||
|
||||
final class SystemRoles
|
||||
{
|
||||
public const string ADMIN_CODE = 'admin';
|
||||
public const string USER_CODE = 'user';
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Module\Core\Infrastructure\Console;
|
||||
|
||||
use App\Module\Core\Application\Rbac\RbacSeeder;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(name: 'app:seed-rbac', description: 'Seed les rôles système RBAC (admin, user).')]
|
||||
final class SeedRbacCommand extends Command
|
||||
{
|
||||
public function __construct(private readonly RbacSeeder $seeder)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$this->seeder->ensureSystemRoles();
|
||||
$io->success('Rôles système RBAC seedés (admin, user).');
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Module\Core;
|
||||
|
||||
use App\Module\Core\Domain\Repository\RoleRepositoryInterface;
|
||||
use App\Module\Core\Domain\Security\SystemRoles;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class SeedRbacCommandTest extends KernelTestCase
|
||||
{
|
||||
public function testSeedsSystemRolesIdempotently(): void
|
||||
{
|
||||
$kernel = self::bootKernel();
|
||||
$app = new Application($kernel);
|
||||
$tester = new CommandTester($app->find('app:seed-rbac'));
|
||||
|
||||
$tester->execute([]);
|
||||
$tester->assertCommandIsSuccessful();
|
||||
$tester->execute([]); // idempotent
|
||||
$tester->assertCommandIsSuccessful();
|
||||
|
||||
$repo = self::getContainer()->get(RoleRepositoryInterface::class);
|
||||
$admin = $repo->findByCode(SystemRoles::ADMIN_CODE);
|
||||
self::assertNotNull($admin);
|
||||
self::assertTrue($admin->isSystem());
|
||||
self::assertNotNull($repo->findByCode(SystemRoles::USER_CODE));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user