Fixes #2990 - Backward compatibility of deleting own notes
This commit is contained in:
parent
222e8c0dd3
commit
e037b6015e
6 changed files with 154 additions and 18 deletions
|
@ -18,9 +18,9 @@ class Delete
|
||||||
actions
|
actions
|
||||||
|
|
||||||
@isDeletable: (actions, ticket, article, ui) ->
|
@isDeletable: (actions, ticket, article, ui) ->
|
||||||
return { isDeletable: true } if ui.permissionCheck('admin')
|
return { isDeletable: true } if ui.permissionCheck('admin')
|
||||||
|
|
||||||
return { isDeletable: false } if !@deletableForAgent(actions, ticket, article, ui)
|
return { isDeletable: false } if !@deletableForAgent(actions, ticket, article, ui)
|
||||||
|
return { isDeletable: true } if !@hasDeletableTimeframe()
|
||||||
|
|
||||||
timeout = @deletableTimeout(actions, ticket, article, ui)
|
timeout = @deletableTimeout(actions, ticket, article, ui)
|
||||||
|
|
||||||
|
@ -28,9 +28,18 @@ class Delete
|
||||||
|
|
||||||
{ isDeletable: true, timeout: timeout }
|
{ isDeletable: true, timeout: timeout }
|
||||||
|
|
||||||
|
@deletableTimeframeSetting: ->
|
||||||
|
App.Config.get('ui_ticket_zoom_article_delete_timeframe')
|
||||||
|
|
||||||
|
@hasDeletableTimeframe: ->
|
||||||
|
@deletableTimeframeSetting() && @deletableTimeframeSetting() > 0
|
||||||
|
|
||||||
@deletableTimeout: (actions, ticket, article, ui) ->
|
@deletableTimeout: (actions, ticket, article, ui) ->
|
||||||
created_at = Date.parse(article.created_at)
|
timeframe_miliseconds = @deletableTimeframeSetting() * 1000
|
||||||
600000 - (Date.parse(new Date()) - created_at)
|
now = Date.parse(new Date())
|
||||||
|
created_at = Date.parse(article.created_at)
|
||||||
|
|
||||||
|
timeframe_miliseconds - (now - created_at)
|
||||||
|
|
||||||
@deletableForAgent: (actions, ticket, article, ui) ->
|
@deletableForAgent: (actions, ticket, article, ui) ->
|
||||||
return false if !ui.permissionCheck('ticket.agent')
|
return false if !ui.permissionCheck('ticket.agent')
|
||||||
|
|
|
@ -26,13 +26,25 @@ class Ticket::ArticlePolicy < ApplicationPolicy
|
||||||
return missing_admin_permission if !user.permissions?('ticket.agent')
|
return missing_admin_permission if !user.permissions?('ticket.agent')
|
||||||
return missing_admin_permission if record.created_by_id != user.id
|
return missing_admin_permission if record.created_by_id != user.id
|
||||||
return missing_admin_permission if record.type.communication? && !record.internal?
|
return missing_admin_permission if record.type.communication? && !record.internal?
|
||||||
return too_old_to_undo if record.created_at <= 10.minutes.ago
|
return too_old_to_undo if deletable_timeframe? && record.created_at <= deletable_timeframe.ago
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def deletable_timeframe_setting
|
||||||
|
Setting.get('ui_ticket_zoom_article_delete_timeframe')
|
||||||
|
end
|
||||||
|
|
||||||
|
def deletable_timeframe?
|
||||||
|
deletable_timeframe_setting&.positive?
|
||||||
|
end
|
||||||
|
|
||||||
|
def deletable_timeframe
|
||||||
|
deletable_timeframe_setting.seconds
|
||||||
|
end
|
||||||
|
|
||||||
def access?(query)
|
def access?(query)
|
||||||
if record.internal == true && user.permissions?('ticket.customer')
|
if record.internal == true && user.permissions?('ticket.customer')
|
||||||
return false
|
return false
|
||||||
|
|
16
db/migrate/20200413160113_issue_2990_delete_timeframe.rb
Normal file
16
db/migrate/20200413160113_issue_2990_delete_timeframe.rb
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
class Issue2990DeleteTimeframe < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Define timeframe where a own created note can get deleted.',
|
||||||
|
name: 'ui_ticket_zoom_article_delete_timeframe',
|
||||||
|
area: 'UI::TicketZoomArticle',
|
||||||
|
description: "Set timeframe in seconds. If it's set to 0 you can delete notes without time limits",
|
||||||
|
options: {},
|
||||||
|
state: 600,
|
||||||
|
preferences: {
|
||||||
|
permission: ['admin.ui']
|
||||||
|
},
|
||||||
|
frontend: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
|
@ -4536,3 +4536,16 @@ Setting.create_if_not_exists(
|
||||||
},
|
},
|
||||||
frontend: true
|
frontend: true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Define timeframe where a own created note can get deleted.',
|
||||||
|
name: 'ui_ticket_zoom_article_delete_timeframe',
|
||||||
|
area: 'UI::TicketZoomArticle',
|
||||||
|
description: "Set timeframe in seconds. If it's set to 0 you can delete notes without time limits",
|
||||||
|
options: {},
|
||||||
|
state: 600,
|
||||||
|
preferences: {
|
||||||
|
permission: ['admin.ui']
|
||||||
|
},
|
||||||
|
frontend: true
|
||||||
|
)
|
||||||
|
|
|
@ -482,16 +482,7 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
|
||||||
|
|
||||||
describe 'DELETE /api/v1/ticket_articles/:id', authenticated_as: -> { user } do
|
describe 'DELETE /api/v1/ticket_articles/:id', authenticated_as: -> { user } do
|
||||||
let(:ticket) do
|
let(:ticket) do
|
||||||
output = create(:ticket)
|
create(:ticket, group: Group.first)
|
||||||
|
|
||||||
# make group ticket was created in available to current user
|
|
||||||
role = user.roles.first
|
|
||||||
map = role.group_ids_access_map
|
|
||||||
map[output.group.id] = :full
|
|
||||||
role.group_ids_access_map = map
|
|
||||||
role.save!
|
|
||||||
|
|
||||||
output
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:article_communication) do
|
let(:article_communication) do
|
||||||
|
@ -617,5 +608,53 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
|
||||||
now: false, later: false, much_later: false
|
now: false, later: false, much_later: false
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with custom timeframe' do
|
||||||
|
before { Setting.set 'ui_ticket_zoom_article_delete_timeframe', 6000 }
|
||||||
|
|
||||||
|
let(:article) { article_note }
|
||||||
|
|
||||||
|
context 'as admin' do
|
||||||
|
let(:user) { admin_user }
|
||||||
|
|
||||||
|
context 'deleting after timeframe' do
|
||||||
|
before { article && travel(8000.seconds) }
|
||||||
|
|
||||||
|
include_examples 'succeeds'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as agent' do
|
||||||
|
let(:user) { agent_user }
|
||||||
|
|
||||||
|
context 'deleting before timeframe' do
|
||||||
|
before { article && travel(5000.seconds) }
|
||||||
|
|
||||||
|
include_examples 'succeeds'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'deleting after timeframe' do
|
||||||
|
before { article && travel(8000.seconds) }
|
||||||
|
|
||||||
|
include_examples 'fails'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with timeframe as 0' do
|
||||||
|
before { Setting.set 'ui_ticket_zoom_article_delete_timeframe', 0 }
|
||||||
|
|
||||||
|
let(:article) { article_note }
|
||||||
|
|
||||||
|
context 'as agent' do
|
||||||
|
let(:user) { agent_user }
|
||||||
|
|
||||||
|
context 'deleting long after' do
|
||||||
|
before { article && travel(99.days) }
|
||||||
|
|
||||||
|
include_examples 'succeeds'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -208,9 +208,9 @@ RSpec.describe 'Ticket zoom', type: :system do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'delete article', authenticated: -> { user } do
|
describe 'delete article', authenticated: -> { user } do
|
||||||
let(:admin_user) { User.find_by! email: 'master@example.com' }
|
let(:admin_user) { create :admin, groups: [Group.first] }
|
||||||
let(:agent_user) { create :agent, password: 'test', groups: [Group.first] }
|
let(:agent_user) { create :agent, groups: [Group.first] }
|
||||||
let(:customer_user) { create :customer, password: 'test' }
|
let(:customer_user) { create :customer }
|
||||||
let(:ticket) { create :ticket, group: agent_user.groups.first, customer: customer_user }
|
let(:ticket) { create :ticket, group: agent_user.groups.first, customer: customer_user }
|
||||||
let(:article) { send(item) }
|
let(:article) { send(item) }
|
||||||
|
|
||||||
|
@ -345,6 +345,53 @@ RSpec.describe 'Ticket zoom', type: :system do
|
||||||
now: false, later: false, much_later: false
|
now: false, later: false, much_later: false
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with custom offset' do
|
||||||
|
before { Setting.set 'ui_ticket_zoom_article_delete_timeframe', 6000 }
|
||||||
|
|
||||||
|
context 'as admin' do
|
||||||
|
let(:user) { admin_user }
|
||||||
|
|
||||||
|
include_examples 'according to permission matrix', item: 'article_note', expects_visible: true, offset: 8000.seconds, description: 'outside of delete timeframe'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as agent' do
|
||||||
|
let(:user) { agent_user }
|
||||||
|
|
||||||
|
include_examples 'according to permission matrix', item: 'article_note', expects_visible: true, offset: 5000.seconds, description: 'outside of delete timeframe'
|
||||||
|
include_examples 'according to permission matrix', item: 'article_note', expects_visible: false, offset: 8000.seconds, description: 'outside of delete timeframe'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with timeframe as 0' do
|
||||||
|
before { Setting.set 'ui_ticket_zoom_article_delete_timeframe', 0 }
|
||||||
|
|
||||||
|
context 'as agent' do
|
||||||
|
let(:user) { agent_user }
|
||||||
|
|
||||||
|
include_examples 'according to permission matrix', item: 'article_note', expects_visible: true, offset: 99.days, description: 'long after'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'button is hidden on the go' do
|
||||||
|
before { Setting.set 'ui_ticket_zoom_article_delete_timeframe', 5 }
|
||||||
|
|
||||||
|
let(:user) { agent_user }
|
||||||
|
let(:item) { 'article_note' }
|
||||||
|
let!(:article) { send(item) }
|
||||||
|
let(:offset) { 0.seconds }
|
||||||
|
|
||||||
|
it 'successfully' do
|
||||||
|
refresh # make sure user roles are loaded
|
||||||
|
|
||||||
|
visit "ticket/zoom/#{ticket.id}"
|
||||||
|
|
||||||
|
within :active_ticket_article, article do
|
||||||
|
find '.js-ArticleAction[data-type=delete]' # make sure delete button did show up
|
||||||
|
expect(page).to have_no_css('.js-ArticleAction[data-type=delete]', wait: 15)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue