From b0a8fa70d027d2686f8609c15cd7febc9062b489 Mon Sep 17 00:00:00 2001 From: Gabriel Jablonski Date: Thu, 9 Apr 2026 16:17:20 -0300 Subject: [PATCH] fix(signatures): allow admins to manage inbox signatures without explicit membership (#260) Administrators have access to all inboxes in an account but the validate_inbox_access filter only checked InboxMember records, returning 401 for admins not explicitly added as inbox members. --- .../v1/profile/inbox_signatures_controller.rb | 10 +++- .../inbox_signatures_controller_spec.rb | 50 +++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/v1/profile/inbox_signatures_controller.rb b/app/controllers/api/v1/profile/inbox_signatures_controller.rb index e375184f6..afe4d5b35 100644 --- a/app/controllers/api/v1/profile/inbox_signatures_controller.rb +++ b/app/controllers/api/v1/profile/inbox_signatures_controller.rb @@ -48,8 +48,14 @@ class Api::V1::Profile::InboxSignaturesController < Api::BaseController end def validate_inbox_access - inbox_id = params[:inbox_id] - return if InboxMember.exists?(user_id: @user.id, inbox_id: inbox_id) + inbox = Inbox.find_by(id: params[:inbox_id]) + return head :not_found unless inbox + + account_user = @user.account_users.find_by(account_id: inbox.account_id) + return head :unauthorized unless account_user + + return if account_user.administrator? + return if InboxMember.exists?(user_id: @user.id, inbox_id: inbox.id) head :unauthorized end diff --git a/spec/controllers/api/v1/profile/inbox_signatures_controller_spec.rb b/spec/controllers/api/v1/profile/inbox_signatures_controller_spec.rb index a2eacaac5..fec0e29a3 100644 --- a/spec/controllers/api/v1/profile/inbox_signatures_controller_spec.rb +++ b/spec/controllers/api/v1/profile/inbox_signatures_controller_spec.rb @@ -102,6 +102,23 @@ RSpec.describe 'Profile Inbox Signatures API', type: :request do expect(response).to have_http_status(:unauthorized) end end + + context 'when the user is an administrator without inbox membership' do + let(:admin) { create(:user, account: account, role: :administrator) } + + it 'returns the inbox signature' do + inbox_signature = create(:inbox_signature, user: admin, inbox: inbox) + + get "/api/v1/profile/inbox_signatures/#{inbox.id}", + headers: admin.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + json_response = response.parsed_body + expect(json_response['inbox_id']).to eq(inbox.id) + expect(json_response['message_signature']).to eq(inbox_signature.message_signature) + end + end end describe 'PUT /api/v1/profile/inbox_signatures/:inbox_id' do @@ -164,6 +181,23 @@ RSpec.describe 'Profile Inbox Signatures API', type: :request do end end + context 'when the user is an administrator without inbox membership' do + let(:admin) { create(:user, account: account, role: :administrator) } + + it 'creates a new inbox signature' do + expect do + put "/api/v1/profile/inbox_signatures/#{inbox.id}", + params: signature_params, + headers: admin.create_new_auth_token, + as: :json + end.to change(InboxSignature, :count).by(1) + + expect(response).to have_http_status(:success) + json_response = response.parsed_body + expect(json_response['message_signature']).to eq('

Custom Signature

') + end + end + context 'when params are invalid' do let(:invalid_params) do { @@ -221,5 +255,21 @@ RSpec.describe 'Profile Inbox Signatures API', type: :request do expect(response).to have_http_status(:unauthorized) end end + + context 'when the user is an administrator without inbox membership' do + let(:admin) { create(:user, account: account, role: :administrator) } + + it 'deletes the inbox signature' do + create(:inbox_signature, user: admin, inbox: inbox) + + expect do + delete "/api/v1/profile/inbox_signatures/#{inbox.id}", + headers: admin.create_new_auth_token, + as: :json + end.to change(InboxSignature, :count).by(-1) + + expect(response).to have_http_status(:no_content) + end + end end end