Merge remote-tracking branch 'origin/feat/module-site-backend' into feat/admin-tables-filter-pagination

# Conflicts:
#	frontend/modules/sites/pages/admin/sites.vue
This commit is contained in:
2026-04-20 17:04:04 +02:00
24 changed files with 611 additions and 82 deletions

View File

@@ -9,6 +9,7 @@ use ApiPlatform\Symfony\Bundle\Test\Client;
use App\Module\Core\Domain\Entity\Permission;
use App\Module\Core\Domain\Entity\Role;
use App\Module\Core\Domain\Entity\User;
use App\Module\Sites\Domain\Entity\Site;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
@@ -123,6 +124,19 @@ abstract class AbstractApiTestCase extends ApiTestCase
$user->setIsAdmin(false);
$user->setPassword($hasher->hashPassword($user, $password));
$user->addRbacRole($role);
// Le helper attache le user jetable a tous les sites existants pour
// neutraliser le filtrage par UserSiteScopedExtension : la plupart
// des tests assume une visibilite globale sur les users cibles. Les
// tests qui valident le comportement "sans sites" doivent creer leur
// user a la main (pas via ce helper).
$siteRepository = $em->getRepository(Site::class);
if (null !== $siteRepository) {
foreach ($siteRepository->findAll() as $site) {
$user->addSite($site);
}
}
$em->persist($user);
$em->flush();

View File

@@ -7,6 +7,7 @@ namespace App\Tests\Module\Core\Api;
use App\Module\Core\Domain\Entity\Permission;
use App\Module\Core\Domain\Entity\Role;
use App\Module\Core\Domain\Entity\User;
use App\Module\Sites\Domain\Entity\Site;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
/**
@@ -41,11 +42,18 @@ final class UserRbacApiTest extends AbstractApiTestCase
/** @var UserPasswordHasherInterface $hasher */
$hasher = self::getContainer()->get(UserPasswordHasherInterface::class);
// User cible standard (non admin).
// User cible standard (non admin). On lui attache tous les sites
// fixtures pour rester visible depuis les callers non-admin munis de
// sites (cf. UserSiteScopedExtension qui filtre `/api/users` par
// intersection de sites). Sans cela, un user `core.users.manage`
// sans site commun avec test_target recevrait un 404 sur le PATCH.
$target = new User();
$target->setUsername('test_target');
$target->setIsAdmin(false);
$target->setPassword($hasher->hashPassword($target, 'secret'));
foreach ($em->getRepository(Site::class)->findAll() as $site) {
$target->addSite($site);
}
$em->persist($target);
// User admin dedie pour le cas d'auto-suicide (pas l'admin fixture).

View File

@@ -50,6 +50,14 @@ final class UserRbacProcessorTest extends TestCase
$this->entityManager->method('getUnitOfWork')->willReturn($this->unitOfWork);
// wrapInTransaction doit executer reellement la closure pour que le
// resultat de persistProcessor->process() soit capture dans $result.
// Sans ce stub, la closure n'est jamais invoquee et $result reste null.
$this->entityManager
->method('wrapInTransaction')
->willReturnCallback(static fn (callable $fn) => $fn())
;
$this->processor = new UserRbacProcessor(
$this->persistProcessor,
$this->entityManager,