-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
249 - Fix invalid access token error (#261)
* handling InvalidAuthenticityToken errors * expanded multi_concern_interaction test * removed addition covered by another PR * WIP - building up application access tests * Tests now passing, including feature tests for authorization * removed VSCode files * added VSCode files to .gitignore * added blank line to end of .gitignore * removing extraneous comments * removed accidental change to admin form * removed accidental change to artworks show view
- Loading branch information
1 parent
186e4f7
commit 04f93c8
Showing
20 changed files
with
452 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# frozen_string_literal: true | ||
|
||
# ExceptionHandlingManager is a concern designed to centralize and manage | ||
# the handling of various application-specific exceptions. | ||
# | ||
# Currently, it includes handling for: | ||
# - ActionController::InvalidAuthenticityToken | ||
# | ||
# Future additions may include but are not limited to: | ||
# - RecordNotFound | ||
# - TimeoutErrors | ||
# - CustomApplicationErrors | ||
# | ||
# This concern is included in the ApplicationController, so all controllers inherit | ||
module ExceptionHandlingManager | ||
extend ActiveSupport::Concern | ||
|
||
included do | ||
rescue_from ActionController::InvalidAuthenticityToken, with: :handle_invalid_token | ||
end | ||
|
||
private | ||
|
||
def handle_invalid_token(exception) | ||
Rails.logger.warn("InvalidAuthenticityToken occurred: #{exception}") | ||
user_was_admin = session[:admin] | ||
reset_session | ||
flash.keep[:danger] = 'Your session has expired. Please log in again.' | ||
|
||
if user_was_admin | ||
redirect_to manage_path | ||
else | ||
redirect_to root_path | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
spec/controllers/concerns/exception_handling_manager_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe ExceptionHandlingManager, type: :controller do | ||
controller(ApplicationController) do | ||
include ExceptionHandlingManager | ||
|
||
def index | ||
render plain: 'Hello, world!' | ||
end | ||
end | ||
|
||
let(:specific_exception) { ActionController::InvalidAuthenticityToken.new('Test Exception Message') } | ||
let(:submitter) { FactoryBot.create(:submitter) } | ||
let(:submitter_session) { { submitter_id: submitter.id } } | ||
let(:admin_session) { { admin: true } } | ||
|
||
before do | ||
routes.draw { get 'index' => 'anonymous#index' } | ||
allow(controller).to receive(:index).and_raise(specific_exception) | ||
end | ||
|
||
context 'as a submitter' do | ||
let(:session) { submitter_session } | ||
|
||
it 'logs the exception to the Rails logger' do | ||
allow(Rails.logger).to receive(:warn) | ||
get(:index, session:) | ||
expect(Rails.logger).to have_received(:warn).with('InvalidAuthenticityToken occurred: Test Exception Message') | ||
end | ||
|
||
it 'resets the session' do | ||
get(:index, session:) | ||
expect(controller.session[:admin]).to be_nil | ||
expect(controller.session[:submitter_id]).to be_nil | ||
end | ||
|
||
it 'sets a flash message and redirects to the root path' do | ||
get(:index, session:) | ||
expect(response.status).to eq(302) | ||
expect(response).to redirect_to(root_path) | ||
expect(flash[:danger]).to eq('Your session has expired. Please log in again.') | ||
end | ||
end | ||
|
||
context 'as an admin' do | ||
let(:session) { admin_session } | ||
|
||
it 'logs the exception to the Rails logger' do | ||
allow(Rails.logger).to receive(:warn) | ||
get(:index, session:) | ||
expect(Rails.logger).to have_received(:warn).with('InvalidAuthenticityToken occurred: Test Exception Message') | ||
end | ||
|
||
it 'resets the session' do | ||
get(:index, session:) | ||
expect(controller.session[:admin]).to be_nil | ||
expect(controller.session[:submitter_id]).to be_nil | ||
end | ||
|
||
it 'sets a flash message and redirects to the manage path' do | ||
get(:index, session:) | ||
expect(response.status).to eq(302) | ||
expect(response).to redirect_to(manage_path) | ||
expect(flash[:danger]).to eq('Your session has expired. Please log in again.') | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
spec/features/application_access/access_invalid_authenticity_missing_session_info_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe 'Application Behavior', type: :feature do | ||
let(:submitter) { FactoryBot.build(:submitter) } | ||
|
||
before do | ||
ActionController::Base.allow_forgery_protection = true | ||
end | ||
|
||
after do | ||
ActionController::Base.allow_forgery_protection = false | ||
end | ||
|
||
context 'when an invalid authenticity token is provided along with a missing or invalid session ID' do | ||
it 'redirects to the root page with an error message' do | ||
# The user never tries to log in, otherwise they would have a session. | ||
# The user never gets to fill in information, so there is no authenticity token to make invalid. | ||
visit publications_path | ||
expect_to_be_on_root_page_with_login_message | ||
end | ||
|
||
it 'allows the user to log in after having been redirected to the root page with an error message' do | ||
visit publications_path | ||
visit_publications_page_as_submitter(submitter) | ||
expect(page).to have_current_path(publications_path) | ||
end | ||
end | ||
end |
97 changes: 97 additions & 0 deletions
97
spec/features/application_access/access_invalid_authenticity_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe 'Handling of invalid authenticity token', type: :feature, js: true do | ||
let(:submitter) { FactoryBot.create(:submitter) } | ||
|
||
before do | ||
ActionController::Base.allow_forgery_protection = true | ||
end | ||
|
||
after do | ||
ActionController::Base.allow_forgery_protection = false | ||
end | ||
|
||
context 'when trying to log in' do | ||
context 'as a submitter' do | ||
it 'triggers an inauthentic token error and redirects to the root path' do | ||
visit root_path | ||
fill_in('submitter[first_name]', with: submitter.first_name) | ||
fill_in('submitter[last_name]', with: submitter.last_name) | ||
find_by_id('submitter_college').find(:xpath, "option[#{submitter.college}]").select_option | ||
fill_in('submitter[department]', with: submitter.department) | ||
fill_in('submitter[mailing_address]', with: submitter.mailing_address) | ||
fill_in('submitter[phone_number]', with: submitter.phone_number) | ||
fill_in('submitter[email_address]', with: submitter.email_address) | ||
make_authenticity_token_invalid | ||
click_on('Next') | ||
expect_to_be_on_root_page_with_expired_error | ||
end | ||
end | ||
|
||
context 'as an admin' do | ||
before do | ||
allow(ENV).to receive(:fetch).and_call_original | ||
end | ||
context 'when the user was previously in an admin session' do | ||
# We are assuming that the previous session was an admin session. | ||
# If it were not, then the user would be redirected to the root path. | ||
it 'triggers an inauthentic token error and redirects to the manage path' do | ||
visit_publications_page_as_admin | ||
visit manage_path | ||
fill_in('username', with: ENV.fetch('ADMIN_USERNAME', nil)) | ||
fill_in('password', with: ENV.fetch('ADMIN_PASSWORD', nil)) | ||
make_authenticity_token_invalid | ||
click_on('Submit') | ||
expect_to_be_on_manage_page_with_expired_error | ||
end | ||
end | ||
|
||
context 'when the user was not previously in an admin session' do | ||
it 'triggers an inauthentic token error and redirects to the root path' do | ||
# We are assuming that the session[:admin] is not already set. | ||
# If it were, then the user would be redirected to the manage path. | ||
visit manage_path | ||
fill_in('username', with: ENV.fetch('ADMIN_USERNAME', nil)) | ||
fill_in('password', with: ENV.fetch('ADMIN_PASSWORD', nil)) | ||
make_authenticity_token_invalid | ||
click_on('Submit') | ||
expect_to_be_on_root_page_with_expired_error | ||
end | ||
end | ||
end | ||
end | ||
|
||
context 'when trying to add a publication' do | ||
context 'as a submitter' do | ||
it 'triggers an inauthentic token error and redirects to the root path' do | ||
visit_publications_page_as_submitter(submitter) | ||
first('a', text: 'New').click # There is no authenticity check for this button | ||
expect(page).to have_current_path(new_artwork_path) | ||
make_authenticity_token_invalid # New artwork will submit an authenticity token. | ||
|
||
fill_in('artwork[author_first_name][]', with: 'Test') | ||
fill_in('artwork[author_last_name][]', with: 'Artist') | ||
fill_in('artwork[work_title]', with: 'Test Artwork') | ||
click_on('Submit') | ||
expect_to_be_on_root_page_with_expired_error | ||
end | ||
end | ||
|
||
context 'as an admin' do | ||
before do | ||
FactoryBot.create(:artwork) # create an artwork to edit | ||
end | ||
it 'triggers an inauthentic token error and redirects to the manage path' do | ||
visit_publications_page_as_admin | ||
expect(page).to have_current_path(publications_path) | ||
find('i.fas.fa-edit', match: :first).click | ||
expect(page).to have_current_path(edit_artwork_path(Artwork.first)) | ||
make_authenticity_token_invalid | ||
click_on('Submit') | ||
expect_to_be_on_manage_page_with_expired_error | ||
end | ||
end | ||
end | ||
end |
14 changes: 14 additions & 0 deletions
14
spec/features/application_access/access_missing_session_info_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe 'Application Behavior', type: :feature do | ||
context 'when a user is not logged in' do | ||
# No submitter_id or admin=true | ||
it 'redirects to a login page with a message to submit your information' do | ||
visit publications_path | ||
expect(current_path).to eq(root_path) | ||
expect(page).to have_content('You must submit your information first.') | ||
end | ||
end | ||
end |
40 changes: 40 additions & 0 deletions
40
spec/features/application_access/access_outside_open_dates_invalid_authenticity_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe 'Application Behavior', type: :feature, js: true do | ||
before do | ||
ActionController::Base.allow_forgery_protection = true | ||
allow(ENV).to receive(:fetch).and_call_original | ||
allow(ENV).to receive(:fetch).with('EXPIRATION_DATE').and_return('Jan 01 2000') | ||
end | ||
|
||
after do | ||
ActionController::Base.allow_forgery_protection = false | ||
end | ||
|
||
context 'when accessing outside open dates and with an invalid authenticity token' do | ||
context 'as an admin' do | ||
before do | ||
FactoryBot.create(:artwork) # create an artwork to edit | ||
end | ||
it 'triggers an inauthentic token error and redirects to the root path' do | ||
visit_publications_page_as_admin | ||
expect(page).to have_current_path(publications_path) | ||
find('i.fas.fa-edit', match: :first).click | ||
expect(page).to have_current_path(edit_artwork_path(Artwork.first)) | ||
make_authenticity_token_invalid | ||
click_on('Submit') | ||
expect_to_be_on_manage_page_with_expired_error | ||
end | ||
end | ||
|
||
context 'as a submitter' do | ||
it 'redirects to the closed page' do | ||
visit root_path | ||
# The user never gets to fill in information, so there is no authenticity token to make invalid. | ||
expect(page).to have_content('The deadline for submissions has passed.') | ||
end | ||
end | ||
end | ||
end |
18 changes: 18 additions & 0 deletions
18
spec/features/application_access/access_outside_open_dates_missing_session_info_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe 'Application Behavior', type: :feature do | ||
let(:submitter) { FactoryBot.build(:submitter) } | ||
|
||
before do | ||
allow(ENV).to receive(:fetch).with('EXPIRATION_DATE').and_return('Jan 01 2000') | ||
end | ||
|
||
context 'when accessing outside open dates and with a missing or invalid session ID' do | ||
it 'redirects to the closed page' do | ||
visit publications_path | ||
expect(page).to have_content('The deadline for submissions has passed.') | ||
end | ||
end | ||
end |
Oops, something went wrong.