Préambule
Dans le cadre de projet touchant des publics variés, la gestion des droits d’accès est souvent un défi. Lorsqu’un tableau doit être consulté par plusieurs utilisateurs aux profils différents, avec des périmètres différents, les règles de filtrages basique ne suffisent plus. De plus, il est encore plus nécessaire dans ce cas d’être rigoureux dans la définition de la politique d’habilitation (i.e. qui voit quoi, et avec quels autorisations ?)
Ce tutoriel détaille la mise en place d’un contrôle d’accès granulaire (ACL) basé sur deux profils utilisateurs, mais on peut facilement l’étendre à autant de profils souhaités.
En prérequis, je vous invite à consulter l’excellent guide de @ailepet avant de lire celui-ci.
Présentation du cas d’étude
Imaginons la mise en place d’une diffusion sélective d’information sur deux populations aux périmètres distincts. Précisons, que dans ce guide on ferra un filtrage par ligne, mais il est possible de le faire également par colonne.
- PROFIL « Responsable d’agence » affecté à une ou plusieurs agences. Il doit pouvoir accéder uniquement en lecture et écriture aux données qui correspondent aux agences de son périmètre.
- PROFIL « Directeur régional » affecté à une ou plusieurs régions. Chaque région regroupe un ensemble d’agences locales. Le directeur régional accède en lecture aux lignes des agences de ses régions. Pour connaitre le périmètre des agences d’un directeur régional, il faut donc déterminer en premier à quel région il est affecté, puis listé les agences dans ses régions.
Création de tables utilisateurs par profil
Pour simplifier la gestion de plusieurs profils, on va créer une table par popultion.
La table SYSTEM_AUTORIZATION_RESPONSABLE_AGENCE contient la liste des directeurs de chaque agence, et leur périmètre (i.e. dans quel agence ils sont affectés). Remarquons qu’il est possible de construire une autre table AGENCES qui contient la liste des agences avec le code, le nom, le code région associé.
| PROFIL | PERIMETRE_AGENCES | |
|---|---|---|
jean.dupont@entreprise.fr |
RESPONSABLE_AGENCE |
['codeAgence1'] |
marie.curie@entreprise.fr |
RESPONSABLE_AGENCE |
['codeAgence2'] |
paul.verlaine@entreprise.fr |
RESPONSABLE_AGENCE |
['codeAgence3', 'codeAgence4'] |
On fait de même pour la population des directeurs régionales dans une autre table SYSTEM_AUTORIZATION_DIRECTEUR_REGIONAL. Cette table contient la liste des directeurs de région et leur affectation de région. A partir de cette affectation de région, on peut en déduire le périmètre des agences associés (on verra plus bas comment automatiser cette association).
| PROFIL | PERIMETRE_REGIONS | PERIMETRE_AGENCES | |
|---|---|---|---|
sophie.martin@entreprise.fr |
DIRECTEUR_REGION |
['codeRegion1'] |
['codeAgence1', 'codeAgence2', 'codeAgence3'] |
luc.bernard@entreprise.fr |
DIRECTEUR_REGION |
['codeRegion1', 'codeRegion2'] |
['codeAgence1', 'codeAgence2', 'codeAgence3', 'codeAgence4'] |
elodie.faure@entreprise.fr |
DIRECTEUR_REGION |
['codeRegion2'] |
['codeAgence3', 'codeAgence4'] |
Appairage des propriétés pour les ACL
Dans la vue des permissions avancées, on commence par définir les appairages suivant par profil. Remarquez que l’on définit les propriétés d’appairage par profil à l’aide des deux tables précédemment créées.
| NAME | PROPRIÉTÉ D’APPAIRAGE | TABLE D’APPAIRAGE | COLONNE_CIBLE |
|---|---|---|---|
Team_RESPONSABLE_AGENCE |
user.Email |
SYSTEM_AUTORIZATION_RESPONSABLE_AGENCE |
EMAIL |
Team_DIRECTEUR_REGION |
user.Email |
SYSTEM_AUTORIZATION_DIRECTEUR_REGIONAL |
EMAIL |
Exemples de règles ACL pour une table accessible à multi-profils
Prenons l’exemple de la table de données opérationnelle DATA_VENTES ci-dessous, pour laquelle on souhaite que
- les responsables d’agence ne voient que les lignes de leurs agences
- les directeurs de région ne voient que les lignes des agences qui appartiennent à leur région.
| ID_VENTE | CODE_AGENCE | DATE_VENTE | PRODUIT | MONTANT_HT |
|---|---|---|---|---|
V001 |
codeAgence1 |
2026-06-01 | Licence Logiciel Pro | 1200.00 |
V002 |
codeAgence2 |
2026-06-02 | Maintenance Annuelle | 450.00 |
V003 |
codeAgence3 |
2026-06-03 | Pack Formation | 2500.00 |
V004 |
codeAgence4 |
2026-06-04 | Licence Logiciel Pro | 1200.00 |
V005 |
codeAgence5 |
2026-06-05 | Support Avancé | 800.00 |
Pour filtrer l’affichage des ventes, selon la politique d’habilitation décrit plus haut, voila les règles ACL à créer.
| Règle | Droits | Explication |
|---|---|---|
user.Access in [OWNER] |
RUCD |
Accès en administration total pour les propriétaires du document. |
user.Team_RESPONSABLE_AGENCE.PROFIL == 'RESPONSABLE_AGENCE' and rec.CODE_AGENCE in user.Team_RESPONSABLE_AGENCE.PERIMETRE_AGENCES |
Rxxx |
Lecture seule des ventes rattachées aux agences du responsable local. |
user.Team_DIRECTEUR_REGION.PROFIL == 'DIRECTEUR_REGION' and rec.CODE_AGENCE in user.Team_DIRECTEUR_REGION.PERIMETRE_AGENCES |
Rxxx |
Lecture seule des ventes de toutes les agences rattachées aux régions du responsable régional. |
Tous les autres |
xxxx |
Bloque l’accès dans tous les autres cas (stratégie deny by default) |
Remarques
- La stratégie deny by default fonctionne par liste blanche (whitelisting). L’accès est strictement interdit par défaut, et seules les exceptions explicitement listées viennent l’autoriser.
- Pour que l’opérateur
inutile dans le cas d’affectation multiple (ex:codeAgence1, codeAgence2), la colonnePERIMETRE_AGENCESutilisés dans les tables utilisateurs doivent être stockée sous forme de chaîne de caractères (i.e. pour des developpeurs Java c’ets comme unToStringd’une collection d’item = une serialisation string = transformation en chaîne de caractères).
Exemples de règles ACL pour une table accessible à un seul profil
Si vous disposez d’une autre table contenant des indicateurs consolidés à l’échelle de la région , par exemple une table DATA_RENTABILITE_REGIONS avec une colonne CODE_REGION, il suffit d’appliquer ces règles ACL.
| Règle | Droits | Explication |
|---|---|---|
user.Access in [OWNER] |
RUCD |
Accès administrateur total au propriétaire du document. |
user.Team_DIRECTEUR_REGION.PROFIL == 'DIRECTEUR_REGION' and rec.CODE_REGION in user.Team_DIRECTEUR_REGION.PERIMETRE_REGIONS |
Rxxx |
Lecture seule restreinte aux lignes de la table macro correspondant aux régions affectées au responsable. |
Tous les autres |
xxxx |
Bloque l’accès dans tous les autres cas (stratégie deny by default) |
Remarque
Attention, on pourrait penser que le test boolean par profil dans l’ACL (
user.Team_DIRECTEUR_REGION.PROFIL == 'DIRECTEUR_REGION') n’est pas nécessaire et que seule la condition sur les données (rec.CODE_REGION in user.Team_DIRECTEUR_REGION.PERIMETRE_REGIONS) suffit. C’est une erreur !Si vous supprimez ce test boolean de profil, les utilisateurs n’ayant pas ce rôle verront tout de même la table s’afficher dans leur menu latéral gauche sous Grist. Même si la table apparaîtra vide à l’intérieur, cela nuit à la clarté de l’interface. Il est préférable que le responsable d’agence n’ai pas connaissance de la table DATA_RENTABILITE_REGIONS. L’ajout du test strict sur le profil au début de la règle permet de masquer complètement l’accès à la table pour les profils non concernés.
Simplifier la gestion des périmètres
Pour s’affranchir d’une saisie manuelle des codes des agences dans la table des responsables régionaux, il est possible d’automatiser la jointure à partir d’une table de référence REGIONS_AGENCES qui structure ce rattachement hiérarchique. Evidement, vous pouvez ajouter deux autres tables AGENCES et REGIONS pour décrire avec d’autres colonnes ces entités… mais ce n’est pas le propos ici des jointures de références multiples dans Grist.
Faisons plus simple avec cette table qui modélise l’affectation des agences dans chaque région.
| CODE_REGION | CODE_AGENCE |
|---|---|
codeRegion1 |
codeAgence1 |
codeRegion1 |
codeAgence2 |
codeRegion1 |
codeAgence3 |
codeRegion2 |
codeAgence4 |
codeRegion2 |
codeAgence5 |
On modifie alors dans la table SYSTEM_AUTORIZATION_DIRECTEUR_REGIONAL de la manière suivante
-
Ajout de la colonne
REGIONS_AFFECTEESde type référence multiple pointant vers la table de correspondance des régionsREGIONS_AGENCES. -
Ajout de la colonne
AGENCES_AFFECTEES, qui va servir à agréger les agences de chaque région présente dans la colonneREGIONS_AFFECTEES. Pour ce faire, on utilise la fonctionlookupRecordsen python pour rechercher les agences.resultats = [] for region in $REGIONS_AFFECTEES: agences = REGIONS_AGENCES.lookupRecords(CODE_REGION=region.CODE_REGION) resultats.extend(agences) return resultats`Ainsi, chaque fois qu’on ajoute une région dans la colonne REGIONS_AFFECTEES, le système calcul et met à jour automatiquement le contenu de la colonne AGENCES_AFFECTEES !
-
En guise de contrôle, on peut ajouter une formule pour compter le nombre d’agences affectés à un directeur régional avec la formule suivante.
return len($AGENCES_AFFECTEES ) if $AGENCES_AFFECTEES else 0 -
Comme dit précédemment, pour pouvoir utiliser ces périmètres dans la définition des règles ACL avec l’opérateur
inil est nécessaire de transformer ces collections en chaîne de caractère. Cela se fait simplement dans une formule Python avec la fonctionrepr(*array*). Pour cela, on modifie la colonnePERIMETRE_REGIONSavec la formule suivante :codesToString = [region.CODE_REGION for region in $REGIONS_AFFECTEES] if $REGIONS_AFFECTEES else [] return repr(codesToString) -
On fait de même pour les codes dans la colonne
PERIMETRE_AGENCEScodesToString = [agence.CODE_AGENCE for agence in $AGENCES_AFFECTEES] if $AGENCES_AFFECTEES else [] return repr(codesToString)
Le poids des mots, le choc des photos.
Ca sera peut être plus parlant avec une capture d’écran, avec 4 profils utilisateurs.
Dans cet exemple, on a 4 profils utilisateurs : directeur d’école, ERUN, IEN de circonscription du premier degré et équipe en DSDEN.
La table DEC est :
- Accessible avec tous les droits pour les propriétaires de l’espace.
- Accessible en lecture seule (Rxxx) aux utilisateurs avec le profil « DEC », et ces derniers ne peuvent voir que les lignes qui correspondent à leur écoles (
rec.UAI in ...). La table DEC a donc une colonneUAIqui contient le code de l’école. - Accessible en lecture seule aux utilisateurs avec le profil « ERUN ». Le perimètre des ERUN est différent. Il est calculé par l’affectation de l’ERUN à une ou plusieurs circonscriptions duquel on en déduit le périmètre des écoles rattachés aux circos (de la même manière que le directeur de région dans l’exemple de ce guide).
Enjoy ^^..