Aller au contenu

Modèle d'accès cible : utilisateurs, sociétés, agences

Modèle cible, pas encore en service

Cette page décrit le modèle d'accès vers lequel Sanu OS doit évoluer, et non le fonctionnement actuel du logiciel. Elle remplacera à terme la logique de rôles et de profils figés décrite dans Rôles & accès, si bien que les deux pages se contredisent tant que ce modèle n'est pas livré. Les écarts avec l'existant sont détaillés en fin de page.

Principes

Le modèle repose sur une idée simple : chaque action exposée par le logiciel est protégée par un seul code de permission, et l'accès d'une personne se résume à l'ensemble des codes qu'elle détient dans une société et, le cas échéant, dans une agence. Il n'existe donc plus de rôle au sens où l'entendait la version précédente, le caissier comme le gérant n'étant plus que des noms donnés par chaque société à des ensembles de codes qu'elle compose elle-même.

Cinq règles en découlent :

  • le catalogue des permissions est défini par la plateforme, chaque code suivant le format module.resource.action, et aucune société ne peut en créer de nouveaux ;
  • chaque société compose ses propres profils d'accès à partir de ce catalogue, les huit profils livrés aujourd'hui devenant de simples modèles recopiés à la création de la société puis modifiables par elle ;
  • une personne peut appartenir à plusieurs sociétés, chacune de ces appartenances faisant l'objet d'une adhésion distincte qui porte son propre profil par défaut ;
  • un autre profil de la même société peut être substitué au profil par défaut pour une agence donnée, et cette substitution remplace le profil par défaut sans jamais s'y ajouter ;
  • un profil énumère ses codes un par un, sans joker du type command.*, afin qu'un code ajouté plus tard au catalogue ne soit jamais accordé à l'insu de la société.

Modèle de données

Modèle de données

Le diagramme s'organise en trois ensembles. L'identité regroupe l'utilisateur, identifié par une adresse e-mail unique sur toute la plateforme, et ses sessions. La structure société reprend la chaîne déjà décrite dans le Glossaire, à savoir la société, ses agences, puis les entrepôts, points de vente et caisses rattachés à chaque agence, à laquelle s'ajoute le poste enregistré qui permet la connexion par PIN. Les habilitations, enfin, relient ces deux ensembles par l'adhésion, qui rattache un utilisateur à une société, et par l'accès agence, qui précise les agences atteintes ainsi que l'éventuelle substitution de profil.

Plusieurs contraintes méritent d'être mentionnées, parce qu'elles garantissent qu'aucune habilitation ne franchit la frontière d'une société :

  • une adhésion est unique pour un couple utilisateur et société, et son profil par défaut appartient à cette même société ;
  • un accès agence est unique pour un couple adhésion et agence, l'agence comme le profil de substitution appartenant à la société de l'adhésion ;
  • un profil d'accès porte un nom unique dans sa société et accorde au moins un code ;
  • le code PIN est enregistré sur l'adhésion et non sur l'utilisateur, si bien qu'un gérant ne peut jamais définir un code valable dans une autre société.

Portée d'une permission et profil effectif

Chaque entrée du catalogue indique si elle s'applique à la société entière ou à une agence. Un code de portée société, comme la création d'un profil d'accès, se vérifie toujours sur le profil par défaut de l'adhésion, l'agence éventuellement transmise étant ignorée. Un code de portée agence, comme la validation d'un écart de caisse, suppose en revanche que l'agence visée soit atteinte, soit parce que l'adhésion couvre toutes les agences présentes et futures, soit parce qu'un accès agence la mentionne ; le profil effectif est alors la substitution définie pour cette agence ou, à défaut, le profil par défaut.

Le tableau suivant reprend les codes utilisés dans les exemples de cette page, tels qu'ils figurent au catalogue.

Code Libellé Portée Sensible
authentication.access_profile.create Créer un profil d'accès Société Non
authentication.access_profile.assign Assigner un profil à un utilisateur Société Non
company.agency.manage Gérer les agences Société Non
company.company.view Voir les infos société Société Non
command.checkout_session.open Ouvrir une session de caisse Agence Non
command.checkout_session.close Fermer sa session de caisse Agence Non
command.checkout_session.view Voir les sessions de caisse Agence Non
command.checkout_session.validate_variance Valider l'écart Z Agence Oui
command.order.create Créer une vente POS Agence Non
command.order.checkout Encaisser une commande Agence Non
command.order.view Voir les commandes Agence Non
stock.stock_transfer.receive Réceptionner un transfert Agence Non
stock.inventory.validate Valider l'écart d'inventaire Agence Oui
finance.report.view_summary Voir les rapports synthétiques Agence Non

La vue consolidée « Toutes les agences », proposée par le sélecteur d'agence, obéit à la même règle appliquée agence par agence : le serveur retient les agences atteintes dont le profil effectif contient le code demandé, limite la lecture à ces seules agences et ne répond par un refus que si aucune ne convient. Cette vue est réservée à la consultation, toute écriture de portée agence exigeant une agence précise.

Connexion

Connexion

La connexion par e-mail et mot de passe identifie d'abord la personne, puis la société, puis l'agence, ce qui inverse l'ordre décrit dans Se connecter & naviguer, où l'agence est choisie avant la saisie des identifiants. Cet ordre s'impose dès lors qu'un même compte peut appartenir à plusieurs sociétés, la liste des agences proposées dépendant de la société retenue. Le choix de la société n'apparaît que si la personne en a plusieurs, et celui de l'agence que si plusieurs agences lui sont accessibles.

La connexion par PIN ne se fait en revanche que depuis un poste de caisse enregistré et rattaché à une agence : la personne touche la vignette portant son nom puis saisit son code, un code de quatre chiffres ne suffisant pas à identifier seul un membre de l'équipe. Une session ouverte par PIN reste attachée à l'agence du poste, n'offre pas la vue consolidée et refuse les actions de portée société.

Après cinq échecs consécutifs, le compte est bloqué pendant 15 minutes, et le PIN d'une adhésion l'est de la même manière lorsque le seuil fixé par la société est atteint ; les réponses d'échec restent volontairement identiques afin de ne pas indiquer laquelle des informations saisies est fausse. Chaque personne ne dispose par ailleurs que d'une session active à la fois. Changer de société ouvre une nouvelle session, alors que changer d'agence ne modifie pas le jeton, puisque l'agence accompagne chaque requête et que les permissions sont résolues par le serveur au moment de la requête.

Contrôle d'une action

Contrôle d'une action

Le diagramme suit un cas précis : Adjo Mensah, caissière à Dépôt Lomé (Bè) mais responsable de dépôt à Dépôt Kara, valide l'écart Z d'une session de caisse de Dépôt Kara. Le serveur vérifie successivement le jeton et l'adhésion, le périmètre, puis la permission, avant de confier l'action au service métier. L'agence retenue pour le contrôle est celle de la ressource visée, déduite de la caisse et du point de vente, et non celle que l'application transmet, afin qu'une requête ne puisse pas atteindre la session d'une autre agence en annonçant une agence autorisée.

Réponse Situation
401 Jeton absent, invalide ou expiré, session révoquée, ou adhésion, société ou utilisateur inactif.
404 Ressource introuvable ou appartenant à une autre société, ou agence non atteinte.
403 Code absent du profil effectif, ou code de portée société demandé depuis une session PIN.
400 Écriture de portée agence sans agence précise, par exemple depuis la vue consolidée.
409 ou 422 Permission accordée, mais règle métier non respectée.

Il m'a semblé préférable de répondre 404 plutôt que 403 lorsque l'agence n'est pas atteinte, afin de ne pas révéler l'existence d'une ressource à une personne qui n'a pas à la connaître. Tout refus est inscrit au journal d'audit, de même que chaque action accordée sur un code sensible, cette dernière inscription se faisant dans la même transaction que l'action.

Exemple

Exemple

L'exemple reprend les sociétés du jeu de démonstration. Ets Sanu & Frères exploite Dépôt Lomé (Bè) et Dépôt Kara, Maison Kouassi exploite une agence fictive nommée Boutique Cocody, et trois personnes illustrent les cas utiles : Komi Agbeko dirige la première société et détient une adhésion en lecture dans la seconde, Adjo Mensah bénéficie d'une substitution de profil à Dépôt Kara, et Selom Lawson n'a accès qu'à Dépôt Lomé (Bè).

Utilisateur Dépôt Lomé (Bè) Dépôt Kara Codes de portée société
Komi Agbeko Direction Direction Direction
Adjo Mensah Caisse Responsable de dépôt, par substitution Aucun
Selom Lawson Responsable de dépôt Hors périmètre Aucun

Adjo Mensah peut ainsi valider un écart Z à Dépôt Kara, mais ne peut plus y créer de vente, puisque la substitution remplace le profil « Caisse » au lieu de s'y ajouter. Il appartiendra à la société de composer un profil réunissant les deux ensembles de codes si l'organisation du dépôt le demande.

Écarts avec l'existant et limites

Aucune des deux API ne met en œuvre ce modèle aujourd'hui, et le manuel décrit encore l'organisation précédente. Les écarts principaux sont les suivants :

  • l'API Django rattache chaque utilisateur à une seule société, accepte les jokers dans les profils, enregistre le PIN sur le profil et, pour une vérification propre à un entrepôt, ne consulte que le profil de l'agence sans revenir au profil général ;
  • l'API Java rattache elle aussi l'utilisateur à une seule société, enregistre le PIN sur l'utilisateur, référence huit profils figés définis dans un fichier de configuration et ne connaît pas de profil par agence ;
  • les pages Rôles & accès et Se connecter & naviguer décrivent toujours un rôle unique par utilisateur et le choix de l'agence avant la saisie des identifiants.

Le modèle comporte par ailleurs des limites qu'il faudra traiter lors de sa mise en œuvre. L'absence de joker oblige à mettre à jour délibérément les profils existants chaque fois qu'un code est ajouté au catalogue, ce qui est voulu mais demande un suivi. Les ressources qui existent à la fois au niveau de la société et de l'agence, comme les coffres de société et les coffres d'agence, devront recevoir des codes distincts plutôt qu'une règle d'exception. L'agence devient en outre la plus petite unité de périmètre, si bien que la restriction à un entrepôt précis, possible aujourd'hui dans l'API Django, disparaît. Enfin, la règle d'une session par personne implique qu'une caissière qui se connecte sur son poste ferme la session ouverte sur le back-office, et qu'un même compte ne peut pas travailler sur deux sociétés dans deux onglets.

Voir aussi