RBAC - Système complet de permissions (Backend + Frontend) #7

Merged
tristan merged 56 commits from feat/rbac-admin-users into develop 2026-04-17 12:34:39 +00:00
Owner

Résumé

Implémentation complète du système RBAC (Role-Based Access Control) pour Coltura.

Backend

  • Entités Permission et Role avec API Platform CRUD
  • PermissionVoter : vérification des permissions effectives (rôles + directes), admin bypass
  • Endpoints PATCH /users/{id}/rbac pour assigner rôles, permissions directes et isAdmin
  • AdminHeadcountGuard : protection contre la suppression du dernier admin
  • Commande app:sync-permissions pour synchroniser les permissions déclarées par les modules
  • Filtrage sidebar par permission RBAC (permission key optionnelle dans sidebar.php)
  • 115 tests PHPUnit (fonctionnels + unitaires)

Frontend

  • Composable usePermissions() avec can(), canAny(), canAll() et admin bypass
  • Page /admin/roles : DataTable, création/édition via drawer, suppression avec confirmation
  • Page /admin/users : DataTable, drawer RBAC avec rôles, permissions directes, résumé effectif
  • PermissionGroup : checkboxes groupées par module avec "tout sélectionner"
  • EffectivePermissions : résumé lecture seule avec badges source ("via Rôle X" / "Direct")
  • Warning auto-édition, toggle isAdmin
  • Tests Vitest pour usePermissions

Permissions déclarées

  • core.users.view — Voir les utilisateurs
  • core.users.manage — Gérer les utilisateurs
  • core.roles.view — Voir les rôles RBAC
  • core.roles.manage — Gérer les rôles et permissions
  • GET /api/permissions accessible à tout utilisateur authentifié (catalogue read-only)

Tickets Lesstime

  • ERP-23 (#343) — Entités Permission et Role
  • ERP-24 (#344) — API CRUD Roles & Permissions
  • ERP-25 (#345) — Voter Symfony + usePermissions
  • ERP-26 (#346) — Interface Admin : Gestion des Rôles
  • ERP-27 (#347) — Interface Admin : Permissions Utilisateur

Test plan

  • make db-reset puis vérifier les fixtures (admin/alice/bob, rôles système)
  • Login admin : sidebar affiche Gestion des rôles + Utilisateurs
  • Login alice : sidebar masque ces onglets (pas de permission)
  • Page /admin/roles : CRUD rôles, permissions groupées, protection rôles système
  • Page /admin/users : assignation rôles + permissions directes, résumé effectif
  • Warning auto-édition quand admin modifie ses propres droits
  • make test : 115 tests PHPUnit passent
  • cd frontend && npm run test : tests Vitest passent

🤖 Generated with Claude Code

## Résumé Implémentation complète du système RBAC (Role-Based Access Control) pour Coltura. ### Backend - Entités Permission et Role avec API Platform CRUD - PermissionVoter : vérification des permissions effectives (rôles + directes), admin bypass - Endpoints `PATCH /users/{id}/rbac` pour assigner rôles, permissions directes et isAdmin - AdminHeadcountGuard : protection contre la suppression du dernier admin - Commande `app:sync-permissions` pour synchroniser les permissions déclarées par les modules - Filtrage sidebar par permission RBAC (`permission` key optionnelle dans sidebar.php) - 115 tests PHPUnit (fonctionnels + unitaires) ### Frontend - Composable `usePermissions()` avec `can()`, `canAny()`, `canAll()` et admin bypass - Page `/admin/roles` : DataTable, création/édition via drawer, suppression avec confirmation - Page `/admin/users` : DataTable, drawer RBAC avec rôles, permissions directes, résumé effectif - PermissionGroup : checkboxes groupées par module avec "tout sélectionner" - EffectivePermissions : résumé lecture seule avec badges source ("via Rôle X" / "Direct") - Warning auto-édition, toggle isAdmin - Tests Vitest pour usePermissions ### Permissions déclarées - `core.users.view` — Voir les utilisateurs - `core.users.manage` — Gérer les utilisateurs - `core.roles.view` — Voir les rôles RBAC - `core.roles.manage` — Gérer les rôles et permissions - `GET /api/permissions` accessible à tout utilisateur authentifié (catalogue read-only) ## Tickets Lesstime - ERP-23 (#343) — Entités Permission et Role - ERP-24 (#344) — API CRUD Roles & Permissions - ERP-25 (#345) — Voter Symfony + usePermissions - ERP-26 (#346) — Interface Admin : Gestion des Rôles - ERP-27 (#347) — Interface Admin : Permissions Utilisateur ## Test plan - [ ] `make db-reset` puis vérifier les fixtures (admin/alice/bob, rôles système) - [ ] Login admin : sidebar affiche Gestion des rôles + Utilisateurs - [ ] Login alice : sidebar masque ces onglets (pas de permission) - [ ] Page /admin/roles : CRUD rôles, permissions groupées, protection rôles système - [ ] Page /admin/users : assignation rôles + permissions directes, résumé effectif - [ ] Warning auto-édition quand admin modifie ses propres droits - [ ] `make test` : 115 tests PHPUnit passent - [ ] `cd frontend && npm run test` : tests Vitest passent 🤖 Generated with [Claude Code](https://claude.com/claude-code)
matthieu added 40 commits 2026-04-16 14:47:58 +00:00
- Expose l'entite Permission via ApiResource (GetCollection + Get uniquement)
- Serialisation limitee au groupe permission:read (id, code, label, module, orphan)
- Securite temporaire is_granted('ROLE_ADMIN'), a remplacer par
  is_granted('core.permissions.view') au ticket #345
- Filtres : SearchFilter exact sur module, BooleanFilter sur orphan
- Configure api_platform.mapping.paths pour que le compile pass AP decouvre
  les ApiResource/ApiFilter declares dans src/Module/Core/Domain/Entity
- Ajoute symfony/browser-kit et symfony/http-client en dev pour les tests
  fonctionnels API Platform, plus KERNEL_CLASS dans phpunit.dist.xml
- Tests fonctionnels PermissionApiTest : collection, get item, filtres
  module et orphan, 405 sur POST, 401 non authentifie, 403 non-admin
Extrait l'helper authenticatedClient(), $alwaysBootKernel et getEm() dans
une classe de base commune aux tests fonctionnels API Platform du module
Core. Supprime la duplication entre PermissionApiTest et RoleApiTest
(flaggee en code review de la Task 2). Prepare le terrain pour le nouveau
UserRbacApiTest introduit avec la Task 4.
Ajoute une operation Patch dediee `PATCH /api/users/{id}/rbac` (nom
`user_rbac_patch`) qui accepte exclusivement les champs RBAC isAdmin,
roles et directPermissions via le groupe user:rbac:write. L'endpoint est
separe volontairement du Patch profil existant pour isoler la modification
des droits de celle des donnees profil (decision 0fc4e16).

UserRbacProcessor delegue au PersistProcessor Doctrine decore et applique
une garde auto-suicide : un admin ne peut pas retirer ses propres droits
administrateur (compare l'etat entrant a l'etat UnitOfWork). La garde
'dernier admin' globale est reportee au ticket #345.

La propriete Doctrine $roles est renommee $rbacRoles pour eviter la
collision avec UserInterface::getRoles() (qui renvoie list<string>) lors
de la normalization API Platform. La cle JSON reste `roles` grace a
SerializedName, le contrat API est inchange.

Tests : 6 unitaires (UserRbacProcessorTest) + 8 fonctionnels
(UserRbacApiTest) couvrant promotion admin, remplacement des collections
roles/directPermissions, 401/403, filtrage du groupe denormalization
(`username` ignore), preservation de isAdmin sur le Patch profil, et
garde auto-suicide.
Introduit AdminHeadcountGuardInterface pour permettre le mock en tests
unitaires, puis cree UserProcessor qui protege DELETE /api/users/{id}
contre la suppression du dernier administrateur via la garde domaine.
- Ajoute #[Groups(['me:read'])] sur getEffectivePermissions() dans User.php
- Fixe la serialisation de isAdmin : le prefixe "is" etait strip par Symfony,
  expose desormais via le getter avec #[SerializedName('isAdmin')] + groups lecture,
  la propriete conserve uniquement le groupe d'ecriture user:rbac:write
- Cree MeApiTest avec 4 tests fonctionnels (isAdmin admin, permissions vides user,
  401 sans auth, effectivePermissions avec role portant une permission)
Ajout de isAdmin et effectivePermissions dans UserData, creation du
composable usePermissions() (can/canAny/canAll) avec bypass admin.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Les items sidebar peuvent declarer une cle `permission` optionnelle.
Le SidebarProvider verifie isGranted() et masque les items dont
l'utilisateur ne possede pas la permission requise.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
La permission core.permissions.view est supprimee du CoreModule.
Le endpoint GET /api/permissions est desormais protege par ROLE_USER
au lieu d'une permission RBAC specifique, car c'est un catalogue
de metadonnees necessaire aux drawers de gestion des roles et users.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
tristan added 2 commits 2026-04-17 08:46:48 +00:00
Supprime la colonne actions des tables users et roles (la ligne cliquable
ouvre deja le drawer). Deplace la suppression d'un role dans le drawer
d'edition (bouton danger avec icone, desactive pour les roles systeme).
Harmonise les boutons annuler en variant tertiary et ajoute les icones
manquantes (plus pour nouveau role, poubelle pour supprimer).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Nouvelle cible idempotente qui cree la base coltura_test, joue les
migrations, charge les fixtures et synchronise les permissions RBAC
(ordre important : sync-permissions apres fixtures qui purge la table
permission). Branchee automatiquement sur install et db-reset pour que
chaque dev ait la BDD de test prete au premier clone et que make test
passe sans etape manuelle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tristan merged commit e8c2789435 into develop 2026-04-17 12:34:39 +00:00
tristan deleted branch feat/rbac-admin-users 2026-04-17 12:34:39 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: MALIO-DEV/Coltura#7