
bankenを使った権限管理
このユーザーはコレができて、あのユーザーはアレができないなどといった、ユーザーのロール毎に権限管理をすることができるgem bankenを試してみました🙋
その他の有名なgemではcancancanやpunditなどがありますが、bankenは、国産という部分と分かりやすい管理方法がとても良かったです。
前提
- rails 5.2.0
- ruby 2.5.1
- Userモデルが存在していて、セッション管理にはsorceryを使用している
- Roomモデル(カラムはuser_id:integerと適当にbody:stringとかで)は既に作られている
- UserモデルとRoomモデルはhas_manyなどで関連付けされている
インストール
とりあえずgemを追加します。
gem 'banken'
次にジェネレーターで必要なファイルを生成します。
$ rails g banken:install
これでapp/loyalties/application_loyalty.rbが作られました。
あとはapp/controllers/application_controller.rbに
class ApplicationController < ActionController::Base
include Banken
protect_from_forgery with: :exception
end
これで準備は完了です👍
ユーザーに権限を設定する
Roomモデルがあったとして、先生かつ教室の担任(作成者みたいな)は更新はできるが、その他のユーザーは読むことしかできない。また、管理者はすべての管理が可能といったことをサクっと実装してみる。
まずはUserモデルにロールを設定できるようカラムを追加します。
$ rails g migration AddRoleToUser role:integer
権限はかならず何か設定されている必要があるので、migrationファイルにはこんな感じで書きます。
class AddRoleToUser < ActiveRecord::Migration[5.2]
def change
add_column :users, :role, :integer, null: false, default: 1
end
end
そして、Userモデルに管理しやすいようenumを使ってロールを記述する。
class User < ApplicationRecord
~~~省略~~~
enum role: {
member: 1,
teacher: 2,
admin: 3
}
~~~省略~~~
end
これでuser.teacher?といったコードが使えるようになりました。
実際に使ってみる
権限管理を記述するloyaltyをジェネレーターで生成します。今回はRoomモデルなので、こんな感じで書きます。
$ rails g banken:loyalty rooms
app/loyalties/rooms_loyalty.rbが生成されているので、中身を編集します。とりあえず今回はeditページが見られないように設定します。
class RoomsLoyalty < ApplicationLoyalty
def edit?
user.admin? || user == record.user
end
end
app/controllers/rooms_controller.rbのeditにこんな感じで追記します。
def edit
authorize! @room
end
これでeditページに関しては、adminか作成者ではない限り、アクセスしようとするとBanken::NotAuthorizedErrorが発生されるようになりました。
最後にviewではこんな感じに
<% if loyalty(@room, :rooms).edit? %>
<%= link_to 'Edit', edit_room_path(@room) %>
<% end %>
これでエディットが可能なユーザーしかそもそもEditリンクが表示されなくなりました。
シンプルでわかりやすい
controllerベースだし、できるorできないのロジックも分かりやすく書けるので、非常に気に入りました。