Skip to content

Permissions limitées

Un rôle dit à GCM ce que l'utilisateur est autorisé à faire. Un périmètre lui dit 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.

Boîte de dialogue d'attribution d'unité utilisateur

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 :

  1. Elle cherche chaque ligne de user_unit_assignments_v2 pour cet utilisateur dans cette organisation.
  2. 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.
  3. 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