Permissions limitées
Un rôle dit à GCM ce que l'utilisateur est autorisé à faire. Un périmètre lui dit où il est autorisé à le faire. Sans périmètre, un Leader peut voir chaque membre de votre espace de travail ; avec un périmètre fixé à Branche Est → Centre Anderson, ce même Leader ne voit que les membres attribués au Centre Anderson et à toutes les cellules en dessous. Les verbes du rôle restent inchangés — ils couvrent toujours voir, créer, modifier, marquer et envoyer — mais les lignes auxquelles ils s'appliquent se réduisent à la portion de l'arbre organisationnel à laquelle l'utilisateur a été attribué.
C'est ainsi que la plupart des églises construisent les shepherds, pasteurs de campus, responsables de zone, et tout autre rôle qui doit gérer une partie de l'organisation sans voir l'ensemble.

Attribuer une unité à un utilisateur
Ouvrez la ligne de l'utilisateur dans Utilisateurs et Rôles, cliquez sur le bouton Unités, et choisissez une ou plusieurs unités organisationnelles dans le sélecteur. L'enregistrement écrit dans user_unit_assignments_v2 avec l'id de l'utilisateur, l'id de l'unité organisationnelle et l'id de l'organisation. Contrairement aux attributions de rôle — qui sont typiquement un seul chip par utilisateur — un utilisateur peut être attribué à plusieurs unités (un superviseur régional peut couvrir trois branches), et les périmètres s'unissent.
Laissez le sélecteur vide pour un accès à l'échelle de toute l'organisation. Une attribution vide signifie aucun filtre de périmètre ne s'applique ; l'utilisateur voit tout ce que le rôle permet. C'est la bonne valeur par défaut pour les org admins, les pasteurs principaux et l'administrateur exécutif.
TIP
Le bouton Unités n'apparaît que sur les utilisateurs dont les rôles incluent des ressources limitables par unité. Un Viewer avec seulement dashboard.view n'a pas de bouton Unités — il n'y a rien que le périmètre puisse filtrer.
Comment le filtre est calculé
Quand un utilisateur limité se connecte, GCM calcule l'ensemble des IDs d'unités organisationnelles qu'il peut voir. Le travail est fait par user_visible_unit_ids(org_id), une fonction PL/pgSQL SECURITY DEFINER dans la base de données :
- Elle cherche chaque ligne de
user_unit_assignments_v2pour cet utilisateur dans cette organisation. - Pour chaque unité attribuée, elle parcourt l'arbre vers le bas via une CTE récursive sur
org_units.parent_unit_id, en collectant chaque descendant. - L'union est renvoyée comme un
uuid[]— l'ensemble visible complet de l'utilisateur.
Un shepherd attribué au Centre Anderson (un enfant de Branche Est) voit :
- Centre Anderson lui-même.
- Chaque cellule sous Centre Anderson (par exemple Cellule Est Anderson, Cellule Ouest Anderson).
- Les nouvelles cellules ajoutées sous Centre Anderson ultérieurement — automatiquement, car la récursion s'exécute au moment de la requête.
Il ne voit pas :
- Branche Est elle-même (le parent).
- Centre Wilson ou tout autre frère sous Branche Est.
- Quoi que ce soit sous Branche Ouest.
Un platform admin obtient NULL de cette fonction, que RLS traite comme aucun filtre — il voit tout à travers chaque tenant.
Où le filtre s'exécute
Le périmètre est appliqué au niveau de la base de données par des politiques RLS restrictives. Chaque table limitable (members, attendances, member_unit_assignments, et d'autres) porte une politique unit_scope_read qui dit : la ligne doit appartenir à l'org actuelle, ET son org_unit_id doit être dans l'ensemble visible de l'utilisateur, OU l'ensemble visible doit être NULL.
Parce que la politique est restrictive, elle s'intersecte avec la vérification de permission. Un Leader avec members.view et un périmètre de Centre Anderson ne voit que les membres du Centre Anderson — les deux conditions doivent passer. La permission seule ne montrera pas de lignes supplémentaires ; le périmètre seul ne lui permettra pas de voir si le rôle n'a pas members.view.
La même politique restrictive s'applique aux écritures. Un Leader limité ne peut pas modifier un membre en dehors de son unité, même si l'id de ligne est forgé dans la requête. La clause WITH CHECK réexécute le filtre de visibilité pour INSERT et UPDATE.
Performance : le wrapper en cache
Appeler user_visible_unit_ids() par ligne serait lent — la CTE récursive se réétendrait pour chaque membre scanné. Postgres ne peut pas toujours la hisser car passer une référence de colonne défait la vérification d'invariance du planificateur.
Pour corriger cela, GCM utilise un wrapper sans paramètres, current_user_visible_unit_ids(), qui met en cache le résultat dans un GUC à portée de transaction (app.uv_units). Le premier appel étend l'arbre ; chaque appel suivant dans la même requête HTTP lit la chaîne uuid[] en cache et renvoie instantanément. Cela a fait passer les requêtes de liste de membres de 4,8 secondes à moins de 200 ms sur un espace de travail de 1 400 membres.
Vous n'avez pas à y penser — chaque politique RLS utilise le wrapper, et chaque chargement de page obtient la valeur en cache gratuitement.
Limiter en écriture vs. en lecture
Le périmètre s'applique à chaque verbe que le rôle accorde sur une ressource limitable. Un Leader avec un périmètre de Centre Anderson :
- Ne voit que les membres et présences du Centre Anderson.
- Ne peut modifier que les membres du Centre Anderson.
- Ne peut marquer la présence que pour les événements du Centre Anderson.
- Ne peut enregistrer des dons que pour les membres du Centre Anderson (le membre du don est vérifié contre son ensemble visible).
Il n'y a aucun moyen d'accorder lecture sur toute l'org et écriture sur une portion — le périmètre est uniforme à travers les verbes du rôle. Si vous avez besoin de ce découpage, créez deux rôles (un en lecture seule, à l'échelle de toute l'organisation ; un en lecture-écriture, limité) et attribuez les deux à l'utilisateur.
Ce qui n'est pas limitable
Certaines ressources sont intrinsèquement à l'échelle de toute l'organisation et ignorent le filtre d'unité :
- Facturation — il n'existe pas de facture limitée par unité ; un espace de travail a un seul abonnement.
- Paramètres, channels, modules — ce sont des configurations à l'échelle de l'espace de travail.
- Le catalogue de rôles lui-même — les rôles sont à l'échelle de l'espace de travail.
- Fonds — un fonds de dons s'applique à toute l'org, pas à une seule unité.
Si une permission contrôle l'une de ces ressources (billing.manage, config.manage, users.manage, giving.manage), le périmètre est ignoré lors de la vérification. Un Leader limité au Centre Anderson qui détiendrait aussi billing.manage verrait toute la page de facturation — mais vous ne devriez pas accorder ces clés à un utilisateur limité en premier lieu.
Retirer un périmètre
Ouvrez la boîte de dialogue Unités et videz le sélecteur. Les lignes dans user_unit_assignments_v2 sont supprimées ; l'utilisateur revient à l'accès à l'échelle de toute l'organisation (sous réserve de ce que son rôle permet encore). Le changement prend effet à son prochain chargement de page.
Suspendre un utilisateur ne vide pas ses attributions d'unité — quand vous le réactivez, il reprend exactement là où il s'est arrêté.
Pour aller plus loin
- Rôles par défaut — ce qu'incluent les rôles initialisés avant de les limiter.
- Accorder des permissions — associer le périmètre aux bons verbes.
- Journal d'audit — voir qui a limité qui.
- Structure organisationnelle — comment l'arbre est construit en premier lieu.
