Browse Source

Fixed searchable models as customer user. Added model.search_preferences to get searchable models by config.

Martin Edenhofer 9 years ago
parent
commit
b2aa52c22a

+ 78 - 41
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

+ 28 - 1
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?

+ 26 - 0
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(

+ 28 - 1
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?

+ 2 - 2
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'] =
     [
       {

+ 31 - 0
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