Pundit for namespace
Có rất nhiều cách để sử dụng gem Pundit cho namespace, sau đây, mình sẽ giới thiệu 2 cách mình đã từng làm để check quyền cho user sử dụng gem Pundit. Cách 1: Sử dụng mặc định của Pundit gem Trong controller: users_controller.rb class Admin::UsersController < ApplicationController ...
Có rất nhiều cách để sử dụng gem Pundit cho namespace, sau đây, mình sẽ giới thiệu 2 cách mình đã từng làm để check quyền cho user sử dụng gem Pundit.
- Cách 1: Sử dụng mặc định của Pundit gem
Trong controller: users_controller.rb
class Admin::UsersController < ApplicationController def index authorize [:admin, :user] @user = User.new end def show authorize [:admin, @user] end end
Trong file policy, ta vẫn định nghĩa các quyền như bình thường
class Admin::UserPolicy < ApplicationPolicy def index? current_user.admin? end def show? @user == current_user end end
Cách này phù hợp khi bạn chỉ cần check các quyền cơ bản liên quan tới user mà thôi bởi ta không thể truyền được 1 đối tượng khác ngoài current_user và object cần truyền(trong trường hợp này là user). Điều này sẽ rất bất tiện trong trường hợp bạn muốn truyền những record khác sang cho policy.
- Cách 2: Custom hàm authorize của gem Ý tưởng: Hàm initialize của Pundit gem được def để nhận vào 2 biến là: current_user và record, chúng ta có thể coi record như một hash để định nghĩa các giá trị có thể truyền vào ở đó
Ta định nghĩa 1 hàm authorize_with_multiple với 2 biến truyền vào là 1 hash và class muốn gọi đến.
module Authorize def authorize_with_multiple args, policy pundit_policy = policy.new current_user, args query = "#{params[:action]}?" unless pundit_policy.public_send query error = Pundit::NotAuthorizedError.new "not allowed" raise error end end end
Khi đó, ta có thể thoải mái truyền vào tất cả các object, biến, ... cần check policy Ví dụ: Trong file users_controller.rb ta có
class Admin::UsersController < ApplicationController def index authorize_with_multiple params.merge(address: Address.first, user: @user), Admin::UserPolicy @user = User.new end def show authorize_with_multiple params.merge(address: Address.first), Admin::UserPolicy end end
Làm như vậy, có nghĩa là ta đã định nghĩa lại record được truyền sang policy của Admin::UserPolicy không chỉ có current_user, mà còn có address và user Ở Admin::UserPolicy, ta có thể gọi ra 1 cách dễ dàng giá trị truyền vào như cách gọi 1 hash record[:address] hay record[:user]. Cách này phù hợp khi bạn cần check policy trên nhiều biến, hay object. Mong rằng các bạn có thể chọn cho mình cách check policy phù hợp với nhu cầu của mình!