fix(review) : resout findings 3e passe review (HIGH frontend + MEDIUMs backend/frontend/E2E)

Backend :
- AuditLogWriter::stripSensitive rendu reellement recursif (matche doc).
- Tests GET /api/permissions/{id} non-admin pour chaque branche OR (gap Codex).
- Gardes non-regression UserRbacProcessor : PATCH /rbac sans clef sites ne
  doit ni auto-selectionner currentSite ni exiger sites.manage.

Frontend :
- useAuditLog : renomme export trompeur fetchLogs -> fetchLogsCached, le
  nom reflete desormais le comportement (cache pollue sinon).
- RoleDrawer / UserRbacDrawer : catch explicite + message d'erreur +
  bouton save disabled si le chargement des referentiels a echoue (evite
  un ecrasement silencieux des droits).
- AuditTimeline / AuditLogDetail : `oui`/`non` passent par common.yes/no.
- AuditTimeline : Intl.RelativeTimeFormat et toLocaleString suivent la
  locale i18n courante (plus de hardcode 'fr').

E2E :
- sidebar-visibility.spec : remplace waitForLoadState('networkidle')
  fragile par attente semantique sur accountDashboardLink (stable en CI).

Tests : 237/237 green, eslint clean, php-cs-fixer clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-04-23 10:31:03 +02:00
parent 25cd6a1ecc
commit b1255bb57a
12 changed files with 271 additions and 48 deletions

View File

@@ -226,6 +226,51 @@ final class PermissionApiTest extends AbstractApiTestCase
self::assertResponseIsSuccessful();
}
public function testNonAdminWithPermissionViewCanGetItem(): void
{
// Miroir item de testNonAdminWithPermissionViewCanListPermissions :
// la security expression OR est repliquee sur `new Get(...)` et doit
// donc aussi s'appliquer ici.
$permission = $this->getEm()->getRepository(Permission::class)
->findOneBy(['code' => 'test.core.users.view'])
;
self::assertNotNull($permission);
$creds = $this->createUserWithPermission('core.permissions.view');
$client = $this->authenticatedClient($creds['username'], $creds['password']);
$client->request('GET', '/api/permissions/'.$permission->getId());
self::assertResponseIsSuccessful();
}
public function testNonAdminWithUsersManageCanGetItem(): void
{
$permission = $this->getEm()->getRepository(Permission::class)
->findOneBy(['code' => 'test.core.users.view'])
;
self::assertNotNull($permission);
$creds = $this->createUserWithPermission('core.users.manage');
$client = $this->authenticatedClient($creds['username'], $creds['password']);
$client->request('GET', '/api/permissions/'.$permission->getId());
self::assertResponseIsSuccessful();
}
public function testNonAdminWithRolesManageCanGetItem(): void
{
$permission = $this->getEm()->getRepository(Permission::class)
->findOneBy(['code' => 'test.core.users.view'])
;
self::assertNotNull($permission);
$creds = $this->createUserWithPermission('core.roles.manage');
$client = $this->authenticatedClient($creds['username'], $creds['password']);
$client->request('GET', '/api/permissions/'.$permission->getId());
self::assertResponseIsSuccessful();
}
private function cleanupTestPermissions(): void
{
$em = $this->getEm();