From 72dd0c031696fd616b7d369cd3959050b879e9b8 Mon Sep 17 00:00:00 2001 From: Rolf Schmidt Date: Wed, 7 Oct 2020 16:53:52 +0200 Subject: [PATCH] Fixes #2517 - Elasticsearch throws error 500 when filtering for owner or custom dropdown-fields inside of report profiles. --- app/controllers/reports_controller.rb | 2 ++ lib/report/ticket_generic_time.rb | 4 +-- lib/search_index_backend.rb | 32 +++++++++++++++++ spec/lib/search_index_backend_spec.rb | 52 +++++++++++++++++++++++++-- 4 files changed, 86 insertions(+), 4 deletions(-) diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb index cf8c37119..8590f3df4 100644 --- a/app/controllers/reports_controller.rb +++ b/app/controllers/reports_controller.rb @@ -39,6 +39,7 @@ class ReportsController < ApplicationController params: backend[:params], timezone: get_params[:timezone], timezone_offset: get_params[:timezone_offset], + current_user: current_user ) end @@ -83,6 +84,7 @@ class ReportsController < ApplicationController sheet: params[:sheet], timezone: get_params[:timezone], timezone_offset: get_params[:timezone_offset], + current_user: current_user ) result = { count: 0, ticket_ids: [] } if result.nil? diff --git a/lib/report/ticket_generic_time.rb b/lib/report/ticket_generic_time.rb index 3d4f0c933..8aa208321 100644 --- a/lib/report/ticket_generic_time.rb +++ b/lib/report/ticket_generic_time.rb @@ -45,7 +45,7 @@ returns end selector.merge!(without_merged_tickets) # do not show merged tickets in reports - result_es = SearchIndexBackend.selectors('Ticket', selector, {}, aggs_interval) + result_es = SearchIndexBackend.selectors('Ticket', selector, { current_user: params[:current_user] }, aggs_interval) case params[:interval] when 'month' stop_interval = 12 @@ -170,7 +170,7 @@ returns end selector.merge!(without_merged_tickets) # do not show merged tickets in reports - result = SearchIndexBackend.selectors('Ticket', selector, { limit: limit }, aggs_interval) + result = SearchIndexBackend.selectors('Ticket', selector, { current_user: params[:current_user], limit: limit }, aggs_interval) return result if params[:sheet].present? assets = {} diff --git a/lib/search_index_backend.rb b/lib/search_index_backend.rb index 6c8da006d..ae5bc233c 100644 --- a/lib/search_index_backend.rb +++ b/lib/search_index_backend.rb @@ -473,6 +473,12 @@ example for aggregations within one year def self.selector2query(selector, options, aggs_interval) options = DEFAULT_QUERY_OPTIONS.merge(options.deep_symbolize_keys) + current_user = options[:current_user] + current_user_id = UserInfo.current_user_id + if current_user + current_user_id = current_user.id + end + query_must = [] query_must_not = [] relative_map = { @@ -493,6 +499,32 @@ example for aggregations within one year # use .keyword in case of compare exact values if data['operator'] == 'is' || data['operator'] == 'is not' + + case data['pre_condition'] + when 'not_set' + data['value'] = if key_tmp.match?(/^(created_by|updated_by|owner|customer|user)_id/) + 1 + else + 'NULL' + end + when 'current_user.id' + raise "Use current_user.id in selector, but no current_user is set #{data.inspect}" if !current_user_id + + data['value'] = [] + wildcard_or_term = 'terms' + + if key_tmp == 'out_of_office_replacement_id' + data['value'].push User.find(current_user_id).out_of_office_agent_of.pluck(:id) + else + data['value'].push current_user_id + end + when 'current_user.organization_id' + raise "Use current_user.id in selector, but no current_user is set #{data.inspect}" if !current_user_id + + user = User.find_by(id: current_user_id) + data['value'] = user.organization_id + end + if data['value'].is_a?(Array) data['value'].each do |value| next if !value.is_a?(String) || value !~ /[A-z]/ diff --git a/spec/lib/search_index_backend_spec.rb b/spec/lib/search_index_backend_spec.rb index 6224c8f19..4f45ce78c 100644 --- a/spec/lib/search_index_backend_spec.rb +++ b/spec/lib/search_index_backend_spec.rb @@ -164,14 +164,17 @@ RSpec.describe SearchIndexBackend, searchindex: true do describe '.selectors' do - let(:ticket1) { create :ticket, title: 'some-title1', state_id: 1 } + let(:organization1) { create :organization } + let(:agent1) { create :agent, organization: organization1 } + let(:customer1) { create :customer, organization: organization1 } + let(:ticket1) { create :ticket, title: 'some-title1', state_id: 1, created_by: agent1 } let(:ticket2) { create :ticket, title: 'some_title2', state_id: 4 } let(:ticket3) { create :ticket, title: 'some::title3', state_id: 1 } let(:ticket4) { create :ticket, title: 'phrase some-title4', state_id: 1 } let(:ticket5) { create :ticket, title: 'phrase some_title5', state_id: 1 } let(:ticket6) { create :ticket, title: 'phrase some::title6', state_id: 1 } let(:ticket7) { create :ticket, title: 'some title7', state_id: 1 } - let(:ticket8) { create :ticket, title: 'sometitle', state_id: 1 } + let(:ticket8) { create :ticket, title: 'sometitle', state_id: 1, owner: agent1, customer: customer1 } before do Ticket.destroy_all # needed to remove not created tickets @@ -194,6 +197,51 @@ RSpec.describe SearchIndexBackend, searchindex: true do end context 'query with contains' do + it 'finds records with pre_condition not_set' do + result = described_class.selectors('Ticket', + { + 'created_by_id' => { + 'pre_condition' => 'not_set', + 'operator' => 'is', + }, + }, + {}, + { + field: 'created_at', # sort to verify result + }) + expect(result).to eq({ count: 7, ticket_ids: [ticket8.id.to_s, ticket7.id.to_s, ticket6.id.to_s, ticket5.id.to_s, ticket4.id.to_s, ticket3.id.to_s, ticket2.id.to_s] }) + end + + it 'finds records with pre_condition current_user.id' do + result = described_class.selectors('Ticket', + { + 'owner_id' => { + 'pre_condition' => 'current_user.id', + 'operator' => 'is', + }, + }, + { current_user: agent1 }, + { + field: 'created_at', # sort to verify result + }) + expect(result).to eq({ count: 1, ticket_ids: [ticket8.id.to_s] }) + end + + it 'finds records with pre_condition current_user.organization_id' do + result = described_class.selectors('Ticket', + { + 'organization_id' => { + 'pre_condition' => 'current_user.organization_id', + 'operator' => 'is', + }, + }, + { current_user: agent1 }, + { + field: 'created_at', # sort to verify result + }) + expect(result).to eq({ count: 1, ticket_ids: [ticket8.id.to_s] }) + end + it 'finds records with containing phrase' do result = described_class.selectors('Ticket', {