Aller au contenu principal

Permissions et RBAC

La Cafête implémente un système RBAC (Role-Based Access Control) avec des permissions granulaires suivant un motif CRUD en dot notation, et un rôle .manage qui agit comme super-permission pour chaque domaine.

Principe du wildcard .manage​

Chaque domaine expose un permission .manage qui englobe toutes les permissions de ce domaine. Par exemple, card.manage donne accès à toutes les opérations sur les cartes (card.read, card.create, card.update, card.delete, etc.).

Les helpers du middleware (require_card_read, require_product_sell, etc.) vérifient soit la permission spécifique, soit la permission .manage correspondante.

Catalogue des permissions​

Cartes​

CodeDescription
card.manageToutes les opérations sur les cartes (super-permission)
card.readConsulter les cartes, soldes, QR, historique
card.balance.readConsulter le solde (rôle porteur)
card.history.readConsulter l'historique (rôle porteur)
card.createCréer de nouvelles cartes
card.updateModifier les infos carte, assigner/réassigner/révoquer/désactiver
card.deleteSupprimer des cartes
card.voidAnnuler des transactions
card.manual_accessAccès manuel aux cartes (recherche admin)
card.assign_newAttribuer une carte
card.deactivateDésactiver une carte
card.debit.lost_cardDébiter le solde d'une carte perdue
card.recharge.cashRechargement en espèces
card.recharge.mobile_moneyRechargement mobile money
card.correctionCorrection de solde
card.balance.manual_adjustPasser un solde en négatif (maternelle seulement)
card.holder.createCréer des porteurs de carte
card.holder.updateModifier des porteurs de carte
card.holder.deleteSupprimer des porteurs de carte
card.link.readVoir les liens parent-enfant
card.link.createCréer des liens parent-enfant
card.link.deleteSupprimer des liens parent-enfant

Enfant (fonctionnalités parent)​

CodeDescription
child.balance.readVoir le solde d'un enfant
child.rechargeRecharger la carte d'un enfant
child.history.readVoir l'historique des transactions d'un enfant

Produits​

CodeDescription
product.manageToutes les opérations sur les produits
product.readVoir les produits
product.createCréer des produits
product.updateModifier des produits
product.deleteSupprimer des produits
product.sellVendre des produits (achat)

Catégories​

CodeDescription
category.createCréer des catégories
category.updateModifier des catégories
category.deleteSupprimer des catégories
category.readVoir les catégories (souvent implicite via product.read)

Stock​

CodeDescription
stock.readVoir les mouvements de stock
stock.adjustAjuster le stock manuellement
stock.purchaseEnregistrer un achat de stock
stock.produceEnregistrer une production de stock
stock.transferEnregistrer un transfert de stock
CodeDescription
menu.readVoir les menus
menu.createCréer des menus
menu.updateModifier des menus
menu.deleteSupprimer des menus

Sites​

CodeDescription
site.manageToutes les opérations sur les sites
site.readVoir les sites
site.createCréer des sites
site.updateModifier des sites
site.deleteSupprimer des sites

Points de vente (POS)​

CodeDescription
pos.readVoir les points de vente
pos.createCréer des points de vente
pos.updateModifier des points de vente
pos.deleteSupprimer des points de vente

Caisses (Registers)​

CodeDescription
register.readVoir les caisses
register.openOuvrir une caisse
register.closeFermer une caisse

Réservations​

CodeDescription
reservation.manageToutes les opérations sur les réservations
reservation.readVoir les réservations
reservation.createCréer des réservations
reservation.updateModifier le statut des réservations
reservation.validateValider une réservation (ready/collected)
reservation.cancelAnnuler une réservation (déclenche le remboursement)
reservation.refundRembourser des réservations
reservation.exportExporter les réservations

Transactions​

CodeDescription
transaction.readVoir l'historique des transactions

Tickets support​

CodeDescription
ticket.readVoir les tickets support
ticket.createCréer des tickets
ticket.updateModifier des tickets

Notifications​

CodeDescription
notification.manageToutes les opérations sur les notifications
notification.readVoir les templates et notifications planifiées
notification.createCréer des templates et notifications planifiées
notification.updateModifier des templates et notifications planifiées
notification.deleteSupprimer des templates et notifications planifiées

Paramètres​

CodeDescription
settings.readVoir les paramètres de l'organisation
settings.updateModifier les paramètres de l'organisation

Utilisateurs​

CodeDescription
user.manageToutes les opérations sur les utilisateurs
user.readVoir les utilisateurs
user.createCréer des utilisateurs
user.updateModifier des utilisateurs
user.deleteSupprimer des utilisateurs

Rôles​

CodeDescription
role.readVoir les rôles
role.createCréer des rôles
role.updateModifier des rôles
role.deleteSupprimer des rôles
role.permission.assignAssigner/retirer des permissions sur les rôles

Statistiques et Analytics​

CodeDescription
stats.exhaustive.readStatistiques cross-organisations
stats.partial.readStatistiques d'organisation (héritage)
analytics.readAnalytics de l'organisation
log.readConsulter les logs
log.manageGérer les logs (super-permission)
anomaly.manageGérer les anomalies
anomaly.threshold.configureConfigurer les seuils d'anomalie

Exports et imports​

CodeDescription
export.manageGérer/effectuer tous les exports
import.manageGérer/effectuer tous les imports
card.export / card.importExporter / importer des cartes
cardholder.export / cardholder.importExporter / importer des porteurs
product.export / product.importExporter / importer des produits
transaction.exportExporter les transactions
stock.exportExporter les mouvements de stock
role.exportExporter les rôles
log.exportExporter les logs
anomaly.exportExporter les anomalies
reservation.exportExporter les réservations

Super-permissions .manage complémentaires​

CodeDescription
cardholder.manageToutes les opérations sur les porteurs
menu.manageToutes les opérations sur les menus
stock.manageToutes les opérations de stock
transaction.manageToutes les opérations sur les transactions
user.manageToutes les opérations sur les utilisateurs
role.manageToutes les opérations sur les rôles

Plateforme (système)​

CodeDescription
platform.user.manageGérer les utilisateurs plateforme
organization.manageGérer les organisations (niveau système)

Rôles système par défaut​

Les rôles ci-dessous sont créés par la migration 0014 avec is_system_role = true.

Rôle (code)Ancien nomDescription
administrateursuper_adminAccès complet à toutes les fonctionnalités
observateurorg_viewerLecture seule
supportsupport_agentSupport technique limité
gestionnaireadmin_n1Gestion complète de l'organisation
superviseursupervisorSupervision et gestion
caissiercashierOpérations de caisse et encaissement
vendeursellerVentes uniquement
porteurcard_holderSelf-service mobile

Détail des permissions par rôle​

Les permissions ci-dessous correspondent au seed par défaut (seed_tenant_roles) et aux migrations. La matrice complète est disponible dans Matrice des rôles.

administrateur (super_admin)​

Toutes les permissions système et tenant.

observateur (org_viewer)​

Lecture seule : organization.manage, stats.exhaustive.read, stats.partial.read, plus les .read de chaque domaine (product, category, stock, card, site, pos, register, user, role, ticket, notification, settings, menu) et user.manage (héritage).

support (support_agent)​

Support technique : organization.manage, user.manage, stats.partial.read et les .read de chaque domaine.

gestionnaire (admin_n1)​

Toutes les permissions tenant (gestion complète de l'organisation).

superviseur (supervisor)​

card.read, card.balance.read, card.history.read, card.manual_access, card.recharge.cash, card.recharge.mobile_money, card.correction, card.debit.lost_card, product.read, category.read, stock.read, menu.read, site.read, pos.read, register.read, reservation.read, reservation.create, reservation.update, reservation.refund, ticket.read, ticket.update, settings.read, user.read, role.read, notification.read, transaction.read, stats.partial.read, analytics.read, log.read, anomaly.manage.

caissier (cashier)​

card.read, card.balance.read, card.history.read, card.recharge.cash, card.assign_new, card.manual_access, menu.read, stock.read, reservation.read, reservation.create, reservation.update, transaction.read, register.read, register.open, register.close.

vendeur (seller)​

product.sell, product.read, category.read, stock.read, card.read, card.balance.read, menu.read, reservation.read, reservation.update, transaction.read.

porteur (card_holder)​

card.balance.read, card.history.read, card.recharge.mobile_money.

Rôle porteur réservé au mobile

Le rôle porteur est destiné aux utilisateurs de l'application mobile (porteurs de carte). Il ne doit pas être attribué au personnel, qui doit être vendeur, caissier, superviseur ou gestionnaire.

Hiérarchie des rôles​

Plateforme (N2) ──────────────────────────────────────────────────
│
├── administrateur ────► toutes permissions
├── observateur ───────► lecture seule
└── support ───────────► tickets + lecture

Organisation (N1) ────────────────────────────────────────────────
│
├── gestionnaire ─────► toutes permissions tenant
├── superviseur ──────► supervision (lecture + gestion courante)
├── caissier ─────────► opérations de caisse
├── vendeur ──────────► vente uniquement
└── porteur ──────────► self-service mobile

Création de rôles custom​

Les organisations peuvent créer des rôles supplémentaires (non-système) :

POST /api/v1/admin/org/roles
Authorization: Bearer ...
X-Tenant-Id: ...

{
"name": "gestionnaire_cuisine",
"description": "Responsable de cuisine"
}
astuce

Les rôles custom sont créés avec is_system_role = false et peuvent être supprimés. Les rôles système (administrateur, gestionnaire, etc.) ont is_system_role = true et sont protégés.

Assignation de permissions à un rôle​

POST /api/v1/admin/org/roles/{id}/permissions
Authorization: Bearer ...

{
"permission_id": "uuid-permission"
}

Le catalogue des permissions est exposé par GET /api/v1/admin/org/permissions. Chaque permission s'assigne individuellement (une requête par permission).

Résolution des permissions au login​

Les permissions sont résolues au login et embarquées dans le JWT pour éviter un lookup DB à chaque requête.

Login → Rôles → role_permissions → Permission codes → JWT claims

Le JWT contient un tableau plat de codes de permission.

Impact sur les modifications de rôles​

Si un admin modifie les permissions d'un rôle après que des utilisateurs sont connectés :

  • Les tokens existants restent valides jusqu'à expiration (15 min)
  • Au prochain login ou refresh, les nouvelles permissions sont résolues
info

Le refresh token re-résout les permissions depuis la DB, donc un refresh suffit pour obtenir les permissions à jour sans re-login.

Vérification des permissions​

Dans le code (middleware)​

Le middleware vérifie les permissions sur chaque route. Par exemple, require_card_read accepte card.read ou card.manage :

Router::new()
.route("/cards", get(list_cards))
.layer(PermissionGuard::new("card.read"))

Helper methods sur JwtClaims​

// Une seule permission (vérifie aussi le .manage implicite selon le helper)
claims.has_permission("card.read")

// TOUTES les permissions requises
claims.has_all_permissions(&["card.read", "card.recharge.cash"])

// AU MOINS une permission
claims.has_any_permission(&["card.read", "card.manage"])

Principe de vérification​

Les fonctions require_* du module authz utilisent un pattern systématique :

pub fn require_card_read(claims: &JwtClaims) -> bool {
claims.has_any_permission(&["card.read", "card.manage"])
}

pub fn require_product_sell(claims: &JwtClaims) -> bool {
claims.has_any_permission(&["product.sell", "product.manage"])
}

Ainsi, {domaine}.manage donne automatiquement accès à toutes les permissions spécifiques de ce domaine.

Wildcard parent des permissions

Toutes les permissions d'un même domaine ne sont pas regroupées sous un seul .manage :

DomaineWildcard parent
card.*card.manage
product.*product.manage
stock.*product.manage
category.*product.manage
menu.*Aucun (permissions individuelles seulement)
site.*site.manage
pos.*site.manage
register.*site.manage
reservation.*reservation.manage
ticket.*reservation.manage
notification.*notification.manage
user.*user.manage (ou organization.manage)
role.*organization.manage
settings.*organization.manage
log.readorganization.manage
analytics.*organization.manage
anomaly.*organization.manage

Les fonctions require_* du middleware utilisent has_any_permission pour accepter soit la permission spécifique, soit le wildcard parent.

Permissions par endpoint​

Tous les endpoints listés ci-dessous sont sous le préfixe /api/v1.

Cartes (endpoints publics / cardholder)​

EndpointPermission requise
POST /cards/resolve-qrcard.read
GET /cards/{id}/balancecard.read
GET /cards/{id}/historycard.read
GET /cards/public/{code}Aucune (public)

Cartes (administration)​

EndpointPermission requise
GET /admin/org/cardscard.read
POST /admin/org/cardscard.create
GET /admin/org/cards/{id}card.read
PUT /admin/org/cards/{id}card.update
DELETE /admin/org/cards/{id}card.delete
POST /admin/org/cards/importcard.create
POST /admin/org/cards/{id}/assigncard.update
POST /admin/org/cards/{id}/reassigncard.update
POST /admin/org/cards/{id}/revokecard.update
POST /admin/org/cards/{id}/deactivatecard.update
POST /admin/org/cards/{id}/activatecard.update
POST /admin/org/cards/{id}/lostcard.update

Porteurs​

EndpointPermission requise
GET /admin/org/cards/holderscard.read
POST /admin/org/cards/holderscard.holder.create
PUT /admin/org/cards/holders/{id}card.holder.update
DELETE /admin/org/cards/holders/{id}card.holder.delete
GET /admin/org/cards/holders/{id}/cardscard.read
GET /admin/org/cards/holders/{id}/reservationscard.read

Liens parent-enfant​

EndpointPermission requise
GET /admin/org/card-holder-linkscard.link.read
POST /admin/org/card-holders/{parent_id}/childrencard.link.create
GET /admin/org/card-holders/{parent_id}/childrencard.link.read
DELETE /admin/org/card-holders/{parent_id}/children/{child_id}card.link.delete

Transactions​

EndpointPermission requise
GET /transactionstransaction.read
POST /transactions/rechargecard.recharge.cash ou card.recharge.mobile_money
POST /transactions/purchaseproduct.sell
POST /transactions/correctioncard.correction
POST /transactions/refundreservation.refund (ou reservation.manage / card.correction / card.manage)
POST /transactions/{id}/voidcard.void (ou card.correction)

Produits​

EndpointPermission requise
GET /productsproduct.read
POST /productsproduct.create
PUT /products/{id}product.update
DELETE /products/{id}product.delete

Stock (rattaché aux produits)​

EndpointPermission requise
POST /admin/org/products/{id}/adjust-stockstock.adjust
POST /admin/org/products/{id}/purchasestock.purchase
POST /admin/org/products/{id}/productionstock.produce
POST /admin/org/products/{id}/transferstock.transfer

Le wildcard pour les permissions stock est product.manage, non stock.manage.

Catégories​

EndpointPermission requise
GET /admin/org/product-categoriesproduct.read
POST /admin/org/product-categoriescategory.create
PUT /admin/org/product-categories/{id}category.update
DELETE /admin/org/product-categories/{id}category.delete

Le wildcard pour les permissions catégorie est product.manage.

EndpointPermission requise
GET /menusmenu.read
POST /menusmenu.create
PUT /menus/{id}menu.update
DELETE /menus/{id}menu.delete

Sites​

EndpointPermission requise
GET /admin/org/sitessite.read
POST /admin/org/sitessite.create
GET /admin/org/sites/{id}site.read
PUT /admin/org/sites/{id}site.update
DELETE /admin/org/sites/{id}site.delete

Points de vente​

EndpointPermission requise
GET /admin/org/points-of-salepos.read
POST /admin/org/points-of-salepos.create
PUT /admin/org/points-of-sale/{id}pos.update
DELETE /admin/org/points-of-sale/{id}pos.delete
POST /admin/org/points-of-sale/{id}/toggle-openpos.read

Le wildcard pour les permissions POS est site.manage.

Caisses​

EndpointPermission requise
GET /admin/org/points-of-sale/{pos_id}/registersregister.read
GET /admin/org/registers/{id}register.read
POST /admin/org/points-of-sale/{pos_id}/registers/openregister.open
POST /admin/org/registers/{id}/closeregister.close

Le wildcard pour les permissions registre est site.manage.

Réservations​

EndpointPermission requise
GET /reservationsreservation.read
POST /reservationsreservation.create
GET /reservations/{id}reservation.read
PATCH /reservations/{id}/statusreservation.update

Tickets support​

EndpointPermission requise
GET /admin/org/ticketsticket.read
GET /admin/org/tickets/{id}ticket.read
POST /admin/org/ticketsticket.create
PUT /admin/org/tickets/{id}ticket.update
PUT /admin/org/tickets/{id}/statusticket.update
POST /admin/org/tickets/{id}/messagesticket.create

Le wildcard pour les permissions ticket est reservation.manage.

Notifications​

EndpointPermission requise
GET /admin/org/notification-templatesnotification.read
POST /admin/org/notification-templatesnotification.create
PUT /admin/org/notification-templates/{id}notification.update
DELETE /admin/org/notification-templates/{id}notification.delete
GET /admin/org/scheduled-notificationsnotification.read
POST /admin/org/scheduled-notificationsnotification.create
PUT /admin/org/scheduled-notifications/{id}notification.update
DELETE /admin/org/scheduled-notifications/{id}notification.delete

Administration (organisation)​

EndpointPermission requise
GET /admin/org/usersuser.read
POST /admin/org/usersuser.create
PUT /admin/org/users/{id}user.update
DELETE /admin/org/users/{id}user.delete
GET /admin/org/rolesrole.read
POST /admin/org/rolesrole.create
PUT /admin/org/roles/{id}role.update
DELETE /admin/org/roles/{id}role.delete
POST /admin/org/roles/{id}/permissionsrole.permission.assign
GET /admin/org/settingssettings.read
PUT /admin/org/settingssettings.update
GET /admin/org/logslog.read
GET /admin/org/audit-loglog.read
GET /admin/org/anomaliesanomaly.manage
POST /admin/org/anomalies/{id}/acknowledgeanomaly.manage
POST /admin/org/anomalies/{id}/resolveanomaly.manage

Le wildcard pour les permissions admin (user, role, settings, log, anomaly) est organization.manage.

Stats et analytics (organisation)​

EndpointPermission requise
GET /admin/org/stats/dashboardanalytics.read
GET /admin/org/stats/revenue-by-typeanalytics.read
GET /admin/org/stats/top-productsanalytics.read
GET /admin/org/stats/sites-revenueanalytics.read
GET /admin/org/stats/hourlyanalytics.read
GET /admin/org/stats/holdersanalytics.read
GET /admin/org/stats/rechargesanalytics.read
GET /admin/org/stats/salesanalytics.read
GET /admin/org/stats/balancesanalytics.read
GET /admin/org/stats/reservationsanalytics.read
GET /admin/org/stats/stockstock.read
GET /admin/org/analytics/*analytics.read

Plateforme (système)​

EndpointPermission requise
GET/POST /admin/system/usersplatform.user.manage
GET/PUT/DELETE /admin/system/users/{id}platform.user.manage
GET/POST/DELETE /admin/system/users/{id}/rolesplatform.user.manage
GET/POST /admin/system/rolesorganization.manage
GET/PUT/DELETE /admin/system/roles/{id}organization.manage
POST/DELETE /admin/system/roles/{id}/permissionsorganization.manage
GET /admin/system/permissionsorganization.manage
GET/POST /admin/system/organizationsorganization.manage
GET/PUT /admin/system/organizations/{id}organization.manage
POST /admin/system/organizations/{id}/suspendorganization.manage
POST /admin/system/organizations/{id}/activateorganization.manage
GET /admin/system/audit-logstats.exhaustive.read
GET /admin/system/anomaliesstats.exhaustive.read
GET /admin/system/logslog.read
GET /admin/system/stats/*stats.exhaustive.read
GET /admin/system/analytics/*stats.exhaustive.read