From e165ee089d51d363d1f101167637cc3188eba200 Mon Sep 17 00:00:00 2001 From: Ken Jones Date: Mon, 7 Aug 2023 11:52:02 +0100 Subject: [PATCH] Fix undefined variable error in controller helper (#25) --- lib/devise/api/controllers/helpers.rb | 4 + spec/dummy/app/controllers/home_controller.rb | 10 ++ spec/dummy/config/routes.rb | 1 + spec/requests/authentication_spec.rb | 132 ++++++++++++++++++ 4 files changed, 147 insertions(+) create mode 100644 spec/dummy/app/controllers/home_controller.rb create mode 100644 spec/requests/authentication_spec.rb diff --git a/lib/devise/api/controllers/helpers.rb b/lib/devise/api/controllers/helpers.rb index 142fa7c..a378221 100644 --- a/lib/devise/api/controllers/helpers.rb +++ b/lib/devise/api/controllers/helpers.rb @@ -51,6 +51,10 @@ def current_devise_api_user private + def resource_class + current_devise_api_user&.class + end + def extract_devise_api_token_from_params params[Devise.api.config.authorization.params_key] end diff --git a/spec/dummy/app/controllers/home_controller.rb b/spec/dummy/app/controllers/home_controller.rb new file mode 100644 index 0000000..4e7e874 --- /dev/null +++ b/spec/dummy/app/controllers/home_controller.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class HomeController < ApplicationController + skip_before_action :verify_authenticity_token, raise: false + before_action :authenticate_devise_api_token! + + def index + render json: { success: true } + end +end diff --git a/spec/dummy/config/routes.rb b/spec/dummy/config/routes.rb index c2e3c4d..867ee7d 100644 --- a/spec/dummy/config/routes.rb +++ b/spec/dummy/config/routes.rb @@ -7,4 +7,5 @@ # root "articles#index" devise_for :users + get :home, to: 'home#index' end diff --git a/spec/requests/authentication_spec.rb b/spec/requests/authentication_spec.rb new file mode 100644 index 0000000..af10d72 --- /dev/null +++ b/spec/requests/authentication_spec.rb @@ -0,0 +1,132 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Authentication', type: :request do + describe 'GET /home' do + context 'when the token is valid and on the header' do + let(:user) { create(:user) } + let(:devise_api_token) { create(:devise_api_token, resource_owner: user) } + + before do + get home_path, headers: authentication_headers_for(user, devise_api_token), as: :json + end + + it 'returns the correct response' do + expect(response).to have_http_status(:success) + expect(JSON.parse(response.body)).to eql({ 'success' => true }) + end + end + + context 'when the token is valid and on the url param' do + let(:user) { create(:user) } + let(:devise_api_token) { create(:devise_api_token, resource_owner: user) } + + before do + get home_path(access_token: devise_api_token.access_token), as: :json + end + + it 'returns the correct response' do + expect(response).to have_http_status(:success) + expect(JSON.parse(response.body)).to eql({ 'success' => true }) + end + end + + context 'when the token is invalid and on the header' do + let(:user) { create(:user) } + let(:devise_api_token) { build(:devise_api_token, resource_owner: user) } + + before do + get home_path, headers: authentication_headers_for(user, devise_api_token), as: :json + end + + it 'returns http unauthorized' do + expect(response).to have_http_status(:unauthorized) + end + + it 'returns an error response' do + expect(parsed_body.error).to eq 'invalid_token' + expect(parsed_body.error_description).to eq([I18n.t('devise.api.error_response.invalid_token')]) + end + + it 'does not return the authenticated resource owner' do + expect(parsed_body.id).to be_nil + expect(parsed_body.email).to be_nil + expect(parsed_body.created_at).to be_nil + expect(parsed_body.updated_at).to be_nil + end + end + + context 'when the token is invalid and on the url param' do + before do + get home_path(access_token: 'invalid'), as: :json + end + + it 'returns http unauthorized' do + expect(response).to have_http_status(:unauthorized) + end + + it 'returns an error response' do + expect(parsed_body.error).to eq 'invalid_token' + expect(parsed_body.error_description).to eq([I18n.t('devise.api.error_response.invalid_token')]) + end + + it 'does not return the authenticated resource owner' do + expect(parsed_body.id).to be_nil + expect(parsed_body.email).to be_nil + expect(parsed_body.created_at).to be_nil + expect(parsed_body.updated_at).to be_nil + end + end + + context 'when the token is expired' do + let(:user) { create(:user) } + let(:devise_api_token) { create(:devise_api_token, :access_token_expired, resource_owner: user) } + + before do + get home_path, headers: authentication_headers_for(user, devise_api_token), as: :json + end + + it 'returns http unauthorized' do + expect(response).to have_http_status(:unauthorized) + end + + it 'returns an error response' do + expect(parsed_body.error).to eq 'expired_token' + expect(parsed_body.error_description).to eq([I18n.t('devise.api.error_response.expired_token')]) + end + + it 'does not return the authenticated resource owner' do + expect(parsed_body.id).to be_nil + expect(parsed_body.email).to be_nil + expect(parsed_body.created_at).to be_nil + expect(parsed_body.updated_at).to be_nil + end + end + + context 'when the token is revoked' do + let(:user) { create(:user) } + let(:devise_api_token) { create(:devise_api_token, :revoked, resource_owner: user) } + + before do + get home_path, headers: authentication_headers_for(user, devise_api_token), as: :json + end + + it 'returns http unauthorized' do + expect(response).to have_http_status(:unauthorized) + end + + it 'returns an error response' do + expect(parsed_body.error).to eq 'revoked_token' + expect(parsed_body.error_description).to eq([I18n.t('devise.api.error_response.revoked_token')]) + end + + it 'does not return the authenticated resource owner' do + expect(parsed_body.id).to be_nil + expect(parsed_body.email).to be_nil + expect(parsed_body.created_at).to be_nil + expect(parsed_body.updated_at).to be_nil + end + end + end +end