fix(rbac) : rattache le rôle de base « user » et gate le frontend par permission
Pull Request — Quality gate / Frontend (build) (pull_request) Successful in 42s
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 1m1s

Un user avec des permissions sur le rôle RBAC « user » ne voyait rien : le
ROLE_USER legacy n'a aucun lien avec le RBAC et getEffectivePermissions() ne lit
que rbacRoles + permissions directes, alors qu'aucun user n'était rattaché au
rôle « user » (table user_role vide, jamais backfillée).

Backend
- DefaultUserRoleAssigner + UserDefaultRoleListener (prePersist) : tout nouvel
  utilisateur est rattaché au rôle « user » sur tous les chemins de persistance.
- Commande app:assign-default-roles (backfill idempotent) + ajout au deploy.sh.
- AppFixtures : seed des rôles système avant la création des users.

Frontend (gating par permission au lieu de ROLE_ADMIN legacy)
- Nouveau middleware « permission » + augmentation PageMeta : definePageMeta
  ({ permission }) (string = requise, array = any), ROLE_ADMIN bypasse.
- Pages directory/reporting/admin gatées par permission ; SidebarFilter accepte
  une liste de permissions (any) ; section admin sans gate de rôle.
- team-absences reste en ROLE_ADMIN (module Absence non RBAC-isé côté backend).
This commit is contained in:
Matthieu
2026-06-29 10:15:46 +02:00
parent 95befb776e
commit 1ab2eeccca
20 changed files with 350 additions and 22 deletions
+4
View File
@@ -129,6 +129,10 @@ services:
tags:
- { name: doctrine.orm.entity_listener, entity: 'App\Module\ProjectManagement\Domain\Entity\Project', event: prePersist }
App\Module\Core\Infrastructure\EventListener\UserDefaultRoleListener:
tags:
- { name: doctrine.orm.entity_listener, entity: 'App\Module\Core\Domain\Entity\User', event: prePersist }
App\Module\Directory\Infrastructure\ApiPlatform\State\ReportDocumentProcessor:
arguments:
$uploadDir: '%task_document_upload_dir%'
+7 -3
View File
@@ -38,12 +38,16 @@ return [
],
],
[
// Plus de gate de rôle au niveau section : chaque item porte sa propre
// permission (RBAC fin), alignée sur la sécurité backend et les middlewares
// de page. La section s'affiche dès qu'au moins un item est autorisé.
'label' => 'sidebar.admin.section',
'icon' => 'mdi:cog-outline',
'roles' => ['ROLE_ADMIN'],
'items' => [
['label' => 'sidebar.admin.teamAbsences', 'to' => '/team-absences', 'icon' => 'mdi:calendar-account-outline', 'module' => 'absence'],
['label' => 'sidebar.admin.directory', 'to' => '/directory', 'icon' => 'mdi:card-account-details-outline', 'module' => 'directory'],
// team-absences : le module Absence est encore gardé par ROLE_ADMIN côté
// backend (pas de permission absence.* câblée) → on reste sur un gate de rôle.
['label' => 'sidebar.admin.teamAbsences', 'to' => '/team-absences', 'icon' => 'mdi:calendar-account-outline', 'module' => 'absence', 'roles' => ['ROLE_ADMIN']],
['label' => 'sidebar.admin.directory', 'to' => '/directory', 'icon' => 'mdi:card-account-details-outline', 'module' => 'directory', 'permission' => ['directory.clients.view', 'directory.prospects.view', 'directory.providers.view']],
['label' => 'sidebar.admin.reporting', 'to' => '/reporting', 'icon' => 'mdi:chart-line', 'module' => 'reporting', 'permission' => 'reporting.view'],
['label' => 'sidebar.admin.administration', 'to' => '/admin', 'icon' => 'mdi:cog-outline', 'permission' => 'core.users.view'],
],