Schienenautorisierung mit Pundit

Pundit ist ein Ruby-Juwel, das die Autorisierung über eine sehr einfache API verwaltet.

Denken Sie daran, dass sich die Autorisierung von der Authentifizierung unterscheidet. Durch die Authentifizierung wird überprüft, ob Sie der sind, für den Sie sich ausgeben, und durch die Autorisierung wird überprüft, ob Sie über die Berechtigung zum Ausführen einer Aktion verfügen.

Pundit befindet sich direkt im Autorisierungslager. Verwenden Sie ein anderes Authentifizierungssystem wie Devise, um die Authentifizierung durchzuführen.

Wie Sie mit Pundit arbeiten

Schritt 1: Sie erstellen eine PolicyKlasse, die sich mit der Autorisierung des Zugriffs auf einen bestimmten Datensatztyp befasst - sei es ein Blogoder Potatooder User.

Schritt 2: Sie rufen die integrierte authorizeFunktion auf und übergeben das, worauf Sie den Zugriff autorisieren möchten.

Schritt 3: Pundit findet die entsprechende PolicyKlasse und ruft die PolicyMethode auf, die dem Namen der von Ihnen autorisierten Methode entspricht. Wenn true zurückgegeben wird, haben Sie die Berechtigung, die Aktion auszuführen. Wenn nicht, wird eine Ausnahme ausgelöst.

Es ist ziemlich einfach. Die Logik für bestimmte Modelle ist in einer eigenen Richtlinienklasse zusammengefasst, die sich hervorragend zum Aufräumen eignet. Die konkurrierende Berechtigungsbibliothek cancancan hatte Probleme mit komplizierten Berechtigungen, die außer Kontrolle gerieten.

Kleinere Änderungen erforderlich

Die einfachen Konventionen von Pundit müssen manchmal angepasst werden, um komplexere Anwendungsfälle für Autorisierungen zu unterstützen.

Greifen Sie innerhalb einer Richtlinie auf weitere Informationen zu

Standardmäßig stellt Pundit Ihrem Autorisierungskontext zwei Objekte zur Verfügung: das Userund das Recordzu autorisierende. Dies ist ausreichend, wenn Sie systemweite Rollen in Ihrem System haben, wie Adminoder Moderator, reicht jedoch nicht aus, wenn Sie eine Autorisierung für einen spezifischeren Kontext benötigen.

Angenommen, Sie hatten ein System, das das Konzept eines unterstützt Organization, und Sie mussten verschiedene Rollen innerhalb dieser Organisationen unterstützen. Die systemweite Autorisierung reicht nicht aus - Sie möchten nicht, dass ein Administrator von Organization Potato in der Lage ist, Organisation Orange etwas anzutun, es sei denn, er ist Administrator beider Organisationen. Wenn Sie diesen Fall autorisieren, benötigen Sie Zugriff auf drei Elemente: die User, die Recordund die Rolleninformationen des Benutzers in der Organization. Der Idealfall wäre, Zugriff auf die Organisation zu haben, zu der der Datensatz gehört. Machen wir es jedoch schwieriger und sagen, dass wir über den Datensatz oder den Benutzer keinen Zugriff darauf haben.

Pundit bietet die Möglichkeit, zusätzlichen Kontext bereitzustellen. Durch Definieren einer aufgerufenen Funktion pundit_userkönnen Sie ändern, was als a betrachtet wird user. Wenn Sie von dieser Funktion ein Objekt mit dem Berechtigungskontext zurückgeben, steht dieser Kontext Ihren Richtlinien zur Verfügung.

application_controller.rb

class ApplicationController < ActionController::Base include Pundit
 def pundit_user AuthorizationContext.new(current_user, current_organization) endend

authorization_context.rb

class AuthorizationContext attr_reader :user, :organization
 def initialize(user, organization) @user = user @organization = organization endend

application_policy.rb

class ApplicationPolicy attr_reader :request_organization, :user, :record
 def initialize(authorization_context, record) @user = authorization_context.user @organization = authorization_context.organization @record = record end
 def index? # Your policy has access to @user, @organization, and @record. endend

Ihre Richtlinien hätten jetzt Zugriff auf alle drei Arten von Informationen. Sie sollten sehen können, wie Sie bei Bedarf auf weitere Informationen zugreifen würden.

Überschreiben Sie die Konvention und geben Sie an, welche Richtlinie verwendet werden soll

Pundit verwendet Namenskonventionen, um das, was Sie autorisieren möchten, mit der richtigen Richtlinie abzugleichen. Meistens funktioniert dies gut, aber in bestimmten Fällen müssen Sie diese Konvention möglicherweise überschreiben, z. B. wenn Sie eine allgemeine Dashboard-Aktion autorisieren möchten, der kein Modell zugeordnet ist. Sie können Symbole übergeben, um anzugeben, welche Aktion oder Richtlinie für die Autorisierung verwendet werden soll:

#Below will call DashboardPolicy#bake_potato?authorize(:dashboard, :bake_potato?)

Wenn Sie ein Modell mit einem anderen Namen haben, können Sie die policy_classFunktion auch innerhalb des Modells selbst überschreiben :

class DashboardForAdmins def self.policy_class DashboardPolicy # This forces Pundit to use Dashboard Policy instead of looking # for DashboardForAdminsPolicy endend

Testen

Die Autorisierung ist eines der Dinge, die ich dringend empfehle, eine automatisierte Testsuite zu haben. Eine falsche Einrichtung kann katastrophal sein, und meiner Meinung nach ist es eines der mühsamsten Dinge, sie manuell zu testen. Es ist ein großartiges Gefühl, einen einzelnen Befehl ausführen zu können und zu wissen, dass Sie versehentlich keine Geschäftsregeln für die Autorisierung geändert haben.

Pundit macht die Testberechtigung sehr einfach.

def test_user_cant_destroy? assert_raises Pundit::NotAuthorizedError do authorize @record, :destroy? endend
def test_user_can_show? authorize @record, :show?end

Insgesamt mag ich Pundit. Ich habe es nur für eine kurze Zeit benutzt, aber ich bevorzuge es bereits gegenüber Cancancan - es fühlt sich einfach wartbarer und testbarer an.

Fanden Sie diese Geschichte hilfreich? Bitte klatschen Sie , um Ihre Unterstützung zu zeigen!

Wenn Sie es nicht hilfreich fanden, lassen Sie mich bitte mit einem Kommentar wissen, warum !