From 7d27d3c8b1a5bb12e191b5f788f771e0bcfbf211 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Thu, 4 Dec 2025 03:02:27 -0800 Subject: [PATCH] allow officers to update joined_at on members and phantoms --- .../api/v1/crew_memberships_controller.rb | 22 ++++++++++++++++--- .../api/v1/phantom_players_controller.rb | 2 +- spec/requests/api/v1/crew_memberships_spec.rb | 16 ++++++++++++-- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/app/controllers/api/v1/crew_memberships_controller.rb b/app/controllers/api/v1/crew_memberships_controller.rb index 6e67b6f..e5968b4 100644 --- a/app/controllers/api/v1/crew_memberships_controller.rb +++ b/app/controllers/api/v1/crew_memberships_controller.rb @@ -9,11 +9,18 @@ module Api before_action :set_crew before_action :set_membership, only: %i[update destroy promote demote] before_action :authorize_crew_officer!, only: %i[destroy] - before_action :authorize_crew_captain!, only: %i[update promote demote] + before_action :authorize_crew_captain!, only: %i[promote demote] + before_action :authorize_membership_update!, only: %i[update] # PUT /crews/:crew_id/memberships/:id def update - if @membership.update(membership_params) + allowed_params = if current_user.crew_captain? + membership_params + else + membership_params.slice(:joined_at) + end + + if @membership.update(allowed_params) render json: CrewMembershipBlueprint.render(@membership, view: :with_user, root: :membership) else render_validation_error_response(@membership) @@ -59,7 +66,16 @@ module Api end def membership_params - params.require(:membership).permit(:role) + params.require(:membership).permit(:role, :joined_at) + end + + def authorize_membership_update! + # Officers can update any membership's joined_at + # Captains can update anything + return if current_user.crew_captain? + return if current_user.crew_officer? + + raise Api::V1::UnauthorizedError end end end diff --git a/app/controllers/api/v1/phantom_players_controller.rb b/app/controllers/api/v1/phantom_players_controller.rb index 351b8bf..2d00771 100644 --- a/app/controllers/api/v1/phantom_players_controller.rb +++ b/app/controllers/api/v1/phantom_players_controller.rb @@ -72,7 +72,7 @@ module Api end def phantom_params - params.require(:phantom_player).permit(:name, :granblue_id, :notes) + params.require(:phantom_player).permit(:name, :granblue_id, :notes, :joined_at) end end end diff --git a/spec/requests/api/v1/crew_memberships_spec.rb b/spec/requests/api/v1/crew_memberships_spec.rb index 534696d..9fc1fdb 100644 --- a/spec/requests/api/v1/crew_memberships_spec.rb +++ b/spec/requests/api/v1/crew_memberships_spec.rb @@ -29,12 +29,24 @@ RSpec.describe 'Api::V1::CrewMemberships', type: :request do context 'as vice captain' do let!(:vc_membership) { create(:crew_membership, crew: crew, user: user, role: :vice_captain) } - it 'returns unauthorized' do + it 'cannot change role but request succeeds' do put "/api/v1/crews/#{crew.id}/memberships/#{target_membership.id}", params: { membership: { role: 'vice_captain' } }, headers: auth_headers - expect(response).to have_http_status(:unauthorized) + # Vice captains can access update endpoint (for joined_at) but role param is ignored + expect(response).to have_http_status(:ok) + expect(target_membership.reload.role).to eq('member') # Role not changed + end + + it 'can update joined_at' do + put "/api/v1/crews/#{crew.id}/memberships/#{target_membership.id}", + params: { membership: { joined_at: '2024-01-15' } }, + headers: auth_headers + + expect(response).to have_http_status(:ok) + json = JSON.parse(response.body) + expect(json['membership']['joined_at']).to include('2024-01-15') end end end