Calcul des droits d'accès
Calcul des droits d'accès
Cette page détaille comment TARS calcule les droits effectifs d'une personne à l'ouverture de sa session. Elle complète Accès et autorisations, qui décrit où les accès sont définis, et Rôles et autorisations, qui décrit les regroupements d'accès.
Ce qui entre dans le calcul
| Entrée | Rôle dans le calcul |
|---|---|
| Organisation d'appartenance | Organisation à laquelle la personne est rattachée |
| Organisation active | Organisation au nom de laquelle elle agit; différente de la précédente quand elle agit pour une organisation descendante ou pour une organisation mandante (procuration) |
| Droits délégués de la procuration | Admin ou rôles métier; une délégation par rôles limite les accès obtenus chez l'organisation mandante |
| Contrats actifs | Portent la liste des accès disponibles pour une organisation |
| Contrats parents transférés | Contrats d'une organisation parente dont le transfert aux organisations filles est activé |
| Rôles métier de la personne | Regroupement d'accès appliqué à la personne |
| Accès personnalisés de la personne | Liste d'accès définie manuellement sur sa fiche, qui ne peut que restreindre |
| Shop | Les droits sont calculés et vérifiés séparément pour Agorastore et Auctelia |
Cas 1 : la personne agit dans sa propre organisation
La personne reçoit tous les accès des contrats actifs de son organisation, plus ceux des contrats des organisations parentes dont le transfert aux filles est activé.
Si ses accès ont été personnalisés, la liste obtenue est filtrée par cette personnalisation.
Marion (Renault) opère dans Renault
Contrats Renault : ["VENDRE", "COMMANDER", "FACTURER"]
Marion sans accès personnalisés → ["VENDRE", "COMMANDER", "FACTURER"]
Marion avec accès personnalisés ["VENDRE"] → ["VENDRE"]
Cas 2 : la personne agit pour une autre organisation
Ce cas correspond à une procuration : l'organisation de la personne a reçu le droit d'agir pour le compte d'une autre organisation.
La personne reçoit l'intersection entre ses droits personnels et les droits de l'organisation active. Contrairement au cas 1, la restriction personnelle (accès personnalisés, ou à défaut droits des rôles métier attribués) s'applique ici même si elle vient des rôles métier et pas seulement d'une personnalisation explicite: dès qu'une des deux existe, elle sert de filtre avant l'intersection avec les droits de l'organisation active.
Pierre (Peugeot) opère chez Citroën
Droits Pierre : ["VENDRE", "COMMANDER", "CONSULTER"]
Droits Citroën : ["COMMANDER", "CONSULTER", "FACTURER"]
→ Résultat : ["COMMANDER", "CONSULTER"]
Sophie (Renault) opère chez Peugeot
Contrats Renault : ["VENDRE", "COMMANDER", "FACTURER", "ADMIN"]
Accès personnalisés : ["VENDRE", "COMMANDER"]
Droits Peugeot : ["COMMANDER", "CONSULTER"]
→ Résultat : ["COMMANDER"]
Lucas (Citroën) opère chez Renault Sport
Droits Lucas : ["CONSULTER", "RAPPORT"]
Droits Renault Sport : ["VENDRE", "FACTURER"]
→ Résultat : aucun accès
Quand le flag PROCURATION est actif sur la boutique, la procuration porte en plus des droits délégués. Une délégation par rôles métier ne laisse passer, après l'intersection, que les accès de ces rôles; une délégation Admin ne filtre rien de plus. Sans le flag, toute procuration vaut délégation Admin.
Pierre (Peugeot) opère chez Citroën avec une procuration « Ventes »
Droits Pierre : ["VENDRE", "COMMANDER", "PUBLIER"]
Droits Citroën : ["VENDRE", "PUBLIER", "FACTURER"]
Accès du rôle délégué Ventes : ["PUBLIER", "FACTURER"]
→ Résultat : ["PUBLIER"]
Le détail, illustré sur une organisation fictive avec un simulateur, est dans Procurations et organisations complexes.
Cas 3 : la personne agit pour une organisation descendante
Une personne peut aussi agir pour une organisation descendante de la sienne (filiale, service), sans procuration. Le calcul est celui du cas 2, sans filtre de droits délégués : intersection de ses droits personnels et des droits de l'organisation active.
Claire (Métropole de Valbrune) opère dans le Parc auto, organisation fille
Droits Claire : ["VENDRE", "COMMANDER", "FACTURER"]
Droits Parc auto : ["VENDRE", "FACTURER"]
→ Résultat : ["VENDRE", "FACTURER"]
Héritage entre organisations d'un même groupe
Les accès d'une organisation parente ne descendent vers ses organisations filles que si le transfert de contrat est activé sur le contrat parent (champ contract.meta.childTransfer = true).
Renault (parent)
├── Renault Sport (enfant)
└── Renault Trucks (enfant)
Avec un contrat Renault ["ADMIN", "VENDRE"] en transfert activé et un contrat Renault Sport ["COURSE", "TUNING"], un employé de Renault Sport dispose de ["ADMIN", "VENDRE", "COURSE", "TUNING"].
L'héritage remonte toute la chaîne d'ancêtres, pas seulement le parent direct: pour une organisation donnée, TARS reconstitue d'abord la liste complète de ses ancêtres (parent, grand-parent, etc., avec protection contre les boucles), puis ne retient, pour chaque ancêtre, que ses contrats dont childTransfer est activé. Le transfert de chaque niveau reste donc une décision indépendante: un grand-parent peut transférer ses accès sans que le parent intermédiaire ait activé le sien, et inversement.
Si les accès d'une personne ont été personnalisés, un contrat ajouté ensuite sur son organisation ou transféré par l'organisation parente n'ajoute pas automatiquement ses accès à cette personne. Ces accès deviennent seulement activables manuellement depuis l'onglet « Accès » de sa fiche.
Séparation par shop
Les droits sont calculés et stockés séparément pour chaque shop.
- Une organisation peut avoir des contrats distincts par shop, par exemple un contrat acheteur chez Auctelia et un contrat acheteur chez Agorastore.
- La session porte deux listes d'accès, une par shop.
- Pour agir sur un objet, la personne doit détenir l'accès requis dans le shop de cet objet.
Marion (Renault) opère dans Renault
Contrats Renault :
Agorastore : ["ITEM_PUBLISH", "ITEM_VIEW", "ORDER_CREATE"]
Auctelia : ["ITEM_VIEW", "AUCTION_CREATE", "BID_PLACE"]
Publier un item dans Agorastore → autorisé
Publier un item dans Auctelia → refusé, l'accès n'existe pas dans ce shop
Créer une enchère dans Auctelia → autorisé
L'intersection de la procuration s'applique elle aussi shop par shop : une personne peut conserver des droits dans un shop et n'en avoir aucun dans l'autre.
Format des clés d'accès et vérification côté frontal
Chaque accès existe sous deux formes équivalentes : une forme hiérarchique à points utilisée dans le code (DOMAINE.RESSOURCE.ACTION, par exemple SALES.CONTRACT.MANAGE) et une forme aplatie utilisée dans les listes de droits de session (DOMAINE_RESSOURCE_ACTION, par exemple SALES_CONTRACT_MANAGE). Les deux formes désignent le même accès du même catalogue fermé.
Pour vérifier un accès, le frontal :
- reconstruit un arbre de droits à partir de la liste plate d'accès du shop actif;
- si la personne est en mode « Admin de l'organisation » (
isOrgAdmin), la vérification retourne vrai sans consulter cet arbre; - sinon, elle recherche si au moins une des clés demandées est présente dans l'arbre.
Ce mécanisme signifie que la garantie « l'admin de l'organisation n'a jamais plus de droits que les contrats » repose entièrement sur la façon dont isOrgAdmin et la liste de droits de session sont calculées côté serveur; le frontal ne la revérifie pas accès par accès.
Cas particuliers
| Situation | Résultat |
|---|---|
| L'organisation active n'a aucun contrat | Aucun accès, quels que soient les droits personnels de la personne |
| Un accès personnalisé ne figure plus dans aucun contrat de l'organisation | L'accès est ignoré; les autres restent valables |
| La personne n'a ni organisation de rattachement ni organisation active | Aucun droit de session n'est retourné |
| Profil super admin | Reçoit l'ensemble des droits disponibles sur tous les shops |
Enchaînement du calcul
flowchart TD
start["Ouverture de session"] --> contrats["Réunir les contrats actifs de l'organisation et des parents en transfert"]
contrats --> base["Constituer les accès de base, par shop"]
base --> perso{"Accès personnalisés définis ?"}
perso -->|Oui| filtre["Filtrer les accès de base par la liste personnalisée"]
perso -->|Non| roles{"Rôles métier définis ?"}
roles -->|Oui| cumul["Retenir les accès des rôles, dans la limite des contrats"]
roles -->|Non| admin["Retenir tous les accès des contrats"]
filtre --> contexte{"Organisation active = organisation d'appartenance ?"}
cumul --> contexte
admin --> contexte
contexte -->|Oui| resultat["Droits effectifs"]
contexte -->|Non| inter["Intersection avec les droits de l'organisation active, par shop"]
inter --> delegation{"Procuration avec des rôles délégués ?"}
delegation -->|Non : descendante ou délégation Admin| resultat
delegation -->|Oui| deleguee["Ne garder que les accès des rôles délégués"]
deleguee --> resultat
Garanties
- Une personne n'obtient jamais plus de droits que ceux ouverts par son organisation, ou que ceux de l'organisation active en cas de procuration.
- Une procuration par rôles métier ne donne jamais plus que les accès des rôles délégués.
- Les accès personnalisés et les rôles métier ne peuvent que restreindre les droits ouverts par les contrats, jamais les étendre.
- L'absence de contrat sur l'organisation active bloque tout accès.
Mécanique de vérification d'un accès
Une fois les droits de session calculés (ci-dessus) et transmis au frontal, chaque contrôle d'accès applicatif passe par la bibliothèque partagée @auctelia/access-manager, utilisée aussi bien par les fronts (tars-monorepo) que par le backend (auctelia/api):
- Un profil super admin (
person.meta.superAdmin) passe toujours, sans consulter la liste de droits. - Sinon, la clé d'accès demandée est cherchée dans
allSessionAccessRights(contrôle global) ou danssessionAccessRights[shopShortId](contrôle par boutique,canPerformActionByShop). - Pour une action sur un objet lié à une organisation associée (procuration),
can()vérifie en plus que l'organisation de la personne figure dans la liste des organisations associées à l'objet avec un rôle autorisé (AssociatedOrganisationsRoles:BUYER,SELLER,PARTNER,CREATOR,EDIT,OWNER,VISITOR) — sauf si la personne est admin, auquel cas ce contrôle est court-circuité. - Une action qui ne correspond à aucune clé du catalogue lève une erreur
NO_SUCH_ACTIONplutôt que d'être silencieusement refusée.
Un interrupteur global côté backend (featureFlags.enableApplyAccess) peut désactiver l'ensemble du système d'accès fin: s'il est éteint, toute personne qui n'a pas le rôle contractuel ADMIN reçoit malgré tout l'intégralité des accès disponibles sur chaque boutique, comme un profil super admin. C'est un interrupteur de secours/migration, pas un réglage courant.
Le catalogue d'accès (~50 clés), la liste exacte des accès par rôle métier et le calcul des droits de session (cas 1, cas 2, héritage de groupe ci-dessus) sont vérifiés directement dans le code du service persons (retrieveSessionAccessRights), pas seulement déduits du front.
Actions par frontal
Cette matrice résume les actions possibles dans chaque frontal: la marketplace (market-front), l'espace personnel (customer-front) et l'admin (admin-front), plus l'inventaire terrain (inventory-front) à part.
Confidentialité
Cette matrice explique qui peut voir les principales données, et à quelle condition.