test: hide sync metadata from public show

This commit is contained in:
Daniel Schädler 2026-04-20 19:48:10 +02:00
parent b65dd35654
commit 2019d0d029
2 changed files with 37 additions and 8 deletions

View File

@ -2,8 +2,10 @@
class TournamentSerializer < SimpleTournamentSerializer class TournamentSerializer < SimpleTournamentSerializer
attributes :description, :playoff_teams_amount, attributes :description, :playoff_teams_amount,
:instant_finalists_amount, :intermediate_round_participants_amount, :instant_finalists_amount, :intermediate_round_participants_amount
:read_only_mode, :sync_target_url, :sync_last_push_error attribute :read_only_mode, if: :sync_metadata_visible?
attribute :sync_target_url, if: :sync_metadata_visible?
attribute :sync_last_push_error, if: :sync_metadata_visible?
# NEVER expose sync_auth_token anywhere - it should only ever be written to or checked against # NEVER expose sync_auth_token anywhere - it should only ever be written to or checked against
has_many :stages has_many :stages
@ -12,7 +14,7 @@ class TournamentSerializer < SimpleTournamentSerializer
object.timer_end&.iso8601 object.timer_end&.iso8601
end end
attribute :sync_last_pushed_at do attribute :sync_last_pushed_at, if: :sync_metadata_visible? do
object.sync_last_pushed_at&.iso8601 object.sync_last_pushed_at&.iso8601
end end
@ -30,4 +32,8 @@ class TournamentSerializer < SimpleTournamentSerializer
} }
end end
end end
def sync_metadata_visible?
scope.present? && scope == object.owner
end
end end

View File

@ -103,21 +103,21 @@ RSpec.describe TournamentsController, type: :controller do
json = deserialize_response(response) json = deserialize_response(response)
expect(json[:id].to_i).to eq(@tournament.id) expect(json[:id].to_i).to eq(@tournament.id)
expected_keys = %i[ expected_keys = %i[
id name code public description playoff_teams_amount instant_finalists_amount id name code public description playoff_teams_amount
intermediate_round_participants_amount read_only_mode sync_target_url instant_finalists_amount intermediate_round_participants_amount
sync_last_push_error sync_last_pushed_at timer_end owner_username stages teams timer_end owner_username stages teams
] ]
expect(json.keys).to match_array(expected_keys) expect(json.keys).to match_array(expected_keys)
expect(json).to eq(TournamentSerializer.new(@tournament).as_json)
expect(json[:name]).to eq(@tournament.name) expect(json[:name]).to eq(@tournament.name)
expect(json[:description]).to eq(@tournament.description) expect(json[:description]).to eq(@tournament.description)
expect(json[:public]).to eq(@tournament.public) expect(json[:public]).to eq(@tournament.public)
end end
it 'returns sync metadata on full tournament payload' do it 'does not return sync metadata on unauthenticated requests' do
pushed_at = Time.utc(2026, 4, 20, 12, 0, 0) pushed_at = Time.utc(2026, 4, 20, 12, 0, 0)
@tournament.update!( @tournament.update!(
read_only_mode: true, read_only_mode: true,
sync_target_url: 'https://remote.example.com/tournaments/1/sync_state',
sync_auth_token: 'shared-secret', sync_auth_token: 'shared-secret',
sync_last_pushed_at: pushed_at, sync_last_pushed_at: pushed_at,
sync_last_push_error: 'push failed' sync_last_push_error: 'push failed'
@ -125,11 +125,34 @@ RSpec.describe TournamentsController, type: :controller do
get :show, params: { id: @tournament.to_param } get :show, params: { id: @tournament.to_param }
json = deserialize_response(response)
expect(json).not_to have_key(:read_only_mode)
expect(json).not_to have_key(:sync_target_url)
expect(json).not_to have_key(:sync_last_pushed_at)
expect(json).not_to have_key(:sync_last_push_error)
expect(json).not_to have_key(:sync_auth_token)
end
it 'returns sync metadata to owner requests' do
pushed_at = Time.utc(2026, 4, 20, 12, 0, 0)
@tournament.update!(
read_only_mode: true,
sync_target_url: 'https://remote.example.com/tournaments/1/sync_state',
sync_auth_token: 'shared-secret',
sync_last_pushed_at: pushed_at,
sync_last_push_error: 'push failed'
)
apply_authentication_headers_for @tournament.owner
get :show, params: { id: @tournament.to_param }
json = deserialize_response(response) json = deserialize_response(response)
expect(json[:read_only_mode]).to eq(true) expect(json[:read_only_mode]).to eq(true)
expect(json[:sync_target_url]).to eq('https://remote.example.com/tournaments/1/sync_state')
expect(json[:sync_last_pushed_at]).to eq(pushed_at.iso8601) expect(json[:sync_last_pushed_at]).to eq(pushed_at.iso8601)
expect(json[:sync_last_push_error]).to eq('push failed') expect(json[:sync_last_push_error]).to eq('push failed')
expect(json).not_to have_key(:sync_auth_token) expect(json).not_to have_key(:sync_auth_token)
expect(json).to eq(TournamentSerializer.new(@tournament, scope: @tournament.owner).as_json)
end end
context 'with simple=true parameter' do context 'with simple=true parameter' do