Merge remote-tracking branch 'origin/stable-5.0' into antifascista-stable

This commit is contained in:
f 2022-04-14 15:45:53 -03:00
commit 089e4c36d3
17 changed files with 453 additions and 151 deletions

View file

@ -4,6 +4,7 @@
[Full Changelog](https://github.com/zammad/zammad/compare/5.0.2...5.0.3) [Full Changelog](https://github.com/zammad/zammad/compare/5.0.2...5.0.3)
**Implemented enhancements:** **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)] - 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)]

View file

@ -21,50 +21,50 @@ GEM
specs: specs:
aasm (5.2.0) aasm (5.2.0)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
actioncable (6.0.4.4) actioncable (6.0.4.7)
actionpack (= 6.0.4.4) actionpack (= 6.0.4.7)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
actionmailbox (6.0.4.4) actionmailbox (6.0.4.7)
actionpack (= 6.0.4.4) actionpack (= 6.0.4.7)
activejob (= 6.0.4.4) activejob (= 6.0.4.7)
activerecord (= 6.0.4.4) activerecord (= 6.0.4.7)
activestorage (= 6.0.4.4) activestorage (= 6.0.4.7)
activesupport (= 6.0.4.4) activesupport (= 6.0.4.7)
mail (>= 2.7.1) mail (>= 2.7.1)
actionmailer (6.0.4.4) actionmailer (6.0.4.7)
actionpack (= 6.0.4.4) actionpack (= 6.0.4.7)
actionview (= 6.0.4.4) actionview (= 6.0.4.7)
activejob (= 6.0.4.4) activejob (= 6.0.4.7)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
actionpack (6.0.4.4) actionpack (6.0.4.7)
actionview (= 6.0.4.4) actionview (= 6.0.4.7)
activesupport (= 6.0.4.4) activesupport (= 6.0.4.7)
rack (~> 2.0, >= 2.0.8) rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.0.4.4) actiontext (6.0.4.7)
actionpack (= 6.0.4.4) actionpack (= 6.0.4.7)
activerecord (= 6.0.4.4) activerecord (= 6.0.4.7)
activestorage (= 6.0.4.4) activestorage (= 6.0.4.7)
activesupport (= 6.0.4.4) activesupport (= 6.0.4.7)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
actionview (6.0.4.4) actionview (6.0.4.7)
activesupport (= 6.0.4.4) activesupport (= 6.0.4.7)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.4) erubi (~> 1.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (6.0.4.4) activejob (6.0.4.7)
activesupport (= 6.0.4.4) activesupport (= 6.0.4.7)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (6.0.4.4) activemodel (6.0.4.7)
activesupport (= 6.0.4.4) activesupport (= 6.0.4.7)
activerecord (6.0.4.4) activerecord (6.0.4.7)
activemodel (= 6.0.4.4) activemodel (= 6.0.4.7)
activesupport (= 6.0.4.4) activesupport (= 6.0.4.7)
activerecord-import (1.2.0) activerecord-import (1.2.0)
activerecord (>= 3.2) activerecord (>= 3.2)
activerecord-nulldb-adapter (0.7.0) activerecord-nulldb-adapter (0.7.0)
@ -75,12 +75,12 @@ GEM
multi_json (~> 1.11, >= 1.11.2) multi_json (~> 1.11, >= 1.11.2)
rack (>= 2.0.8, < 3) rack (>= 2.0.8, < 3)
railties (>= 5.2.4.1) railties (>= 5.2.4.1)
activestorage (6.0.4.4) activestorage (6.0.4.7)
actionpack (= 6.0.4.4) actionpack (= 6.0.4.7)
activejob (= 6.0.4.4) activejob (= 6.0.4.7)
activerecord (= 6.0.4.4) activerecord (= 6.0.4.7)
marcel (~> 1.0.0) marcel (~> 1.0.0)
activesupport (6.0.4.4) activesupport (6.0.4.7)
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
minitest (~> 5.1) minitest (~> 5.1)
@ -291,7 +291,7 @@ GEM
http_parser.rb (0.6.0) http_parser.rb (0.6.0)
http_parser.rb (0.6.0-x86_64-linux-musl) http_parser.rb (0.6.0-x86_64-linux-musl)
httpclient (2.8.3) httpclient (2.8.3)
i18n (1.8.10) i18n (1.10.0)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
icalendar (2.7.1) icalendar (2.7.1)
ice_cube (~> 0.16) ice_cube (~> 0.16)
@ -319,11 +319,11 @@ GEM
logging (2.3.0) logging (2.3.0)
little-plugger (~> 1.1) little-plugger (~> 1.1)
multi_json (~> 1.14) multi_json (~> 1.14)
loofah (2.13.0) loofah (2.14.0)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
lumberjack (1.2.8) lumberjack (1.2.8)
marcel (1.0.1) marcel (1.0.2)
memoizable (0.4.2) memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1) thread_safe (~> 0.3, >= 0.3.1)
messagebird-rest (3.0.0) messagebird-rest (3.0.0)
@ -331,8 +331,8 @@ GEM
mime-types (3.3.1) mime-types (3.3.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2021.0225) mime-types-data (3.2021.0225)
mini_mime (1.1.1) mini_mime (1.1.2)
mini_portile2 (2.6.1) mini_portile2 (2.8.0)
mini_racer (0.2.9) mini_racer (0.2.9)
libv8 (>= 6.9.411) libv8 (>= 6.9.411)
minitest (5.15.0) minitest (5.15.0)
@ -349,9 +349,8 @@ GEM
net-ldap (0.17.0) net-ldap (0.17.0)
netrc (0.11.0) netrc (0.11.0)
nio4r (2.5.8) nio4r (2.5.8)
nio4r (2.5.8-x86_64-linux-musl) nokogiri (1.13.3)
nokogiri (1.12.5) mini_portile2 (~> 2.8.0)
mini_portile2 (~> 2.6.1)
racc (~> 1.4) racc (~> 1.4)
nokogiri (1.12.5-x86_64-linux-musl) nokogiri (1.12.5-x86_64-linux-musl)
mini_portile2 (~> 2.6.1) mini_portile2 (~> 2.6.1)
@ -443,7 +442,7 @@ GEM
binding_of_caller (~> 1.0) binding_of_caller (~> 1.0)
pry (~> 0.13) pry (~> 0.13)
public_suffix (4.0.6) public_suffix (4.0.6)
puma (4.3.10) puma (4.3.11)
nio4r (~> 2.0) nio4r (~> 2.0)
puma (4.3.8-x86_64-linux-musl) puma (4.3.8-x86_64-linux-musl)
nio4r (~> 2.0) nio4r (~> 2.0)
@ -451,27 +450,26 @@ GEM
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
pundit-matchers (1.7.0) pundit-matchers (1.7.0)
rspec-rails (>= 3.0.0) rspec-rails (>= 3.0.0)
racc (1.5.2) racc (1.6.0)
racc (1.5.2-x86_64-linux-musl)
rack (2.2.3) rack (2.2.3)
rack-livereload (0.3.17) rack-livereload (0.3.17)
rack rack
rack-test (1.1.0) rack-test (1.1.0)
rack (>= 1.0, < 3) rack (>= 1.0, < 3)
rails (6.0.4.4) rails (6.0.4.7)
actioncable (= 6.0.4.4) actioncable (= 6.0.4.7)
actionmailbox (= 6.0.4.4) actionmailbox (= 6.0.4.7)
actionmailer (= 6.0.4.4) actionmailer (= 6.0.4.7)
actionpack (= 6.0.4.4) actionpack (= 6.0.4.7)
actiontext (= 6.0.4.4) actiontext (= 6.0.4.7)
actionview (= 6.0.4.4) actionview (= 6.0.4.7)
activejob (= 6.0.4.4) activejob (= 6.0.4.7)
activemodel (= 6.0.4.4) activemodel (= 6.0.4.7)
activerecord (= 6.0.4.4) activerecord (= 6.0.4.7)
activestorage (= 6.0.4.4) activestorage (= 6.0.4.7)
activesupport (= 6.0.4.4) activesupport (= 6.0.4.7)
bundler (>= 1.3.0) bundler (>= 1.3.0)
railties (= 6.0.4.4) railties (= 6.0.4.7)
sprockets-rails (>= 2.0.0) sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5) rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1) actionpack (>= 5.0.1.rc1)
@ -480,11 +478,11 @@ GEM
rails-dom-testing (2.0.3) rails-dom-testing (2.0.3)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
nokogiri (>= 1.6) nokogiri (>= 1.6)
rails-html-sanitizer (1.4.1) rails-html-sanitizer (1.4.2)
loofah (~> 2.3) loofah (~> 2.3)
railties (6.0.4.4) railties (6.0.4.7)
actionpack (= 6.0.4.4) actionpack (= 6.0.4.7)
activesupport (= 6.0.4.4) activesupport (= 6.0.4.7)
method_source method_source
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0) thor (>= 0.20.3, < 2.0)
@ -610,7 +608,7 @@ GEM
tins (~> 1.0) tins (~> 1.0)
test-unit (3.4.7) test-unit (3.4.7)
power_assert power_assert
thor (1.1.0) thor (1.2.1)
thread_safe (0.3.6) thread_safe (0.3.6)
tilt (2.0.10) tilt (2.0.10)
timers (4.3.3) timers (4.3.3)
@ -666,7 +664,7 @@ GEM
writeexcel (1.0.5) writeexcel (1.0.5)
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.4.2) zeitwerk (2.5.4)
zendesk_api (1.33.0) zendesk_api (1.33.0)
faraday (>= 0.9.0, < 2.0.0) faraday (>= 0.9.0, < 2.0.0)
hashie (>= 3.5.2, < 5.0.0) hashie (>= 3.5.2, < 5.0.0)

View file

@ -2,6 +2,7 @@ class App.ControllerObserver extends App.Controller
model: 'Ticket' model: 'Ticket'
template: 'tba' template: 'tba'
globalRerender: true globalRerender: true
lastAttributes: undefined
### ###
observe: observe:
@ -25,7 +26,7 @@ class App.ControllerObserver extends App.Controller
# rerender, e. g. on language change # rerender, e. g. on language change
if @globalRerender if @globalRerender
@controllerBind('ui:rerender', => @controllerBind('ui:rerender', =>
@lastAttributres = undefined @lastAttributes = undefined
@maybeRender(App[@model].fullLocal(@object_id)) @maybeRender(App[@model].fullLocal(@object_id))
) )
@ -43,32 +44,40 @@ class App.ControllerObserver extends App.Controller
if !@subscribeId if !@subscribeId
@subscribeId = object.subscribe(@subscribe) @subscribeId = object.subscribe(@subscribe)
# remember current attributes return if !@hasChanged(object)
@render(object)
hasChanged: (object) =>
currentAttributes = {} currentAttributes = {}
objectCloned = $.extend(true, {}, object)
if @observe if @observe
for key, active of @observe for key, active of @observe
if active if active && !_.isFunction(value)
currentAttributes[key] = object[key] currentAttributes[key] = objectCloned[key]
if @observeNot if @observeNot
for key, value of object for key, value of objectCloned
if key isnt 'cid' && !@observeNot[key] && !_.isFunction(value) && !_.isObject(value) if key isnt 'cid' && !@observeNot[key] && !_.isFunction(value)
currentAttributes[key] = value currentAttributes[key] = value
if !@lastAttributres if !@lastAttributes
@lastAttributres = {} @lastAttributes = currentAttributes
else return true
diff = difference(currentAttributes, @lastAttributres)
if _.isEmpty(diff) diff = difference(currentAttributes, @lastAttributes)
@log 'debug', 'maybeRender no diff, no rerender' if _.isEmpty(diff)
return @log 'debug', 'maybeRender no diff, no rerender'
return false
@log 'debug', 'maybeRender.diff', diff, @observe, @model @log 'debug', 'maybeRender.diff', diff, @observe, @model
@lastAttributres = currentAttributes @lastAttributes = currentAttributes
@render(object, diff) true
render: (object, diff) => render: (object) =>
@log 'debug', 'render', @template, object, diff @log 'debug', 'render', @template, object
@html App.view(@template)( @html App.view(@template)(
object: object object: object
) )

View file

@ -202,7 +202,7 @@ class Object extends App.ControllerObserver
value = $(e.target).html() value = $(e.target).html()
org = App.Organization.find(@object_id) org = App.Organization.find(@object_id)
if org[name] isnt value if org[name] isnt value
@lastAttributres[name] = value @lastAttributes[name] = value
data = {} data = {}
data[name] = value data[name] = value
org.updateAttributes(data) org.updateAttributes(data)

View file

@ -257,7 +257,7 @@ class EmailReply extends App.Controller
quote_header = App.FullQuoteHeader.fullQuoteHeaderForward(article) quote_header = App.FullQuoteHeader.fullQuoteHeaderForward(article)
body = "<br/><div>---Begin forwarded message:---<br/><br/></div><div><blockquote type=\"cite\">#{quote_header}#{body}</blockquote></div><div><br></div>" body = "<br/><div>---#{App.i18n.translateInline('Begin forwarded message')}:---<br/><br/></div><div><blockquote type=\"cite\">#{quote_header}#{body}</blockquote></div><div><br></div>"
articleNew = {} articleNew = {}
articleNew.body = body articleNew.body = body

View file

@ -24,7 +24,7 @@ class Internal
internal = true internal = true
if article.internal == true if article.internal == true
internal = false internal = false
ui.lastAttributres.internal = internal ui.lastAttributes.internal = internal
article.updateAttributes(internal: internal) article.updateAttributes(internal: internal)
# runtime update # runtime update

View file

@ -218,11 +218,11 @@ class ArticleViewItem extends App.ControllerObserver
) )
@articleActions = new App.TicketZoomArticleActions( @articleActions = new App.TicketZoomArticleActions(
el: @$('.js-article-actions') el: @$('.js-article-actions')
ticket: @ticket ticket: @ticket
article: article article: article
lastAttributres: @lastAttributres lastAttributes: @lastAttributes
form_id: @form_id form_id: @form_id
) )
# set see more # set see more
@ -305,34 +305,38 @@ class ArticleViewItem extends App.ControllerObserver
e.stopPropagation() e.stopPropagation()
article_id = $(e.target).closest('.ticket-article-item').data('id') article_id = $(e.target).closest('.ticket-article-item').data('id')
article = App.TicketArticle.find(article_id)
@ajax( @ajax(
id: 'retrySecurityProcess' id: 'retrySecurityProcess'
type: 'POST' type: 'POST'
url: "#{@apiPath}/ticket_articles/#{article_id}/retry_security_process" url: "#{@apiPath}/ticket_articles/#{article_id}/retry_security_process"
processData: true processData: true
success: (data, status, xhr) => success: (encryption_data, status, xhr) =>
if data.sign.success for data in encryption_data
@notify continue if article.preferences.security.type isnt data.type
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 if data.sign.success
@notify @notify
type: 'success' type: 'success'
msg: App.i18n.translateContent('Decryption success!') msg: App.i18n.translateContent('Verify sign success!')
else if data.encryption.comment else if data.sign.comment
comment = App.i18n.translateContent('Decryption failed!') + ' ' + App.i18n.translateContent(data.encryption.comment || '') comment = App.i18n.translateContent('Verify sign failed!') + ' ' + App.i18n.translateContent(data.sign.comment || '')
@notify @notify
type: 'error' type: 'error'
msg: comment msg: comment
timeout: 2000 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) => error: (xhr) =>
@notify @notify

View file

@ -19,7 +19,7 @@ class App.TicketZoomTitle extends App.ControllerObserver
title = $(e.target).ceg() || '' title = $(e.target).ceg() || ''
# update title # update title
return if title is @lastAttributres.title return if title is @lastAttributes.title
ticket = App.Ticket.find(@object_id) ticket = App.Ticket.find(@object_id)
ticket.title = title ticket.title = title

View file

@ -220,7 +220,7 @@ class Object extends App.ControllerObserver
value = $(e.target).html() value = $(e.target).html()
user = App.User.find(@object_id) user = App.User.find(@object_id)
if user[name] isnt value if user[name] isnt value
@lastAttributres[name] = value @lastAttributes[name] = value
data = {} data = {}
data[name] = value data[name] = value
user.updateAttributes(data) user.updateAttributes(data)

View file

@ -65,9 +65,9 @@ Date.prototype.getWeek = function() {
function difference(object1, object2) { function difference(object1, object2) {
var changes = {}; var changes = {};
for (var name in object1) { _.uniq(Object.keys(object1).concat(Object.keys(object2))).forEach(function(name) {
if (name in object2) { if (name in object1 && name in object2) {
if (_.isObject(object2[name]) && !_.isArray(object2[name])) { if (_.isObject(object1[name]) && !_.isArray(object1[name]) && _.isObject(object2[name]) && !_.isArray(object2[name])) {
var diff = difference(object1[name], object2[name]); var diff = difference(object1[name], object2[name]);
if (!_.isEmpty(diff)) { if (!_.isEmpty(diff)) {
changes[name] = diff; changes[name] = diff;
@ -75,8 +75,10 @@ function difference(object1, object2) {
} else if (!_.isEqual(object1[name], object2[name])) { } else if (!_.isEqual(object1[name], object2[name])) {
changes[name] = object2[name]; changes[name] = object2[name];
} }
} else {
changes[name] = object2[name]
} }
} })
return changes; return changes;
} }

View file

@ -10,7 +10,7 @@ when 'mysql2'
# Because of missing ticket updates in high load environments # Because of missing ticket updates in high load environments
# we changed the transaction isolation level equally to postgres # we changed the transaction isolation level equally to postgres
# to READ COMMITTED which fixed the problem entirely #3877 # 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') conn.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED')
end end
when 'postgresql' when 'postgresql'

0
contrib/backup/zammad_db_user_helper.sh Normal file → Executable file
View file

View file

@ -10,9 +10,11 @@ class SecureMailing
end end
def self.retry(article) def self.retry(article)
result = []
active_backends.each do |backend| active_backends.each do |backend|
"#{backend}::Retry".constantize.process(article) result << "#{backend}::Retry".constantize.process(article)
end end
result
end end
def self.outgoing(mail, security) def self.outgoing(mail, security)

View file

@ -536,7 +536,9 @@ test('difference', function() {
object2 = { object2 = {
key1: 123, key1: 123,
} }
result = {} result = {
key2: undefined
}
item = difference(object1, object2) item = difference(object1, object2)
deepEqual(item, result) deepEqual(item, result)
@ -547,38 +549,106 @@ test('difference', function() {
key1: 123, key1: 123,
key2: 124 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 = {} result = {}
item = difference(object1, object2) item = difference(object1, object2)
deepEqual(item, result) 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) { test('auth - not existing user', function(assert) {

View file

@ -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))
});

View file

@ -588,8 +588,7 @@ RSpec.describe 'Ticket zoom', type: :system do
end end
context 'certificate not present at time of arrival' do context 'certificate not present at time of arrival' do
let(:mail) do
it 'retry' do
smime1 = create(:smime_certificate, :with_private, fixture: system_email_address) smime1 = create(:smime_certificate, :with_private, fixture: system_email_address)
smime2 = create(:smime_certificate, :with_private, fixture: sender_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 smime1.destroy
smime2.destroy smime2.destroy
mail
end
it 'does retry successfully' do
parsed_mail = Channel::EmailParser.new.parse(mail.to_s) parsed_mail = Channel::EmailParser.new.parse(mail.to_s)
ticket, article, _user, _mail = Channel::EmailParser.new.process({ group_id: group.id }, parsed_mail['raw']) 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') 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' click '.js-securityRetryProcess'
expect(page).to have_css('.article-content', text: 'somebody with some text') expect(page).to have_css('.article-content', text: 'somebody with some text')
end 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
end end

View file

@ -282,7 +282,7 @@ class ClearbitTest < ActiveSupport::TestCase
organization6 = Organization.find_by('name LIKE ?', 'APIHub Inc%') organization6 = Organization.find_by('name LIKE ?', 'APIHub Inc%')
assert(ExternalSync.find_by(source: 'clearbit', object: 'Organization', o_id: organization6.id)) assert(ExternalSync.find_by(source: 'clearbit', object: 'Organization', o_id: organization6.id))
assert_equal(false, organization6.shared) assert_equal(false, organization6.shared)
assert_equal('The marketing data engine to deeply understand your customers, identify future prospects, &amp; personalize every single marketing &amp; sales interaction.', organization6.note) assert_equal('The Clearbit Data Activation Platform helps B2B teams understand customers, identify prospects, &amp; personalize interactions with real-time intelligence.', organization6.note)
end end