chore: more updates
This commit is contained in:
@@ -125,6 +125,7 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize @conversation, :destroy?
|
||||
::DeleteObjectJob.perform_later(@conversation, Current.user, request.ip)
|
||||
head :ok
|
||||
end
|
||||
|
||||
@@ -168,6 +168,9 @@ export default {
|
||||
// Don't show snooze if the conversation is already snoozed/resolved/pending
|
||||
return this.status === wootConstants.STATUS_TYPE.OPEN;
|
||||
},
|
||||
isAdmin() {
|
||||
return this.currentUser?.role === 'administrator';
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('inboxAssignableAgents/fetch', [this.inboxId]);
|
||||
@@ -286,11 +289,13 @@ export default {
|
||||
@click.stop="$emit('assignTeam', team)"
|
||||
/>
|
||||
</MenuItemWithSubmenu>
|
||||
<hr class="m-1 rounded border-b border-n-weak dark:border-n-weak" />
|
||||
<MenuItem
|
||||
:option="deleteOption"
|
||||
variant="icon"
|
||||
@click.stop="deleteConversation()"
|
||||
/>
|
||||
<template v-if="isAdmin">
|
||||
<hr class="m-1 rounded border-b border-n-weak dark:border-n-weak" />
|
||||
<MenuItem
|
||||
:option="deleteOption"
|
||||
variant="icon"
|
||||
@click.stop="deleteConversation()"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -305,5 +305,6 @@ class Conversation < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
Conversation.include_mod_with('Audit::Conversation')
|
||||
Conversation.include_mod_with('Concerns::Conversation')
|
||||
Conversation.prepend_mod_with('Conversation')
|
||||
|
||||
@@ -2,4 +2,8 @@ class ConversationPolicy < ApplicationPolicy
|
||||
def index?
|
||||
true
|
||||
end
|
||||
|
||||
def destroy?
|
||||
@account_user&.administrator?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
module Enterprise::Audit::Conversation
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
audited only: [], on: [:destroy]
|
||||
end
|
||||
end
|
||||
@@ -926,4 +926,63 @@ RSpec.describe 'Conversations API', type: :request do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /api/v1/accounts/{account.id}/conversations/:id' do
|
||||
let(:conversation) { create(:conversation, account: account) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let(:administrator) { create(:user, account: account, role: :administrator) }
|
||||
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
delete "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}"
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated agent' do
|
||||
before do
|
||||
create(:inbox_member, user: agent, inbox: conversation.inbox)
|
||||
end
|
||||
|
||||
it 'returns unauthorized' do
|
||||
delete "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
response_body = response.parsed_body
|
||||
expect(response_body['error']).to eq('You are not authorized to do this action')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated administrator' do
|
||||
before do
|
||||
create(:inbox_member, user: administrator, inbox: conversation.inbox)
|
||||
end
|
||||
|
||||
it 'successfully deletes the conversation' do
|
||||
expect do
|
||||
delete "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}",
|
||||
headers: administrator.create_new_auth_token,
|
||||
as: :json
|
||||
end.to have_enqueued_job(DeleteObjectJob).with(conversation, administrator, anything)
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
|
||||
it 'can delete conversations from inboxes without direct access' do
|
||||
other_inbox = create(:inbox, account: account)
|
||||
other_conversation = create(:conversation, account: account, inbox: other_inbox)
|
||||
|
||||
expect do
|
||||
delete "/api/v1/accounts/#{account.id}/conversations/#{other_conversation.display_id}",
|
||||
headers: administrator.create_new_auth_token,
|
||||
as: :json
|
||||
end.to have_enqueued_job(DeleteObjectJob).with(other_conversation, administrator, anything)
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Conversation Audit', type: :model do
|
||||
let(:account) { create(:account) }
|
||||
let(:conversation) { create(:conversation, account: account) }
|
||||
|
||||
before do
|
||||
# Enable auditing for conversations
|
||||
conversation.class.send(:include, Enterprise::Audit::Conversation) if defined?(Enterprise::Audit::Conversation)
|
||||
end
|
||||
|
||||
describe 'audit logging on destroy' do
|
||||
it 'creates an audit log when conversation is destroyed' do
|
||||
skip 'Enterprise audit module not available' unless defined?(Enterprise::Audit::Conversation)
|
||||
|
||||
expect do
|
||||
conversation.destroy!
|
||||
end.to change { Audited::Audit.count }.by(1)
|
||||
|
||||
audit = Audited::Audit.last
|
||||
expect(audit.auditable_type).to eq('Conversation')
|
||||
expect(audit.action).to eq('destroy')
|
||||
expect(audit.auditable_id).to eq(conversation.id)
|
||||
end
|
||||
|
||||
it 'does not create audit log for other actions by default' do
|
||||
skip 'Enterprise audit module not available' unless defined?(Enterprise::Audit::Conversation)
|
||||
|
||||
expect do
|
||||
conversation.update!(priority: 'high')
|
||||
end.not_to(change { Audited::Audit.count })
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,34 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ConversationPolicy, type: :policy do
|
||||
subject { described_class }
|
||||
|
||||
let(:account) { create(:account) }
|
||||
let(:conversation) { create(:conversation, account: account) }
|
||||
let(:administrator) { create(:user, account: account, role: :administrator) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let(:administrator_context) { { user: administrator, account: account, account_user: administrator.account_users.first } }
|
||||
let(:agent_context) { { user: agent, account: account, account_user: agent.account_users.first } }
|
||||
|
||||
permissions :destroy? do
|
||||
context 'when user is an administrator' do
|
||||
it 'allows destroy' do
|
||||
expect(subject).to permit(administrator_context, conversation)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is an agent' do
|
||||
it 'denies destroy' do
|
||||
expect(subject).not_to permit(agent_context, conversation)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
permissions :index? do
|
||||
context 'for any authenticated user' do
|
||||
it 'allows index' do
|
||||
expect(subject).to permit(agent_context, conversation)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user