Improved checks on 'Follow Up Possible' on frontend/backend API if set in user group

This commit is contained in:
Muhammad Nuzaihan 2018-02-05 21:00:30 +08:00
parent 956525fd55
commit 4c38d7a719
6 changed files with 120 additions and 19 deletions

View file

@ -3,9 +3,9 @@
Zammad is a web based open source helpdesk/customer support system with many Zammad is a web based open source helpdesk/customer support system with many
features to manage customer communication via several channels like telephone, features to manage customer communication via several channels like telephone,
facebook, twitter, chat and e-mails. It is distributed under the GNU AFFERO facebook, twitter, chat and e-mails. It is distributed under the GNU AFFERO
General Public License (AGPL) and tested on Linux, Solaris, AIX, FreeBSD, General Public License (AGPL).
OpenBSD and Mac OS 10.x. Do you receive many e-mails and want to answer them
with a team of agents? Do you receive many e-mails and want to answer them with a team of agents?
You're going to love Zammad! You're going to love Zammad!

View file

@ -848,7 +848,7 @@ class App.TicketZoom extends App.Controller
error: (settings, details) => error: (settings, details) =>
App.Event.trigger 'notify', { App.Event.trigger 'notify', {
type: 'error' type: 'error'
msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to update!') msg: App.i18n.translateContent(details.error_human || details.error || settings.responseJSON.error || 'Unable to update!')
timeout: 2000 timeout: 2000
} }
@autosaveStart() @autosaveStart()

View file

@ -8,11 +8,17 @@ class Edit extends App.ObserverController
render: (ticket, diff) => render: (ticket, diff) =>
defaults = ticket.attributes() defaults = ticket.attributes()
delete defaults.article # ignore article infos delete defaults.article # ignore article infos
followUpPossible = App.Group.find(defaults.group_id).follow_up_possible
ticketState = App.TicketState.find(defaults.state_id).name
taskState = @taskGet('ticket') taskState = @taskGet('ticket')
if !_.isEmpty(taskState) if !_.isEmpty(taskState)
defaults = _.extend(defaults, taskState) defaults = _.extend(defaults, taskState)
if followUpPossible == 'new_ticket' && ticketState != 'closed' ||
followUpPossible != 'new_ticket' ||
@permissionCheck('admin') || @permissionCheck('ticket.agent')
new App.ControllerForm( new App.ControllerForm(
elReplace: @el elReplace: @el
model: App.Ticket model: App.Ticket
@ -25,6 +31,19 @@ class Edit extends App.ObserverController
isDisabled: !ticket.editable() isDisabled: !ticket.editable()
#bookmarkable: true #bookmarkable: true
) )
else
new App.ControllerForm(
elReplace: @el
model: App.Ticket
screen: 'edit'
handlers: [
@ticketFormChanges
]
filter: @formMeta.filter
params: defaults
isDisabled: ticket.editable()
#bookmarkable: true
)
@markForm(true) @markForm(true)

View file

@ -964,8 +964,8 @@ class App.Utils
senders = App.Utils.parseAddressListLocal(article.from) senders = App.Utils.parseAddressListLocal(article.from)
if senders if senders
for sender in senders for sender in senders
if sender && sender.address && sender.address.match('@') if sender && sender.match('@')
senderIsLocal = isLocalAddress(sender.address) senderIsLocal = isLocalAddress(sender)
# check if article recipient is local # check if article recipient is local
recipientIsLocal = false recipientIsLocal = false

View file

@ -7,6 +7,7 @@ class TicketsController < ApplicationController
include TicketStats include TicketStats
prepend_before_action :authentication_check prepend_before_action :authentication_check
before_action :follow_up_possible_check, only: :update
# GET /api/v1/tickets # GET /api/v1/tickets
def index def index
@ -124,7 +125,7 @@ class TicketsController < ApplicationController
if !local_customer && clean_customer[:id].present? if !local_customer && clean_customer[:id].present?
local_customer = User.find_by(id: clean_customer[:id]) local_customer = User.find_by(id: clean_customer[:id])
end end
if clean_customer[:email].present? if !local_customer && clean_customer[:email].present?
local_customer = User.find_by(email: clean_customer[:email].downcase) local_customer = User.find_by(email: clean_customer[:email].downcase)
end end
if !local_customer && clean_customer[:login].present? if !local_customer && clean_customer[:login].present?
@ -599,6 +600,14 @@ class TicketsController < ApplicationController
private private
def follow_up_possible_check
ticket = Ticket.find(params[:id])
return true if ticket.group.follow_up_possible != 'new_ticket' # check if the setting for follow_up_possible is disabled
return true if ticket.state.name != 'closed' # check if the ticket state is already closed
raise Exceptions::UnprocessableEntity, 'Cannot follow up on a closed ticket. Please create a new ticket.'
end
def ticket_all(ticket) def ticket_all(ticket)
# get attributes to update # get attributes to update

View file

@ -48,6 +48,7 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest
roles: roles, roles: roles,
) )
UserInfo.current_user_id = nil UserInfo.current_user_id = nil
end end
test '01.01 ticket create with agent - missing group' do test '01.01 ticket create with agent - missing group' do
@ -1733,4 +1734,76 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
end end
test '06.01 - ticket with follow up possible set to new_ticket' do
group = Group.create_or_update(
name: "GroupWithNoFollowUp-#{rand(9_999_999_999)}",
active: true,
updated_by_id: 1,
created_by_id: 1,
follow_up_possible: 'new_ticket' # disable follow up possible
)
ticket = Ticket.create!(
title: 'ticket with wrong ticket id',
group_id: group.id,
customer_id: @customer_without_org.id,
state: Ticket::State.lookup(name: 'closed'), # set the ticket to closed
priority: Ticket::Priority.lookup(name: '2 normal'),
updated_by_id: 1,
created_by_id: 1,
)
state = Ticket::State.find_by(name: 'open') # try to open a ticket from a closed state
# customer
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-customer1@example.com', 'customer1pw')
params = {
state_id: state.id, # set the state id
}
put "/api/v1/tickets/#{ticket.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials)
assert_response(422)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_equal('Cannot follow up on a closed ticket. Please create a new ticket.', result['error'])
ticket = Ticket.create!(
title: 'ticket with wrong ticket id',
group_id: group.id,
customer_id: @customer_without_org.id,
state: Ticket::State.lookup(name: 'closed'), # set the ticket to closed
priority: Ticket::Priority.lookup(name: '2 normal'),
updated_by_id: 1,
created_by_id: 1,
)
# admin
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin@example.com', 'adminpw')
put "/api/v1/tickets/#{ticket.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials)
assert_response(422)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_equal('Cannot follow up on a closed ticket. Please create a new ticket.', result['error'])
ticket = Ticket.create!(
title: 'ticket with wrong ticket id',
group_id: group.id,
customer_id: @customer_without_org.id,
state: Ticket::State.lookup(name: 'closed'), # set the ticket to closed
priority: Ticket::Priority.lookup(name: '2 normal'),
updated_by_id: 1,
created_by_id: 1,
)
# agent
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw')
put "/api/v1/tickets/#{ticket.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials)
assert_response(422)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_equal('Cannot follow up on a closed ticket. Please create a new ticket.', result['error'])
end
end end