目次
- ActiveAdminにCanCanを使った権限機能を追加する(1) - sessanの日記
- ActiveAdminにCanCanを使った権限機能を追加する(2) - sessanの日記
- ActiveAdminにCanCanを使った権限機能を追加する(3) - sessanの日記
今回は、いよいよActiveAdmin側に権限による制御を入れていく。
前提
が実施済みであること
作業の流れ
- ApplicationControllerに権限がないページにアクセスしたときのエラー制御を追加
- ApplicationControllerにAdminUserの権限を初期化する処理を追加
- ActiveAdminの各種画面に権限制御を入れていく
1. ApplicationControllerに権限がないページにアクセスしたときのエラー制御を追加
ApplicationControllerに以下のエラー制御を追加する。
rescue_from CanCan::AccessDenied do |exception| redirect_to admin_dashboard_path, :alert => exception.message end
2. ApplicationControllerにAdminUserの権限を初期化する処理を追加
ApplicationControllerに以下の権限初期化処理を追加する
def current_ability @current_ability ||= Ability.new(current_admin_user) end
3. ActiveAdminの各種画面に権限制御を入れていく
3.1. ActiveAdmin-CanCanの権限制御を自動で行うinitializerの追加
本当は、一個ずつのリソース毎にメニューを表示するかどうか、設定していくことが出来るんだけど、面倒くさいので、一括でやりたいと思って調べたら、本家に以下のようなパッチが出ていた。
Deep integration of CanCan into ActiveAdmin — Gist
上のinitializerを置けば、権限に応じてActiveAdminのメニューやdefault_actionボタンなどよろしくやってくれる。以下の機能があるらしい。
- 良い感じにリソースをロードして認証してくれる
- メニューはアクセス権限があるときだけ表示される
- インデックスページの右側のデフォルトアクションボタンも権限に応じて表示してくれる
- リソースページの右上のメンバーアクションも権限に応じて表示してくれる
- auto_linkヘルパーを使うと、権限に応じたリンクを自動的に作ってくれる。
※ただし、私が試したところ、上記のinitializerで最後のResourceControllerの定義を書くとなぜかrails初期化時にdevise周りでエラーが発生したので、ResourceControllerの定義のところだけコメントアウトした。コメントアウトした後動作確認したけど、上記3, 4は動作しているように見えた。1はそもそも何のことを言っているのか、よくわからない。2は動作しなかったので後で手動で制御することにした。
※上記サイトに記載されているadd_default_action_itemsのなかで、以下のようなところがあるが、これは誤植?かもしれなく、
:model => active_admin_config.resource_label
↑ではなく、# lib/active_admin/resource/action_items.rbと同じように、
:model => active_admin_config.resource_name
としたら、正しく動作した。
あと、ActiveAdminのメニューなどを見やすくするために、as:を使っている人やnamescpace付きのクラスをActiveAdminに登録している場合、以下のようにしていると思うが、
ActiveAdmin.register My::Model do end ActiveAdmin.register Model, as: "Something Else" do end
こういうのがあるとエラーが出てしまうので、以下のパッチを追加しておく。
module CanCan class ControllerResource # Just use the active admin resource_class def resource_class @controller.resource_class end end end
参考:Deep integration of CanCan into ActiveAdmin — Gistのコメント部分。
3.2. 権限のないメニューを消す
権限のないリソースに対しては、画面上部のメニューを出さないようにしたい。
以下のようなコードをActiveAdminのモデル登録用の各クラスに以下のように入れていく。
ActiveAdmin.register AdminRole do menu :parent => "Admin" , :if => proc {can?(:manage, AdminRole) } end
3.3. URLで直打ちで表示できないように、認可を各ページに入れる
おそらく、コメントアウトしたResourceControllerのところで実行されるはずだった以下のコードは自分で実行しないと行けない。
load_resource :except => :index authorize_resource
実際は、ActiveAdminのモデル登録用の各クラスに以下のように入れていく。
ActiveAdmin.register ClassName do controller do load_resource :except => :index authorize_resource end end
これでメニューに出ていないリソースにURL直打ちでアクセスしたとしても、エラーメッセージが出て表示されない。
3.4. ダッシュボードに表示している内容も権限毎に変える
ダッシュボードでsectionなどを定義している場合は、今ログインしている人の権限に応じて、以下のような制御を入れる。
section "summary", :if => Proc.new {current_admin_user.has_role? :admin} do link_to "hoge" end