LoginSignup
13

More than 5 years have passed since last update.

Garage + Doorkeeper + DeviseによるDouble Molelの扱い方

Last updated at Posted at 2015-12-13

はじめに

garage + doorkeeperを使ってapiを作成する場面がよくあると思うのですが、userモデルが2つあるときはどうすれば良いのか自分なりに考えてやってみました。あくまで一例なので、他にあれば是非コメントして頂きたいです。

設計

  • モデルはTeacherモデルとStudentモデルを作る

  • garage + doorkeeper

  • deviseを使う

初期設定

では重要なのはgaraga.rbの設定ですね。まずはそちらの設定から見ていきましょう。
cookpadのサイト
http://techlife.cookpad.com/entry/2014/11/06/100000
を参考にして以下のように最低限は用意しました。

garage.rb

Garage.configure {}
Garage::TokenScope.configure {}

Doorkeeper.configure do
  orm :active_record
  default_scopes :public
  optional_scopes(*Garage::TokenScope.optional_scopes)

  resource_owner_from_credentials do |routes|
    User.find_by(email: params[:username])
  end
end

ではここからどうするか、まず問題点を幾つか挙げました。

問題点

  • resource_owner_credentialsをどう分けるか

  • 権限関係

解決策

まずresource_owner_credentialsですがこれはscopeで分けることにしました。
garageのdefaultのscopeはpuclicですがそれとは別に特定のscopeを定義して分けることができるので、これを使って以下のようにしました。

garage.rb
  resource_owner_from_credentials do |routes|
    if params[:scope] == "student"
      Student.find_by(email: params[:email])
    elsif params[:scope] == "teacher"
      Teacher.find_by(email: params[:email])
    end
  end

これでどちらかを取得することができます。ポリーモーフィック関連使ってできるのかとか様々な方法を考えてみたのですが、これが一番楽に実装できそうなので、これに落ち着きました。

では権限系の設定はGarage::TokenScope.configureでできるのこちらで行います。こちらは以下のようにしました。

Garage::TokenScope.configure do
  register :student, desc: 'enable to access student authority' do
    access :read, Student
    access :write, Student
  end
  register :teacher, desc: 'enable to access teacher authority' do
    access :read, Teacher
    access :write, Teacher
  end
end

ただこれだとcontrollerでuserを権限問題で作れないので、これを解決するために、以下のようにコントローラーでかく必要があります。

students_controller.rb
class StudentController < ApplicationController
  include Garage::RestfulActions
  before_action except: :create do
    doorkeeper_authorize! :student
  end

  def require_resources
    @resources = Student.all
  end

  def require_resource
    @resource = Student.find(params[:id])
  end

  def create_resource
    @resources.create(student_params)
  end

  def update_resource
    @resource.update_attributes!(student_params)
  end

  def destroy_resource
    @resource.destroy!
  end

  private
  def studnet_params
    params.permit(:email, :password, :password_confirmation)
  end
end

このような感じで基本的にはscopeで分ければ良いのかなという結論になりました。
ここらへんは参考文献が少なく難しいところなので、もしこうしたほうが良いとかありましたらコメントよろしくお願いします。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13