diff --git a/app/controllers/super_admin/instance_statuses_controller.rb b/app/controllers/super_admin/instance_statuses_controller.rb index b0e97b95d..15a930c3e 100644 --- a/app/controllers/super_admin/instance_statuses_controller.rb +++ b/app/controllers/super_admin/instance_statuses_controller.rb @@ -7,6 +7,7 @@ class SuperAdmin::InstanceStatusesController < SuperAdmin::ApplicationController redis_metrics chatwoot_edition instance_meta + baileys_api_version end def chatwoot_edition @@ -56,4 +57,10 @@ class SuperAdmin::InstanceStatusesController < SuperAdmin::ApplicationController rescue Redis::CannotConnectError @metrics['Redis alive'] = false end + + def baileys_api_version + @metrics['Baileys API version'] = Whatsapp::Providers::WhatsappBaileysService.status[:packageInfo][:version] + rescue Whatsapp::Providers::WhatsappBaileysService::ProviderUnavailableError => e + @metrics['Baileys API version'] = e.message + end end diff --git a/app/services/whatsapp/providers/whatsapp_baileys_service.rb b/app/services/whatsapp/providers/whatsapp_baileys_service.rb index babd34b43..0c97a9190 100644 --- a/app/services/whatsapp/providers/whatsapp_baileys_service.rb +++ b/app/services/whatsapp/providers/whatsapp_baileys_service.rb @@ -8,6 +8,24 @@ class Whatsapp::Providers::WhatsappBaileysService < Whatsapp::Providers::BaseSer DEFAULT_URL = ENV.fetch('BAILEYS_PROVIDER_DEFAULT_URL', nil) DEFAULT_API_KEY = ENV.fetch('BAILEYS_PROVIDER_DEFAULT_API_KEY', nil) + def self.status + if DEFAULT_URL.blank? || DEFAULT_API_KEY.blank? + raise ProviderUnavailableError, 'Missing BAILEYS_PROVIDER_DEFAULT_URL or BAILEYS_PROVIDER_DEFAULT_API_KEY setup' + end + + response = HTTParty.get( + "#{DEFAULT_URL}/status", + headers: { 'x-api-key' => DEFAULT_API_KEY } + ) + + unless response.success? + Rails.logger.error response.body + raise ProviderUnavailableError, 'Baileys API is unavailable' + end + + response.parsed_response.deep_symbolize_keys + end + def setup_channel_provider response = HTTParty.post( "#{provider_url}/connections/#{whatsapp_channel.phone_number}", diff --git a/spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb b/spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb index 9ff5dc193..ef5eecd54 100644 --- a/spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb +++ b/spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb @@ -13,6 +13,83 @@ describe Whatsapp::Providers::WhatsappBaileysService do stub_const('Whatsapp::Providers::WhatsappBaileysService::DEFAULT_CLIENT_NAME', 'chatwoot-test') end + describe '.status' do + context 'when DEFAULT_URL or DEFAULT_API_KEY are missing' do + it 'raises ProviderUnavailableError when DEFAULT_URL is blank' do + stub_const('Whatsapp::Providers::WhatsappBaileysService::DEFAULT_URL', '') + stub_const('Whatsapp::Providers::WhatsappBaileysService::DEFAULT_API_KEY', 'test_key') + + expect do + described_class.status + end.to raise_error(Whatsapp::Providers::WhatsappBaileysService::ProviderUnavailableError, + 'Missing BAILEYS_PROVIDER_DEFAULT_URL or BAILEYS_PROVIDER_DEFAULT_API_KEY setup') + end + + it 'raises ProviderUnavailableError when DEFAULT_API_KEY is blank' do + stub_const('Whatsapp::Providers::WhatsappBaileysService::DEFAULT_URL', 'http://test.com') + stub_const('Whatsapp::Providers::WhatsappBaileysService::DEFAULT_API_KEY', '') + + expect do + described_class.status + end.to raise_error(Whatsapp::Providers::WhatsappBaileysService::ProviderUnavailableError, + 'Missing BAILEYS_PROVIDER_DEFAULT_URL or BAILEYS_PROVIDER_DEFAULT_API_KEY setup') + end + + it 'raises ProviderUnavailableError when both are blank' do + stub_const('Whatsapp::Providers::WhatsappBaileysService::DEFAULT_URL', nil) + stub_const('Whatsapp::Providers::WhatsappBaileysService::DEFAULT_API_KEY', nil) + + expect do + described_class.status + end.to raise_error(Whatsapp::Providers::WhatsappBaileysService::ProviderUnavailableError, + 'Missing BAILEYS_PROVIDER_DEFAULT_URL or BAILEYS_PROVIDER_DEFAULT_API_KEY setup') + end + end + + context 'when DEFAULT_URL and DEFAULT_API_KEY are present' do + before do + stub_const('Whatsapp::Providers::WhatsappBaileysService::DEFAULT_URL', 'http://test.com') + stub_const('Whatsapp::Providers::WhatsappBaileysService::DEFAULT_API_KEY', 'test_key') + end + + context 'when response is successful' do + it 'returns the status response with symbolized keys' do + stub_request(:get, 'http://test.com/status') + .with(headers: { 'x-api-key' => 'test_key' }) + .to_return( + status: 200, + headers: { 'Content-Type' => 'application/json' }, + body: { packageInfo: { version: '1.0.0' } }.to_json + ) + + result = described_class.status + + expect(result).to eq({ packageInfo: { version: '1.0.0' } }) + end + end + + context 'when response is unsuccessful' do + it 'logs the error and raises ProviderUnavailableError' do + stub_request(:get, 'http://test.com/status') + .with(headers: { 'x-api-key' => 'test_key' }) + .to_return( + status: 500, + body: 'Internal Server Error', + headers: {} + ) + + allow(Rails.logger).to receive(:error) + + expect do + described_class.status + end.to raise_error(Whatsapp::Providers::WhatsappBaileysService::ProviderUnavailableError, 'Baileys API is unavailable') + + expect(Rails.logger).to have_received(:error).with('Internal Server Error') + end + end + end + end + describe '#setup_channel_provider' do context 'when response is successful' do it 'calls the connection endpoint' do