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>
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>
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>
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>
- 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)
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 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.
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.
- 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
isAdmin, roles et directPermissions ne doivent pas etre modifiables via
PATCH /api/users/{id}. L exposition en ecriture sera traitee par un
processor dedie dans le ticket #344 (spec section 2 OUT).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Documente le bug Doctrine Migrations 3.x (tri par FQCN au lieu de
version timestamp avec plusieurs migrations_paths) et la regle
provisoire : migrations d'init au namespace racine, namespace
modulaire reserve aux migrations applicatives.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bug decouvert a l'execution de 'make db-reset' sur base vide : Doctrine
Migrations 3.x avec plusieurs 'migrations_paths' execute les migrations
dans l'ordre (namespace, version) et non (version, namespace). Le
Version20260414150034 sous 'App\Module\Core\...' passait donc avant
Version20260407095546 sous 'DoctrineMigrations', provoquant un
"relation user does not exist".
Deplacement du fichier vers 'migrations/' (namespace DoctrineMigrations).
Le chemin modulaire reste configure pour les futurs modules, mais
la migration RBAC d'initialisation vit a la racine pour que
'make db-reset' fonctionne en one-shot.
Smoke test end-to-end valide :
- db-reset + fixtures : admin (is_admin=t, role admin), alice/bob
(is_admin=f, role user)
- app:sync-permissions : 4 permissions Core ajoutees, idempotent au 2e run
- User::getRoles() : ['ROLE_USER', 'ROLE_ADMIN'] pour admin, ['ROLE_USER']
pour alice/bob
- User::getEffectivePermissions() : union triee des permissions via roles
Ticket #343 - 7/7 : smoke test end-to-end OK.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ensureSystemRole() recopie desormais la description depuis la migration
RBAC pour que les chemins prod (migration) et dev (fixtures) produisent
un etat identique.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- AppFixtures : rattachement des users aux entites Role via
RoleRepositoryInterface. Re-seed idempotent des roles systeme dans
ensureSystemRole() pour compenser le purger Doctrine qui vide la table
role avant load(), afin que "make db-reset && make fixtures" reste un
workflow one-shot.
- CreateUserCommand : flag --admin attache au role systeme admin + is_admin,
sinon au role user. Gestion d'erreur explicite si les roles systeme sont
absents (FAILURE + message pointant vers la migration).
- CreateUserCommand devient final, descriptions traduites en francais.
Ticket #343 - 6/7 : fixtures et command alignes sur le RBAC relationnel.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Nouvelles tables permission, role, role_permission, user_role, user_permission
- Ajout user.is_admin (BOOLEAN, default false)
- Seed des roles systeme admin et user via SQL brut (autonome, pas besoin
de fixtures pour cette etape)
- Migration des donnees : is_admin reflete ROLE_ADMIN du JSON roles, puis
rattachement user_role selon admin/user
- Drop user.roles en dernier (apres la migration de donnees)
- down() recree la colonne roles et la rehydrate depuis is_admin
Ticket #343 - 5/7 : persistance + migration donnees safe.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>