Rails Authorization with Pundit

Pundit er en Ruby-perle som håndterer autorisasjon via en veldig enkel API.

Husk at autorisasjon er forskjellig fra autentisering - autentisering er å bekrefte at du er den du sier du er, og autorisasjon er å bekrefte at du har tillatelse til å utføre en handling.

Pundit er rett innenfor autorisasjonsleiren - bruk et annet autentiseringssystem som Devise for å håndtere autentisering.

Hvordan du jobber med Pundit

Trinn 1: Du oppretter en Policyklasse som handler om å autorisere tilgang til en bestemt type post - enten det er en Blogeller Potatoeller User.

Trinn 2: Du kaller den innebygde authorizefunksjonen, og sender inn det du prøver å gi tilgang til.

Trinn 3: Pundit finner riktig Policyklasse og kaller Policymetoden som samsvarer med navnet på metoden du autoriserer. Hvis det blir sant, har du tillatelse til å utføre handlingen. Hvis ikke, vil det kaste et unntak.

Det er ganske greit. Logikk for bestemte modeller er innkapslet i sin egen policyklasse, noe som er flott for å holde ting ryddig. Konkurrerende autorisasjonsbibliotek cancancan hadde problemer med kompliserte tillatelser som gikk ut av hånden.

Mindre tilpasninger kreves

Noen ganger må Pundits enkle konvensjoner justeres for å støtte mer kompliserte saker om autorisasjonsbruk.

Få tilgang til mer informasjon fra en policy

Som standard gir Pundit to objekter til autorisasjonskonteksten din: den Userog den som Recorder autorisert. Dette er tilstrekkelig hvis du har systemomfattende roller i systemet ditt som Admineller Moderator, men er ikke nok når du trenger autorisering til en mer spesifikk kontekst.

La oss si at du hadde et system som støttet begrepet en Organization, og at du måtte støtte forskjellige roller i disse organisasjonene. Autorisering over hele systemet vil ikke kutte det - du vil ikke at en administrator av Organization Potato skal kunne gjøre ting mot Organization Orange med mindre de er administrator for begge organisasjonene. Når du godkjenner denne saken, trenger du tilgang til 3 elementer: informasjonen om User, Recordbrukerens rolle i Organization. Det ideelle tilfellet ville være å ha tilgang til organisasjonen posten tilhører, men la oss gjøre det vanskeligere og si at vi ikke har tilgang til det via posten eller brukeren.

Pundit gir en mulighet til å gi ytterligere sammenheng. Ved å definere en funksjon som kalles pundit_user, lar dette deg endre det som regnes som en user. Hvis du returnerer et objekt med autorisasjonskonteksten fra den funksjonen, vil denne konteksten være tilgjengelig for policyene dine.

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

Retningslinjene dine vil nå ha tilgang til alle tre typer informasjon - du bør kunne se hvordan du vil få tilgang til mer informasjon hvis du trenger det.

Overstyr konvensjonen og spesifiser hvilken policy som skal brukes

Pundit bruker navngivningskonvensjoner for å matche det du prøver å autorisere med riktig policy. Mesteparten av tiden fungerer dette bra, men i visse tilfeller må du kanskje overstyre denne konvensjonen, for eksempel når du vil godkjenne en generell dashbordhandling som ikke har en tilknyttet modell. Du kan legge inn symboler for å spesifisere hvilken handling eller policy som skal brukes for autorisasjon:

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

Hvis du har en modell som er navngitt annerledes, kan du også overstyre policy_classfunksjonen i selve modellen:

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

Testing

Autorisasjon er en av de tingene jeg sterkt anbefaler å ha en automatisert testpakke rundt. Å sette dem opp feil kan være katastrofalt, og det er etter min mening en av de mest kjedelige tingene å teste manuelt. Det å kunne kjøre en enkelt kommando og vite at du ikke utilsiktet har endret noen autoriseringsregler er en god følelse.

Pundit gjør testtillatelse veldig enkel.

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

Totalt sett liker jeg Pundit. Jeg har bare brukt det en kort stund, men jeg foretrekker det allerede fremfor cancancan - det føles bare mer vedlikeholdbart og testbart.

Fant du denne historien nyttig? Vennligst klapp for å vise din støtte!

Hvis du ikke syntes det var nyttig, kan du gi meg beskjed om det med en kommentar !