punditを用いた権限管理

はてなのようなブログサイトだと、
「サイト運営」「ブログ管理者」「寄稿者」「一般ユーザー」といったような構造で権限が別れていると思う。 これらの「権限」によって表示出来るページを制限する仕組みを「認可(Authorization)」と言い
この「認可」の仕組みを提供してくれるのが、Punditというgemである。

実装方法

1. インストール

gemfileに追記してインストール。

Gemfile
gem 'pundit'
bundle install

2. 初期化

コントローラにPunditをincludeする。

app/controller/apprication_controller.rb
class ApplicationController < ActionController::Base
  include Pundit
end

以下のコマンドでpolicyファイルを作成する。

rails g pundit:install

作成後、サーバを再起動することでpolicyファイルの設定を拾う様になる。

3. policyの設定を書く

ジェネレータを使うと次のファイルが生成される。

app/policies/application_policy.ruby
class ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    @user = user
    @record = record
  end

  def index?
    false
  end

  def show?
    false
  end

  def create?
    false
  end

  def new?
    create?
  end

  def update?
    false
  end

  def edit?
    update?
  end

  def destroy?
    false
  end

  class Scope
    attr_reader :user, :scope

    def initialize(user, scope)
      @user = user
      @scope = scope
    end

    def resolve
      scope.all
    end
  end
end

基本的にこれを継承してコントローラごとに管理する。
各アクションを実行できるかどうかを以下のように真偽値で判定する。 trueで処理を続行し、falseでPundit::NotAuthorizedErrorを返す

def index?
  true
end

def update?
  user.admin? || user.writer?
end

4. コントローラでauthorizeを呼ぶ

app/controllers/users_controller.rb
def index
  authorize User

  ~~
end

def update
  authorize User

  ~~
end

~~

このように各アクションの処理の前にauthorize を実行することで policyファイルに沿った判定を行う。