diff --git a/src/Module/Core/Infrastructure/DataFixtures/AppFixtures.php b/src/Module/Core/Infrastructure/DataFixtures/AppFixtures.php index dbd31f5..46176d7 100644 --- a/src/Module/Core/Infrastructure/DataFixtures/AppFixtures.php +++ b/src/Module/Core/Infrastructure/DataFixtures/AppFixtures.php @@ -28,6 +28,11 @@ use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; * systeme de maniere idempotente avant de rattacher les utilisateurs, afin * que le workflow "make db-reset && make fixtures" reste one-shot. * + * Idempotence complete (y compris `doctrine:fixtures:load --append`, sans + * purge) : roles via ensureSystemRole, utilisateurs via ensureUser (lookup par + * username). Rejouer la fixture ne cree donc aucun doublon ni violation + * d'unicite de username. + * * Dependance explicite a SitesFixtures (ticket 2) : les 3 sites Chatellerault, * Saint-Jean et Pommevic doivent etre presents en base avant d'etre rattaches * aux users. L'inversion volontaire de l'ordre (AppFixtures ← SitesFixtures) @@ -75,8 +80,7 @@ class AppFixtures extends Fixture implements DependentFixtureInterface $saintJean = $this->requireSite('Saint-Jean'); $pommevic = $this->requireSite('Pommevic'); - $admin = new User(); - $admin->setUsername('admin'); + $admin = $this->ensureUser($manager, 'admin'); $admin->setIsAdmin(true); $admin->setPassword($this->passwordHasher->hashPassword($admin, 'admin')); $admin->addRbacRole($adminRole); @@ -87,8 +91,7 @@ class AppFixtures extends Fixture implements DependentFixtureInterface $admin->setCurrentSite($chatellerault); $manager->persist($admin); - $alice = new User(); - $alice->setUsername('alice'); + $alice = $this->ensureUser($manager, 'alice'); $alice->setPassword($this->passwordHasher->hashPassword($alice, 'alice')); $alice->addRbacRole($userRole); // Alice : un seul site, site courant = ce site. @@ -96,8 +99,7 @@ class AppFixtures extends Fixture implements DependentFixtureInterface $alice->setCurrentSite($chatellerault); $manager->persist($alice); - $bob = new User(); - $bob->setUsername('bob'); + $bob = $this->ensureUser($manager, 'bob'); $bob->setPassword($this->passwordHasher->hashPassword($bob, 'bob')); $bob->addRbacRole($userRole); // Bob : site different de Alice, pour prouver le filtrage par site @@ -135,6 +137,27 @@ class AppFixtures extends Fixture implements DependentFixtureInterface return $role; } + /** + * Retourne l'utilisateur correspondant au username, en le creant s'il + * n'existe pas encore. Rend la fixture idempotente y compris en + * `doctrine:fixtures:load --append` (sans purge) : sans ce lookup, recreer + * « admin » / « alice » / « bob » violerait l'unicite de username. Meme + * esprit que ensureSystemRole ci-dessus et RbacDemoFixtures::ensureDemoUsers. + */ + private function ensureUser(ObjectManager $manager, string $username): User + { + $user = $manager->getRepository(User::class)->findOneBy(['username' => $username]); + + if (null !== $user) { + return $user; + } + + $user = new User(); + $user->setUsername($username); + + return $user; + } + private function requireSite(string $name): SiteInterface { $site = $this->siteProvider->findByName($name);