From ce9c5a0f46a1b61bce763749b346c30f1f169ec1 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Tue, 4 Aug 2015 14:30:35 +0200 Subject: [PATCH 01/13] Use downcast to search for email or login (in case of case sensitive db's). --- lib/import/otrs.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/import/otrs.rb b/lib/import/otrs.rb index d655deda2..f83cbdf75 100644 --- a/lib/import/otrs.rb +++ b/lib/import/otrs.rb @@ -1116,7 +1116,7 @@ module Import::OTRS } # check if customer already exists - user_old = User.where( login: user_new[:login] ).first + user_old = User.where( login: user_new[:login].downcase ).first # create / update agent if user_old @@ -1304,9 +1304,9 @@ module Import::OTRS end end - user = User.where( email: email ).first + user = User.where( email: email.downcase ).first if !user - user = User.where( login: email ).first + user = User.where( login: email.downcase ).first end if !user begin @@ -1334,7 +1334,7 @@ module Import::OTRS ) rescue ActiveRecord::RecordNotUnique log "User #{email} was handled by another thread, taking this." - user = User.find_by( login: email ) + user = User.find_by( login: email.downcase ) if !user log "User #{email} wasn't created sleep and retry." sleep rand 3 From 847fa907c351daad719669e0502aa900e81b2534 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Tue, 4 Aug 2015 20:57:11 +0200 Subject: [PATCH 02/13] Fixed org logo detection in wizard. --- .../javascripts/app/controllers/getting_started.js.coffee | 5 +++++ app/controllers/getting_started_controller.rb | 7 +++++++ lib/static_assets.rb | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/app/assets/javascripts/app/controllers/getting_started.js.coffee b/app/assets/javascripts/app/controllers/getting_started.js.coffee index 8d76bdcc0..87b375439 100644 --- a/app/assets/javascripts/app/controllers/getting_started.js.coffee +++ b/app/assets/javascripts/app/controllers/getting_started.js.coffee @@ -287,6 +287,11 @@ class Base extends App.ControllerContent @navigate '#import/' + data.import_backend return + # import config options + if data.config + for key, value of data.config + App.Config.set(key, value) + # render page @render() ) diff --git a/app/controllers/getting_started_controller.rb b/app/controllers/getting_started_controller.rb index 4147f56df..ab9df6295 100644 --- a/app/controllers/getting_started_controller.rb +++ b/app/controllers/getting_started_controller.rb @@ -977,8 +977,15 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password} system_online_service: Setting.get('system_online_service'), addresses: addresses, groups: groups, + config: config, } true end + def config + { + product_logo: Setting.get('product_logo') + } + end + end diff --git a/lib/static_assets.rb b/lib/static_assets.rb index 981368bee..2ce877a28 100644 --- a/lib/static_assets.rb +++ b/lib/static_assets.rb @@ -45,6 +45,7 @@ returns preferences: { 'Content-Type' => content_type }, + created_by_id: 1, ) filename(file) end @@ -91,6 +92,7 @@ returns preferences: { 'Content-Type' => content_type }, + created_by_id: 1, ) StaticAssets.sync filename(file) @@ -142,6 +144,10 @@ generate filename based on Store model extention = '.jpg' elsif file.preferences['Content-Type'] =~ /png/i extention = '.png' + elsif file.preferences['Content-Type'] =~ /gif/i + extention = '.gif' + elsif file.preferences['Content-Type'] =~ /svg/i + extention = '.svg' end "#{hash}#{extention}" end From 1741bc1bd1498eb6f24dcd9da9e943b6bdb5c312 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Tue, 4 Aug 2015 21:42:49 +0200 Subject: [PATCH 03/13] Fixed namespace. --- app/controllers/getting_started_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/getting_started_controller.rb b/app/controllers/getting_started_controller.rb index ab9df6295..e99b07c79 100644 --- a/app/controllers/getting_started_controller.rb +++ b/app/controllers/getting_started_controller.rb @@ -977,12 +977,12 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password} system_online_service: Setting.get('system_online_service'), addresses: addresses, groups: groups, - config: config, + config: config_to_update, } true end - def config + def config_to_update { product_logo: Setting.get('product_logo') } From 9643e2f2149c5b76526559621452b2373b831492 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 5 Aug 2015 11:40:50 +0200 Subject: [PATCH 04/13] Improved performance of html utils (do replacement in a copy of sting, replace it later once), added word markup removal. --- .../app/lib/app_post/utils.js.coffee | 66 +++++++---- public/assets/tests/html-utils.js | 108 +++++++++--------- 2 files changed, 102 insertions(+), 72 deletions(-) diff --git a/app/assets/javascripts/app/lib/app_post/utils.js.coffee b/app/assets/javascripts/app/lib/app_post/utils.js.coffee index a3096c1bc..064d7bf6a 100644 --- a/app/assets/javascripts/app/lib/app_post/utils.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/utils.js.coffee @@ -100,47 +100,62 @@ class App.Utils # textWithoutTags = App.Utils.htmlRemoveTags( html ) @htmlRemoveTags: (html) -> + htmlTmp = $( '
' + html.html() + '
' ) + + # remove comments + @_removeComments( htmlTmp ) + + # remove work markup + htmlTmp = @_removeWordMarkup( htmlTmp ) # remove tags, keep content - html.find('div, span, p, li, ul, ol, a, b, u, i, label, small, strong, strike, pre, code, center, blockquote, form, textarea, font, address, table, thead, tbody, tr, td, h1, h2, h3, h4, h5, h6').replaceWith( -> + htmlTmp.find('div, span, p, li, ul, ol, a, b, u, i, label, small, strong, strike, pre, code, center, blockquote, form, textarea, font, address, table, thead, tbody, tr, td, h1, h2, h3, h4, h5, h6').replaceWith( -> $(@).contents() ) # remove tags & content - html.find('div, span, p, li, ul, ol, a, b, u, i, label, small, strong, strike, pre, code, center, blockquote, form, textarea, font, table, thead, tbody, tr, td, h1, h2, h3, h4, h5, h6, br, hr, img, input, select, button, style, applet, canvas, script, frame, iframe').remove() + htmlTmp.find('div, span, p, li, ul, ol, a, b, u, i, label, small, strong, strike, pre, code, center, blockquote, form, textarea, font, table, thead, tbody, tr, td, h1, h2, h3, h4, h5, h6, br, hr, img, input, select, button, style, applet, embed, noframes, canvas, script, frame, iframe').remove() - html + html.html(htmlTmp) # htmlOnlyWithRichtext = App.Utils.htmlRemoveRichtext( html ) @htmlRemoveRichtext: (html) -> + htmlTmp = $( '
' + html.html() + '
' ) # remove comments - @_removeComments( html ) + @_removeComments( htmlTmp ) # remove style and class - @_removeAttributes( html ) + @_removeAttributes( htmlTmp ) + + # remove work markup + htmlTmp = @_removeWordMarkup( htmlTmp ) # remove tags, keep content - html.find('li, ul, ol, a, b, u, i, label, small, strong, strike, pre, code, center, blockquote, form, textarea, font, address, table, thead, tbody, tr, td, h1, h2, h3, h4, h5, h6').replaceWith( -> + htmlTmp.find('li, ul, ol, a, b, u, i, label, small, strong, strike, pre, code, center, blockquote, form, textarea, font, address, table, thead, tbody, tr, td, h1, h2, h3, h4, h5, h6').replaceWith( -> $(@).contents() ) # remove tags & content - html.find('li, ul, ol, a, b, u, i, label, small, strong, strike, pre, code, center, blockquote, form, textarea, font, address, table, thead, tbody, tr, td, h1, h2, h3, h4, h5, h6, hr, img, input, select, button, style, applet, canvas, script, frame, iframe').remove() + htmlTmp.find('li, ul, ol, a, b, u, i, label, small, strong, strike, pre, code, center, blockquote, form, textarea, font, address, table, thead, tbody, tr, td, h1, h2, h3, h4, h5, h6, hr, img, input, select, button, style, applet, embed, noframes, canvas, script, frame, iframe').remove() - html + html.html(htmlTmp) # cleanHtmlWithRichText = App.Utils.htmlCleanup( html ) @htmlCleanup: (html) -> + htmlTmp = $( '
' + html.html() + '
' ) # remove comments - @_removeComments( html ) + @_removeComments( htmlTmp ) # remove style and class - @_removeAttributes( html ) + @_removeAttributes( htmlTmp ) + + # remove work markup + htmlTmp = @_removeWordMarkup( htmlTmp ) # remove tags, keep content - html.find('a, font, small, time').replaceWith( -> + htmlTmp.find('a, font, small, time').replaceWith( -> $(@).contents() ) @@ -148,31 +163,32 @@ class App.Utils # New type of the tag replacementTag = 'div'; - # Replace all a tags with the type of replacementTag - html.find('h1, h2, h3, h4, h5, h6, textarea').each( -> + # Replace all x tags with the type of replacementTag + htmlTmp.find('h1, h2, h3, h4, h5, h6, textarea').each( -> outer = this.outerHTML; # Replace opening tag - regex = new RegExp('<' + this.tagName, 'i'); - newTag = outer.replace(regex, '<' + replacementTag); + regex = new RegExp('<' + this.tagName, 'i') + newTag = outer.replace(regex, '<' + replacementTag) # Replace closing tag - regex = new RegExp(' - html.find('div, span, p, li, ul, ol, a, b, u, i, label, small, strong, strike, pre, code, center, blockquote, h1, h2, h3, h4, h5, h6') + html.find('*') .removeAttr( 'style' ) .removeAttr( 'class' ) .removeAttr( 'title' ) + .removeAttr( 'lang' ) html @_removeComments: (html) -> @@ -182,6 +198,14 @@ class App.Utils ) html + @_removeWordMarkup: (html) -> + htmlTmp = html.get(0).outerHTML + regex = new RegExp('<(/w|w)\:[A-Za-z]{3}>') + htmlTmp = htmlTmp.replace(regex, '') + regex = new RegExp('<(/o|o)\:[A-Za-z]{1}>') + htmlTmp = htmlTmp.replace(regex, '') + $(htmlTmp) + # signatureNeeded = App.Utils.signatureCheck( message, signature ) @signatureCheck: (message, signature) -> messageText = $( '
' + message + '
' ).text().trim() diff --git a/public/assets/tests/html-utils.js b/public/assets/tests/html-utils.js index 18e42afc1..b603ee1b0 100644 --- a/public/assets/tests/html-utils.js +++ b/public/assets/tests/html-utils.js @@ -212,43 +212,47 @@ test( "htmlEscape", function() { test( "htmlRemoveTags", function() { var source = "
test
" - var should = "test" + var should = "
test
" var result = App.Utils.htmlRemoveTags( $(source) ) equal( result.html(), should, source ) + source = "
test
" + should = "
test
" + result = App.Utils.htmlRemoveTags( $(source) ) + equal( result.html(), should, source ) + source = "some link to somewhere" - should = "some link to somewhere" + should = "
some link to somewhere
" result = App.Utils.htmlRemoveTags( $(source) ) equal( result.html(), should, source ) source = "
some link to somewhere
" - should = "some link to somewhere" + should = "
some link to somewhere
" result = App.Utils.htmlRemoveTags( $(source) ) equal( result.html(), should, source ) source = "
some link to somewhere
" - should = "some link to somewhere" + should = "
some link to somewhere
" result = App.Utils.htmlRemoveTags( $(source) ) equal( result.html(), should, source ) source = "
some link to somewhere

123
" - should = "some link to somewhere 123 " + should = "
some link to somewhere 123
" result = App.Utils.htmlRemoveTags( $(source) ) equal( result.html(), should, source ) source = "
test 123
" - should = "test 123" + should = "
test 123
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
" - should = "test 123" + should = "
test 123
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
This is some text!
" - //should = "
This is some text!
" - should = "This is some text!" + should = "
This is some text!
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) }); @@ -257,145 +261,147 @@ test( "htmlRemoveTags", function() { test( "htmlRemoveRichtext", function() { var source = "
test
" - var should = "test" + var should = "
test
" var result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) + source = "
1.1.1     Description
" + should = "
1.1.1     Description
" + result = App.Utils.htmlRemoveRichtext( $(source) ) + equal( result.html(), should, source ) + source = "some link to somewhere" - should = "some link to somewhere" + should = "
some link to somewhere
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
test
" - should = " test " + should = "
test
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
test
" - should = " test " + should = "
test
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
test
" - should = "
test
" + should = "
test
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
test
" - should = "
test
" + should = "
test
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
test
123
" - should = "
test
123" + should = "
test
123
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) - source = "
test
" - should = "
test
" + source = "
test
" + should = "
test
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
" - //should = "
test
" - should = " test " + should = "
test
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "

" - should = "
" - result = App.Utils.htmlRemoveRichtext( $(source) ) - equal( result.html(), should, source ) - - source = "

" should = "

" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) + source = "

" + should = "

" + result = App.Utils.htmlRemoveRichtext( $(source) ) + equal( result.html(), should, source ) + source = "
test 123
" - //should = "
test 123
" - should = "test 123" + should = "
test 123
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
This is some text!
" - //should = "
This is some text!
" - should = "This is some text!" + should = "
This is some text!
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) - }); // htmlCleanup test( "htmlCleanup", function() { var source = "
test
" - var should = "test" + var should = "
test
" var result = App.Utils.htmlCleanup( $(source) ) equal( result.html(), should, source ) source = "some link to somewhere" - should = "some link to somewhere" - result = App.Utils.htmlCleanup( $(source) ) - equal( result.html(), should, source ) - - source = "

some link to somewhere

" + //should = "some link to somewhere" should = "
some link to somewhere
" result = App.Utils.htmlCleanup( $(source) ) equal( result.html(), should, source ) + source = "

some link to somewhere

" + should = "
some link to somewhere
" + result = App.Utils.htmlCleanup( $(source) ) + equal( result.html(), should, source ) + source = "
some link to somewhere" - //should = "
some link to somewhere
" - should = "some link to somewhere" + should = "
some link to somewhere
" result = App.Utils.htmlCleanup( $(source) ) equal( result.html(), should, source ) source = "
" - //should = "
some link to somewhere
" - should = "some link to somewhere" + should = "
some link to somewhere
" result = App.Utils.htmlCleanup( $(source) ) equal( result.html(), should, source ) - source = "

some link to somewhere


" - should = "
some link to somewhere

" + source = "

some h1 for somewhere


" + should = "
some h1 for somewhere

" result = App.Utils.htmlCleanup( $(source) ) equal( result.html(), should, source ) source = "

" - should = "
" + should = "

" result = App.Utils.htmlCleanup( $(source) ) equal( result.html(), should, source ) source = "

" - should = "

" + should = "

" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
test 123
" //should = "
test 123
" - should = "test 123" + should = "
test 123
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
test 123
some other value
" - //should = "
ttest 123 some other value
" - should = "test 123 some other value" + should = "
test 123 some other value
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
test 123
some other value
" - //should = "
test 123 some other value
" - should = "test 123 some other value" + should = "
test 123 some other value
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) source = "
This is some text!
" - //should = "
This is some text!
" - should = "This is some text!" + should = "
This is some text!
" result = App.Utils.htmlRemoveRichtext( $(source) ) equal( result.html(), should, source ) + source = "

some link to somewhere from wordabc

" + should = "

some link to somewhere from wordabc

" + result = App.Utils.htmlCleanup( $(source) ) + equal( result.html(), should, source ) + }); // wrap From 405589a29331f56243ab7260549e90c803567ccc Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Tue, 4 Aug 2015 16:54:17 +0200 Subject: [PATCH 05/13] Added check if there are any options to display (e.g. options = null). --- .../app/views/generic/searchable_select_options.jst.eco | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/app/views/generic/searchable_select_options.jst.eco b/app/assets/javascripts/app/views/generic/searchable_select_options.jst.eco index d255b2be6..bf6cf3fc2 100644 --- a/app/assets/javascripts/app/views/generic/searchable_select_options.jst.eco +++ b/app/assets/javascripts/app/views/generic/searchable_select_options.jst.eco @@ -1,3 +1,5 @@ -<% for option in @options: %> -
+
+ +
+

Checkbox

diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 3d2e79fc1..22312bb30 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -3,8 +3,9 @@ class SearchController < ApplicationController before_action :authentication_check - # GET /api/v1/search_user_org - def search_user_org + # GET|POST /api/v1/search/:objects + + def search_generic # enable search only for agents and admins if !current_user.role?(Z_ROLENAME_AGENT) && !current_user.role?(Z_ROLENAME_ADMIN) @@ -16,11 +17,17 @@ class SearchController < ApplicationController query = params[:query] limit = params[:limit] || 10 + # convert objects string into array of class names + # e.g. user-ticket-another_object = %w( User Ticket AnotherObject ) + objects = params[:objects].split('-').map { |object| + object.camelize + } + # try search index backend assets = {} result = [] if SearchIndexBackend.enabled? - items = SearchIndexBackend.search( query, limit, %w(User Organization) ) + items = SearchIndexBackend.search( query, limit, objects ) items.each { |item| require item[:type].to_filename record = Kernel.const_get( item[:type] ).find( item[:id] ) @@ -29,34 +36,23 @@ class SearchController < ApplicationController } else # do query - users = User.search( - query: query, - limit: limit, - current_user: current_user, - ) - users.each do |user| - item = { - id: user.id, - type: user.class.to_s - } - result.push item - assets = user.assets(assets) - end + objects.each { |object| - organizations = Organization.search( - query: query, - limit: limit, - current_user: current_user, - ) + found_objects = object.constantize.search( + query: query, + limit: limit, + current_user: current_user, + ) - organizations.each do |organization| - item = { - id: organization.id, - type: organization.class.to_s - } - result.push item - assets = organization.assets(assets) - end + 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 + } end render json: { @@ -68,64 +64,54 @@ class SearchController < ApplicationController # GET /api/v1/search def search - # build result list - tickets = Ticket.search( - limit: params[:limit], - query: params[:term], - current_user: current_user, - ) - assets = {} - ticket_result = [] - tickets.each do |ticket| - assets = ticket.assets(assets) - ticket_result.push ticket.id - end + assets = {} + result = [] + objects = %w( Ticket User Organization ) + if SearchIndexBackend.enabled? - # do query - users = User.search( - query: params[:term], - limit: params[:limit], - current_user: current_user, - ) - user_result = [] - users.each do |user| - user_result.push user.id - assets = user.assets(assets) - end + found_objects = {} + items = SearchIndexBackend.search( params[:term], params[:limit], objects ) + items.each { |item| + require item[:type].to_filename + record = Kernel.const_get( item[:type] ).find( item[:id] ) + assets = record.assets(assets) - organizations = Organization.search( - query: params[:term], - limit: params[:limit], - current_user: current_user, - ) - - organization_result = [] - organizations.each do |organization| - organization_result.push organization.id - assets = organization.assets(assets) - end - - result = [] - if ticket_result[0] - data = { - name: 'Ticket', - ids: ticket_result, + found_objects[ item[:type] ] ||= [] + found_objects[ item[:type] ].push item[:id] } - result.push data - end - if user_result[0] - data = { - name: 'User', - ids: user_result, + + found_objects.each { |object, object_ids| + + data = { + name: object, + ids: object_ids, + } + result.push data } - result.push data - end - if organization_result[0] - data = { - name: 'Organization', - ids: organization_result, + else + + objects.each { |object| + + found_objects = object.constantize.search( + query: params[:term], + limit: params[:limit], + current_user: current_user, + ) + + object_ids = [] + found_objects.each do |found_object| + object_ids.push found_object.id + assets = found_object.assets(assets) + end + + next if object_ids.empty? + + data = { + name: object, + ids: object_ids, + } + result.push data } - result.push data end # return result diff --git a/config/routes/search.rb b/config/routes/search.rb index 827cd97db..44eed8c42 100644 --- a/config/routes/search.rb +++ b/config/routes/search.rb @@ -2,9 +2,8 @@ Zammad::Application.routes.draw do api_path = Rails.configuration.api_path # search - match api_path + '/search', to: 'search#search', via: [:get, :post] - - # search_user_org - match api_path + '/search_user_org', to: 'search#search_user_org', via: [:get, :post] + match api_path + '/search', to: 'search#search', via: [:get, :post] + # search_generic + match api_path + '/search/:objects', to: 'search#search_generic', via: [:get, :post] end From a24f45ce6f998195164689c5ebcb52e2b025f0c9 Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Wed, 5 Aug 2015 11:48:21 +0200 Subject: [PATCH 09/13] Rubocop improvement. --- app/controllers/search_controller.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 22312bb30..f3562aeab 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -19,9 +19,7 @@ class SearchController < ApplicationController # convert objects string into array of class names # e.g. user-ticket-another_object = %w( User Ticket AnotherObject ) - objects = params[:objects].split('-').map { |object| - object.camelize - } + objects = params[:objects].split('-').map(&:camelize) # try search index backend assets = {} From 13b0758c2ae9b8e07113eb7e142e2762f78c6c7b Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 5 Aug 2015 12:42:35 +0200 Subject: [PATCH 10/13] Close recipientlist on tab. --- .../lib/app_post/user_organization_autocompletion.js.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/javascripts/app/lib/app_post/user_organization_autocompletion.js.coffee b/app/assets/javascripts/app/lib/app_post/user_organization_autocompletion.js.coffee index 4c13dc901..c870df54a 100644 --- a/app/assets/javascripts/app/lib/app_post/user_organization_autocompletion.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/user_organization_autocompletion.js.coffee @@ -114,6 +114,10 @@ class App.UserOrganizationAutocompletion extends App.Controller item = '' @close() + # if tab / close recipientList + if e.keyCode is 9 + @close() + # ignore arrow keys if e.keyCode is 37 return From 3f6cb885b2522ae5bf3cf7381d38776bc7a0942b Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 5 Aug 2015 13:58:53 +0200 Subject: [PATCH 11/13] Added permission related search for tickets. --- app/controllers/search_controller.rb | 44 +++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index f3562aeab..a9bad5b6d 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -20,6 +20,7 @@ class SearchController < ApplicationController # convert objects string into array of class names # e.g. user-ticket-another_object = %w( User Ticket AnotherObject ) objects = params[:objects].split('-').map(&:camelize) + search_tickets = objects.delete('Ticket') # try search index backend assets = {} @@ -32,7 +33,25 @@ class SearchController < ApplicationController assets = record.assets(assets) result.push item } + + # 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', + } + result.push item + end + end else + # do query objects.each { |object| @@ -62,13 +81,18 @@ class SearchController < ApplicationController # GET /api/v1/search def search + # get params + query = params[:term] + limit = params[:limit] || 10 + assets = {} result = [] - objects = %w( Ticket User Organization ) + search_index_objects = %w( User Organization ) if SearchIndexBackend.enabled? + # to query search index backend (excluse tickets here, see below) found_objects = {} - items = SearchIndexBackend.search( params[:term], params[:limit], objects ) + items = SearchIndexBackend.search( query, limit, search_index_objects ) items.each { |item| require item[:type].to_filename record = Kernel.const_get( item[:type] ).find( item[:id] ) @@ -78,6 +102,18 @@ class SearchController < ApplicationController found_objects[ item[:type] ].push item[:id] } + # do ticket query by Ticket class to handle ticket permissions + tickets = Ticket.search( + query: query, + limit: limit, + current_user: current_user, + ) + tickets.each do |ticket| + found_objects[ 'Ticket' ] ||= [] + found_objects[ 'Ticket' ].push ticket.id + end + + # generate whole result found_objects.each { |object, object_ids| data = { @@ -91,8 +127,8 @@ class SearchController < ApplicationController objects.each { |object| found_objects = object.constantize.search( - query: params[:term], - limit: params[:limit], + query: query, + limit: limit, current_user: current_user, ) From e84a91da5d462c78442b9ff202c45a243cb49b44 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 5 Aug 2015 16:40:04 +0200 Subject: [PATCH 12/13] Moved search result attributes to model. --- .../app/controllers/navigation.js.coffee | 24 +++---------------- .../app/models/organization.js.coffee | 7 ++++++ .../javascripts/app/models/ticket.js.coffee | 8 ++++++- .../javascripts/app/models/user.js.coffee | 7 ++++++ 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/app/assets/javascripts/app/controllers/navigation.js.coffee b/app/assets/javascripts/app/controllers/navigation.js.coffee index 084e82b8f..56fc6dac4 100644 --- a/app/assets/javascripts/app/controllers/navigation.js.coffee +++ b/app/assets/javascripts/app/controllers/navigation.js.coffee @@ -166,35 +166,17 @@ class App.Navigation extends App.ControllerWidgetPermanent area.result = [] for id in area.ids ticket = App.Ticket.find( id ) - data = - display: "##{ticket.number} - #{ticket.title}" - id: ticket.id - class: "level-#{ticket.level()} ticket-popover" - url: ticket.uiUrl() - iconClass: "priority" - area.result.push data + area.result.push ticket.searchResultAttributes() else if area.name is 'User' area.result = [] for id in area.ids user = App.User.find( id ) - data = - display: "#{user.displayName()}" - id: user.id - class: "user user-popover" - url: user.uiUrl() - iconClass: "user" - area.result.push data + area.result.push user.searchResultAttributes() else if area.name is 'Organization' area.result = [] for id in area.ids organization = App.Organization.find( id ) - data = - display: "#{organization.displayName()}" - id: organization.id - class: "organization organization-popover" - url: organization.uiUrl() - iconClass: "organization" - area.result.push data + area.result.push organization.searchResultAttributes() @renderResult(result) diff --git a/app/assets/javascripts/app/models/organization.js.coffee b/app/assets/javascripts/app/models/organization.js.coffee index 1748a4b76..68a60be0e 100644 --- a/app/assets/javascripts/app/models/organization.js.coffee +++ b/app/assets/javascripts/app/models/organization.js.coffee @@ -30,3 +30,10 @@ class App.Organization extends App.Model user = App.User.find( user_id ) data['members'].push user data + + searchResultAttributes: -> + display: "#{@displayName()}" + id: @id + class: "organization organization-popover" + url: @uiUrl() + iconClass: "organization" \ No newline at end of file diff --git a/app/assets/javascripts/app/models/ticket.js.coffee b/app/assets/javascripts/app/models/ticket.js.coffee index c941a3963..e87e0f3f3 100644 --- a/app/assets/javascripts/app/models/ticket.js.coffee +++ b/app/assets/javascripts/app/models/ticket.js.coffee @@ -50,4 +50,10 @@ class App.Ticket extends App.Model iconActivity: (user) -> if @owner_id == user.id return 'important' - '' \ No newline at end of file + '' + searchResultAttributes: -> + display: "##{@number} - #{@title}" + id: @id + class: "level-#{@level()} ticket-popover" + url: @uiUrl() + iconClass: "priority" diff --git a/app/assets/javascripts/app/models/user.js.coffee b/app/assets/javascripts/app/models/user.js.coffee index a37b09397..cedbf80c4 100644 --- a/app/assets/javascripts/app/models/user.js.coffee +++ b/app/assets/javascripts/app/models/user.js.coffee @@ -119,3 +119,10 @@ class App.User extends App.Model data['groups'].push group data + + searchResultAttributes: -> + display: "#{@displayName()}" + id: @id + class: "user user-popover" + url: @uiUrl() + iconClass: "user" \ No newline at end of file From d5cae2d3d633082b12a304f35557bd2e5b18edda Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 5 Aug 2015 16:59:14 +0200 Subject: [PATCH 13/13] Fixed non search index based ticket search. --- app/controllers/search_controller.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index a9bad5b6d..2b8469e8d 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -87,12 +87,15 @@ class SearchController < ApplicationController assets = {} result = [] - search_index_objects = %w( User Organization ) + objects = %w( Ticket User Organization ) if SearchIndexBackend.enabled? + # to ticket search in serparate call + objects.delete('Ticket') + # to query search index backend (excluse tickets here, see below) found_objects = {} - items = SearchIndexBackend.search( query, limit, search_index_objects ) + items = SearchIndexBackend.search( query, limit, objects ) items.each { |item| require item[:type].to_filename record = Kernel.const_get( item[:type] ).find( item[:id] )