Lieu approprié pour proposer une prédicat de permissions ?

Dans l’intérêt de proposer une solution pour Restrict exposure of full name to certain groups, j’aimerais définir un prédicat de permissions (côté serveur) qui répond à la question :

En fonction de la portée/contexte de l’utilisateur actuel, est-il acceptable de révéler le nom complet des (autres) utilisateurs ?

(La portée pourrait être définie par une requête client, ou par une étape de traitement interne, comme la génération de messages électroniques de résumé.)

Quelle est la bonne construction pour un tel prédicat ? Où dans la base de code devrait-il se trouver ? Je pense que cela pourrait appartenir à un gardien (guardian) — suis-je sur la bonne voie ? Des avis sur lequel ?

J’imagine que ce nouveau prédicat engloberait de nombreuses (mais pas toutes) instances de SiteSettings.enable_names? actuellement dans la base de code. (Atteindre les Serializers qui renvoient user.name colmate la plupart des fuites de données, mais pas toutes.) Un avantage agréable est que cela introduirait un point d’extension par lequel un futur plugin pourrait modifier le comportement (ce qui n’est pas possible actuellement, à ma connaissance, sinon je le ferais !). Donc, si j’arrive à faire fonctionner cela, cela deviendrait une pull-request au cœur de Discourse — et j’aimerais soumettre une PR qui a une chance d’être acceptée.

1 « J'aime »

Voici ce que j’ai appris/déduit :

  • Guardian est bien ce qui encapsule « Qu’est-ce que l’utilisateur est autorisé à faire ? » (Une instance de Guardian a aussi une instance de User.)
  • Ainsi, l’endroit approprié pour un prédicat de permission est simplement une méthode sur Guardian (lib/guardian.rb).
  • Si la méthode est du type « L’utilisateur peut-il faire Z à un objet Xxxx ? », alors elle appartient probablement à l’un des fichiers de mixin XxxxGuardian (lib/guardian/...).
  • Sinon, elle va dans la définition de base de Guardian.
  • ApplicationController gère un attribut guardian reflétant la requête/le client actuel, et le fournit aux sérialiseurs comme leur scope, de sorte que le Guardian actuel est disponible quand nécessaire (sauf quand il ne l’est pas[1])
  • Il existe des endroits où un Guardian prêt à l’emploi n’est pas disponible, généralement dans une tâche backend exécutée par le système, mais si vous avez une référence à un « utilisateur agissant » (par exemple, l’utilisateur destinataire, lors de la génération d’une notification par e-mail), vous pouvez créer un gardien approprié à la volée : Guardian.new(the_user).

  1. ↩︎