diff --git a/app/models/concerns/channelable.rb b/app/models/concerns/channelable.rb index d88aae90a..0b23283e1 100644 --- a/app/models/concerns/channelable.rb +++ b/app/models/concerns/channelable.rb @@ -4,9 +4,14 @@ module Channelable validates :account_id, presence: true belongs_to :account has_one :inbox, as: :channel, dependent: :destroy_async, touch: true + after_update :create_audit_log_entry end def messaging_window_enabled? false end + + def create_audit_log_entry; end end + +Channelable.prepend_mod_with('Channelable') diff --git a/enterprise/app/models/enterprise/channelable.rb b/enterprise/app/models/enterprise/channelable.rb new file mode 100644 index 000000000..e46fdb2be --- /dev/null +++ b/enterprise/app/models/enterprise/channelable.rb @@ -0,0 +1,34 @@ +module Enterprise::Channelable + extend ActiveSupport::Concern + + # Active support concern has `included` which changes the order of the method lookup chain + # https://stackoverflow.com/q/40061982/3824876 + # manually prepend the instance methods to combat this + included do + prepend InstanceMethods + end + + module InstanceMethods + def create_audit_log_entry + account = self.account + associated_type = 'Account' + + return if inbox.nil? + + auditable_id = inbox.id + auditable_type = 'Inbox' + audited_changes = saved_changes.except('updated_at') + + return if audited_changes.blank? + + Enterprise::AuditLog.create( + auditable_id: auditable_id, + auditable_type: auditable_type, + action: 'update', + associated_id: account.id, + associated_type: associated_type, + audited_changes: audited_changes + ) + end + end +end diff --git a/spec/enterprise/models/inbox_spec.rb b/spec/enterprise/models/inbox_spec.rb index 978a7ba5d..2cc7eeea9 100644 --- a/spec/enterprise/models/inbox_spec.rb +++ b/spec/enterprise/models/inbox_spec.rb @@ -40,14 +40,60 @@ RSpec.describe Inbox do describe 'audit log' do context 'when inbox is created' do it 'has associated audit log created' do - expect(Audited::Audit.where(auditable_type: 'Inbox', action: 'create').count).to eq 1 + expect(Audited::Audit.where(auditable_type: 'Inbox', action: 'create').count).to eq(1) end end context 'when inbox is updated' do it 'has associated audit log created' do - inbox.update(auto_assignment_config: { max_assignment_limit: 2 }) - expect(Audited::Audit.where(auditable_type: 'Inbox', action: 'update').count).to eq 1 + inbox.update(name: 'Updated Inbox') + expect(Audited::Audit.where(auditable_type: 'Inbox', action: 'update').count).to eq(1) + end + end + + context 'when channel is updated' do + it 'has associated audit log created' do + previous_color = inbox.channel.widget_color + new_color = '#ff0000' + inbox.channel.update(widget_color: new_color) + + # check if channel update creates an audit log against inbox + expect(Audited::Audit.where(auditable_type: 'Inbox', action: 'update').count).to eq(1) + # Check for the specific widget_color update in the audit log + expect(Audited::Audit.where(auditable_type: 'Inbox', action: 'update', + audited_changes: { 'widget_color' => [previous_color, new_color] }).count).to eq(1) + end + end + end + + describe 'audit log with api channel' do + let!(:channel) { create(:channel_api) } + let!(:inbox) { channel.inbox } + + context 'when inbox is created' do + it 'has associated audit log created' do + expect(Audited::Audit.where(auditable_type: 'Inbox', action: 'create').count).to eq(1) + end + end + + context 'when inbox is updated' do + it 'has associated audit log created' do + inbox.update(name: 'Updated Inbox') + expect(Audited::Audit.where(auditable_type: 'Inbox', action: 'update').count).to eq(1) + end + end + + context 'when channel is updated' do + it 'has associated audit log created' do + previous_webhook = inbox.channel.webhook_url + new_webhook = 'https://example2.com' + inbox.channel.update(webhook_url: new_webhook) + + # check if channel update creates an audit log against inbox + expect(Audited::Audit.where(auditable_type: 'Inbox', action: 'update').count).to eq(1) + # Check for the specific webhook_update update in the audit log + expect(Audited::Audit.where(auditable_type: 'Inbox', action: 'update', + audited_changes: { 'webhook_url' => [previous_webhook, new_webhook] }).count).to eq(1) end end end