bankenを使った権限管理

2018年8月20日 カテゴリー: rails タグ: rails 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できないのロジックも分かりやすく書けるので、非常に気に入りました。