+1

Dynamic role dùng cancancan

Chắc bạn đã từng biết hoặc đã từng sử dụng cancancan trong Rails để quản lý role của user. Mình sẽ chỉ cho bạn cách dùng cancancan để tạo role dynamic.

  • Trước hết để tạo được dynamic role dùng cancancan cần phải dùng gem
gem 'cancancan'

và sau đó chạy câu lệnh dưới để tạo model ability dùng để quản lý role

rails g cancan:ability

Bạn có thể dọc thêm tài liệu cách dùng gem cancancan tạo đây

Giả sử model một user có một role và một role có nhiều user. Trong role có quyền cho phép hoặc ko cho phép các thao tác :read, :create, :update, :destroy

Mình sẽ cần chuẩn bị code như sau:

  • User model : user thuộc một role
class User < ActiveRecord::Base
  belongs_to :role
end
  • Role model : một role gồm có nhiều user và các giá trị phần quyền sẽ được lưu dưới dạng Hash
class Role < ActiveRecord::Base
   has_many :users
   serialize :permissions, Hash
end
  • Giả sử giao diện quản lý role của bạn như ảnh dưới thì bạn có thể thao tác chỉnh sử role tùy ý.
<div class="col-md-6">
  <%= form_for [:admin, @role] do |f| %>
    <p>
      <%= f.label :name %>
      <%= f.text_field :name, class: "form-control" %>
    </p>

    <div class="row" style="justify-content: space-between; font-weight: bold;">
      <div>Function</div>
      <div>Read</div>
      <div>Create</div>
      <div>Update</div>
      <div>Destroy</div>
    </div>
    <div class="row" style="justify-content: space-between;">
      <div>Function 1</div>
      <div><%= check_box_tag "role[permissions][function1][read]" %></div>
      <div><%= check_box_tag "role[permissions][function1][create]" %></div>
      <div><%= check_box_tag "role[permissions][function1][update]]" %></div>
      <div><%= check_box_tag "role[permissions][function1][destroy]" %></div>
    </div>

    <div class="row" style="justify-content: space-between;">
      <div>Function 2</div>
      <div><%= check_box_tag "role[permissions][function2][read]" %></div>
      <div><%= check_box_tag "role[permissions][function2][create]" %></div>
      <div><%= check_box_tag "role[permissions][function2][update]" %></div>
      <div><%= check_box_tag "role[permissions][function2][destroy]" %></div>
    </div>

  <div class="row"><%= f.submit "Save", class: "btn btn-primary" %></div>
  <% end %>
</div>

  • Lúc save role vào db mình có thể thực hiện xử ly params để lưu vào dưới dạnh như
{'function1' => [:read, :create, :update], 'function2': [:read, :create, :update]}
  • Phân quyền trong model ability
class Ability
  include CanCan::Ability

  def initialize(user)
    if user.admin?
      can :manage, :all
    elsif
      user.role.permissions.each do |subject, action|
        can action,
          (klass = subject.to_s.classify.safe_constantize) ? klass : subject.to_sym
      end
    end
  end
end

Code trên sẽ tạo được role của user vd như:

can :read, Function1
can :create, Function1
can :update, Function1
can :destroy, Function1

...

  • Bước cuối cùng để dùng được dynamic role là trong những controller mình cần sét role phải authorize_resource của user.

Đến đây là mình có thể tạo được dynamic role dùng gem cancancan. Nó cũng không có gì quá là khó khăn. Mong giải pháp trên có thể giải quyết được vấn đề của bạn.

Tài liệu tham khảo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí