Giới thiệu về gem Pundit
Bài đăng này đã không được cập nhật trong 9 năm
Nếu bạn xây dựng một ứng dụng với nhiều loại user và điều bạn lo lắng nhất chính là phân quyền cho các user của bạn. Hiện tại có rất nhiều giải pháp cho vấn đề trên và một trong số đó là sử dụng gem pundit
Gem pundit là một thư viện giúp xây dựng một hệ thống hạn chế tài nguyên của một user được phép sử dụng.
Cài đặt
 gem "pundit"
Sau khi bundle, chạy dòng lệnh sau để sinh ra policy
rails g pundit:install
Để bắt đầu sử dụng gem Pundit, bạn cần include Pundit vào application_controller.rb như sau
class ApplicationController < ActionController::Base
  include Pundit
  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
  protect_from_forgery with: :exception
  private
  def user_not_authorized
    flash[:error] = t "notification.not_admin"
    redirect_to request.referrer || new_user_session_path
  end
Sử dụng Pundit gem
Bạn cần restart Rails server để Rails có thể tìm thấy đường dẫn mới app/policies/. Tại đây bạn sẽ tìm thấy file mặc định của Pundit là application_policy.rb như sau:
class ApplicationPolicy
  attr_reader :user, :model
  def initialize current_user, model
    raise Pundit::NotAuthorizedError,"login" unless user
    @ user = user
    @ model = model
  end
  def index
  end
  def show
    scope.where(id: model.id).exists?
  end
  .
  .
  .
  def scope
    Pundit.policy_scope! user, model.class
  end
  class Scope
    attr_reader :user, :scope
    def initialize cuser, scope
      @ user = user
      @ scope = scope
    end
    def resolve
      scope
    end
  end
end
Khi đó ta thấy:
- Tham số đầu tiên là một user. Trong controller, Pundit sẽ truyền vào current_user
- Tham số thứ 2 là một model cần được authorize. Ở đây ta có thể không nhất thiết phải là một object của ActiveRecord hay là một ActiveModel, nó chỉ cần là một thực thể mà thôi.
Policy của pundit có các hàm tương ứng với các hàm trong controller để kiểm tra policy cho các hàm đó.
Ví dụ: Trong user_controller.rb của bạn:
class UsersController < ApplicationController
  def show
  end
  def index
    @ users = User.all
  end
 end
Khi đó trong user_policy.rb sẽ có các hàm tương ứng như sau:
class UserPolicy < ApplicationPolicy
  class Scope
    attr_reader :user, :scope
  def initialize user, scope
    @ user = user
    @ scope = scope
  end
  def index?
    @ user.present?
  end
  def show?
    @ user.present?
  end
 end
Chú ý
Với các hàm create, new và index ta cần authorize class User (Chúng ta sẽ thảo luận về lí do sau đó )
Sử dụng gem Pundit trong view
Sau khi sử lí ở controller, ta cần kiểm tra cả ở view để ẩn hiện các link phù hợp với từng action.
Ví dụ views/posts/index.html.erb
<% if policy(user).edit? %>
  <td><%= link_to 'Edit', user, method: :put} %></td>
<% end %>
Kết luận
Trên đây mình đã giới thiệu với các bạn về gem Pundit, một sự lựa chọn đáng cân nhắc nếu bạn đang tìm kiếm giải pháp phân quyền cho ứng dụng Rails của mình. Còn nhiều vấn đề khác nhau cho gem này chúng ta sẽ thảo luận trong những bài tiếp theo. Cảm ơn đã tham khảo bài viết này
Nguồn tham khảo
All rights reserved
 
  
 