Rails Autorisation med Pundit

Pundit er en Ruby perle, der håndterer autorisation via en meget enkel API.

Husk, at godkendelse er forskellig fra godkendelse - godkendelse er at bekræfte, at du er den, du siger, du er, og autorisation er at bekræfte, at du har tilladelse til at udføre en handling.

Pundit er helt inden for autorisationslejren - brug et andet godkendelsessystem som Devise til at håndtere godkendelse.

Hvordan du arbejder med Pundit

Trin 1: Du opretter en Policyklasse, der beskæftiger sig med godkendelse af adgang til en bestemt type post - hvad enten det er en Blogeller Potatoeller User.

Trin 2: Du kalder den indbyggede authorizefunktion og videregiver det, du prøver at give adgang til.

Trin 3: Pundit finder den passende Policyklasse og kalder den Policymetode, der matcher navnet på den metode, du godkender. Hvis det returnerer sandt, har du tilladelse til at udføre handlingen. Hvis ikke, kaster det en undtagelse.

Det er ret ligetil. Logik for bestemte modeller er indkapslet i sin egen politiklasse, hvilket er fantastisk til at holde tingene ryddelige. Konkurrerende autorisationsbibliotek cancancan havde problemer med komplicerede tilladelser, der kom ud af hånden.

Mindre tweaks kræves

Pundits enkle konventioner skal undertiden finjusteres for at understøtte mere komplekse sager om godkendelsesbrug.

Få adgang til flere oplysninger inden for en politik

Som standard leverer Pundit to objekter til din autorisationskontekst: den Userog den der Recorder autoriseret. Dette er tilstrækkeligt, hvis du har roller i hele systemet i dit system som Admineller Moderator, men ikke er nok, når du har brug for autorisation til en mere specifik kontekst.

Lad os sige, at du havde et system, der understøttede begrebet en Organization, og at du var nødt til at støtte forskellige roller inden for disse organisationer. Autorisation, der dækker hele systemet, klipper ikke det - du vil ikke have, at en administrator af Organization Potato skal kunne gøre ting til Organization Orange, medmindre de er administrator for begge organisationer. Når du godkender denne sag, skal du have adgang til 3 emner: informationen om User, Recordbrugerens rolle i Organization. Det ideelle tilfælde ville være at have adgang til den organisation, posten tilhører, men lad os gøre det sværere og sige, at vi ikke har adgang til det via posten eller brugeren.

Pundit giver mulighed for at give yderligere sammenhæng. Ved at definere en kaldet funktion pundit_usergiver dette dig mulighed for at ændre, hvad der betragtes som en user. Hvis du returnerer et objekt med autorisationskonteksten fra denne funktion, vil denne kontekst være tilgængelig for dine politikker.

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

Dine politikker vil nu have adgang til alle tre slags oplysninger - du skal kunne se, hvordan du vil få adgang til flere oplysninger, hvis du har brug for det.

Tilsidesæt konvention og angiv, hvilken politik der skal bruges

Pundit bruger navngivningskonventioner til at matche det, du prøver at godkende, med den rigtige politik. Det meste af tiden fungerer dette godt, men i visse tilfælde skal du muligvis tilsidesætte denne konvention, f.eks. Når du vil godkende en generel dashboardhandling, der ikke har en tilknyttet model. Du kan indsende symboler for at specificere, hvilken handling eller politik, der skal bruges til godkendelse:

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

Hvis du har en model, der er navngivet forskelligt, kan du også tilsidesætte policy_classfunktionen i selve modellen:

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

Testning

Autorisation er en af ​​de ting, jeg stærkt anbefaler at have en automatiseret testpakke rundt. At konfigurere dem forkert kan være katastrofalt, og det er efter min mening en af ​​de mest kedelige ting at teste manuelt. At være i stand til at køre en enkelt kommando og vide, at du ikke utilsigtet har ændret autoriseringsforretningsregler, er en fantastisk følelse.

Pundit gør testtilladelse meget enkel.

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

Samlet set kan jeg godt lide Pundit. Jeg har kun brugt det i et kort stykke tid, men jeg foretrækker det allerede frem for cancancan - det føles bare mere vedligeholdeligt og testbart.

Fandt du denne historie hjælpsom? Venligst klapp for at vise din støtte!

Hvis du ikke fandt det nyttigt, så lad mig vide hvorfor med en kommentar !