Pundit, CanCan...

Nebojša Stričević

Strika

http://strika.info

http://servisne.info

http://tribelib.com

5 godina Ruby

Nebojša Stričević odgovoriće na pitanja: Kako se definiše Pundit policy? A kako CanCanCan ability? Šta su prednosti jednog, a šta drugog? Šta treba “trpati” u sloj za autorizaciju, a šta ne?

Da li korisnik može da uradi nešto sa resursom?

  • Da li korisnik može da obriše post?
  • Da li korisnik može da objavi post?
  • Da li korisnik može da izmeni komentar?

Zadatak 1

Samo autor posta može da izmeni post

Pundit

class PostPolicy
  def initialize(user, post)
    @user = user
    @post = post
  end

  def update?
    @post.author?(@user)
  end
end

Pundit

<% if policy(@post).update? %>
  <%= link_to "Edit post", ... %>
<% end %>

Pundit

def update
  @post = Post.find(params[:id])
  authorize @post, :update?
  ...
end

CanCan

class Ability
  include CanCan::Ability

  def initialize(user)
    can :update, Post do |post|
      post.author?(user)
    end
  end
end

CanCan

<% if can? :update, @post %>
  <%= link_to "Edit", ... %>
<% end %>

CanCan

def update
  @post = Post.find(params[:id])
  authorize! :update, @post
  ...
end

Zadatak 2

I admin može da izmeni post

Pundit

class PostPolicy
  ...

  def update?
    @post.author?(@user) || @user.admin?
  end
end

CanCan

class Ability
  include CanCan::Ability

  def initialize(user)
    can :update, Post do |post|
      post.author?(user)
    end

    if user.admin?
     can :manage, :all
    end
  end
end

Zadatak 3

Objavljen post se ne može izmeniti

View

<% if @post.author?(current_user) && !@post.published? %>
  <%= link_to "Edit Post", ... %>
<% end %>

Controller

def update
  @post = Post.find(params[:id])

  if !@post.author? || !@post.published?
    raise "Can't do that!"
  end

  ...

end

Pundit

class PostPolicy
  ...

  def update?
    !@post.published? && (@post.author?(@user) || @user.admin?)
  end
end

CanCan

class Ability
  include CanCan::Ability

  def initialize(user)
    can :update, Post do |post|
      !post.published? && post.author?(user)
    end

    if user.admin?
     can :manage, :all
    end
  end
end

Ability test

ability = Ability.new(root)
ability.can?(:update, post)

Korisnik koji sme sve.

Authorization or domain logic

!@post.published? && (@post.author?(@user) || @user.admin?)

Strika neće odgovoriti na pitanja...

  1. Sanity check - da li ovo što pričam ima smisla?
  2. Da li postoji (jasna) granica između autorizacije i domenskog koda?
  3. Da li je OK staviti "!post.published?" u Pundit policy?
  4. Kako da organizujemo isti kod kada koristimo CanCan?

Hvala!

Pundit, CanCan

By strika

Pundit, CanCan

  • 1,083