権限管理 gem ; cancan
Devise に次いでの衝撃
Devise が認証機能を持たせる gem に対して、
cancan は認証後の権限を管理する gem
最終的にやること
cancan を用いて 登録 email 権限ごとに挙動 を変化させること
前提条件
rails g devise user
からの流れで
ユーザー1 matsu@matsu.jp ユーザー2 take@take.jp
が Devise gem を使った users テーブルに保存されている。
rails g scaffold task name:string rake db:migrate
をしていること
準備/環境
Gem file に cancan を添える
gem 'cancan'
モデル
権限管理をするための Model クラスを作成。gem の設定上 Ability
Modelを
設置しなければいけないらしい。既存 Model と衝突しないように。
$ rails g cancan:ability create app/models/ability.rb
どのように権限をつけるか設定をする
設定箇所は initialize 内
app/models/ability.rb class Ability include CanCan::Ability def initialize(user) end end
設定例
登録 user の email が 'matsu' とマッチしていたら「権限」を持っていると設定する。
app/models/ability.rb class Ability include CanCan::Ability def initialize(user) if user.email =~ /matsu@.*/ ### else ### end end end
具体的にどう権限を持たせるか
各 controller 中のCRUD(create, read, update, delete)で
制限をかける。もしくは 全権利(management)を割り当てる。
app/models/ability.rb class Ability include CanCan::Ability def initialize(user) user ||= User.new # 新規ユーザーの為に or 代入が必須 if user.email =~ /matsu@.*/ can :manage, Task # matsu@.* のユーザーは task controller の全権限を持つ else can :read, Task # matsu@.* 以外のユーザーは task controller の read だけ権限を持つ end end end
コントローラ
TasksController に権限管理を定義したメソッドを付与する
app/views/tasks_controller.rb TasksController < ApplicationController load_and_authorize_resource # このメソッドを付与する ... end
cancan 用 マスアサインメント対応
app/controller/application_controller.rb class ApplicationController < ActionController::Base before_filter do resource = controller_name.singularize.to_sym method = "#{resource}_params" params[resource] &&= send(method) if respond_to?(method, true) end protect_from_forgery with: :exception end
各コントローラ側のマスアサインメント用paramsの値は、各々設定。下の例は tasks
def tasks_params params.require(:tasks).permit(:name) end
ビュー
Tasks の view に次の if-else 分岐を書く
app/views/tasks/index.html.erb <h1>Listing tasks</h1> <% if can? :destroy, Task %> I can destroy user! <% else %> I cannot destroy user ...! <% end %> <table> <thead>
matsu@matsu.com でログインして/tasksに遷移すると、
I can destroy! が表示される。tasks controller のどこにでもアクセスできる。
take@take.com でログインして/tasksに遷移すると
I cannot destroy user ...! が表示される(未ログイン状態でも同じ)
tasks controller の read, create にしかアクセスできない。
destroy をしようとすると 警告 You are not authorized to access this page.
が表示されて destroy できない。
very hot な cool gem
マスアサインメント引用
https://github.com/ryanb/cancan/issues/835#issuecomment-18663815