- 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)
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.
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>
- Suppression de la colonne JSON roles (persiste jusqu'a la migration Task 5)
- Ajout is_admin bool (seul levier de bypass RBAC via getRoles())
- Ajout ManyToMany User-Role (EAGER, table user_role)
- Ajout ManyToMany User-Permission directes (EAGER, table user_permission)
- getEffectivePermissions() : union dedupliquee triee, utilisee par le
futur PermissionVoter (#345)
- getRbacRoles() pour ne pas shadow getRoles() de UserInterface Symfony
- Tests unitaires couvrant derivation getRoles, union, deduplication, tri
Ticket #343 - 3/7 : migration du User vers le modele RBAC relationnel.
Fetch EAGER documente : evite le lazy-load au refresh JWT.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>