From a4c7b738885fac80a16aeef70a32cb6ff3fe49b0 Mon Sep 17 00:00:00 2001 From: Sojan Jose Date: Wed, 14 May 2025 23:58:54 -0700 Subject: [PATCH] fix: Manage Twilio SMS channel via inbox API (#11457) - Currently Chatwoot manages Twilio Inbox creation in a separate controller , We want to move this to inboxes api so that we have a unified API for inbox related changes --------- Co-authored-by: Muhsin Keloth --- .../channels/twilio_channels_controller.rb | 3 ++ app/models/channel/twilio_sms.rb | 5 +++ app/views/api/v1/models/_inbox.json.jbuilder | 4 ++ .../v1/accounts/inboxes_controller_spec.rb | 42 +++++++++++++++++++ 4 files changed, 54 insertions(+) diff --git a/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb b/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb index ebf8e49dd..58ec3bfca 100644 --- a/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb +++ b/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb @@ -1,3 +1,6 @@ +# TODO : Move this to inboxes controller and deprecate this controller +# No need to retain this controller as we could handle everything centrally in inboxes controller + class Api::V1::Accounts::Channels::TwilioChannelsController < Api::V1::Accounts::BaseController before_action :authorize_request diff --git a/app/models/channel/twilio_sms.rb b/app/models/channel/twilio_sms.rb index 8dbe47703..e4575f58a 100644 --- a/app/models/channel/twilio_sms.rb +++ b/app/models/channel/twilio_sms.rb @@ -30,6 +30,11 @@ class Channel::TwilioSms < ApplicationRecord # The same parameter is used to store api_key_secret if api_key authentication is opted validates :auth_token, presence: true + EDITABLE_ATTRS = [ + :account_sid, + :auth_token + ].freeze + # Must have _one_ of messaging_service_sid _or_ phone_number, and messaging_service_sid is preferred validates :messaging_service_sid, uniqueness: true, presence: true, unless: :phone_number? validates :phone_number, absence: true, if: :messaging_service_sid? diff --git a/app/views/api/v1/models/_inbox.json.jbuilder b/app/views/api/v1/models/_inbox.json.jbuilder index 42a1a7370..0747924d9 100644 --- a/app/views/api/v1/models/_inbox.json.jbuilder +++ b/app/views/api/v1/models/_inbox.json.jbuilder @@ -62,6 +62,10 @@ json.instagram_id resource.channel.try(:instagram_id) if resource.instagram? json.messaging_service_sid resource.channel.try(:messaging_service_sid) json.phone_number resource.channel.try(:phone_number) json.medium resource.channel.try(:medium) if resource.twilio? +if resource.twilio? && Current.account_user&.administrator? + json.auth_token resource.channel.try(:auth_token) + json.account_sid resource.channel.try(:account_sid) +end if resource.email? ## Email Channel Attributes diff --git a/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb b/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb index 7b3dafccb..f8655da44 100644 --- a/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb @@ -147,6 +147,32 @@ RSpec.describe 'Inboxes API', type: :request do expect(data[:imap_login]).to eq('test@test.com') end + context 'when it is a Twilio inbox' do + let(:twilio_channel) { create(:channel_twilio_sms, account: account, account_sid: 'AC123', auth_token: 'secrettoken') } + let(:twilio_inbox) { create(:inbox, channel: twilio_channel, account: account) } + + it 'returns auth_token and account_sid for admin' do + get "/api/v1/accounts/#{account.id}/inboxes/#{twilio_inbox.id}", + headers: admin.create_new_auth_token, + as: :json + expect(response).to have_http_status(:success) + data = JSON.parse(response.body, symbolize_names: true) + expect(data[:auth_token]).to eq('secrettoken') + expect(data[:account_sid]).to eq('AC123') + end + + it "doesn't return auth_token and account_sid for agent" do + create(:inbox_member, user: agent, inbox: twilio_inbox) + get "/api/v1/accounts/#{account.id}/inboxes/#{twilio_inbox.id}", + headers: agent.create_new_auth_token, + as: :json + expect(response).to have_http_status(:success) + data = JSON.parse(response.body, symbolize_names: true) + expect(data[:auth_token]).to be_nil + expect(data[:account_sid]).to be_nil + end + end + it 'fetch API inbox without hmac token when agent' do api_channel = create(:channel_api, account: account) api_inbox = create(:inbox, channel: api_channel, account: account) @@ -518,6 +544,22 @@ RSpec.describe 'Inboxes API', type: :request do expect(email_channel.reload.email).to eq('emailtest@email.test') end + it 'updates twilio sms inbox when administrator' do + twilio_sms_channel = create(:channel_twilio_sms, account: account) + twilio_sms_inbox = create(:inbox, channel: twilio_sms_channel, account: account) + expect(twilio_sms_inbox.reload.channel.account_sid).not_to eq('account_sid') + expect(twilio_sms_inbox.reload.channel.auth_token).not_to eq('new_auth_token') + + patch "/api/v1/accounts/#{account.id}/inboxes/#{twilio_sms_inbox.id}", + headers: admin.create_new_auth_token, + params: { channel: { account_sid: 'account_sid', auth_token: 'new_auth_token' } }, + as: :json + + expect(response).to have_http_status(:success) + expect(twilio_sms_inbox.reload.channel.account_sid).to eq('account_sid') + expect(twilio_sms_inbox.reload.channel.auth_token).to eq('new_auth_token') + end + it 'updates email inbox with imap when administrator' do email_channel = create(:channel_email, account: account) email_inbox = create(:inbox, channel: email_channel, account: account)