From 4ed74c003bb9433575371a0d785cb17cd4e8343a Mon Sep 17 00:00:00 2001 From: Jay Varner Date: Mon, 22 Sep 2025 09:02:51 -0400 Subject: [PATCH] Improve blocking direct public access to private letters and entities. --- app/controllers/entities_controller.rb | 18 +++++---------- app/controllers/letters_controller.rb | 8 +++++++ spec/requests/entities_spec.rb | 13 +++++++++-- spec/requests/letters_spec.rb | 32 ++++++++++++++++++++++---- 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/app/controllers/entities_controller.rb b/app/controllers/entities_controller.rb index ef5d5c2..6ffd2c7 100644 --- a/app/controllers/entities_controller.rb +++ b/app/controllers/entities_controller.rb @@ -32,15 +32,6 @@ def index render end - def show - @entity = if request.host.include?('beckettapi') - Entity.find(params[:id]) - else - Entity.published.find(params[:id]) - end - render - end - # GET /entities/autocomplete?search=* def autocomplete query = strip_tags params[:search] @@ -84,9 +75,12 @@ def reindex end def set_entity - entity = Entity.find(params[:id]) - entity.save if ENV['RAILS_ENV'] == 'test' - @entity = entity + @entity = if request.headers.key?('HTTP_REFERER') && request.headers['HTTP_REFERER'].include?('beckettapi') + Entity.find(params[:id]) + else + Entity.published.find(params[:id]) + end + @entity.save if ENV['RAILS_ENV'] == 'test' end def set_filters diff --git a/app/controllers/letters_controller.rb b/app/controllers/letters_controller.rb index e4dd11e..10670d5 100644 --- a/app/controllers/letters_controller.rb +++ b/app/controllers/letters_controller.rb @@ -30,6 +30,14 @@ def index render end + def show + @letter = if request.headers.key?('HTTP_REFERER') && request.headers['HTTP_REFERER'].include?('beckettapi') + Letter.find(params[:id]) + else + Letter.published.find(params[:id]) + end + end + private def set_letter diff --git a/spec/requests/entities_spec.rb b/spec/requests/entities_spec.rb index e4f0c1d..7c380c5 100644 --- a/spec/requests/entities_spec.rb +++ b/spec/requests/entities_spec.rb @@ -78,6 +78,7 @@ describe 'GET /show' do it 'renders a successful response' do entity = create(:entity, :published) + entity.save get entity_url(entity), as: :json expect(response).to be_successful end @@ -85,7 +86,7 @@ it 'renders unpublished when requested from beckettapi' do entity = create(:entity) expect(entity.published).to be(false) - get '/entities', params: { id: entity.id }, headers: { HTTP_REFERER: 'beckettapi.ecdsdev.org' } + get(entity_url(entity), headers: { HTTP_REFERER: 'beckettapi.ecdsdev.org' }) expect(response).to be_successful end @@ -93,7 +94,7 @@ entity = create(:entity) expect(entity.published).to be(false) get entity_url(entity) - # The recomendation causes the test to fail. + # The recommendation causes the test to fail. # rubocop:disable RSpecRails/HaveHttpStatus expect(response.status).to eq 404 # rubocop:enable RSpecRails/HaveHttpStatus @@ -111,6 +112,8 @@ rand(0..3).times { mention.tag_list.add(Faker::Hipster.word) } mention.save end + Letter.find_each(&:save) + entity.save expect(entity.letters.count).to eq(11) get "/entities/#{entity.id}/letters?relation=mention&start_date=1963-01-01" expect(json[:letters].map {|letter| Date.parse(letter[:date]) }.min).to be >= DateTime.new(1963, 1, 1) @@ -123,6 +126,8 @@ 10.times { create(:published_letter, date: Faker::Date.in_date_period(year: rand(1972..1975))) } entity = create(:place_entity, letters_sent_to: Letter.all) expect(entity.letters_sent_to.count).to eq(10) + entity.save + expect(entity.published).to be(true) get "/entities/#{entity.id}/letters?relation=destination&end_date=1974-06-01" expect(json[:letters].map {|letter| Date.parse(letter[:date]) }.min).to be >= DateTime.new(1972, 1, 1) expect(json[:letters].map {|letter| Date.parse(letter[:date]) }.min).to be <= DateTime.new(1974, 6, 1) @@ -133,6 +138,8 @@ 10.times { create(:published_letter, date: Faker::Date.in_date_period(year: rand(1971..1975))) } entity = create(:person_entity, letters_sent: Letter.all) expect(entity.letters_sent.count).to eq(10) + Letter.find_each(&:save) + entity.save get "/entities/#{entity.id}/letters?relation=sent&start_date=1972-01-01&end_date=1974-06-01" expect(json[:letters].map {|letter| Date.parse(letter[:date]) }.min).to be >= DateTime.new(1972, 1, 1) expect(json[:letters].map {|letter| Date.parse(letter[:date]) }.min).to be <= DateTime.new(1974, 6, 1) @@ -143,6 +150,8 @@ create_list(:published_letter, 10) entity = create(:place_entity, letters_sent_from: Letter.all) expect(entity.letters_sent_from.count).to eq(10) + Letter.find_each(&:save) + entity.save get "/entities/#{entity.id}/letters?relation=origin&per_page=4&page=2" expect(json[:total_pages]).to eq(3) expect(json[:letters].count).to eq(4) diff --git a/spec/requests/letters_spec.rb b/spec/requests/letters_spec.rb index 1b12083..6d4ee50 100644 --- a/spec/requests/letters_spec.rb +++ b/spec/requests/letters_spec.rb @@ -138,23 +138,47 @@ it 'contains all three repositories' do premiere = create(:letter_repository) letter = premiere.letter + letter.repositories << premiere.repository + letter.save create(:letter_repository, letter:, repository: create(:published_repository), placement: 'deuxieme') create(:letter_repository, letter:, repository: create(:published_repository), placement: 'troisieme') get letter_url(letter), as: :json - expectd_keys = %w[repository format collection repository_information second_repository third_repository] - expect(json[:repositories].keys).to eq(expectd_keys) + expected_keys = %w[repository format collection repository_information second_repository third_repository] + expect(json[:repositories].keys).to eq(expected_keys) expect(response).to be_successful end it 'does not contain non-public repository' do premiere = create(:letter_repository) + expect(premiere.repository.published).to be(true) letter = premiere.letter + letter.repositories << premiere.repository create(:letter_repository, letter:, repository: create(:repository, published: false), placement: 'deuxieme') + letter.save get letter_url(letter), as: :json - expectd_keys = %w[repository format collection repository_information] - expect(json[:repositories].keys).to eq(expectd_keys) + expect(letter.published).to be(true) + expect(letter.repositories.count).to eq(2) + expected_keys = %w[repository format collection repository_information] + expect(json[:repositories].keys).to eq(expected_keys) expect(response).to be_successful end + + it 'renders unpublished when requested from beckettapi' do + letter = create(:letter) + expect(letter.published).to be(false) + get(letter_url(letter), headers: { HTTP_REFERER: 'beckettapi.ecdsdev.org' }) + expect(response).to be_successful + end + + it 'return 404 when unpublished and not requested from beckettapi' do + letter = create(:letter) + expect(letter.published).to be(false) + get letter_url(letter) + # The recommendation causes the test to fail. + # rubocop:disable RSpecRails/HaveHttpStatus + expect(response.status).to eq 404 + # rubocop:enable RSpecRails/HaveHttpStatus + end end describe 'POST /create' do