deviseでログイン前にapiリクエストしたときにカスタマイズjsonを返したいとき

f:id:ihatov08:20160728001100j:plain
deviseでログイン前にapiリクエストしたときにカスタマイズjsonを返したいときのカスタマイズ方法です。

ref: How To: Redirect to a specific page when the user can not be authenticated · plataformatec/devise Wiki

CustomFailureクラスを作成

Devise::FailureAppを継承したCustomFailureを作成します。respondメソッドをオーバーライドしてcontent typeがapplication/jsonだったらjson返すように設定しました。

lib/custom_failure.rb

class CustomFailure < Devise::FailureApp
def respond
if request.content_type == "application/json"
self.status = 401
self.content_type = "application/json"
self.response_body = {
result: false,
message: I18n.t('devise.failure.unauthenticated'),
error_code: Constant::ApiErrorCode::UNAUTHENTICATED
}.to_json
elsif http_auth?
http_auth
elsif warden_options[:recall]
recall
else
redirect
end
end
end

respondメソッドにelsifでrequestのcontent_typeがapplication/jsonだったらという条件分岐を加えればOKですね!

devise/failure_app.rb at master · plataformatec/devise · GitHub

libの読み込み設定

libをはじめに読み込まれるように設定します。

config/application.rb

config.autoload_paths += %W(#{config.root}/lib)

確認方法です。

www.tom08.net

deviseの設定に加える

deviseの設定に加えればOKです!

config/initializers/devise.rb

  config.warden do |manager|
manager.failure_app = CustomFailure
end

Rspec

テストも追加してみました!libのテストをするときは

rails_helper.rb

require File.expand_path('../../config/environment', __FILE__)

が記述されているか確認してください!

また該当specファイルでrequireしましょう!

spec/lib/custom_failure_spec.rb

require 'rails_helper'
require 'custom_failure'
RSpec.describe 'lib/CustomFailure', type: :request do
describe 'POST /api/v1/users/update_setting.json' do
let(:request_header) do
{ 'CONTENT_TYPE' => 'application/json', 'ACCEPT' => 'application/json' }
end
let(:user) do
'{"user_email": "test@test.com", "user_token": "dammy", "email": "change@test.com"}'
end
before do
@user = create(:user, email: "test@test.com", authentication_token: "dammy")
end
context "認証前にリクエスト" do
before do
post api_v1_users_update_setting_path(format: :json), user, request_header
end
it "401を返す" do
expect(response).to have_http_status(401)
end
it "application/jsonで返す" do
expect(response.content_type).to eq('application/json')
end
it "JSONに含まれるキーが適切である" do
result = JSON.parse(response.body)
expect(result).to have_key('result')
expect(result).to have_key('message')
expect(result).to have_key('error_code')
end
it "レスポンスパラメータが適切である" do
body = JSON.parse(response.body)
expect(body["result"]).to eq false
expect(body["message"]).to eq I18n.t('devise.failure.unauthenticated')
expect(body["error_code"]).to eq 1
end
end
end
end

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です