[Ruby on Rails]sorceryによる認証 – (6)部署別のアクセス制限 #3 コントローラ

2015.07.08

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

前回に引き続き、部署別のアクセス制限をsorceryで行うサンプルについてです。今回はコントローラのソースコードを取り上げます。尚、作成したサンプルは以下のGithubに置いてあります。全ソースを見たい方は参考にしてください。
sorcery_api_sample

ソースコード

では、ソースコードです。今回変更した部分のみを載せておきます。

UsersController

module Api
  module V1
    class UsersController
    (中略)
      def create
        respond_to do |format|
          @user = User.new(user_params)

          if @user.save_relation(department_params)
            format.json { render nothing: true, status: :created }
          else
            format.json { render nothing: true, status: :bad_request }
          end
        end
      end

      def update
        respond_to do |format|
          if @user.update_relation(user_params, department_params)
            format.json { render :show }
          else
            format.json { render json: @user.errors, status: :unprocessable_entity }
          end
        end
      end
      (中略)
      private
        def department_params
          params.require(:department).permit(:department_id)
        end

ユーザ情報を登録するcreateアクションではUserモデルのsave_relation()メソッドを、updateアクションではupdate_relation()メソッドを呼び出しています。メソッドについては前回を参照してください。また部署のIDをパラメータとして取得するためdepartment_params()を追加しています。

ApplicationBaseController

全てのコントローラ(今回はAPIのバージョンV1の場合)の親クラスとなるApplicationBaseControllerには、管理部のユーザのみ参照を許可するfilterを追加しました。

module Api
  module V1
    class ApplicationBaseController < ApplicationController
      before_action :require_valid_token    
    (中略)
      def administrator_only
        access_token = request.headers[:HTTP_ACCESS_TOKEN]
        api_key = ApiKey.find_by_access_token(access_token)
        user = User.find(api_key.user_id)
        if user.user_department.department_id != Department::ADMINISTRATOR
          respond_to do |format|
            format.json { render nothing: true, status: :unauthorized }
          end
        end
      end

リクエスト時に送られてくるAccessTokenよりユーザ情報を取得し、その所属部署のIDが管理部かどうかを判定しています。「user.user_department.department_id」というようにUserモデルから関連するUserDepartmentモデルを参照できるのは、前回モデルにhas_oneなどの関連の定義をしたためです。

SampleController

最後にユーザの所属部署ごとにアクセス制限を行うSampleControllerについてです。こちらは前回記述した分も含め、全てのソースコードを載せておきます。

module Api
  module V1
    class SampleController < Api::V1::ApplicationBaseController
      skip_before_filter :require_valid_token, only: :public
      before_filter :administrator_only, only: :admin

      def public
        @message = 'public'
      end

      def restrict
        @message = 'authorized'
      end

      def admin
        @message = 'admin'
      end
    end
  end
end

ログインしていないユーザを含め全ユーザに公開するpublicアクションは「skip_before_filter」でログインのチェックを行わないようにしています。
管理部のユーザのみ参照させるadminアクションは「before_filter」でadministrator_only()を呼び出すことにより、これを実現しています。
ログインしているユーザは部署を問わず参照させるrestrictアクションについては以前から変更無く、ApplicationBaseControllerの「before_action」でログイン済みユーザかをチェックしています。

まとめ

以上で部署別のアクセス制限を行う実装については以上になります。ユーザの所属部署をUserテーブルとは別テーブルに保持したことにより、sorceryのソースには一切触れない形での実装となりました。このような作り込みが必要にはなりますが、一方既存のデータ構造を変更すること無しに実現できることは、sorceryのシンプルな構造のメリットと言えるかと思います。