cleanupTestData(); parent::tearDown(); } /** * L'admin (isAdmin=true, role systeme sans permission explicite) doit * obtenir un payload /me avec isAdmin=true et effectivePermissions=[]. */ public function testMeEndpointReturnsIsAdminAndEffectivePermissionsForAdmin(): void { $client = $this->authenticatedClient('admin', 'admin'); $response = $client->request('GET', '/api/me', [ 'headers' => ['Accept' => 'application/ld+json'], ]); self::assertResponseIsSuccessful(); $data = $response->toArray(); self::assertSame('admin', $data['username'], 'Le champ username doit etre "admin".'); self::assertTrue($data['isAdmin'], 'isAdmin doit etre true pour l\'admin fixture.'); self::assertArrayHasKey('effectivePermissions', $data, 'effectivePermissions doit etre present dans le payload.'); self::assertIsArray($data['effectivePermissions'], 'effectivePermissions doit etre un tableau JSON.'); // Le role systeme admin n'a pas de permissions explicites : tableau vide attendu. self::assertSame([], $data['effectivePermissions'], 'effectivePermissions doit etre [] pour l\'admin sans permissions explicites.'); } /** * Un utilisateur standard (isAdmin=false, role user sans permission) doit * obtenir isAdmin=false et effectivePermissions=[]. */ public function testMeEndpointReturnsEmptyPermissionsForStandardUser(): void { $client = $this->authenticatedClient('alice', 'alice'); $response = $client->request('GET', '/api/me', [ 'headers' => ['Accept' => 'application/ld+json'], ]); self::assertResponseIsSuccessful(); $data = $response->toArray(); self::assertFalse($data['isAdmin'], 'isAdmin doit etre false pour alice.'); self::assertArrayHasKey('effectivePermissions', $data, 'effectivePermissions doit etre present dans le payload.'); self::assertSame([], $data['effectivePermissions'], 'effectivePermissions doit etre [] pour un user sans role avec permission.'); } /** * Une requete non authentifiee sur /api/me doit retourner 401. */ public function testMeEndpointRequiresAuthentication(): void { $client = self::createClient(); $client->request('GET', '/api/me', [ 'headers' => ['Accept' => 'application/ld+json'], ]); self::assertResponseStatusCodeSame(401); } /** * Un user rattache a un role portant la permission `core.users.view` doit * retrouver cette permission dans effectivePermissions, triee alphabetiquement. */ public function testMeEndpointReturnsEffectivePermissionsForUserWithRolePermissions(): void { // --- Preparation des donnees de test --- self::bootKernel(); $em = $this->getEm(); $this->cleanupTestData(); /** @var UserPasswordHasherInterface $hasher */ $hasher = self::getContainer()->get(UserPasswordHasherInterface::class); $permission = new Permission('test.me.core.users.view', 'View users (test me)', 'core'); $em->persist($permission); $role = new Role('test_me_viewer', 'Viewer (test me)', false); $role->addPermission($permission); $em->persist($role); $user = new User(); $user->setUsername('test_me_viewer_user'); $user->setIsAdmin(false); $user->setPassword($hasher->hashPassword($user, 'secret')); $user->addRbacRole($role); $em->persist($user); $em->flush(); $em->clear(); // --- Appel API --- $client = $this->authenticatedClient('test_me_viewer_user', 'secret'); $response = $client->request('GET', '/api/me', [ 'headers' => ['Accept' => 'application/ld+json'], ]); self::assertResponseIsSuccessful(); $data = $response->toArray(); self::assertArrayHasKey('effectivePermissions', $data, 'effectivePermissions doit etre present dans le payload.'); self::assertContains( 'test.me.core.users.view', $data['effectivePermissions'], 'effectivePermissions doit contenir le code de permission du role attribue.', ); // Verifie le tri alphabetique (contrat spec section 9 ticket-343). $sorted = $data['effectivePermissions']; $copy = $sorted; sort($copy); self::assertSame($copy, $sorted, 'effectivePermissions doit etre trie alphabetiquement.'); } /** * Purge les entites de test creees par les methodes ci-dessus. * Ordre : users d'abord (FK vers roles), puis roles, puis permissions. */ private function cleanupTestData(): void { $em = $this->getEm(); $em->createQuery( 'DELETE FROM '.User::class.' u WHERE u.username LIKE :prefix' )->setParameter('prefix', self::TEST_USER_PREFIX.'%')->execute(); $em->createQuery( 'DELETE FROM '.Role::class.' r WHERE r.code LIKE :prefix' )->setParameter('prefix', self::TEST_ROLE_PREFIX.'%')->execute(); $em->createQuery( 'DELETE FROM '.Permission::class.' p WHERE p.code LIKE :prefix' )->setParameter('prefix', self::TEST_PERMISSION_PREFIX.'%')->execute(); } }