show error for cross-environment API key usage
This commit is contained in:
committed by
Pete Matsyburka
parent
90d86b58c2
commit
3c616a824c
+1
-1
@@ -66,7 +66,7 @@ RSpec/ExampleLength:
|
||||
Max: 40
|
||||
|
||||
RSpec/MultipleMemoizedHelpers:
|
||||
Max: 6
|
||||
Max: 9
|
||||
|
||||
Metrics/BlockNesting:
|
||||
Max: 4
|
||||
|
||||
@@ -25,9 +25,9 @@ module Api
|
||||
render json: { error: 'Too many requests' }, status: :too_many_requests
|
||||
end
|
||||
|
||||
if Rails.env.production?
|
||||
unless Rails.env.development?
|
||||
rescue_from CanCan::AccessDenied do |e|
|
||||
render json: { error: e.message }, status: :forbidden
|
||||
render json: { error: access_denied_error_message(e) }, status: :forbidden
|
||||
end
|
||||
|
||||
rescue_from JSON::ParserError do |e|
|
||||
@@ -39,6 +39,38 @@ module Api
|
||||
|
||||
private
|
||||
|
||||
def access_denied_error_message(error)
|
||||
return 'Not authorized' if request.headers['X-Auth-Token'].blank?
|
||||
return 'Not authorized' unless error.subject.is_a?(ActiveRecord::Base)
|
||||
return 'Not authorized' unless error.subject.respond_to?(:account_id)
|
||||
|
||||
linked_account_record_exists =
|
||||
if current_user.account.testing?
|
||||
current_user.account.linked_account_accounts.where(account_type: 'testing')
|
||||
.exists?(account_id: error.subject.account_id)
|
||||
else
|
||||
current_user.account.testing_accounts.exists?(id: error.subject.account_id)
|
||||
end
|
||||
|
||||
return 'Not authorized' unless linked_account_record_exists
|
||||
|
||||
object_name = error.subject.model_name.human
|
||||
id = error.subject.id
|
||||
|
||||
message =
|
||||
if current_user.account.testing?
|
||||
"#{object_name} #{id} not found using testing API key; Use production API key to " \
|
||||
"access production #{object_name.downcase.pluralize}."
|
||||
else
|
||||
"#{object_name} #{id} not found using production API key; Use testing API key to " \
|
||||
"access testing #{object_name.downcase.pluralize}."
|
||||
end
|
||||
|
||||
Rollbar.warning(message) if defined?(Rollbar)
|
||||
|
||||
message
|
||||
end
|
||||
|
||||
def paginate(relation, field: :id)
|
||||
result = relation.order(field => :desc)
|
||||
.limit([params.fetch(:limit, DEFAULT_LIMIT).to_i, MAX_LIMIT].min)
|
||||
|
||||
@@ -5,5 +5,14 @@ FactoryBot.define do
|
||||
name { Faker::Company.name }
|
||||
locale { 'en-US' }
|
||||
timezone { 'UTC' }
|
||||
|
||||
trait :with_testing_account do
|
||||
after(:create) do |account|
|
||||
testing_account = account.dup.tap { |a| a.name = "Testing - #{account.name}" }
|
||||
testing_account.uuid = SecureRandom.uuid
|
||||
account.testing_accounts << testing_account
|
||||
account.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,11 +3,17 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Submission API', type: :request do
|
||||
let!(:account) { create(:account) }
|
||||
let!(:author) { create(:user, account:) }
|
||||
let!(:folder) { create(:template_folder, account:) }
|
||||
let!(:templates) { create_list(:template, 2, account:, author:, folder:) }
|
||||
let!(:multiple_submitters_template) { create(:template, submitter_count: 3, account:, author:, folder:) }
|
||||
let(:account) { create(:account, :with_testing_account) }
|
||||
let(:testing_account) { account.testing_accounts.first }
|
||||
let(:author) { create(:user, account:) }
|
||||
let(:testing_author) { create(:user, account: testing_account) }
|
||||
let(:folder) { create(:template_folder, account:) }
|
||||
let(:testing_folder) { create(:template_folder, account: testing_account) }
|
||||
let(:templates) { create_list(:template, 2, account:, author:, folder:) }
|
||||
let(:multiple_submitters_template) { create(:template, submitter_count: 3, account:, author:, folder:) }
|
||||
let(:testing_templates) do
|
||||
create_list(:template, 2, account: testing_account, author: testing_author, folder: testing_folder)
|
||||
end
|
||||
|
||||
describe 'GET /api/submissions' do
|
||||
it 'returns a list of submissions' do
|
||||
@@ -41,6 +47,31 @@ describe 'Submission API', type: :request do
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.parsed_body).to eq(JSON.parse(show_submission_body(submission).to_json))
|
||||
end
|
||||
|
||||
it 'returns an authorization error if test account API token is used with a production submission' do
|
||||
submission = create(:submission, :with_submitters, :with_events, template: templates[0], created_by_user: author)
|
||||
|
||||
get "/api/submissions/#{submission.id}", headers: { 'x-auth-token': testing_author.access_token.token }
|
||||
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
expect(response.parsed_body).to eq(
|
||||
JSON.parse({ error: "Submission #{submission.id} not found using testing API key; " \
|
||||
'Use production API key to access production submissions.' }.to_json)
|
||||
)
|
||||
end
|
||||
|
||||
it 'returns an authorization error if production account API token is used with a test submission' do
|
||||
submission = create(:submission, :with_submitters, :with_events, template: testing_templates[0],
|
||||
created_by_user: testing_author)
|
||||
|
||||
get "/api/submissions/#{submission.id}", headers: { 'x-auth-token': author.access_token.token }
|
||||
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
expect(response.parsed_body).to eq(
|
||||
JSON.parse({ error: "Submission #{submission.id} not found using production API key; " \
|
||||
'Use testing API key to access testing submissions.' }.to_json)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/submissions' do
|
||||
|
||||
@@ -3,10 +3,16 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Submitter API', type: :request do
|
||||
let!(:account) { create(:account) }
|
||||
let!(:author) { create(:user, account:) }
|
||||
let!(:folder) { create(:template_folder, account:) }
|
||||
let!(:templates) { create_list(:template, 2, account:, author:, folder:) }
|
||||
let(:account) { create(:account, :with_testing_account) }
|
||||
let(:testing_account) { account.testing_accounts.first }
|
||||
let(:author) { create(:user, account:) }
|
||||
let(:testing_author) { create(:user, account: testing_account) }
|
||||
let(:folder) { create(:template_folder, account:) }
|
||||
let(:testing_folder) { create(:template_folder, account: testing_account) }
|
||||
let(:templates) { create_list(:template, 2, account:, author:, folder:) }
|
||||
let(:testing_templates) do
|
||||
create_list(:template, 2, account: testing_account, author: testing_author, folder: testing_folder)
|
||||
end
|
||||
|
||||
describe 'GET /api/submitters' do
|
||||
it 'returns a list of submitters' do
|
||||
@@ -42,6 +48,34 @@ describe 'Submitter API', type: :request do
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.parsed_body).to eq(JSON.parse(submitter_body(submitter).to_json))
|
||||
end
|
||||
|
||||
it 'returns an authorization error if test account API token is used with a production submitter' do
|
||||
submitter = create(:submission, :with_submitters, :with_events,
|
||||
template: templates[0],
|
||||
created_by_user: author).submitters.first
|
||||
|
||||
get "/api/submitters/#{submitter.id}", headers: { 'x-auth-token': testing_author.access_token.token }
|
||||
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
expect(response.parsed_body).to eq(
|
||||
JSON.parse({ error: "Submitter #{submitter.id} not found using " \
|
||||
'testing API key; Use production API key to access production submitters.' }.to_json)
|
||||
)
|
||||
end
|
||||
|
||||
it 'returns an authorization error if production account API token is used with a test submitter' do
|
||||
submitter = create(:submission, :with_submitters, :with_events,
|
||||
template: testing_templates[0],
|
||||
created_by_user: testing_author).submitters.first
|
||||
|
||||
get "/api/submitters/#{submitter.id}", headers: { 'x-auth-token': author.access_token.token }
|
||||
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
expect(response.parsed_body).to eq(
|
||||
JSON.parse({ error: "Submitter #{submitter.id} not found using production API key; " \
|
||||
'Use testing API key to access testing submitters.' }.to_json)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT /api/submitters' do
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Templates API', type: :request do
|
||||
let!(:account) { create(:account) }
|
||||
let!(:author) { create(:user, account:) }
|
||||
let!(:folder) { create(:template_folder, account:) }
|
||||
let!(:template_preferences) { { 'request_email_subject' => 'Subject text', 'request_email_body' => 'Body Text' } }
|
||||
let(:account) { create(:account, :with_testing_account) }
|
||||
let(:testing_account) { account.testing_accounts.first }
|
||||
let(:author) { create(:user, account:) }
|
||||
let(:testing_author) { create(:user, account: testing_account) }
|
||||
let(:folder) { create(:template_folder, account:) }
|
||||
let(:template_preferences) { { 'request_email_subject' => 'Subject text', 'request_email_body' => 'Body Text' } }
|
||||
|
||||
describe 'GET /api/templates' do
|
||||
it 'returns a list of templates' do
|
||||
@@ -48,6 +50,38 @@ describe 'Templates API', type: :request do
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.parsed_body).to eq(JSON.parse(template_body(template).to_json))
|
||||
end
|
||||
|
||||
it 'returns an authorization error if test account API token is used with a production template' do
|
||||
template = create(:template, account:,
|
||||
author:,
|
||||
folder:,
|
||||
external_id: SecureRandom.base58(10),
|
||||
preferences: template_preferences)
|
||||
|
||||
get "/api/templates/#{template.id}", headers: { 'x-auth-token': testing_author.access_token.token }
|
||||
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
expect(response.parsed_body).to eq(
|
||||
JSON.parse({ error: "Template #{template.id} not found using testing API key; " \
|
||||
'Use production API key to access production templates.' }.to_json)
|
||||
)
|
||||
end
|
||||
|
||||
it 'returns an authorization error if production account API token is used with a test template' do
|
||||
template = create(:template, account: testing_account,
|
||||
author: testing_author,
|
||||
folder:,
|
||||
external_id: SecureRandom.base58(10),
|
||||
preferences: template_preferences)
|
||||
|
||||
get "/api/templates/#{template.id}", headers: { 'x-auth-token': author.access_token.token }
|
||||
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
expect(response.parsed_body).to eq(
|
||||
JSON.parse({ error: "Template #{template.id} not found using production API key; " \
|
||||
'Use testing API key to access testing templates.' }.to_json)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT /api/templates' do
|
||||
|
||||
Reference in New Issue
Block a user