Der richtige Ort, um eine Berechtigungsprädikat vorzuschlagen?

Um eine Lösung für Restrict exposure of full name to certain groups vorzuschlagen, möchte ich ein (serverseitiges) Berechtigungsprädikat definieren, das die Frage beantwortet:

Basierend auf dem aktuellen Benutzerumfang/Kontext, ist es in Ordnung, die vollständigen Namen anderer Benutzer preiszugeben?

(Der Umfang könnte durch eine Client-Anfrage oder durch einen internen Verarbeitungsschritt, wie z. B. die Generierung von Digest-E-Mails, festgelegt werden.)

Was ist die richtige Konstruktion für ein solches Prädikat? Wo im Code sollte es leben? Ich denke, dass dies vielleicht in einen Guardian gehört – bin ich auf dem richtigen Weg? Irgendwelche Meinungen dazu?

Ich stelle mir vor, dass dieses neue Prädikat viele (aber nicht alle) Instanzen von SiteSettings.enable_names? im Code ersetzen würde. (Das Treffen der Serializer, die user.name liefern, schließt die meisten Datenlecks, aber nicht alle.) Ein schöner Vorteil davon ist, dass es eine Erweiterungsmöglichkeit einführen würde, mit der ein zukünftiges Plugin das Verhalten ändern könnte (derzeit nicht möglich, soweit ich weiß, oder ich würde es einfach tun!). Wenn ich das also zum Laufen bringe, wäre dies ein Pull-Request zum Discourse-Kern – und ich möchte einen PR einreichen, der eine Chance hat, akzeptiert zu werden.

1 „Gefällt mir“

Hier ist, was ich gelernt/abgeleitet habe:

  • Guardian ist tatsächlich das, was „Was darf der Benutzer tun?“ kapselt (eine Guardian-Instanz hat auch eine User-Instanz).
  • Somit ist der richtige Ort für ein Berechtigungsprädikat einfach als Methode auf Guardian (lib/guardian.rb).
  • Wenn die Methode lautet „Kann der Benutzer Z mit einem Xxxx-Objekt tun?“, dann gehört sie wahrscheinlich in eine der XxxxGuardian-Mixin-Dateien (lib/guardian/...).
  • Andernfalls gehört sie in die Basisdefinition von Guardian.
  • ApplicationController verwaltet ein guardian-Attribut, das die aktuelle Anfrage/den aktuellen Client widerspiegelt, und stellt es Serializern als deren scope zur Verfügung, sodass der aktuelle Guardian bei Bedarf verfügbar ist (außer wenn er es nicht ist[1])
  • Es gibt Stellen, an denen kein fertiger Guardian verfügbar ist, typischerweise in einer Backend-Aufgabe, die vom System ausgeführt wird, aber wenn Sie einen „handelnden Benutzer“ haben (z. B. den Empfängerbenutzer bei der Erstellung einer E-Mail-Benachrichtigung), können Sie einen geeigneten Guardian im Handumdrehen erstellen: Guardian.new(the_user).

  1. ↩︎