Regles et matrices

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.

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éeRôle dans le calcul
Organisation d'appartenanceOrganisation à laquelle la personne est rattachée
Organisation activeOrganisation 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 procurationAdmin ou rôles métier; une délégation par rôles limite les accès obtenus chez l'organisation mandante
Contrats actifsPortent la liste des accès disponibles pour une organisation
Contrats parents transférésContrats d'une organisation parente dont le transfert aux organisations filles est activé
Rôles métier de la personneRegroupement d'accès appliqué à la personne
Accès personnalisés de la personneListe d'accès définie manuellement sur sa fiche, qui ne peut que restreindre
ShopLes 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 :

  1. reconstruit un arbre de droits à partir de la liste plate d'accès du shop actif;
  2. si la personne est en mode « Admin de l'organisation » (isOrgAdmin), la vérification retourne vrai sans consulter cet arbre;
  3. 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

SituationRésultat
L'organisation active n'a aucun contratAucun accès, quels que soient les droits personnels de la personne
Un accès personnalisé ne figure plus dans aucun contrat de l'organisationL'accès est ignoré; les autres restent valables
La personne n'a ni organisation de rattachement ni organisation activeAucun droit de session n'est retourné
Profil super adminReç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 dans sessionAccessRights[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_ACTION plutô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.

Copyright © 2026