diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 66394c20c..7e0025692 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -21,60 +21,78 @@ class SearchController < ApplicationController # convert objects string into array of class names # e.g. user-ticket-another_object = %w( User Ticket AnotherObject ) if !params[:objects] - objects_all = %w( Ticket User Organization ) + objects = %w( Ticket User Organization ) else - objects_all = params[:objects].split('-').map(&:camelize) + objects = params[:objects].split('-').map(&:camelize) end - objects = objects_all.clone -puts "OBJECTS: #{objects.inspect}" - search_tickets = objects.delete('Ticket') -puts "OBJECTS_a: #{objects_all.inspect}/#{search_tickets.inspect}" + + # get priorities of result + objects_in_order = [] + objects_in_order_hash = {} + objects.each { |object| + preferences = object.constantize.search_preferences(current_user) + next if !preferences + objects_in_order_hash[preferences[:prio]] = object + } + objects_in_order_hash.keys.sort.reverse.each {|prio| + objects_in_order.push objects_in_order_hash[prio] + } + # try search index backend assets = {} result = [] if SearchIndexBackend.enabled? - items = SearchIndexBackend.search( query, limit, objects ) - items.each { |item| - require item[:type].to_filename - record = Kernel.const_get( item[:type] ).find( item[:id] ) - assets = record.assets(assets) - result.push item + + # get direct search index based objects + objects_with_direct_search_index = [] + objects_without_direct_search_index = [] + objects.each { |object| + preferences = object.constantize.search_preferences(current_user) + next if !preferences + if preferences[:direct_search_index] + objects_with_direct_search_index.push object + else + objects_without_direct_search_index.push object + end } - # do ticket query by Ticket class to handle ticket permissions - if search_tickets - tickets = Ticket.search( - query: query, - limit: limit, - current_user: current_user, - ) - tickets.each do |ticket| - assets = ticket.assets(assets) - item = { - id: ticket.id, - type: 'Ticket', - } + # do only one query to index search backend + if !objects_with_direct_search_index.empty? + items = SearchIndexBackend.search( query, limit, objects_with_direct_search_index ) + items.each { |item| + require item[:type].to_filename + record = Kernel.const_get( item[:type] ).find( item[:id] ) + assets = record.assets(assets) result.push item - end + } end + + # e. g. do ticket query by Ticket class to handle ticket permissions + objects_without_direct_search_index.each { |object| + object_result = search_generic_backend(object, query, limit, current_user, assets) + if !object_result.empty? + result = result.concat(object_result) + end + } + + # sort order by object priority + result_in_order = [] + objects_in_order.each { |object| + result.each {|item| + next if item[:type] != object + item[:id] = item[:id].to_i + result_in_order.push item + } + } + result = result_in_order + else # do query - objects_all.each { |object| - - found_objects = object.constantize.search( - query: query, - limit: limit, - current_user: current_user, - ) - - found_objects.each do |found_object| - item = { - id: found_object.id, - type: found_object.class.to_s - } - result.push item - assets = found_object.assets(assets) + objects_in_order.each { |object| + object_result = search_generic_backend(object, query, limit, current_user, assets) + if !object_result.empty? + result = result.concat(object_result) end } end @@ -85,4 +103,23 @@ puts "OBJECTS_a: #{objects_all.inspect}/#{search_tickets.inspect}" } end + private + + def search_generic_backend(object, query, limit, current_user, assets) + found_objects = object.constantize.search( + query: query, + limit: limit, + current_user: current_user, + ) + result = [] + found_objects.each do |found_object| + item = { + id: found_object.id, + type: found_object.class.to_s + } + result.push item + assets = found_object.assets(assets) + end + result + end end diff --git a/app/models/organization/search.rb b/app/models/organization/search.rb index a9ab57261..1eb8448a1 100644 --- a/app/models/organization/search.rb +++ b/app/models/organization/search.rb @@ -5,6 +5,33 @@ class Organization =begin +search organizations preferences + + result = Organization.search_preferences(user_model) + +returns if user has permissions to search + + result = { + prio: 1000, + direct_search_index: true + } + +returns if user has no permissions to search + + result = false + +=end + + def search_preferences(current_user) + return false if !current_user.role?('Agent') && !current_user.role?(Z_ROLENAME_ADMIN) + { + prio: 1000, + direct_search_index: true, + } + end + +=begin + search organizations result = Organization.search( @@ -27,7 +54,7 @@ returns current_user = params[:current_user] # enable search only for agents and admins - return [] if !current_user.role?('Agent') && !current_user.role?(Z_ROLENAME_ADMIN) + return [] if !search_preferences(current_user) # try search index backend if SearchIndexBackend.enabled? diff --git a/app/models/ticket/search.rb b/app/models/ticket/search.rb index 0a00baa50..338f3cd4a 100644 --- a/app/models/ticket/search.rb +++ b/app/models/ticket/search.rb @@ -3,6 +3,32 @@ module Ticket::Search =begin +search tickets preferences + + result = Ticket.search_preferences(user_model) + +returns if user has permissions to search + + result = { + prio: 3000, + direct_search_index: false + } + +returns if user has no permissions to search + + result = false + +=end + + def search_preferences(_current_user) + { + prio: 3000, + direct_search_index: false, + } + end + +=begin + search tickets via search index result = Ticket.search( diff --git a/app/models/user/search.rb b/app/models/user/search.rb index 1c470b4b5..54db73abe 100644 --- a/app/models/user/search.rb +++ b/app/models/user/search.rb @@ -5,6 +5,33 @@ class User =begin +search user preferences + + result = User.search_preferences(user_model) + +returns if user has permissions to search + + result = { + prio: 1000, + direct_search_index: true + } + +returns if user has no permissions to search + + result = false + +=end + + def search_preferences(current_user) + return false if !current_user.role?('Agent') && !current_user.role?(Z_ROLENAME_ADMIN) + { + prio: 2000, + direct_search_index: true, + } + end + +=begin + search user result = User.search( @@ -27,7 +54,7 @@ returns current_user = params[:current_user] # enable search only for agents and admins - return [] if !current_user.role?('Agent') && !current_user.role?(Z_ROLENAME_ADMIN) + return [] if !search_preferences(current_user) # try search index backend if SearchIndexBackend.enabled? diff --git a/lib/search_index_backend.rb b/lib/search_index_backend.rb index 30d2efa4b..b7c84bdd7 100644 --- a/lib/search_index_backend.rb +++ b/lib/search_index_backend.rb @@ -150,7 +150,7 @@ return search result =end - def self.search( query, _limit = 10, index = nil, query_extention = {} ) + def self.search( query, limit = 10, index = nil, query_extention = {} ) return [] if !query url = build_url() @@ -166,7 +166,7 @@ return search result end data = {} data['from'] = 0 - data['size'] = 10 + data['size'] = limit data['sort'] = [ { diff --git a/test/controllers/search_controller_test.rb b/test/controllers/search_controller_test.rb index faefb8945..760241ae4 100644 --- a/test/controllers/search_controller_test.rb +++ b/test/controllers/search_controller_test.rb @@ -152,6 +152,37 @@ class SearchControllerTest < ActionDispatch::IntegrationTest updated_by_id: 1, created_by_id: 1, ) + + # configure es + if ENV['ES_URL'] + #fail "ERROR: Need ES_URL - hint ES_URL='http://172.0.0.1:9200'" + Setting.set('es_url', ENV['ES_URL']) + + # Setting.set('es_url', 'http://172.0.0.1:9200') + # Setting.set('es_index', 'estest.local_zammad') + # Setting.set('es_user', 'elasticsearch') + # Setting.set('es_password', 'zammad') + + # set max attachment size in mb + Setting.set('es_attachment_max_size_in_mb', 1 ) + + if ENV['ES_INDEX'] + #fail "ERROR: Need ES_INDEX - hint ES_INDEX='estest.local_zammad'" + Setting.set('es_index', ENV['ES_INDEX']) + end + + # drop/create indexes + #Rake::Task["searchindex:drop"].execute + #Rake::Task["searchindex:create"].execute + system('rake searchindex:rebuild') + + # execute background jobs + # execute background jobs + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + sleep 6 + end end test 'settings index with nobody' do