Contexte
Suite à mon fil précédent sur le déréférencement à travers une Référence, même document de formation, même schéma de tables :
- Clients (Adresse_mail, etc.)
- Commandes (Client → Référence vers Clients, renseignée après coup : une commande peut exister sans client assigné le temps qu’un commercial la traite)
Attribut utilisateur configuré (inchangé par rapport au fil précédent) :
- Nom :
Client - Propriété d’appairage :
user.Email - Table d’appairage :
Clients - Colonne cible :
Adresse_mail
Suivant la solution du fil précédent, la règle de ligne sur Commandes compare une colonne miroir aplatie à l’attribut utilisateur :
$Client_email == user.Client.Adresse_mail
Comportement attendu
Seul le client concerné par une commande (ou un utilisateur enregistré comme tel dans la table Clients) doit voir la ligne correspondante. Un utilisateur connecté qui n’est pas un client enregistré ne doit voir aucune commande.
Comportement observé (le piège)
Sur une commande dont le champ Client n’a pas encore été renseigné ($Client_email vaut donc None), n’importe quel utilisateur connecté qui n’est pas un client enregistré (donc pour qui user.Client.Adresse_mail vaut lui aussi None) voit malgré tout la ligne. La règle matche alors qu’elle ne devrait matcher pour personne.
Cause
None == None vaut True en Python. Les deux côtés de la comparaison peuvent être vides pour des raisons totalement indépendantes :
- côté
rec: la colonne miroir vautNonetant que la commande n’a pas de client assigné (situation normale et temporaire) ; - côté
user: le lookup de l’attribut utilisateur vautNonedès que l’utilisateur connecté n’a pas de correspondance dans la table Clients (situation normale pour n’importe quel utilisateur qui n’est pas censé avoir ce rôle, un autre commercial par exemple).
Ces deux None sans rapport l’un avec l’autre suffisent à rendre la comparaison vraie.
Solution
Garder systématiquement la comparaison contre le cas où l’un des deux côtés est vide, avant de comparer :
$Client_email and user.Client.Adresse_mail and $Client_email == user.Client.Adresse_mail
Méthode de test qui a permis de le découvrir
Le test « Voir en tant que » sur le cas nominal (le bon client, une commande bien assignée) ne suffit pas à détecter ce piège : il faut spécifiquement tester le cas négatif (un utilisateur qui ne devrait avoir accès à rien, sur une ligne où le champ de rattachement est encore vide) pour le voir apparaître.
Question
Comme pour mon fil précédent : comportement déjà documenté ailleurs (une référence serait bienvenue), ou suffisamment silencieux pour mériter un avertissement dans la documentation officielle des règles d’accès ? La combinaison « champ de Référence pas encore renseigné + comparaison naïve avec un attribut utilisateur » me semble un cas assez générique pour toucher beaucoup de documents Grist en production, au-delà de mon cas d’usage.