From 188119317e19560136a36ffa190c031c958cb833 Mon Sep 17 00:00:00 2001 From: Gabriel Jablonski Date: Tue, 29 Jul 2025 17:43:57 -0300 Subject: [PATCH] chore: allow non-admin to call `setup_channel_provider` and add localization (#90) * chore: allow non-admin to call `setup_channel_provider` and add localization * feat: allow agents to setup channel provider for assigned inboxes and handle unauthorized access --- .../api/v1/accounts/inboxes_controller.rb | 2 +- .../widgets/conversation/MessagesView.vue | 6 ++++- .../i18n/locale/en/conversation.json | 3 ++- .../i18n/locale/pt_BR/conversation.json | 3 ++- app/policies/inbox_policy.rb | 4 ---- .../v1/accounts/inboxes_controller_spec.rb | 24 ++++++++++++++++++- 6 files changed, 33 insertions(+), 9 deletions(-) diff --git a/app/controllers/api/v1/accounts/inboxes_controller.rb b/app/controllers/api/v1/accounts/inboxes_controller.rb index 51c4ffb9a..3f416a5b5 100644 --- a/app/controllers/api/v1/accounts/inboxes_controller.rb +++ b/app/controllers/api/v1/accounts/inboxes_controller.rb @@ -4,7 +4,7 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController before_action :fetch_agent_bot, only: [:set_agent_bot] before_action :validate_limit, only: [:create] # we are already handling the authorization in fetch inbox - before_action :check_authorization, except: [:show] + before_action :check_authorization, except: [:show, :setup_channel_provider] def index @inboxes = policy_scope(Current.account.inboxes.order_by_name.includes(:channel, { avatar_attachment: [:blob] })) diff --git a/app/javascript/dashboard/components/widgets/conversation/MessagesView.vue b/app/javascript/dashboard/components/widgets/conversation/MessagesView.vue index 80360171b..81e5d081b 100644 --- a/app/javascript/dashboard/components/widgets/conversation/MessagesView.vue +++ b/app/javascript/dashboard/components/widgets/conversation/MessagesView.vue @@ -477,7 +477,11 @@ export default { .catch(e => { // eslint-disable-next-line no-console console.error('Error setting up provider connection:', e); - useAlert('Failed to reconnect. Please try again or contact support.'); + useAlert( + this.$t( + 'CONVERSATION.INBOX.WHATSAPP_BAILEYS_PROVIDER_CONNECTION.RECONNECT_FAILED' + ) + ); }); }, }, diff --git a/app/javascript/dashboard/i18n/locale/en/conversation.json b/app/javascript/dashboard/i18n/locale/en/conversation.json index db572c620..1e7ccdb2e 100644 --- a/app/javascript/dashboard/i18n/locale/en/conversation.json +++ b/app/javascript/dashboard/i18n/locale/en/conversation.json @@ -255,7 +255,8 @@ "WHATSAPP_BAILEYS_PROVIDER_CONNECTION": { "NOT_CONNECTED": "WhatsApp is not connected. Please link your device again.", "NOT_CONNECTED_CONTACT_ADMIN": "WhatsApp is not connected. Click this button to try to reconnect, or please contact your administrator to link your device again.", - "LINK_DEVICE": "Link device" + "LINK_DEVICE": "Link device", + "RECONNECT_FAILED": "Failed to reconnect. Please contact your administrator to link your device again." } } }, diff --git a/app/javascript/dashboard/i18n/locale/pt_BR/conversation.json b/app/javascript/dashboard/i18n/locale/pt_BR/conversation.json index 519d2d24e..32a60ff25 100644 --- a/app/javascript/dashboard/i18n/locale/pt_BR/conversation.json +++ b/app/javascript/dashboard/i18n/locale/pt_BR/conversation.json @@ -255,7 +255,8 @@ "WHATSAPP_BAILEYS_PROVIDER_CONNECTION": { "NOT_CONNECTED": "O WhatsApp não está conectado. Por favor conecte o seu dispositivo novamente.", "NOT_CONNECTED_CONTACT_ADMIN": "O WhatsApp não está conectado. Clique no botão ao lado para tentar reconectar, ou contate o seu administrador para conectar o dispositivo novamente.", - "LINK_DEVICE": "Conectar dispositivo" + "LINK_DEVICE": "Conectar dispositivo", + "RECONNECT_FAILED": "Falha ao reconectar. Por favor, contate o seu administrador para conectar o dispositivo novamente." } } }, diff --git a/app/policies/inbox_policy.rb b/app/policies/inbox_policy.rb index d9f4f1066..519f7f7f2 100644 --- a/app/policies/inbox_policy.rb +++ b/app/policies/inbox_policy.rb @@ -58,10 +58,6 @@ class InboxPolicy < ApplicationPolicy @account_user.administrator? end - def setup_channel_provider? - @account_user.administrator? - end - def disconnect_channel_provider? @account_user.administrator? end diff --git a/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb b/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb index fb7c045e9..f7bb2e699 100644 --- a/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb @@ -941,6 +941,28 @@ RSpec.describe 'Inboxes API', type: :request do expect(response).to have_http_status(:ok) end + + it 'allows agents to setup channel provider for assigned inboxes' do + create(:inbox_member, user: agent, inbox: inbox) + service_double = instance_double(Whatsapp::Providers::WhatsappBaileysService, setup_channel_provider: true) + allow(Whatsapp::Providers::WhatsappBaileysService).to receive(:new) + .with(whatsapp_channel: channel) + .and_return(service_double) + + post "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/setup_channel_provider", + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:ok) + end + + it 'returns unauthorized for agents not assigned to the inbox' do + post "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/setup_channel_provider", + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:unauthorized) + end end end @@ -994,7 +1016,7 @@ RSpec.describe 'Inboxes API', type: :request do headers: admin.create_new_auth_token, as: :json - expect(response).to have_http_status(:internal_server_error) + expect(response).to have_http_status(:ok) expect(channel.reload.provider_connection).to eq('connection' => 'close') end end