From 55f625731344c0c9dea9fb89ef93008b1c226974 Mon Sep 17 00:00:00 2001 From: Sojan Jose Date: Tue, 24 Feb 2026 20:29:53 -0800 Subject: [PATCH] chore(hub): clean up legacy Captain hub flow (#13640) ## Summary This PR cleans up legacy Hub/Captain integration paths and simplifies hub URL behavior coverage in tests. ## Changes - remove legacy Captain account endpoint flow from `ChatwootHub` - remove obsolete spec coverage tied to that retired flow - keep hub URL handling centralized in `base_url` with enterprise overlay precedence - simplify hub URL specs to assert explicit static URL expectations where applicable ## Reproduce Run the focused hub specs from this branch: - `bundle exec rspec spec/lib/chatwoot_hub_spec.rb spec/enterprise/lib/chatwoot_hub_spec.rb` ## Testing Validated locally with: - `bundle exec rspec spec/lib/chatwoot_hub_spec.rb spec/enterprise/lib/chatwoot_hub_spec.rb` - `bundle exec rubocop lib/chatwoot_hub.rb spec/lib/chatwoot_hub_spec.rb enterprise/lib/enterprise/chatwoot_hub.rb spec/enterprise/lib/chatwoot_hub_spec.rb` --- enterprise/lib/enterprise/chatwoot_hub.rb | 9 ++++ lib/chatwoot_hub.rb | 55 +++++++++++++---------- spec/enterprise/lib/chatwoot_hub_spec.rb | 21 +++++++++ spec/lib/chatwoot_hub_spec.rb | 37 +++++---------- 4 files changed, 74 insertions(+), 48 deletions(-) create mode 100644 enterprise/lib/enterprise/chatwoot_hub.rb create mode 100644 spec/enterprise/lib/chatwoot_hub_spec.rb diff --git a/enterprise/lib/enterprise/chatwoot_hub.rb b/enterprise/lib/enterprise/chatwoot_hub.rb new file mode 100644 index 000000000..a9d572d2d --- /dev/null +++ b/enterprise/lib/enterprise/chatwoot_hub.rb @@ -0,0 +1,9 @@ +module Enterprise::ChatwootHub + ENTERPRISE_BASE_URL = 'https://hub.2.chatwoot.com'.freeze + + def base_url + return ENV.fetch('CHATWOOT_HUB_URL', ENTERPRISE_BASE_URL) if Rails.env.development? + + ENTERPRISE_BASE_URL + end +end diff --git a/lib/chatwoot_hub.rb b/lib/chatwoot_hub.rb index c18fb299b..be5a07e05 100644 --- a/lib/chatwoot_hub.rb +++ b/lib/chatwoot_hub.rb @@ -1,12 +1,30 @@ # TODO: lets use HTTParty instead of RestClient class ChatwootHub - BASE_URL = ENV.fetch('CHATWOOT_HUB_URL', 'https://hub.2.chatwoot.com') - PING_URL = "#{BASE_URL}/ping".freeze - REGISTRATION_URL = "#{BASE_URL}/instances".freeze - PUSH_NOTIFICATION_URL = "#{BASE_URL}/send_push".freeze - EVENTS_URL = "#{BASE_URL}/events".freeze - BILLING_URL = "#{BASE_URL}/billing".freeze - CAPTAIN_ACCOUNTS_URL = "#{BASE_URL}/instance_captain_accounts".freeze + DEFAULT_BASE_URL = 'https://hub.2.chatwoot.com'.freeze + + def self.base_url + DEFAULT_BASE_URL + end + + def self.ping_url + "#{base_url}/ping" + end + + def self.registration_url + "#{base_url}/instances" + end + + def self.push_notification_url + "#{base_url}/send_push" + end + + def self.events_url + "#{base_url}/events" + end + + def self.billing_base_url + "#{base_url}/billing" + end def self.installation_identifier identifier = InstallationConfig.find_by(name: 'INSTALLATION_IDENTIFIER')&.value @@ -15,7 +33,7 @@ class ChatwootHub end def self.billing_url - "#{BILLING_URL}?installation_identifier=#{installation_identifier}" + "#{billing_base_url}?installation_identifier=#{installation_identifier}" end def self.pricing_plan @@ -68,7 +86,7 @@ class ChatwootHub begin info = instance_config info = info.merge(instance_metrics) unless ENV['DISABLE_TELEMETRY'] - response = RestClient.post(PING_URL, info.to_json, { content_type: :json, accept: :json }) + response = RestClient.post(ping_url, info.to_json, { content_type: :json, accept: :json }) parsed_response = JSON.parse(response) rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e Rails.logger.error "Exception: #{e.message}" @@ -80,7 +98,7 @@ class ChatwootHub def self.register_instance(company_name, owner_name, owner_email) info = { company_name: company_name, owner_name: owner_name, owner_email: owner_email, subscribed_to_mailers: true } - RestClient.post(REGISTRATION_URL, info.merge(instance_config).to_json, { content_type: :json, accept: :json }) + RestClient.post(registration_url, info.merge(instance_config).to_json, { content_type: :json, accept: :json }) rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e Rails.logger.error "Exception: #{e.message}" rescue StandardError => e @@ -89,32 +107,23 @@ class ChatwootHub def self.send_push(fcm_options) info = { fcm_options: fcm_options } - RestClient.post(PUSH_NOTIFICATION_URL, info.merge(instance_config).to_json, { content_type: :json, accept: :json }) + RestClient.post(push_notification_url, info.merge(instance_config).to_json, { content_type: :json, accept: :json }) rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e Rails.logger.error "Exception: #{e.message}" rescue StandardError => e ChatwootExceptionTracker.new(e).capture_exception end - def self.get_captain_settings(account) - info = { - installation_identifier: installation_identifier, - chatwoot_account_id: account.id, - account_name: account.name - } - HTTParty.post(CAPTAIN_ACCOUNTS_URL, - body: info.to_json, - headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' }) - end - def self.emit_event(event_name, event_data) return if ENV['DISABLE_TELEMETRY'] info = { event_name: event_name, event_data: event_data } - RestClient.post(EVENTS_URL, info.merge(instance_config).to_json, { content_type: :json, accept: :json }) + RestClient.post(events_url, info.merge(instance_config).to_json, { content_type: :json, accept: :json }) rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e Rails.logger.error "Exception: #{e.message}" rescue StandardError => e ChatwootExceptionTracker.new(e).capture_exception end end + +ChatwootHub.singleton_class.prepend_mod_with('ChatwootHub') diff --git a/spec/enterprise/lib/chatwoot_hub_spec.rb b/spec/enterprise/lib/chatwoot_hub_spec.rb new file mode 100644 index 000000000..24d78d028 --- /dev/null +++ b/spec/enterprise/lib/chatwoot_hub_spec.rb @@ -0,0 +1,21 @@ +require 'rails_helper' + +RSpec.describe ChatwootHub do + describe '.base_url' do + it 'uses the static hub url outside development for enterprise edition' do + with_modified_env CHATWOOT_HUB_URL: 'https://custom.example.com' do + allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('production')) + + expect(described_class.base_url).to eq('https://hub.2.chatwoot.com') + end + end + + it 'uses CHATWOOT_HUB_URL in development for enterprise edition' do + with_modified_env CHATWOOT_HUB_URL: 'https://custom.example.com' do + allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('development')) + + expect(described_class.base_url).to eq('https://custom.example.com') + end + end + end +end diff --git a/spec/lib/chatwoot_hub_spec.rb b/spec/lib/chatwoot_hub_spec.rb index 0f53971af..a1051e619 100644 --- a/spec/lib/chatwoot_hub_spec.rb +++ b/spec/lib/chatwoot_hub_spec.rb @@ -1,6 +1,13 @@ require 'rails_helper' describe ChatwootHub do + describe '.base_url' do + it 'uses the static hub url' do + expect(described_class::DEFAULT_BASE_URL).to eq('https://hub.2.chatwoot.com') + expect(described_class.base_url).to eq('https://hub.2.chatwoot.com') + end + end + it 'generates installation identifier' do installation_identifier = described_class.installation_identifier expect(installation_identifier).not_to be_nil @@ -12,7 +19,7 @@ describe ChatwootHub do version = '1.1.1' allow(RestClient).to receive(:post).and_return({ version: version }.to_json) expect(described_class.sync_with_hub['version']).to eq version - expect(RestClient).to have_received(:post).with(described_class::PING_URL, described_class.instance_config + expect(RestClient).to have_received(:post).with(described_class.ping_url, described_class.instance_config .merge(described_class.instance_metrics).to_json, { content_type: :json, accept: :json }) end @@ -21,7 +28,7 @@ describe ChatwootHub do with_modified_env DISABLE_TELEMETRY: 'true' do allow(RestClient).to receive(:post).and_return({ version: version }.to_json) expect(described_class.sync_with_hub['version']).to eq version - expect(RestClient).to have_received(:post).with(described_class::PING_URL, + expect(RestClient).to have_received(:post).with(described_class.ping_url, described_class.instance_config.to_json, { content_type: :json, accept: :json }) end end @@ -41,7 +48,7 @@ describe ChatwootHub do info = { company_name: company_name, owner_name: owner_name, owner_email: owner_email, subscribed_to_mailers: true } allow(RestClient).to receive(:post) described_class.register_instance(company_name, owner_name, owner_email) - expect(RestClient).to have_received(:post).with(described_class::REGISTRATION_URL, + expect(RestClient).to have_received(:post).with(described_class.registration_url, info.merge(described_class.instance_config).to_json, { content_type: :json, accept: :json }) end end @@ -54,7 +61,7 @@ describe ChatwootHub do info = { event_name: event_name, event_data: event_data } allow(RestClient).to receive(:post) described_class.emit_event(event_name, event_data) - expect(RestClient).to have_received(:post).with(described_class::EVENTS_URL, + expect(RestClient).to have_received(:post).with(described_class.events_url, info.merge(described_class.instance_config).to_json, { content_type: :json, accept: :json }) end @@ -64,29 +71,9 @@ describe ChatwootHub do allow(RestClient).to receive(:post) described_class.emit_event(event_name, event_data) expect(RestClient).not_to have_received(:post) - .with(described_class::EVENTS_URL, + .with(described_class.events_url, info.merge(described_class.instance_config).to_json, { content_type: :json, accept: :json }) end end end - - context 'when fetching captain settings' do - it 'returns the captain settings' do - account = create(:account) - stub_request(:post, ChatwootHub::CAPTAIN_ACCOUNTS_URL).with( - body: { installation_identifier: described_class.installation_identifier, chatwoot_account_id: account.id, account_name: account.name } - ).to_return( - body: { account_email: 'test@test.com', account_id: '123', access_token: '123', assistant_id: '123' }.to_json - ) - - expect(described_class.get_captain_settings(account).body).to eq( - { - account_email: 'test@test.com', - account_id: '123', - access_token: '123', - assistant_id: '123' - }.to_json - ) - end - end end