From f5c588be0b7c85ab52cc1261003d825710346ab6 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 3 Oct 2018 08:23:22 +0200 Subject: [PATCH] Implemented issue #2261 - Make stats store and cti log searchable via elastichsearch & destroy stats store if user got deleted. --- app/models/cti/log.rb | 2 ++ app/models/stats_store.rb | 45 ++++++++++++++++++++++---- app/models/stats_store/search_index.rb | 20 ++++++++++++ app/models/user.rb | 4 +++ lib/models.rb | 24 +++++++++++++- lib/tasks/search_index_es.rake | 4 +-- test/unit/user_test.rb | 22 +++++++++++++ 7 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 app/models/stats_store/search_index.rb diff --git a/app/models/cti/log.rb b/app/models/cti/log.rb index a86af3c7f..1b39766a2 100644 --- a/app/models/cti/log.rb +++ b/app/models/cti/log.rb @@ -1,5 +1,7 @@ module Cti class Log < ApplicationModel + include HasSearchIndexBackend + self.table_name = 'cti_logs' store :preferences diff --git a/app/models/stats_store.rb b/app/models/stats_store.rb index 1048c412c..b218012d7 100644 --- a/app/models/stats_store.rb +++ b/app/models/stats_store.rb @@ -1,6 +1,14 @@ # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ class StatsStore < ApplicationModel + include HasSearchIndexBackend + include StatsStore::SearchIndex + + # rubocop:disable Rails/InverseOf + belongs_to :stats_store_object, class_name: 'ObjectLookup', foreign_key: 'stats_store_object_id' + belongs_to :related_stats_store_object, class_name: 'ObjectLookup', foreign_key: 'related_stats_store_object_id' + # rubocop:enable Rails/InverseOf + store :data =begin @@ -19,7 +27,7 @@ class StatsStore < ApplicationModel # lookups if data[:object] - object_id = ObjectLookup.by_name( data[:object] ) + object_id = ObjectLookup.by_name(data[:object]) end StatsStore.where(stats_store_object_id: object_id, o_id: data[:o_id], key: data[:key]) @@ -40,7 +48,7 @@ class StatsStore < ApplicationModel # lookups if data[:object] - data[:stats_store_object_id] = ObjectLookup.by_name( data[:object] ) + data[:stats_store_object_id] = ObjectLookup.by_name(data[:object]) data.delete(:object) end @@ -73,7 +81,7 @@ class StatsStore < ApplicationModel # lookups if data[:object] - data[:stats_store_object_id] = ObjectLookup.by_name( data[:object] ) + data[:stats_store_object_id] = ObjectLookup.by_name(data[:object]) data.delete(:object) end @@ -98,7 +106,7 @@ class StatsStore < ApplicationModel # lookups if data[:object] - object_id = ObjectLookup.by_name( data[:object] ) + object_id = ObjectLookup.by_name(data[:object]) end # create history @@ -114,6 +122,31 @@ class StatsStore < ApplicationModel StatsStore.create(record) end +=begin + + StatsStore.remove( + object: 'User', + o_id: ticket.owner_id, + ) + +=end + + def self.remove(data) + + # lookups + if data[:object] + object_id = ObjectLookup.by_name(data[:object]) + end + + # create history + record = { + stats_store_object_id: object_id, + o_id: data[:o_id], + } + + StatsStore.where(record).destroy_all + end + =begin cleanup old stats store @@ -122,11 +155,11 @@ cleanup old stats store optional you can put the max oldest stats store entries as argument - StatsStore.cleanup(3.months) + StatsStore.cleanup(12.months) =end - def self.cleanup(diff = 3.months) + def self.cleanup(diff = 12.months) StatsStore.where('updated_at < ?', Time.zone.now - diff).delete_all true end diff --git a/app/models/stats_store/search_index.rb b/app/models/stats_store/search_index.rb new file mode 100644 index 000000000..34a9faa90 --- /dev/null +++ b/app/models/stats_store/search_index.rb @@ -0,0 +1,20 @@ +# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ +module StatsStore::SearchIndex + + def search_index_attribute_lookup + attributes = super + return if !attributes + + begin + return if !Kernel.const_get(attributes['stats_store_object']) + record = Kernel.const_get(attributes['stats_store_object']).lookup(id: o_id) + return if !record + attributes['stats_store_object_ref'] = record.search_index_attribute_lookup + rescue + return + end + + attributes + end + +end diff --git a/app/models/user.rb b/app/models/user.rb index 4e78f2106..b0c85ee09 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1167,6 +1167,10 @@ raise 'Minimum one user need to have admin permissions' ::RecentView.where(created_by_id: id).destroy_all ::UserDevice.remove(id) ::Token.where(user_id: id).destroy_all + ::StatsStore.remove( + object: 'User', + o_id: id, + ) true end diff --git a/lib/models.rb b/lib/models.rb index c6df06d8a..e750b2219 100644 --- a/lib/models.rb +++ b/lib/models.rb @@ -60,7 +60,7 @@ returns =begin -get list of searchable models +get list of searchable models for UI result = Models.searchable @@ -82,6 +82,28 @@ returns =begin +get list of indexable models + + result = Models.indexable + +returns + + [Model1, Model2, Model3] + +=end + + def self.indexable + models = [] + all.each_key do |model_class| + next if !model_class + next if !model_class.new.respond_to? :search_index_update_backend + models.push model_class + end + models + end + +=begin + get reference list of a models result = Models.references('User', 2) diff --git a/lib/tasks/search_index_es.rake b/lib/tasks/search_index_es.rake index 59993ab9e..7771fd055 100644 --- a/lib/tasks/search_index_es.rake +++ b/lib/tasks/search_index_es.rake @@ -25,7 +25,7 @@ namespace :searchindex do end mapping = {} - Models.searchable.each do |local_object| + Models.indexable.each do |local_object| mapping.merge!(get_mapping_properties_object(local_object)) end @@ -125,7 +125,7 @@ namespace :searchindex do task :reload, [:opts] => :environment do |_t, _args| puts 'reload data...' - Models.searchable.each do |model_class| + Models.indexable.each do |model_class| puts " reload #{model_class}" started_at = Time.zone.now puts " - started at #{started_at}" diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index 194284dd2..79c6c23d3 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -1260,6 +1260,21 @@ class UserTest < ActiveSupport::TestCase Token.create!(action: 'api', user_id: agent1_id) + StatsStore.add( + object: 'User', + o_id: agent1_id, + key: 'some_key', + data: { A: 1, B: 2 }, + created_at: Time.zone.now, + created_by_id: 1, + ) + item = StatsStore.search( + object: 'User', + o_id: agent1_id, + key: 'some_key', + ) + assert(item) + agent1.destroy! assert_equal(0, UserDevice.where(user_id: agent1_id).count) @@ -1271,6 +1286,13 @@ class UserTest < ActiveSupport::TestCase assert_equal(0, Taskbar.where(user_id: agent1_id).count) assert_equal(0, RecentView.where(created_by_id: agent1_id).count) assert_equal(0, Token.where(user_id: agent1_id).count) + assert_equal(0, Token.where(user_id: agent1_id).count) + item = StatsStore.search( + object: 'User', + o_id: agent1_id, + key: 'some_key', + ) + assert_nil(item) end test 'adding group drops cache' do