Giới thiệu về gem Pundit
Bài đăng này đã không được cập nhật trong 8 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