Aller au contenu

Système RBAC — rôles, permissions et isolation par commune

Contexte

Système de contrôle d'accès basé sur les rôles (RBAC) pour la plateforme ESM, conçu et implémenté à partir du 2026-06-14, sur 3 couches (Prisma, Express, React), avec permissions et rôles entièrement gérés en base de données, sans code en dur. Découle de l'analyse de conformité identifiant que le schéma initial avait ProfilUtilisateur mais aucune table Permission (ProjetESM/architecture/analyse-cadre-logique-cas-utilisation).

Contenu

Modèle de données (ajout pur, aucune table existante modifiée)

model Permission {
  id          String             @id @default(cuid())
  code        String             @unique   // ex: "ENFANT_CREER"
  libelle     String
  description String?
  module      String             // ex: "ENFANTS", "PILOTAGE", "ADMIN"
  profils     ProfilPermission[]
}

model ProfilPermission {
  profilId     String
  permissionId String
  profil       ProfilUtilisateur @relation(fields: [profilId], references: [id])
  permission   Permission        @relation(fields: [permissionId], references: [id])
  @@id([profilId, permissionId])
}

ProfilUtilisateur.communeCodeCommune.code porte nativement l'isolation géographique. Règle clé : la permission spéciale ACCES_TOUTES_COMMUNES détermine si un profil voit toutes les communes ou seulement la sienne.

Architecture en défense en profondeur (3 niveaux)

Requête HTTP
  → authentificationMiddleware : vérifie JWT + charge permissionCodes[] + communeCode depuis DB
  → autoriser('PERMISSION_CODE') : bloque (403) si permission absente — automatique via RouteConfig.permission
  → scopeCommune : req.communeFilter = {} (accès global) | { communeCode } (filtre commune)
  → Repository Prisma : prisma.enfant.findMany({ where: { ...req.communeFilter } })

Frontend (miroir, pas garde-fou réel) :
  authStore.permissionCodes[] → usePermission('X') → SideMenu conditionnel + ProtectedRoute

Principe non négociable : le frontend ne fait que refléter les permissions pour l'UX — la sécurité réelle est toujours assurée par les middlewares backend, jamais par le frontend seul.

32 permissions, réparties en 10 modules (état au 2026-06-23)

Module Nb Codes
ENFANTS 5 LIRE, CREER, MODIFIER, SUPPRIMER, VALIDER
ACCOMPAGNEMENT 4 LIRE, CREER, SUIVI_CREER, CAS_ORIENTE_CREER
ACTEURS 3 LIRE, CREER, MODIFIER
FORMATIONS 3 LIRE, CREER, SUPPORT_GERER
INSERTION 3 LIRE, CREER, MODIFIER
MOBILISATION 3 LIRE, COMITE_GERER, CONCERTATION_GERER
PILOTAGE 6 INDICATEUR_LIRE/SAISIR/CREER, ETUDE_LIRE/CREER, RAPPORT_EXPORTER
ADMIN 3 UTILISATEUR_GERER, REFERENTIEL_MODIFIER, EQUIPE_GERER
AUDIT 1 AUDIT_LIRE
SYSTEM 1 ACCES_TOUTES_COMMUNES

8 profils réels (évolution depuis les 4 profils métier initiaux)

Le document profils-utilisateurs-permissions.md (initial) décrivait 4 profils métier (Agent de terrain, MEAL Communal, MEAL National, Chargé de Projet) + Administrateur système. En pratique, le système a évolué vers 8 profils avec un flux de validation hiérarchique :

Agent de terrain (PSYCHOLOGUE / ASSISTANT_SOCIAL) → [SAISIE]
        ↓
MEAL Communal   → [VALIDATION ou REJET, sa commune]
        ↓
MEAL National   → [CONTRÔLE QUALITÉ GLOBAL, toutes communes]
        ↓
Chargé de projet / Bailleur → [LECTURE SEULE, reporting]

+ ADMIN / SUPER_ADMIN : accès total (32/32)

Total de permissions accordées par profil : PSYCHOLOGUE/ASSISTANT_SOCIAL 21/32, MEAL_COMMUNAL 24/32, MEAL_NATIONAL 20/32, CHARGE_PROJET 10/32, BAILLEUR 10/32, ADMIN/SUPER_ADMIN 32/32.

Règle transversale : aucun profil métier (même MEAL National) n'a accès à l'administration des utilisateurs ni aux journaux de sécurité — réservé à l'Administrateur système.

Dérive seed.ts vs base réelle (constatée le 2026-06-24)

INSERTION_MODIFIER et CONCERTATION_GERER ont été ajoutées aux profils terrain via script direct en base, sans mise à jour de seed.ts — signalé comme dette technique à corriger avant tout prochain db push (risque d'écraser ces permissions au reseed).

Décision / Conclusion

RBAC implémenté en 2 missions séquentielles (schéma+seed, puis middlewares+routes), avec isolation par commune systématique sauf pour les profils disposant de ACCES_TOUTES_COMMUNES. Voir ProjetESM/debug/tests-rbac-conformite pour la validation empirique complète (66/66 tests passants, avec historique des 3 corrections trouvées en testant réellement plutôt qu'en supposant).

Liens connexes