Ruby on Rails
Autorisatie met CanCan
Zoeken…
Invoering
CanCan is een eenvoudige autorisatiestrategie voor Rails die is losgekoppeld van gebruikersrollen. Alle machtigingen worden op één locatie opgeslagen.
Opmerkingen
Vergeet voor het gebruik van CanCan niet om Gebruikers aan te maken, hetzij door een juweel te bedenken of handmatig. Maak een Admin-gebruiker aan voor maximale functionaliteit van CanCan.
Aan de slag met CanCan
CanCan is een populaire autorisatiebibliotheek voor Ruby on Rails die de gebruikerstoegang tot specifieke bronnen beperkt. Het nieuwste juweeltje (CanCanCan) is een voortzetting van het dode project CanCan .
Machtigingen worden gedefinieerd in de klasse Ability
en kunnen worden gebruikt vanuit controllers, views, helpers of elke andere plaats in de code.
Om autorisatie-ondersteuning aan een app toe te voegen, voegt u de CanCanCan-edelsteen toe aan de Gemfile
:
gem 'cancancan'
Definieer vervolgens de vaardigheidsklasse:
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
end
end
Controleer vervolgens de autorisatie met load_and_authorize_resource
om geautoriseerde modellen in de controller te laden:
class ArticlesController < ApplicationController
load_and_authorize_resource
def show
# @article is already loaded and authorized
end
end
authorize!
om autorisatie te controleren of een uitzondering te maken
def show
@article = Article.find(params[:id])
authorize! :read, @article
end
can?
om te controleren of een object is geautoriseerd tegen een bepaalde actie ergens in de controllers, views of helpers
<% if can? :update, @article %>
<%= link_to "Edit", edit_article_path(@article) %>
<% end %>
Opmerking: hierbij wordt ervan uitgegaan dat de ondertekende gebruiker wordt geleverd door de methode current_user
.
Vaardigheden definiëren
Vaardigheden worden in de klasse Ability
gedefinieerd met behulp van can
en cannot
methoden. Overweeg het volgende voorbeeld met commentaar voor basisreferentie:
class Ability
include CanCan::Ability
def initialize(user)
# for any visitor or user
can :read, Article
if user
if user.admin?
# admins can do any action on any model or action
can :manage, :all
else
# regular users can read all content
can :read, :all
# and edit, update and destroy their own user only
can [:edit, :destroy], User, id: user_id
# but cannot read hidden articles
cannot :read, Article, hidden: true
end
else
# only unlogged visitors can visit a sign_up page:
can :read, :sign_up
end
end
end
Omgaan met een groot aantal vaardigheden
Zodra het aantal definities van vaardigheden begint te groeien, wordt het steeds moeilijker om met het bestand Ability te werken.
De eerste strategie om deze kwestie aan te pakken, is om vaardigheden te verplaatsen naar zinvolle methoden, zoals in dit voorbeeld:
class Ability
include CanCan::Ability
def initialize(user)
anyone_abilities
if user
if user.admin?
admin_abilities
else
authenticated_abilities
end
else
guest_abilities
end
end
private
def anyone_abilities
# define abilities for everyone, both logged users and visitors
end
def guest_abilities
# define abilities for visitors only
end
def authenticated_abilities
# define abilities for logged users only
end
def admin_abilities
# define abilities for admins only
end
end
Zodra deze klasse groot genoeg is geworden, kun je proberen deze in verschillende klassen op te splitsen om de verschillende verantwoordelijkheden als volgt te verwerken:
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
self.merge Abilities::Everyone.new(user)
if user
if user.admin?
self.merge Abilities::Admin.new(user)
else
self.merge Abilities::Authenticated.new(user)
end
else
self.merge Abilities::Guest.new(user)
end
end
end
en definieer die klassen dan als:
# app/models/abilities/guest.rb
module Abilities
class Guest
include CanCan::Ability
def initialize(user)
# Abilities for anonymous visitors only
end
end
end
en ga zo maar door met Abilities::Authenticated
, Abilities::Admin
of een ander.
Test snel een vaardigheid
Als je snel wilt testen of een vaardigheidsklasse de juiste machtigingen geeft, kun je een vaardigheid in de console of in een andere context initialiseren terwijl de railsomgeving is geladen, geef je een gebruikersinstantie door om te testen tegen:
test_ability = Ability.new(User.first)
test_ability.can?(:show, Post) #=> true
other_ability = Ability.new(RestrictedUser.first)
other_ability.cannot?(:show, Post) #=> true
Meer informatie: https://github.com/ryanb/cancan/wiki/Testing-Abilities