From d2d597b05c48b7f2541ac8928b20c94490928b1b Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Fri, 2 Feb 2018 12:27:19 +0100 Subject: [PATCH] Added possibility to create customer at ticket create with customer hash. --- ...r_attributes_by_current_user_permission.rb | 38 +++++++ app/controllers/tickets_controller.rb | 40 ++++++- app/controllers/users_controller.rb | 39 +------ test/controllers/tickets_controller_test.rb | 107 +++++++++++++++--- 4 files changed, 170 insertions(+), 54 deletions(-) create mode 100644 app/controllers/concerns/checks_user_attributes_by_current_user_permission.rb diff --git a/app/controllers/concerns/checks_user_attributes_by_current_user_permission.rb b/app/controllers/concerns/checks_user_attributes_by_current_user_permission.rb new file mode 100644 index 000000000..9bd88e0b4 --- /dev/null +++ b/app/controllers/concerns/checks_user_attributes_by_current_user_permission.rb @@ -0,0 +1,38 @@ +module ChecksUserAttributesByCurrentUserPermission + extend ActiveSupport::Concern + + private + + def check_attributes_by_current_user_permission(params) + return true if current_user.permissions?('admin.user') + + %i[role_ids roles].each do |key| + next if !params[key] + if current_user.permissions?('ticket.agent') + params.delete(key) + else + logger.info "Role assignment is only allowed by admin! current_user_id: #{current_user.id} assigned to #{params[key].inspect}" + raise Exceptions::NotAuthorized, 'This role assignment is only allowed by admin!' + end + end + if current_user.permissions?('ticket.agent') && !params[:role_ids] && !params[:roles] && params[:id].blank? + params[:role_ids] = Role.signup_role_ids + end + + %i[group_ids groups].each do |key| + next if !params[key] + if current_user.permissions?('ticket.agent') + params.delete(key) + else + logger.info "Group relation assignment is only allowed by admin! current_user_id: #{current_user.id} assigned to #{params[key].inspect}" + raise Exceptions::NotAuthorized, 'Group relation is only allowed by admin!' + end + end + + return true if current_user.permissions?('ticket.agent') + + response_access_deny + false + end + +end diff --git a/app/controllers/tickets_controller.rb b/app/controllers/tickets_controller.rb index 700db1361..9b2414be3 100644 --- a/app/controllers/tickets_controller.rb +++ b/app/controllers/tickets_controller.rb @@ -3,6 +3,7 @@ class TicketsController < ApplicationController include CreatesTicketArticles include ClonesTicketArticleAttachments + include ChecksUserAttributesByCurrentUserPermission include TicketStats prepend_before_action :authentication_check @@ -77,6 +78,12 @@ class TicketsController < ApplicationController # POST /api/v1/tickets def create + customer = {} + if params[:customer].class == ActionController::Parameters + customer = params[:customer] + params.delete(:customer) + end + clean_params = Ticket.association_name_to_id_convert(params) # overwrite params @@ -88,16 +95,16 @@ class TicketsController < ApplicationController end # try to create customer if needed - if clean_params[:customer_id] && clean_params[:customer_id] =~ /^guess:(.+?)$/ + if clean_params[:customer_id].present? && clean_params[:customer_id] =~ /^guess:(.+?)$/ email = $1 if email !~ /@/ || email =~ /(>|<|\||\!|"|ยง|'|\$|%|&|\(|\)|\?|\s)/ render json: { error: 'Invalid email of customer' }, status: :unprocessable_entity return end - customer = User.find_by(email: email.downcase) - if !customer + local_customer = User.find_by(email: email.downcase) + if !local_customer role_ids = Role.signup_role_ids - customer = User.create( + local_customer = User.create( firstname: '', lastname: '', email: email, @@ -106,7 +113,30 @@ class TicketsController < ApplicationController role_ids: role_ids, ) end - clean_params[:customer_id] = customer.id + clean_params[:customer_id] = local_customer.id + end + + # try to create customer if needed + if clean_params[:customer_id].blank? && customer.present? + check_attributes_by_current_user_permission(customer) + clean_customer = User.association_name_to_id_convert(customer) + local_customer = nil + if !local_customer && clean_customer[:id].present? + local_customer = User.find_by(id: clean_customer[:id]) + end + if clean_customer[:email].present? + local_customer = User.find_by(email: clean_customer[:email].downcase) + end + if !local_customer && clean_customer[:login].present? + local_customer = User.find_by(login: clean_customer[:login].downcase) + end + if !local_customer + role_ids = Role.signup_role_ids + local_customer = User.new(clean_customer) + local_customer.role_ids = role_ids + local_customer.save! + end + clean_params[:customer_id] = local_customer.id end clean_params = Ticket.param_cleanup(clean_params, true) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 043a067a8..dc20b18ef 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,6 +1,8 @@ # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ class UsersController < ApplicationController + include ChecksUserAttributesByCurrentUserPermission + prepend_before_action :authentication_check, except: %i[create password_reset_send password_reset_verify image] prepend_before_action :authentication_check_only, only: [:create] @@ -175,7 +177,7 @@ class UsersController < ApplicationController else # permission check - permission_check_by_permission(params) + check_attributes_by_current_user_permission(params) user = User.new(clean_params) user.associations_from_param(params) @@ -259,13 +261,13 @@ class UsersController < ApplicationController # @response_message 200 [User] Updated User record. # @response_message 401 Invalid session. def update - permission_check_by_permission(params) + check_attributes_by_current_user_permission(params) user = User.find(params[:id]) access!(user, 'change') # permission check - permission_check_by_permission(params) + check_attributes_by_current_user_permission(params) user.with_lock do clean_params = User.association_name_to_id_convert(params) clean_params = User.param_cleanup(clean_params, true) @@ -1074,35 +1076,4 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content true end - def permission_check_by_permission(params) - return true if current_user.permissions?('admin.user') - - %i[role_ids roles].each do |key| - next if !params[key] - if current_user.permissions?('ticket.agent') - params.delete(key) - else - logger.info "Role assignment is only allowed by admin! current_user_id: #{current_user.id} assigned to #{params[key].inspect}" - raise Exceptions::NotAuthorized, 'This role assignment is only allowed by admin!' - end - end - if current_user.permissions?('ticket.agent') && !params[:role_ids] && !params[:roles] && params[:id].blank? - params[:role_ids] = Role.signup_role_ids - end - - %i[group_ids groups].each do |key| - next if !params[key] - if current_user.permissions?('ticket.agent') - params.delete(key) - else - logger.info "Group relation assignment is only allowed by admin! current_user_id: #{current_user.id} assigned to #{params[key].inspect}" - raise Exceptions::NotAuthorized, 'Group relation is only allowed by admin!' - end - end - - return true if current_user.permissions?('ticket.agent') - - response_access_deny - false - end end diff --git a/test/controllers/tickets_controller_test.rb b/test/controllers/tickets_controller_test.rb index e2619e870..785ab7001 100644 --- a/test/controllers/tickets_controller_test.rb +++ b/test/controllers/tickets_controller_test.rb @@ -127,7 +127,30 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest assert_equal(@agent.id, result['created_by_id']) end - test '01.04 ticket create with agent - wrong owner_id - 0' do + test '01.04 ticket create with agent - minimal article and customer.email' do + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') + params = { + title: 'a new ticket #3', + group: 'Users', + priority: '2 normal', + state: 'new', + customer: @customer_without_org.email, + article: { + body: 'some test 123', + }, + } + post '/api/v1/tickets', params: params.to_json, headers: @headers.merge('Authorization' => credentials) + assert_response(201) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal(Ticket::State.lookup(name: 'new').id, result['state_id']) + assert_equal('a new ticket #3', result['title']) + assert_equal(@customer_without_org.id, result['customer_id']) + assert_equal(@agent.id, result['updated_by_id']) + assert_equal(@agent.id, result['created_by_id']) + end + + test '01.05 ticket create with agent - wrong owner_id - 0' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #4', @@ -147,7 +170,7 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest assert_equal('Invalid value for param \'owner_id\': 0', result['error']) end - test '01.05 ticket create with agent - wrong owner_id - ""' do + test '01.06 ticket create with agent - wrong owner_id - ""' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #5', @@ -175,7 +198,7 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest assert_equal(@agent.id, result['created_by_id']) end - test '01.06 ticket create with agent - wrong owner_id - 99999' do + test '01.07 ticket create with agent - wrong owner_id - 99999' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #6', @@ -195,7 +218,7 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest assert_equal('Invalid value for param \'owner_id\': 99999', result['error']) end - test '01.07 ticket create with agent - wrong owner_id - nil' do + test '01.08 ticket create with agent - wrong owner_id - nil' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #7', @@ -219,7 +242,7 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest assert_equal(@agent.id, result['created_by_id']) end - test '01.08 ticket create with agent - minimal article with guess customer' do + test '01.09 ticket create with agent - minimal article with guess customer' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #8', @@ -242,7 +265,7 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest assert_equal(@agent.id, result['created_by_id']) end - test '01.09 ticket create with agent - minimal article with guess customer' do + test '01.10 ticket create with agent - minimal article with guess customer' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #9', @@ -263,7 +286,32 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest assert_equal(@agent.id, result['created_by_id']) end - test '01.10 ticket create with agent - minimal article with missing body - with customer' do + test '01.11 ticket create with agent - minimal article with customer hash' do + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') + params = { + title: 'a new ticket #9', + group: 'Users', + customer: { + firstname: 'some firstname', + lastname: 'some lastname', + email: 'some_new_customer@example.com', + }, + article: { + body: 'some test 123', + }, + } + post '/api/v1/tickets', params: params.to_json, headers: @headers.merge('Authorization' => credentials) + assert_response(201) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal(Ticket::State.lookup(name: 'new').id, result['state_id']) + assert_equal('a new ticket #9', result['title']) + assert_equal(User.lookup(email: 'some_new_customer@example.com').id, result['customer_id']) + assert_equal(@agent.id, result['updated_by_id']) + assert_equal(@agent.id, result['created_by_id']) + end + + test '01.12 ticket create with agent - minimal article with missing body - with customer.id' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #10', @@ -280,7 +328,7 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest assert_equal('Need at least article: { body: "some text" }', result['error']) end - test '01.11 ticket create with agent - minimal article and attachment with customer' do + test '01.13 ticket create with agent - minimal article and attachment with customer' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #11', @@ -316,7 +364,7 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest assert_not(file.preferences['Content-ID']) end - test '01.12 ticket create with agent - minimal article and attachment with customer' do + test '01.14 ticket create with agent - minimal article and attachment with customer' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #12', @@ -359,7 +407,7 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest assert_not(file.preferences['Content-ID']) end - test '01.13 ticket create with agent - minimal article and attachment missing mine-type with customer' do + test '01.15 ticket create with agent - minimal article and attachment missing mine-type with customer' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #13', @@ -382,7 +430,7 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest assert_equal('Invalid base64 for attachment with index \'0\'', result['error']) end - test '01.14 ticket create with agent - minimal article and attachment invalid base64 with customer' do + test '01.16 ticket create with agent - minimal article and attachment invalid base64 with customer' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #14', @@ -404,7 +452,7 @@ class TicketsControllerTest < ActionDispatch::IntegrationTest assert_equal('Attachment needs \'mime-type\' param for attachment with index \'0\'', result['error']) end - test '01.15 ticket create with agent - minimal article and inline attachments with customer' do + test '01.17 ticket create with agent - minimal article and inline attachments with customer' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #15', @@ -444,7 +492,7 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO assert(file.preferences['Content-ID']) end - test '01.16 ticket create with agent - minimal article and inline attachments with customer' do + test '01.18 ticket create with agent - minimal article and inline attachments with customer' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') params = { title: 'a new ticket #16', @@ -925,7 +973,36 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO assert_equal(@customer_without_org.id, result['created_by_id']) end - test '03.03 ticket with wrong ticket id' do + test '03.03 ticket create with customer with wrong customer hash' do + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-customer1@example.com', 'customer1pw') + params = { + title: 'a new ticket #c2', + state: 'new', + priority: '2 normal', + group: 'Users', + customer: { + firstname: @agent.firstname, + lastname: @agent.lastname, + email: @agent.email, + }, + article: { + content_type: 'text/plain', # or text/html + body: 'some body', + sender: 'System', + }, + } + post '/api/v1/tickets', params: params.to_json, headers: @headers.merge('Authorization' => credentials) + assert_response(201) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert_equal(Ticket::State.lookup(name: 'new').id, result['state_id']) + assert_equal('a new ticket #c2', result['title']) + assert_equal(@customer_without_org.id, result['customer_id']) + assert_equal(@customer_without_org.id, result['updated_by_id']) + assert_equal(@customer_without_org.id, result['created_by_id']) + end + + test '03.04 ticket with wrong ticket id' do ticket = Ticket.create!( title: 'ticket with wrong ticket id', group: Group.lookup(name: 'Users'), @@ -958,7 +1035,7 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO assert_equal('Not authorized', result['error']) end - test '03.04 ticket with correct ticket id' do + test '03.05 ticket with correct ticket id' do title = "ticket with corret ticket id testme#{rand(999_999_999)}" ticket = Ticket.create!( title: title,