From 469d532b0652afadaa82be00b5e36eaee299ec91 Mon Sep 17 00:00:00 2001 From: Martin Gruner Date: Mon, 14 Feb 2022 08:59:42 +0100 Subject: [PATCH 01/10] Maintenance: Bump rails from 6.0.4.4 to 6.0.4.6 and puma from 4.3.10 to 4.3.11. --- Gemfile.lock | 124 +++++++++++++++++++++++++-------------------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index bb6e27eaa..15fee5c1f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -21,50 +21,50 @@ GEM specs: aasm (5.2.0) concurrent-ruby (~> 1.0) - actioncable (6.0.4.4) - actionpack (= 6.0.4.4) + actioncable (6.0.4.6) + actionpack (= 6.0.4.6) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.4.4) - actionpack (= 6.0.4.4) - activejob (= 6.0.4.4) - activerecord (= 6.0.4.4) - activestorage (= 6.0.4.4) - activesupport (= 6.0.4.4) + actionmailbox (6.0.4.6) + actionpack (= 6.0.4.6) + activejob (= 6.0.4.6) + activerecord (= 6.0.4.6) + activestorage (= 6.0.4.6) + activesupport (= 6.0.4.6) mail (>= 2.7.1) - actionmailer (6.0.4.4) - actionpack (= 6.0.4.4) - actionview (= 6.0.4.4) - activejob (= 6.0.4.4) + actionmailer (6.0.4.6) + actionpack (= 6.0.4.6) + actionview (= 6.0.4.6) + activejob (= 6.0.4.6) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.4.4) - actionview (= 6.0.4.4) - activesupport (= 6.0.4.4) + actionpack (6.0.4.6) + actionview (= 6.0.4.6) + activesupport (= 6.0.4.6) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.4.4) - actionpack (= 6.0.4.4) - activerecord (= 6.0.4.4) - activestorage (= 6.0.4.4) - activesupport (= 6.0.4.4) + actiontext (6.0.4.6) + actionpack (= 6.0.4.6) + activerecord (= 6.0.4.6) + activestorage (= 6.0.4.6) + activesupport (= 6.0.4.6) nokogiri (>= 1.8.5) - actionview (6.0.4.4) - activesupport (= 6.0.4.4) + actionview (6.0.4.6) + activesupport (= 6.0.4.6) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.4.4) - activesupport (= 6.0.4.4) + activejob (6.0.4.6) + activesupport (= 6.0.4.6) globalid (>= 0.3.6) - activemodel (6.0.4.4) - activesupport (= 6.0.4.4) - activerecord (6.0.4.4) - activemodel (= 6.0.4.4) - activesupport (= 6.0.4.4) + activemodel (6.0.4.6) + activesupport (= 6.0.4.6) + activerecord (6.0.4.6) + activemodel (= 6.0.4.6) + activesupport (= 6.0.4.6) activerecord-import (1.2.0) activerecord (>= 3.2) activerecord-nulldb-adapter (0.7.0) @@ -75,12 +75,12 @@ GEM multi_json (~> 1.11, >= 1.11.2) rack (>= 2.0.8, < 3) railties (>= 5.2.4.1) - activestorage (6.0.4.4) - actionpack (= 6.0.4.4) - activejob (= 6.0.4.4) - activerecord (= 6.0.4.4) + activestorage (6.0.4.6) + actionpack (= 6.0.4.6) + activejob (= 6.0.4.6) + activerecord (= 6.0.4.6) marcel (~> 1.0.0) - activesupport (6.0.4.4) + activesupport (6.0.4.6) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -281,7 +281,7 @@ GEM ffi-compiler (>= 1.0, < 2.0) http_parser.rb (0.6.0) httpclient (2.8.3) - i18n (1.8.10) + i18n (1.9.1) concurrent-ruby (~> 1.0) icalendar (2.7.1) ice_cube (~> 0.16) @@ -307,11 +307,11 @@ GEM logging (2.3.0) little-plugger (~> 1.1) multi_json (~> 1.14) - loofah (2.13.0) + loofah (2.14.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) lumberjack (1.2.8) - marcel (1.0.1) + marcel (1.0.2) memoizable (0.4.2) thread_safe (~> 0.3, >= 0.3.1) messagebird-rest (3.0.0) @@ -319,8 +319,8 @@ GEM mime-types (3.3.1) mime-types-data (~> 3.2015) mime-types-data (3.2021.0225) - mini_mime (1.1.1) - mini_portile2 (2.6.1) + mini_mime (1.1.2) + mini_portile2 (2.7.1) mini_racer (0.2.9) libv8 (>= 6.9.411) minitest (5.15.0) @@ -335,8 +335,8 @@ GEM net-ldap (0.17.0) netrc (0.11.0) nio4r (2.5.8) - nokogiri (1.12.5) - mini_portile2 (~> 2.6.1) + nokogiri (1.13.1) + mini_portile2 (~> 2.7.0) racc (~> 1.4) nori (2.6.0) notiffany (0.1.3) @@ -423,32 +423,32 @@ GEM binding_of_caller (~> 1.0) pry (~> 0.13) public_suffix (4.0.6) - puma (4.3.10) + puma (4.3.11) nio4r (~> 2.0) pundit (2.1.1) activesupport (>= 3.0.0) pundit-matchers (1.7.0) rspec-rails (>= 3.0.0) - racc (1.5.2) + racc (1.6.0) rack (2.2.3) rack-livereload (0.3.17) rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (6.0.4.4) - actioncable (= 6.0.4.4) - actionmailbox (= 6.0.4.4) - actionmailer (= 6.0.4.4) - actionpack (= 6.0.4.4) - actiontext (= 6.0.4.4) - actionview (= 6.0.4.4) - activejob (= 6.0.4.4) - activemodel (= 6.0.4.4) - activerecord (= 6.0.4.4) - activestorage (= 6.0.4.4) - activesupport (= 6.0.4.4) + rails (6.0.4.6) + actioncable (= 6.0.4.6) + actionmailbox (= 6.0.4.6) + actionmailer (= 6.0.4.6) + actionpack (= 6.0.4.6) + actiontext (= 6.0.4.6) + actionview (= 6.0.4.6) + activejob (= 6.0.4.6) + activemodel (= 6.0.4.6) + activerecord (= 6.0.4.6) + activestorage (= 6.0.4.6) + activesupport (= 6.0.4.6) bundler (>= 1.3.0) - railties (= 6.0.4.4) + railties (= 6.0.4.6) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -457,11 +457,11 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.4.1) + rails-html-sanitizer (1.4.2) loofah (~> 2.3) - railties (6.0.4.4) - actionpack (= 6.0.4.4) - activesupport (= 6.0.4.4) + railties (6.0.4.6) + actionpack (= 6.0.4.6) + activesupport (= 6.0.4.6) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) @@ -583,7 +583,7 @@ GEM tins (~> 1.0) test-unit (3.4.7) power_assert - thor (1.1.0) + thor (1.2.1) thread_safe (0.3.6) tilt (2.0.10) timers (4.3.3) @@ -634,7 +634,7 @@ GEM writeexcel (1.0.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.4.2) + zeitwerk (2.5.4) zendesk_api (1.33.0) faraday (>= 0.9.0, < 2.0.0) hashie (>= 3.5.2, < 5.0.0) From 30fd5d34da1242fc1dff24e860a28e7ddcf1e649 Mon Sep 17 00:00:00 2001 From: Rolf Schmidt Date: Wed, 16 Feb 2022 16:20:14 +0100 Subject: [PATCH 02/10] Fixes #3957 - S/MIME function buttons no longer working in tickets. --- .../ticket_zoom/article_view.coffee | 46 ++++++++++--------- lib/secure_mailing.rb | 4 +- spec/system/ticket/zoom_spec.rb | 18 +++++++- 3 files changed, 44 insertions(+), 24 deletions(-) diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee index 66a6a5e87..223d2f9cf 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee @@ -305,34 +305,38 @@ class ArticleViewItem extends App.ControllerObserver e.stopPropagation() article_id = $(e.target).closest('.ticket-article-item').data('id') + article = App.TicketArticle.find(article_id) @ajax( id: 'retrySecurityProcess' type: 'POST' url: "#{@apiPath}/ticket_articles/#{article_id}/retry_security_process" processData: true - success: (data, status, xhr) => - if data.sign.success - @notify - type: 'success' - msg: App.i18n.translateContent('Verify sign success!') - else if data.sign.comment - comment = App.i18n.translateContent('Verify sign failed!') + ' ' + App.i18n.translateContent(data.sign.comment || '') - @notify - type: 'error' - msg: comment - timeout: 2000 + success: (encryption_data, status, xhr) => + for data in encryption_data + continue if article.preferences.security.type isnt data.type - if data.encryption.success - @notify - type: 'success' - msg: App.i18n.translateContent('Decryption success!') - else if data.encryption.comment - comment = App.i18n.translateContent('Decryption failed!') + ' ' + App.i18n.translateContent(data.encryption.comment || '') - @notify - type: 'error' - msg: comment - timeout: 2000 + if data.sign.success + @notify + type: 'success' + msg: App.i18n.translateContent('Verify sign success!') + else if data.sign.comment + comment = App.i18n.translateContent('Verify sign failed!') + ' ' + App.i18n.translateContent(data.sign.comment || '') + @notify + type: 'error' + msg: comment + timeout: 2000 + + if data.encryption.success + @notify + type: 'success' + msg: App.i18n.translateContent('Decryption success!') + else if data.encryption.comment + comment = App.i18n.translateContent('Decryption failed!') + ' ' + App.i18n.translateContent(data.encryption.comment || '') + @notify + type: 'error' + msg: comment + timeout: 2000 error: (xhr) => @notify diff --git a/lib/secure_mailing.rb b/lib/secure_mailing.rb index d28236784..96ada9c01 100644 --- a/lib/secure_mailing.rb +++ b/lib/secure_mailing.rb @@ -10,9 +10,11 @@ class SecureMailing end def self.retry(article) + result = [] active_backends.each do |backend| - "#{backend}::Retry".constantize.process(article) + result << "#{backend}::Retry".constantize.process(article) end + result end def self.outgoing(mail, security) diff --git a/spec/system/ticket/zoom_spec.rb b/spec/system/ticket/zoom_spec.rb index f7e988c95..3fd9ec3cf 100644 --- a/spec/system/ticket/zoom_spec.rb +++ b/spec/system/ticket/zoom_spec.rb @@ -588,8 +588,7 @@ RSpec.describe 'Ticket zoom', type: :system do end context 'certificate not present at time of arrival' do - - it 'retry' do + let(:mail) do smime1 = create(:smime_certificate, :with_private, fixture: system_email_address) smime2 = create(:smime_certificate, :with_private, fixture: sender_email_address) @@ -612,6 +611,10 @@ RSpec.describe 'Ticket zoom', type: :system do smime1.destroy smime2.destroy + mail + end + + it 'does retry successfully' do parsed_mail = Channel::EmailParser.new.parse(mail.to_s) ticket, article, _user, _mail = Channel::EmailParser.new.process({ group_id: group.id }, parsed_mail['raw']) expect(Ticket::Article.find(article.id).body).to eq('no visible content') @@ -624,6 +627,17 @@ RSpec.describe 'Ticket zoom', type: :system do click '.js-securityRetryProcess' expect(page).to have_css('.article-content', text: 'somebody with some text') end + + it 'does fail on retry (S/MIME function buttons no longer working in tickets #3957)' do + parsed_mail = Channel::EmailParser.new.parse(mail.to_s) + ticket, article, _user, _mail = Channel::EmailParser.new.process({ group_id: group.id }, parsed_mail['raw']) + expect(Ticket::Article.find(article.id).body).to eq('no visible content') + + visit "#ticket/zoom/#{ticket.id}" + expect(page).to have_no_css('.article-content', text: 'somebody with some text') + click '.js-securityRetryProcess' + expect(page).to have_css('#notify', text: 'Decryption failed! Unable to find private key to decrypt') + end end end From 91dc61bbaa9722dd07ec6cc06ac2a9c302b2e92e Mon Sep 17 00:00:00 2001 From: Rolf Schmidt Date: Wed, 16 Feb 2022 16:20:25 +0100 Subject: [PATCH 03/10] Fixes #3920 - Not translated text with forwarding e-mails. --- .../controllers/ticket_zoom/article_action/email_reply.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/email_reply.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/email_reply.coffee index f7bcf3867..91857781c 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/email_reply.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/email_reply.coffee @@ -257,7 +257,7 @@ class EmailReply extends App.Controller quote_header = App.FullQuoteHeader.fullQuoteHeaderForward(article) - body = "
---Begin forwarded message:---

#{quote_header}#{body}

" + body = "
---#{App.i18n.translateInline('Begin forwarded message')}:---

#{quote_header}#{body}

" articleNew = {} articleNew.body = body From 4cb5a7776bef5036c5b69cf581d7089804c85f2b Mon Sep 17 00:00:00 2001 From: Rolf Schmidt Date: Thu, 17 Feb 2022 08:35:55 +0100 Subject: [PATCH 04/10] Maintenance: Fix difference function to compare both ways and also make sure that the observer copies hashes to prevent references. --- .../_application_controller/observer.coffee | 43 ++-- .../controllers/organization_profile.coffee | 2 +- .../article_action/internal.coffee | 2 +- .../ticket_zoom/article_view.coffee | 10 +- .../app/controllers/ticket_zoom/title.coffee | 2 +- .../app/controllers/user_profile.coffee | 2 +- app/assets/javascripts/application.js | 10 +- public/assets/tests/core.js | 130 ++++++++--- .../assets/tests/qunit/controller_observer.js | 202 ++++++++++++++++++ 9 files changed, 343 insertions(+), 60 deletions(-) create mode 100644 public/assets/tests/qunit/controller_observer.js diff --git a/app/assets/javascripts/app/controllers/_application_controller/observer.coffee b/app/assets/javascripts/app/controllers/_application_controller/observer.coffee index 293c02528..a50b3915f 100644 --- a/app/assets/javascripts/app/controllers/_application_controller/observer.coffee +++ b/app/assets/javascripts/app/controllers/_application_controller/observer.coffee @@ -2,6 +2,7 @@ class App.ControllerObserver extends App.Controller model: 'Ticket' template: 'tba' globalRerender: true + lastAttributes: undefined ### observe: @@ -25,7 +26,7 @@ class App.ControllerObserver extends App.Controller # rerender, e. g. on language change if @globalRerender @controllerBind('ui:rerender', => - @lastAttributres = undefined + @lastAttributes = undefined @maybeRender(App[@model].fullLocal(@object_id)) ) @@ -43,32 +44,40 @@ class App.ControllerObserver extends App.Controller if !@subscribeId @subscribeId = object.subscribe(@subscribe) - # remember current attributes + return if !@hasChanged(object) + + @render(object) + + hasChanged: (object) => currentAttributes = {} + + objectCloned = $.extend(true, {}, object) if @observe for key, active of @observe - if active - currentAttributes[key] = object[key] + if active && !_.isFunction(value) + currentAttributes[key] = objectCloned[key] + if @observeNot - for key, value of object - if key isnt 'cid' && !@observeNot[key] && !_.isFunction(value) && !_.isObject(value) + for key, value of objectCloned + if key isnt 'cid' && !@observeNot[key] && !_.isFunction(value) currentAttributes[key] = value - if !@lastAttributres - @lastAttributres = {} - else - diff = difference(currentAttributes, @lastAttributres) - if _.isEmpty(diff) - @log 'debug', 'maybeRender no diff, no rerender' - return + if !@lastAttributes + @lastAttributes = currentAttributes + return true + + diff = difference(currentAttributes, @lastAttributes) + if _.isEmpty(diff) + @log 'debug', 'maybeRender no diff, no rerender' + return false @log 'debug', 'maybeRender.diff', diff, @observe, @model - @lastAttributres = currentAttributes + @lastAttributes = currentAttributes - @render(object, diff) + true - render: (object, diff) => - @log 'debug', 'render', @template, object, diff + render: (object) => + @log 'debug', 'render', @template, object @html App.view(@template)( object: object ) diff --git a/app/assets/javascripts/app/controllers/organization_profile.coffee b/app/assets/javascripts/app/controllers/organization_profile.coffee index ad7890c68..4aefe61b3 100644 --- a/app/assets/javascripts/app/controllers/organization_profile.coffee +++ b/app/assets/javascripts/app/controllers/organization_profile.coffee @@ -202,7 +202,7 @@ class Object extends App.ControllerObserver value = $(e.target).html() org = App.Organization.find(@object_id) if org[name] isnt value - @lastAttributres[name] = value + @lastAttributes[name] = value data = {} data[name] = value org.updateAttributes(data) diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/internal.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/internal.coffee index b748be467..667ea1ad5 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/internal.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/internal.coffee @@ -24,7 +24,7 @@ class Internal internal = true if article.internal == true internal = false - ui.lastAttributres.internal = internal + ui.lastAttributes.internal = internal article.updateAttributes(internal: internal) # runtime update diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee index 223d2f9cf..18234a14f 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee @@ -218,11 +218,11 @@ class ArticleViewItem extends App.ControllerObserver ) @articleActions = new App.TicketZoomArticleActions( - el: @$('.js-article-actions') - ticket: @ticket - article: article - lastAttributres: @lastAttributres - form_id: @form_id + el: @$('.js-article-actions') + ticket: @ticket + article: article + lastAttributes: @lastAttributes + form_id: @form_id ) # set see more diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/title.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/title.coffee index a9acea2ea..3555967a5 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/title.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/title.coffee @@ -19,7 +19,7 @@ class App.TicketZoomTitle extends App.ControllerObserver title = $(e.target).ceg() || '' # update title - return if title is @lastAttributres.title + return if title is @lastAttributes.title ticket = App.Ticket.find(@object_id) ticket.title = title diff --git a/app/assets/javascripts/app/controllers/user_profile.coffee b/app/assets/javascripts/app/controllers/user_profile.coffee index 43f11effb..2ec790d05 100644 --- a/app/assets/javascripts/app/controllers/user_profile.coffee +++ b/app/assets/javascripts/app/controllers/user_profile.coffee @@ -220,7 +220,7 @@ class Object extends App.ControllerObserver value = $(e.target).html() user = App.User.find(@object_id) if user[name] isnt value - @lastAttributres[name] = value + @lastAttributes[name] = value data = {} data[name] = value user.updateAttributes(data) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 4e4974fce..45ebcbd50 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -65,9 +65,9 @@ Date.prototype.getWeek = function() { function difference(object1, object2) { var changes = {}; - for (var name in object1) { - if (name in object2) { - if (_.isObject(object2[name]) && !_.isArray(object2[name])) { + _.uniq(Object.keys(object1).concat(Object.keys(object2))).forEach(function(name) { + if (name in object1 && name in object2) { + if (_.isObject(object1[name]) && !_.isArray(object1[name]) && _.isObject(object2[name]) && !_.isArray(object2[name])) { var diff = difference(object1[name], object2[name]); if (!_.isEmpty(diff)) { changes[name] = diff; @@ -75,8 +75,10 @@ function difference(object1, object2) { } else if (!_.isEqual(object1[name], object2[name])) { changes[name] = object2[name]; } + } else { + changes[name] = object2[name] } - } + }) return changes; } diff --git a/public/assets/tests/core.js b/public/assets/tests/core.js index 765594dfe..8f2e35819 100644 --- a/public/assets/tests/core.js +++ b/public/assets/tests/core.js @@ -536,7 +536,9 @@ test('difference', function() { object2 = { key1: 123, } - result = {} + result = { + key2: undefined + } item = difference(object1, object2) deepEqual(item, result) @@ -547,38 +549,106 @@ test('difference', function() { key1: 123, key2: 124 } + result = { + key2: 124 + } + item = difference(object1, object2) + deepEqual(item, result) + + object1 = { + customer_id: 1, + organization_id: 2, + } + object2 = { + customer_id: 1, + organization_id: null, + } + result = { + organization_id: null, + } + item = difference(object1, object2) + deepEqual(item, result) + + object1 = { + customer_id: 1, + organization_id: null, + } + object2 = { + customer_id: 1, + organization_id: 2, + } + result = { + organization_id: 2, + } + item = difference(object1, object2) + deepEqual(item, result) + + object1 = { + customer_id: 1, + preferences: { resolved: true }, + } + object2 = { + customer_id: 1, + preferences: {}, + } + result = { + preferences: { resolved: undefined } + } + item = difference(object1, object2) + deepEqual(item, result) + + object1 = { + customer_id: 1, + } + object2 = { + customer_id: 1, + preferences: { resolved: true }, + } + result = { + preferences: { resolved: true } + } + item = difference(object1, object2) + deepEqual(item, result) + + object1 = { + customer_id: 1, + preferences: {}, + } + object2 = { + customer_id: 1, + preferences: { resolved: true }, + } + result = { + preferences: { resolved: true } + } + item = difference(object1, object2) + deepEqual(item, result) + + object1 = { + customer_id: 1, + preferences: { resolved: false }, + } + object2 = { + customer_id: 1, + preferences: { resolved: true }, + } + result = { + preferences: { resolved: true } + } + item = difference(object1, object2) + deepEqual(item, result) + + object1 = { + customer_id: 1, + preferences: { resolved: true }, + } + object2 = { + customer_id: 1, + preferences: { resolved: true }, + } result = {} item = difference(object1, object2) deepEqual(item, result) - - object1 = { - customer_id: 1, - organization_id: 2, - } - object2 = { - customer_id: 1, - organization_id: null, - } - result = { - organization_id: null, - } - item = difference(object1, object2) - deepEqual(item, result) - - object1 = { - customer_id: 1, - organization_id: null, - } - object2 = { - customer_id: 1, - organization_id: 2, - } - result = { - organization_id: 2, - } - item = difference(object1, object2) - deepEqual(item, result) - }); test('auth - not existing user', function(assert) { diff --git a/public/assets/tests/qunit/controller_observer.js b/public/assets/tests/qunit/controller_observer.js new file mode 100644 index 000000000..1f9b4878a --- /dev/null +++ b/public/assets/tests/qunit/controller_observer.js @@ -0,0 +1,202 @@ +QUnit.test( "controller observer tests - observe", assert => { + + App.Ticket.refresh([{ + id: 1, + title: 'ticket', + state_id: 1, + customer_id: 33, + organization_id: 1, + owner_id: 1, + preferences: { a: 1, b: 2 }, + }]) + + var observer1 = new App.ControllerObserver({ + object_id: 1, + template: 'version', + observe: { + title: true, + preferences: true, + }, + }) + + var ticket = App.Ticket.find(1) + + assert.equal(false, observer1.hasChanged(ticket)) + + // track title changes + ticket.title = 'title 2' + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.title = undefined + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.title = 'title 3' + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + // track no owner_id changes + ticket.owner_id = 2 + + assert.equal(false, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + // track preferences changes + ticket.preferences['a'] = 3 + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.preferences['c'] = 3 + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + // track no new_attribute1 changes + ticket.new_attribute1 = 'na 3' + + assert.equal(false, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.new_attribute2 = function() { console.log(1) } + + assert.equal(false, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.new_attribute2 = function() { console.log(2) } + + assert.equal(false, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + // track title changes + ticket.title = function() { console.log(1) } + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.title = function() { console.log(2) } + + assert.equal(false, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.title = 1 + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + +}); + +QUnit.test( "controller observer tests - observeNot", assert => { + + App.Ticket.refresh([{ + id: 2, + title: 'ticket', + state_id: 1, + customer_id: 33, + organization_id: 1, + owner_id: 1, + preferences: { a: 1, b: 2 }, + }]) + + var observer1 = new App.ControllerObserver({ + object_id: 2, + template: 'version', + observeNot: { + title: true, + preferences: true, + }, + }) + + var ticket = App.Ticket.find(2) + + assert.equal(false, observer1.hasChanged(ticket)) + + // track no title changes + ticket.title = 'title 2' + + assert.equal(false, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + // track owner_id changes + ticket.owner_id = 2 + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.owner_id = undefined + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.owner_id = 3 + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + // track no preferences changes + ticket.preferences['a'] = 3 + + assert.equal(false, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.preferences['c'] = 3 + assert.equal(false, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + // track preferences2 changes + ticket.preferences2 = {} + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.preferences2['a'] = 3 + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.preferences2['a'] = 2 + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.preferences2['c'] = 3 + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + // track new_attribute1 changes + ticket.new_attribute1 = 'na 3' + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + // track no new_attribute2 changes (because of function content) + ticket.new_attribute2 = function() { console.log(1) } + + assert.equal(false, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.new_attribute2 = function() { console.log(2) } + + assert.equal(false, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + // track owner_id changes (pnly if content has no function content) + ticket.owner_id = function() { console.log(1) } + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.owner_id = function() { console.log(2) } + + assert.equal(false, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + + ticket.owner_id = 1 + + assert.equal(true, observer1.hasChanged(ticket)) + assert.equal(false, observer1.hasChanged(ticket)) + +}); From ca2885dce0323e9246fc088e967aa9272298605d Mon Sep 17 00:00:00 2001 From: Rolf Schmidt Date: Fri, 18 Feb 2022 10:45:23 +0000 Subject: [PATCH 05/10] =?UTF-8?q?Fixes=20#3969=20-=20Frequent=20=E2=80=9CL?= =?UTF-8?q?ost=20connection=20to=20MySQL=20server=20during=20query?= =?UTF-8?q?=E2=80=9D=20errors=20resulting=20in=20client-side=20Error=20500?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/initializers/db_preferences.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/db_preferences.rb b/config/initializers/db_preferences.rb index 265b0d552..26aeccf0a 100644 --- a/config/initializers/db_preferences.rb +++ b/config/initializers/db_preferences.rb @@ -10,7 +10,7 @@ when 'mysql2' # Because of missing ticket updates in high load environments # we changed the transaction isolation level equally to postgres # to READ COMMITTED which fixed the problem entirely #3877 - ActiveRecord::ConnectionAdapters::Mysql2Adapter.set_callback :checkout, :before do |conn| + ActiveRecord::ConnectionAdapters::Mysql2Adapter.set_callback :checkout, :after do |conn| conn.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED') end when 'postgresql' From d16b9b5ba41f2dc429b9430ad28d564e7070141a Mon Sep 17 00:00:00 2001 From: Rolf Schmidt Date: Tue, 22 Feb 2022 11:13:10 +0000 Subject: [PATCH 06/10] Maintenance: Bump nokogiri from 1.13.1 to 1.13.3. --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 15fee5c1f..3c139b558 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -320,7 +320,7 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2021.0225) mini_mime (1.1.2) - mini_portile2 (2.7.1) + mini_portile2 (2.8.0) mini_racer (0.2.9) libv8 (>= 6.9.411) minitest (5.15.0) @@ -335,8 +335,8 @@ GEM net-ldap (0.17.0) netrc (0.11.0) nio4r (2.5.8) - nokogiri (1.13.1) - mini_portile2 (~> 2.7.0) + nokogiri (1.13.3) + mini_portile2 (~> 2.8.0) racc (~> 1.4) nori (2.6.0) notiffany (0.1.3) From e5c56f1a1cf4e2a0c6d37d0faae5a3818897352d Mon Sep 17 00:00:00 2001 From: Rolf Schmidt Date: Tue, 22 Feb 2022 12:41:32 +0000 Subject: [PATCH 07/10] Maintenance: Fix file permissions for db user helper. --- contrib/backup/zammad_db_user_helper.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 contrib/backup/zammad_db_user_helper.sh diff --git a/contrib/backup/zammad_db_user_helper.sh b/contrib/backup/zammad_db_user_helper.sh old mode 100644 new mode 100755 From fba5cdc838e7b2b6f56ab65b6943d7b582a2b384 Mon Sep 17 00:00:00 2001 From: Martin Gruner Date: Tue, 1 Mar 2022 10:06:14 +0100 Subject: [PATCH 08/10] Maintenance: Fix Clearbit integration test. --- test/integration/clearbit_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/clearbit_test.rb b/test/integration/clearbit_test.rb index fb4381aff..aa7a37879 100644 --- a/test/integration/clearbit_test.rb +++ b/test/integration/clearbit_test.rb @@ -282,7 +282,7 @@ class ClearbitTest < ActiveSupport::TestCase organization6 = Organization.find_by('name LIKE ?', 'APIHub Inc%') assert(ExternalSync.find_by(source: 'clearbit', object: 'Organization', o_id: organization6.id)) assert_equal(false, organization6.shared) - assert_equal('The marketing data engine to deeply understand your customers, identify future prospects, & personalize every single marketing & sales interaction.', organization6.note) + assert_equal('The Clearbit Data Activation Platform helps B2B teams understand customers, identify prospects, & personalize interactions with real-time intelligence.', organization6.note) end From 658952a5cd964cbca7e46ddcd850a9d911aefbba Mon Sep 17 00:00:00 2001 From: Martin Gruner Date: Tue, 8 Mar 2022 21:16:22 +0100 Subject: [PATCH 09/10] Maintenance: Updated Rails. --- Gemfile.lock | 102 +++++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3c139b558..b33d03103 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -21,50 +21,50 @@ GEM specs: aasm (5.2.0) concurrent-ruby (~> 1.0) - actioncable (6.0.4.6) - actionpack (= 6.0.4.6) + actioncable (6.0.4.7) + actionpack (= 6.0.4.7) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.4.6) - actionpack (= 6.0.4.6) - activejob (= 6.0.4.6) - activerecord (= 6.0.4.6) - activestorage (= 6.0.4.6) - activesupport (= 6.0.4.6) + actionmailbox (6.0.4.7) + actionpack (= 6.0.4.7) + activejob (= 6.0.4.7) + activerecord (= 6.0.4.7) + activestorage (= 6.0.4.7) + activesupport (= 6.0.4.7) mail (>= 2.7.1) - actionmailer (6.0.4.6) - actionpack (= 6.0.4.6) - actionview (= 6.0.4.6) - activejob (= 6.0.4.6) + actionmailer (6.0.4.7) + actionpack (= 6.0.4.7) + actionview (= 6.0.4.7) + activejob (= 6.0.4.7) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.4.6) - actionview (= 6.0.4.6) - activesupport (= 6.0.4.6) + actionpack (6.0.4.7) + actionview (= 6.0.4.7) + activesupport (= 6.0.4.7) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.4.6) - actionpack (= 6.0.4.6) - activerecord (= 6.0.4.6) - activestorage (= 6.0.4.6) - activesupport (= 6.0.4.6) + actiontext (6.0.4.7) + actionpack (= 6.0.4.7) + activerecord (= 6.0.4.7) + activestorage (= 6.0.4.7) + activesupport (= 6.0.4.7) nokogiri (>= 1.8.5) - actionview (6.0.4.6) - activesupport (= 6.0.4.6) + actionview (6.0.4.7) + activesupport (= 6.0.4.7) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.4.6) - activesupport (= 6.0.4.6) + activejob (6.0.4.7) + activesupport (= 6.0.4.7) globalid (>= 0.3.6) - activemodel (6.0.4.6) - activesupport (= 6.0.4.6) - activerecord (6.0.4.6) - activemodel (= 6.0.4.6) - activesupport (= 6.0.4.6) + activemodel (6.0.4.7) + activesupport (= 6.0.4.7) + activerecord (6.0.4.7) + activemodel (= 6.0.4.7) + activesupport (= 6.0.4.7) activerecord-import (1.2.0) activerecord (>= 3.2) activerecord-nulldb-adapter (0.7.0) @@ -75,12 +75,12 @@ GEM multi_json (~> 1.11, >= 1.11.2) rack (>= 2.0.8, < 3) railties (>= 5.2.4.1) - activestorage (6.0.4.6) - actionpack (= 6.0.4.6) - activejob (= 6.0.4.6) - activerecord (= 6.0.4.6) + activestorage (6.0.4.7) + actionpack (= 6.0.4.7) + activejob (= 6.0.4.7) + activerecord (= 6.0.4.7) marcel (~> 1.0.0) - activesupport (6.0.4.6) + activesupport (6.0.4.7) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -281,7 +281,7 @@ GEM ffi-compiler (>= 1.0, < 2.0) http_parser.rb (0.6.0) httpclient (2.8.3) - i18n (1.9.1) + i18n (1.10.0) concurrent-ruby (~> 1.0) icalendar (2.7.1) ice_cube (~> 0.16) @@ -435,20 +435,20 @@ GEM rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (6.0.4.6) - actioncable (= 6.0.4.6) - actionmailbox (= 6.0.4.6) - actionmailer (= 6.0.4.6) - actionpack (= 6.0.4.6) - actiontext (= 6.0.4.6) - actionview (= 6.0.4.6) - activejob (= 6.0.4.6) - activemodel (= 6.0.4.6) - activerecord (= 6.0.4.6) - activestorage (= 6.0.4.6) - activesupport (= 6.0.4.6) + rails (6.0.4.7) + actioncable (= 6.0.4.7) + actionmailbox (= 6.0.4.7) + actionmailer (= 6.0.4.7) + actionpack (= 6.0.4.7) + actiontext (= 6.0.4.7) + actionview (= 6.0.4.7) + activejob (= 6.0.4.7) + activemodel (= 6.0.4.7) + activerecord (= 6.0.4.7) + activestorage (= 6.0.4.7) + activesupport (= 6.0.4.7) bundler (>= 1.3.0) - railties (= 6.0.4.6) + railties (= 6.0.4.7) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -459,9 +459,9 @@ GEM nokogiri (>= 1.6) rails-html-sanitizer (1.4.2) loofah (~> 2.3) - railties (6.0.4.6) - actionpack (= 6.0.4.6) - activesupport (= 6.0.4.6) + railties (6.0.4.7) + actionpack (= 6.0.4.7) + activesupport (= 6.0.4.7) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) From 348002559fe097eab62b21da4b70926b395a8ad5 Mon Sep 17 00:00:00 2001 From: Martin Gruner Date: Tue, 15 Mar 2022 12:02:20 +0100 Subject: [PATCH 10/10] Trigger a build. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fe6c3c78..be9eb66cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ [Full Changelog](https://github.com/zammad/zammad/compare/5.0.2...5.0.3) + **Implemented enhancements:** - Possibility to specify the order of objects [294](https://github.com/zammad/zammad/issues/294) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[object manager attribute](https://github.com/zammad/zammad/labels/object manager attribute)]