Skip to content

Commit

Permalink
feat: auditlog for team and inbox member updates (#7516)
Browse files Browse the repository at this point in the history
- adds an audit log when an agent is added or removed from a team
- adds an audit log when an agent is added or removed from an inbox

Co-authored-by: Sojan Jose <sojan@pepalo.com>
  • Loading branch information
vishnu-narayanan and sojan-official committed Aug 16, 2023
1 parent 2df8327 commit 7b8a3fc
Show file tree
Hide file tree
Showing 9 changed files with 249 additions and 16 deletions.
85 changes: 70 additions & 15 deletions app/javascript/dashboard/helper/auditlogHelper.js
Expand Up @@ -30,6 +30,10 @@ const translationKeys = {
'accountuser:create': `AUDIT_LOGS.ACCOUNT_USER.ADD`,
'accountuser:update:self': `AUDIT_LOGS.ACCOUNT_USER.EDIT.SELF`,
'accountuser:update:other': `AUDIT_LOGS.ACCOUNT_USER.EDIT.OTHER`,
'inboxmember:create': `AUDIT_LOGS.INBOX_MEMBER.ADD`,
'inboxmember:destroy': `AUDIT_LOGS.INBOX_MEMBER.REMOVE`,
'teammember:create': `AUDIT_LOGS.TEAM_MEMBER.ADD`,
'teammember:destroy': `AUDIT_LOGS.TEAM_MEMBER.REMOVE`,
'account:update': `AUDIT_LOGS.ACCOUNT.EDIT`,
};

Expand Down Expand Up @@ -102,6 +106,58 @@ function handleAccountUserUpdate(auditLogItem, translationPayload, agentList) {
return translationPayload;
}

function setUserInPayload(auditLogItem, translationPayload, agentList) {
const userIdChange = auditLogItem.audited_changes.user_id;
if (userIdChange && userIdChange !== undefined) {
translationPayload.user = getAgentName(userIdChange, agentList);
}
return translationPayload;
}

function setTeamIdInPayload(auditLogItem, translationPayload) {
if (auditLogItem.audited_changes.team_id) {
translationPayload.team_id = auditLogItem.audited_changes.team_id;
}
return translationPayload;
}

function setInboxIdInPayload(auditLogItem, translationPayload) {
if (auditLogItem.audited_changes.inbox_id) {
translationPayload.inbox_id = auditLogItem.audited_changes.inbox_id;
}
return translationPayload;
}

function handleInboxTeamMember(auditLogItem, translationPayload, agentList) {
if (auditLogItem.audited_changes) {
translationPayload = setUserInPayload(
auditLogItem,
translationPayload,
agentList
);
translationPayload = setTeamIdInPayload(auditLogItem, translationPayload);
translationPayload = setInboxIdInPayload(auditLogItem, translationPayload);
}
return translationPayload;
}

function handleAccountUser(
auditLogItem,
translationPayload,
agentList,
action
) {
if (action === 'create') {
return handleAccountUserCreate(auditLogItem, translationPayload, agentList);
}

if (action === 'update') {
return handleAccountUserUpdate(auditLogItem, translationPayload, agentList);
}

return translationPayload;
}

export function generateTranslationPayload(auditLogItem, agentList) {
let translationPayload = {
agentName: getAgentName(auditLogItem.user_id, agentList),
Expand All @@ -112,21 +168,20 @@ export function generateTranslationPayload(auditLogItem, agentList) {
const action = auditLogItem.action.toLowerCase();

if (auditableType === 'accountuser') {
if (action === 'create') {
translationPayload = handleAccountUserCreate(
auditLogItem,
translationPayload,
agentList
);
}

if (action === 'update') {
translationPayload = handleAccountUserUpdate(
auditLogItem,
translationPayload,
agentList
);
}
translationPayload = handleAccountUser(
auditLogItem,
translationPayload,
agentList,
action
);
}

if (auditableType === 'inboxmember' || auditableType === 'teammember') {
translationPayload = handleInboxTeamMember(
auditLogItem,
translationPayload,
agentList
);
}

return translationPayload;
Expand Down
42 changes: 42 additions & 0 deletions app/javascript/dashboard/helper/specs/auditlogHelper.spec.js
Expand Up @@ -98,6 +98,48 @@ describe('Helper functions', () => {
});
});

it('should handle InboxMember or TeamMember', () => {
const auditLogItemInboxMember = {
auditable_type: 'InboxMember',
action: 'create',
audited_changes: {
user_id: 2,
},
user_id: 1,
auditable_id: 789,
};

const payloadInboxMember = generateTranslationPayload(
auditLogItemInboxMember,
agentList
);
expect(payloadInboxMember).toEqual({
agentName: 'Agent 1',
id: 789,
user: 'Agent 2',
});

const auditLogItemTeamMember = {
auditable_type: 'TeamMember',
action: 'create',
audited_changes: {
user_id: 3,
},
user_id: 1,
auditable_id: 789,
};

const payloadTeamMember = generateTranslationPayload(
auditLogItemTeamMember,
agentList
);
expect(payloadTeamMember).toEqual({
agentName: 'Agent 1',
id: 789,
user: 'Agent 3',
});
});

it('should handle generic case like Team create', () => {
const auditLogItem = {
auditable_type: 'Team',
Expand Down
10 changes: 9 additions & 1 deletion app/javascript/dashboard/i18n/locale/en/auditLogs.json
Expand Up @@ -56,8 +56,16 @@
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
},
"INBOX_MEMBER": {
"ADD": "%{agentName} added %{user} to the inbox(#%{inbox_id})",
"REMOVE": "%{agentName} removed %{user} from the inbox(#%{inbox_id})"
},
"TEAM_MEMBER": {
"ADD": "%{agentName} added %{user} to the team(#%{team_id})",
"REMOVE": "%{agentName} removed %{user} from the team(#%{team_id})"
},
"ACCOUNT": {
"EDIT": "%{agentName} updated the account configuration (#%{id})"
}
}
}
}
2 changes: 2 additions & 0 deletions app/models/inbox_member.rb
Expand Up @@ -35,3 +35,5 @@ def remove_agent_from_round_robin
::AutoAssignment::InboxRoundRobinService.new(inbox: inbox).remove_agent_from_queue(user_id) if inbox.present?
end
end

InboxMember.include_mod_with('Audit::InboxMember')
2 changes: 2 additions & 0 deletions app/models/team_member.rb
Expand Up @@ -19,3 +19,5 @@ class TeamMember < ApplicationRecord
belongs_to :team
validates :user_id, uniqueness: { scope: :team_id }
end

TeamMember.include_mod_with('Audit::TeamMember')
31 changes: 31 additions & 0 deletions enterprise/app/models/enterprise/audit/inbox_member.rb
@@ -0,0 +1,31 @@
module Enterprise::Audit::InboxMember
extend ActiveSupport::Concern

included do
after_commit :create_audit_log_entry_on_create, on: :create
after_commit :create_audit_log_entry_on_delete, on: :destroy
end

private

def create_audit_log_entry_on_create
create_audit_log_entry('create')
end

def create_audit_log_entry_on_delete
create_audit_log_entry('destroy')
end

def create_audit_log_entry(action)
return if inbox.blank?

Enterprise::AuditLog.create(
auditable_id: id,
auditable_type: 'InboxMember',
action: action,
associated_id: inbox&.account_id,
audited_changes: attributes.except('updated_at', 'created_at'),
associated_type: 'Account'
)
end
end
31 changes: 31 additions & 0 deletions enterprise/app/models/enterprise/audit/team_member.rb
@@ -0,0 +1,31 @@
module Enterprise::Audit::TeamMember
extend ActiveSupport::Concern

included do
after_commit :create_audit_log_entry_on_create, on: :create
after_commit :create_audit_log_entry_on_delete, on: :destroy
end

private

def create_audit_log_entry_on_create
create_audit_log_entry('create')
end

def create_audit_log_entry_on_delete
create_audit_log_entry('destroy')
end

def create_audit_log_entry(action)
return if team.blank?

Enterprise::AuditLog.create(
auditable_id: id,
auditable_type: 'TeamMember',
action: action,
associated_id: team&.account_id,
audited_changes: attributes.except('updated_at', 'created_at'),
associated_type: 'Account'
)
end
end
31 changes: 31 additions & 0 deletions spec/enterprise/models/inbox_member_spec.rb
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe InboxMember, type: :model do
let(:user) { create(:user) }
let(:inbox) { create(:inbox) }
let!(:inbox_member) { create(:inbox_member, inbox: inbox, user: user) }

describe 'audit log' do
context 'when inbox member is created' do
it 'has associated audit log created' do
expect(Audited::Audit.where(auditable: inbox_member, action: 'create').count).to eq(1)
end

it 'has user_id in audited_changes matching user.id' do
audit_log = Audited::Audit.find_by(auditable: inbox_member, action: 'create')
expect(audit_log.audited_changes['user_id']).to eq(user.id)
end
end

context 'when inbox member is destroyed' do
it 'has associated audit log created' do
inbox_member.destroy
audit_log = Audited::Audit.find_by(auditable: inbox_member, action: 'destroy')
expect(audit_log).to be_present
expect(audit_log.audited_changes['inbox_id']).to eq(inbox.id)
end
end
end
end
31 changes: 31 additions & 0 deletions spec/enterprise/models/team_member_spec.rb
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe TeamMember, type: :model do
let(:user) { create(:user) }
let(:team) { create(:team) }
let!(:team_member) { create(:team_member, user: user, team: team) }

describe 'audit log' do
context 'when team member is created' do
it 'has associated audit log created' do
expect(Audited::Audit.where(auditable: team_member, action: 'create').count).to eq(1)
end

it 'has user_id in audited_changes matching user.id' do
audit_log = Audited::Audit.find_by(auditable: team_member, action: 'create')
expect(audit_log.audited_changes['user_id']).to eq(user.id)
end
end

context 'when team member is destroyed' do
it 'has associated audit log created' do
team_member.destroy
audit_log = Audited::Audit.find_by(auditable: team_member, action: 'destroy')
expect(audit_log).to be_present
expect(audit_log.audited_changes['team_id']).to eq(team.id)
end
end
end
end

0 comments on commit 7b8a3fc

Please sign in to comment.