punditとは?
Railsにおける認可の仕組みです。
cancancanとの違い
cancancanはユーザに対して、どんなアクションが許可するかを定義する(コントローラ寄り)のに対して、Punditではリソースに対して誰が許可されるのかを定義する(モデル寄り)。
基本的な使い方
1.Punditをincludeする。
punditを使いたいコントローラでpubditをincludeします。基本的にはbaseコントローラみたいな物を作ってそこに宣言する形が多いでしょう。
1 2 3 |
class 使いたいコントローラー名 < ActionController::Base include Pundit end |
2.ApplicationPolicyを作成する。
下記コマンドを実行すれば、「app/policies/」配下に「application_policy.rb」が作成されます。
1 |
rails g pundit:install |
生成される内容は下記です。
1 2 3 4 5 6 7 8 9 10 11 12 |
class ApplicationPolicy attr_reader :user, :record def initialize(user, record) @user = user @record = record end def index? false end end |
このApplicationPolicyを継承して個々のPolicyを作成していきます。
initializeの@user
current_user(アクセスしているユーザー)が割り当てられます。逆に言えば、モデルにcurrent_userという変数にアクセスするユーザーが割り当てられていないとエラーになってしまうので、割り当てるようにしましょう。(基本的にはdeviseで使われているユーザー変数がデフォルトでcurrent_userになっているのでそれで自動対応になると思います。)
initializeの@record
対応するモデル(リソースオブジェクト)のインスタンスを割り当てます。
3.ポリシーファイル(コントローラ名Policy)を作成する。
app/policyフォルダの直下に「コントローラ名Policy.rb」というポリシーファイルを作成します。
アクション名 + ?
戻り値がtrueなら認可、戻り値がfalseなら拒否となります。拒否した場合は、「Pundit::NotAuthorizedError」という例外が投げられます。
例えば、「record.user_id == user.id」
4.コントローラで対象の権限があるかチェックする。
authorize モデル(リソースオブジェクト)
対象のリソースに対して権限があるかどうかチェックしてくれます。コントローラで使います。
Scope
ApplicationPolicyの中にデフォルトでScopeというクラスも含まれています。用途としては対象のモデルだけでなくモデルの中に含まれている属性まで加味して表示させるリソースを制御したい場合に使用します。(例えば、管理者権限を持っているユーザーに対しては管理者情報も表示させる等)
1 2 3 4 5 6 7 8 9 10 11 12 |
class Scope attr_reader :user, :scope def initialize(user, scope) @user = user @scope = scope end def resolve scope.all end end |
具体的にはresolveメソッドにてユーザーの属性による分岐をさせます。(scopeというのが全体の情報です。)
1 2 3 4 5 6 7 |
def resolve if 管理者 scope.all else scope.all.find(1) end end |
コントローラー側からpolicy_scopeメソッドを使って呼び出します。引き渡したユーザーによってresolveメソッドの結果を返してくれます。
1 2 3 |
def index @users = policy_scope(User) end |
この記事へのコメントはありません。