diff --git a/app/controllers/api/v1/widget/contacts_controller.rb b/app/controllers/api/v1/widget/contacts_controller.rb index 9a7d5193a..3fc1e8aac 100644 --- a/app/controllers/api/v1/widget/contacts_controller.rb +++ b/app/controllers/api/v1/widget/contacts_controller.rb @@ -1,6 +1,7 @@ class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController include WidgetHelper + before_action :ensure_inbox_active, only: [:update, :set_user, :destroy_custom_attributes] before_action :validate_hmac, only: [:set_user] before_action :validate_hmac_for_identified_update, only: [:update] diff --git a/app/controllers/api/v1/widget/direct_uploads_controller.rb b/app/controllers/api/v1/widget/direct_uploads_controller.rb index a6abdb3e1..fc13e547c 100644 --- a/app/controllers/api/v1/widget/direct_uploads_controller.rb +++ b/app/controllers/api/v1/widget/direct_uploads_controller.rb @@ -1,6 +1,7 @@ class Api::V1::Widget::DirectUploadsController < ActiveStorage::DirectUploadsController include WebsiteTokenHelper before_action :set_web_widget + before_action :ensure_inbox_active before_action :set_contact def create @@ -8,4 +9,15 @@ class Api::V1::Widget::DirectUploadsController < ActiveStorage::DirectUploadsCon super end + + private + + def ensure_inbox_active + return if @web_widget.inbox.active? + + render json: { + error: 'inbox_disabled', + message: 'This inbox is currently disabled' + }, status: :forbidden + end end diff --git a/app/controllers/api/v1/widget/events_controller.rb b/app/controllers/api/v1/widget/events_controller.rb index 2cf17c964..ac8bb95e7 100644 --- a/app/controllers/api/v1/widget/events_controller.rb +++ b/app/controllers/api/v1/widget/events_controller.rb @@ -1,6 +1,8 @@ class Api::V1::Widget::EventsController < Api::V1::Widget::BaseController include Events::Types + before_action :ensure_inbox_active + def create Rails.configuration.dispatcher.dispatch(permitted_params[:name], Time.zone.now, contact_inbox: @contact_inbox, event_info: permitted_params[:event_info].to_h.merge(event_info)) diff --git a/app/controllers/api/v1/widget/integrations/dyte_controller.rb b/app/controllers/api/v1/widget/integrations/dyte_controller.rb index fde425b26..65f2b5826 100644 --- a/app/controllers/api/v1/widget/integrations/dyte_controller.rb +++ b/app/controllers/api/v1/widget/integrations/dyte_controller.rb @@ -1,4 +1,5 @@ class Api::V1::Widget::Integrations::DyteController < Api::V1::Widget::BaseController + before_action :ensure_inbox_active before_action :set_message def add_participant_to_meeting diff --git a/app/controllers/api/v1/widget/labels_controller.rb b/app/controllers/api/v1/widget/labels_controller.rb index 52d1fa3d3..e1ea9a435 100644 --- a/app/controllers/api/v1/widget/labels_controller.rb +++ b/app/controllers/api/v1/widget/labels_controller.rb @@ -1,4 +1,6 @@ class Api::V1::Widget::LabelsController < Api::V1::Widget::BaseController + before_action :ensure_inbox_active + def create if conversation.present? && label_defined_in_account? conversation.label_list.add(permitted_params[:label]) diff --git a/app/models/campaign.rb b/app/models/campaign.rb index 479b5bdd0..4ec1496f8 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -58,6 +58,7 @@ class Campaign < ApplicationRecord def trigger! return unless one_off? return unless feature_enabled? + return unless inbox.active? return unless mark_processing! execute_campaign diff --git a/spec/controllers/api/v1/widget/contacts_controller_spec.rb b/spec/controllers/api/v1/widget/contacts_controller_spec.rb index 1d1616d2e..5f90a900f 100644 --- a/spec/controllers/api/v1/widget/contacts_controller_spec.rb +++ b/spec/controllers/api/v1/widget/contacts_controller_spec.rb @@ -37,6 +37,18 @@ RSpec.describe '/api/v1/widget/contacts', type: :request do expect(ContactIdentifyAction).to have_received(:new).with(expected_params) expect(identify_action).to have_received(:perform) end + + it 'does not update the contact when the inbox is disabled' do + web_widget.inbox.update!(active: false) + + patch '/api/v1/widget/contact', + params: params, + headers: { 'X-Auth-Token' => token }, + as: :json + + expect(response).to have_http_status(:forbidden) + expect(ContactIdentifyAction).not_to have_received(:new) + end end context 'with update contact' do @@ -255,6 +267,18 @@ RSpec.describe '/api/v1/widget/contacts', type: :request do expect(response).to have_http_status(:unauthorized) end + + it 'does not set user when the inbox is disabled' do + web_widget.inbox.update!(active: false) + + patch '/api/v1/widget/contact/set_user', + params: params.merge(identifier_hash: correct_identifier_hash), + headers: { 'X-Auth-Token' => token }, + as: :json + + expect(response).to have_http_status(:forbidden) + expect(ContactIdentifyAction).not_to have_received(:new) + end end end @@ -263,19 +287,32 @@ RSpec.describe '/api/v1/widget/contacts', type: :request do context 'with invalid website token' do it 'returns unauthorized' do - post '/api/v1/widget/destroy_custom_attributes', params: { website_token: '' } + post '/api/v1/widget/contact/destroy_custom_attributes', params: { website_token: '' } expect(response).to have_http_status(:not_found) end end context 'with correct website token' do it 'calls destroy custom attributes' do - post '/api/v1/widget/destroy_custom_attributes', + post '/api/v1/widget/contact/destroy_custom_attributes', params: params, headers: { 'X-Auth-Token' => token }, as: :json expect(contact.reload.custom_attributes).to eq({}) end + + it 'does not destroy custom attributes when the inbox is disabled' do + contact.update!(custom_attributes: { 'test' => 'value' }) + web_widget.inbox.update!(active: false) + + post '/api/v1/widget/contact/destroy_custom_attributes', + params: params, + headers: { 'X-Auth-Token' => token }, + as: :json + + expect(response).to have_http_status(:forbidden) + expect(contact.reload.custom_attributes).to eq('test' => 'value') + end end end end diff --git a/spec/controllers/api/v1/widget/direct_uploads_controller_spec.rb b/spec/controllers/api/v1/widget/direct_uploads_controller_spec.rb index bf1da7d37..b9173adf6 100644 --- a/spec/controllers/api/v1/widget/direct_uploads_controller_spec.rb +++ b/spec/controllers/api/v1/widget/direct_uploads_controller_spec.rb @@ -34,6 +34,24 @@ RSpec.describe '/api/v1/widget/direct_uploads', type: :request do json_response = response.parsed_body expect(json_response['content_type']).to eq('image/png') end + + it 'does not create direct upload when the inbox is disabled' do + web_widget.inbox.update!(active: false) + + post api_v1_widget_direct_uploads_url, + params: { + website_token: web_widget.website_token, + blob: { + filename: 'avatar.png', + byte_size: '1234', + checksum: 'dsjbsdhbfif3874823mnsdbf', + content_type: 'image/png' + } + }, + headers: { 'X-Auth-Token' => token } + + expect(response).to have_http_status(:forbidden) + end end end end diff --git a/spec/controllers/api/v1/widget/events_controller_spec.rb b/spec/controllers/api/v1/widget/events_controller_spec.rb index fdc8cb4fa..2ef95355e 100644 --- a/spec/controllers/api/v1/widget/events_controller_spec.rb +++ b/spec/controllers/api/v1/widget/events_controller_spec.rb @@ -34,6 +34,20 @@ RSpec.describe '/api/v1/widget/events', type: :request do .with(params[:name], anything, contact_inbox: contact_inbox, event_info: { test_id: 'test', browser_language: nil, widget_language: nil, browser: anything }) end + + it 'does not dispatch events when the inbox is disabled' do + token + web_widget.inbox.update!(active: false) + + expect(Rails.configuration.dispatcher).not_to receive(:dispatch) + + post '/api/v1/widget/events', + params: params, + headers: { 'X-Auth-Token' => token }, + as: :json + + expect(response).to have_http_status(:forbidden) + end end end end diff --git a/spec/controllers/api/v1/widget/integrations/dyte_controller_spec.rb b/spec/controllers/api/v1/widget/integrations/dyte_controller_spec.rb index c5a4e1bdc..fe09314ec 100644 --- a/spec/controllers/api/v1/widget/integrations/dyte_controller_spec.rb +++ b/spec/controllers/api/v1/widget/integrations/dyte_controller_spec.rb @@ -70,6 +70,17 @@ RSpec.describe '/api/v1/widget/integrations/dyte', type: :request do } ) end + + it 'does not add a participant when the inbox is disabled' do + web_widget.inbox.update!(active: false) + + post add_participant_to_meeting_api_v1_widget_integrations_dyte_url, + headers: { 'X-Auth-Token' => token }, + params: { website_token: web_widget.website_token, message_id: integration_message.id }, + as: :json + + expect(response).to have_http_status(:forbidden) + end end end end diff --git a/spec/controllers/api/v1/widget/labels_controller_spec.rb b/spec/controllers/api/v1/widget/labels_controller_spec.rb index 42572f256..8a57d4a3e 100644 --- a/spec/controllers/api/v1/widget/labels_controller_spec.rb +++ b/spec/controllers/api/v1/widget/labels_controller_spec.rb @@ -39,6 +39,18 @@ RSpec.describe '/api/v1/widget/labels', type: :request do expect(conversation.reload.label_list.count).to eq 1 expect(conversation.reload.label_list.first).to eq 'customer-support' end + + it 'does not add labels when the inbox is disabled' do + web_widget.inbox.update!(active: false) + + post '/api/v1/widget/labels', + params: params, + headers: { 'X-Auth-Token' => token }, + as: :json + + expect(response).to have_http_status(:forbidden) + expect(conversation.reload.label_list.count).to eq 0 + end end context 'with invalid website token' do @@ -67,6 +79,18 @@ RSpec.describe '/api/v1/widget/labels', type: :request do expect(response).to have_http_status(:success) expect(conversation.reload.label_list.count).to eq 0 end + + it 'does not remove labels when the inbox is disabled' do + web_widget.inbox.update!(active: false) + + delete "/api/v1/widget/labels/#{params[:label]}", + params: params, + headers: { 'X-Auth-Token' => token }, + as: :json + + expect(response).to have_http_status(:forbidden) + expect(conversation.reload.label_list.count).to eq 1 + end end context 'with invalid website token' do diff --git a/spec/models/campaign_spec.rb b/spec/models/campaign_spec.rb index e4bdd05e4..813dfdc2e 100644 --- a/spec/models/campaign_spec.rb +++ b/spec/models/campaign_spec.rb @@ -142,6 +142,17 @@ RSpec.describe Campaign do campaign.trigger! end + it 'does not trigger the campaign when the inbox is disabled' do + campaign.save! + twilio_inbox.update!(active: false) + + expect(Twilio::OneoffSmsCampaignService).not_to receive(:new) + + campaign.trigger! + + expect(campaign.reload.active?).to be true + end + it 'keeps the campaign processing when triggering fails' do campaign.save! sms_service = double