Giới thiệu về gem Pundit
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 ...
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
https://github.com/elabs/pundit