Fixed issue#301 - Using #{article.body} in trigger gives html.

This commit is contained in:
Martin Edenhofer 2016-11-13 19:33:12 +01:00
parent fe47e5a8f2
commit aa29a75841
39 changed files with 592 additions and 319 deletions

View file

@ -738,22 +738,21 @@ perform changes on ticket
}
# get subject
value['subject'].gsub!(/\#\{config\.(.+?)\}/, '<%= c "\\1", false %>')
value['subject'].gsub!(/\#\{(.+?)\}/, '<%= d "\\1", false %>')
subject = NotificationFactory::Mailer.template(
templateInline: value['subject'],
locale: 'en-en',
objects: objects,
quote: false,
)
subject = subject_build(subject)
value['body'].gsub!(/\#\{config\.(.+?)\}/, '<%= c "\\1", true %>')
value['body'].gsub!(/\#\{(.+?)\}/, '<%= d "\\1", true %>')
body = NotificationFactory::Mailer.template(
templateInline: value['body'],
locale: 'en-en',
objects: objects,
quote: true,
)
Ticket::Article.create(
ticket_id: id,
to: recipient_string,

View file

@ -121,6 +121,49 @@ returns
Ticket::Article.where('ticket_id = ? AND sender_id NOT IN (?)', ticket_id, sender.id).order('created_at DESC').first
end
=begin
get body as html
article = Ticket::Article.find(123)
article.body_as_html
=end
def body_as_html
return '' if !body
return body if content_type && content_type =~ %r{text/html}i
body.text2html
end
=begin
get body as text
article = Ticket::Article.find(123)
article.body_as_text
=end
def body_as_text
return '' if !body
return body if !content_type || content_type.empty? || content_type =~ %r{text/plain}i
body.html2text
end
=begin
get body as text with quote sign "> " at the beginning of each line
article = Ticket::Article.find(123)
article.body_as_text
=end
def body_as_text_with_quote
body_as_text.word_wrap.message_quote
end
private
# strip not wanted chars

View file

@ -1,9 +1,9 @@
Dein <%= c 'product_name' %> Passwort wurde geändert
Dein #{config.product_name} Passwort wurde geändert
<div>Hallo <%= d 'user.firstname' %>,</div>
<div>Hallo #{user.firstname},</div>
<br>
<div>das Passwort für Dein <%= c 'product_name' %> Account <b><%= d 'user.login' %></b> wurde kürzlich geändert.</div>
<div>das Passwort für Dein #{config.product_name} Account <b>#{user.login}</b> wurde kürzlich geändert.</div>
<br>
<div>Diese Aktivität ist Dir nicht bekannt? In diesen Fall kontaktiere Deinen System-Administrator.</div>
<br>
<div>Dein <%= c 'product_name' %> Team</div>
<div>Dein #{config.product_name} Team</div>

View file

@ -1,9 +1,9 @@
Your <%= c 'product_name' %> password has been changed
Your #{product_name} password has been changed
<p>Hi <%= d 'user.firstname' %>,</p>
<p>Hi #{user.firstname},</p>
<br>
<p>The password for your <%= c 'product_name' %> account <b><%= d 'user.login' %></b> has been changed recently.</p>
<p>The password for your #{product_name} account <b>#{user.login}</b> has been changed recently.</p>
<br>
<p>This activity is not known to you? If not, contact your system administrator.</p>
<br>
<p>Your <%= c 'product_name' %> Team</p>
<p>Your #{product_name} Team</p>

View file

@ -1,15 +1,15 @@
Zurücksetzen Deines <%= c 'product_name' %> Passworts
Zurücksetzen Deines #{config.product_name} Passworts
<div>Hallo <%= d 'user.firstname' %>,</div>
<div>Hallo #{user.firstname},</div>
<br>
<div>wir haben eine Anfrage zum Zurücksetzen des Passworts für <%= c 'product_name' %> Account <b><%= d 'user.login' %></b> erhalten.</div>
<div>wir haben eine Anfrage zum Zurücksetzen des Passworts für #{config.product_name} Account <b>#{user.login}</b> erhalten.</div>
<br>
<div>Wenn Sie Ihr Passwort zurückzusetzen wollen, klicken Sie auf den unten stehenden Link (oder kopieren Sie die URL in den Browser einfügen):</div>
<br>
<div><a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#password_reset_verify/<%= d 'token.name' %>"><%= c 'http_type' %>://<%= c 'fqdn' %>/#password_reset_verify/<%= d 'token.name' %></a></div>
<div><a href="#{config.http_type}://#{config.fqdn}/#password_reset_verify/#{token.name}">#{config.http_type}://#{config.fqdn}/#password_reset_verify/#{token.name}</a></div>
<br>
<div>Dieser Link führt Sie zu einer Seite, auf der Sie Ihr Passwort ändern können.</div>
<br>
<div>Wenn Sie Ihr Passwort nicht zurücksetzen wollen, ignorieren Sie diese Meldung. Das Passwort bleibt unverändert.</div>
<br>
<div>Dein <%= c 'product_name' %> Team</div>
<div>Dein #{config.product_name} Team</div>

View file

@ -1,15 +1,15 @@
Reset your <%= c 'product_name' %> password
Reset your #{config.product_name} password
<div>Hi <%= d 'user.firstname' %>,</div>
<div>Hi #{user.firstname},</div>
<br>
<div>We received a request to reset the password for your <%= c 'product_name' %> account <b><%= d 'user.login' %></b>.</div>
<div>We received a request to reset the password for your #{config.product_name} account <b>#{user.login}</b>.</div>
<br>
<div>If you want to reset your password, click on the link below (or copy and paste the URL into your browser):</div>
<br>
<div><a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#password_reset_verify/<%= d 'token.name' %>"><%= c 'http_type' %>://<%= c 'fqdn' %>/#password_reset_verify/<%= d 'token.name' %></a></div>
<div><a href="#{config.http_type}://#{config.fqdn}/#password_reset_verify/#{token.name}">#{config.http_type}://#{config.fqdn}/#password_reset_verify/#{token.name}</a></div>
<br>
<div>This link takes you to a page where you can change your password.</div>
<br>
<div>If you don't want to reset your password, please ignore this message. Your password will not be reseted.</div>
<br>
<div>Your <%= c 'product_name' %> Team</div>
<div>Your #{config.product_name} Team</div>

View file

@ -1,9 +1,9 @@
Bestätigung des <%= c 'product_name' %> Accounts, <%= d 'user.firstname' %> <%= d 'user.lastname' %>
Bestätigung des #{config.product_name} Accounts, #{user.firstname} #{user.lastname}
<div>Hallo <%= d 'user.firstname' %>,</div>
<div>Hallo #{user.firstname},</div>
<br>
<div>bestätige Deine E-Mail-Adresse um Deine Registrierung bei <%= c 'product_name' %> abzuschließen. Es ist einfach - klick einfach auf den Link unten.</div>
<div>bestätige Deine E-Mail-Adresse um Deine Registrierung bei #{config.product_name} abzuschließen. Es ist einfach - klick einfach auf den Link unten.</div>
<br>
<div><a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#email_verify/<%= d 'token.name' %>"><%= c 'http_type' %>://<%= c 'fqdn' %>/#email_verify/<%= d 'token.name' %></a></div>
<div><a href="#{config.http_type}://#{config.fqdn}/#email_verify/#{token.name}">#{config.http_type}://#{config.fqdn}/#email_verify/#{token.name}</a></div>
<br>
<div>Dein <%= c 'product_name' %> Team</div>
<div>Dein #{config.product_name} Team</div>

View file

@ -1,9 +1,9 @@
Confirm your <%= c 'product_name' %> account, <%= d 'user.firstname' %> <%= d 'user.lastname' %>
Confirm your #{config.product_name} account, #{user.firstname} #{user.lastname}
<div>Hi <%= d 'user.firstname' %>,</div>
<div>Hi #{user.firstname},</div>
<br>
<div>Confirm your email address to complete your <%= c 'product_name' %> account. It's easy, just click the link below.</div>
<div>Confirm your email address to complete your #{config.product_name} account. It's easy, just click the link below.</div>
<br>
<div><a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#email_verify/<%= d 'token.name' %>"><%= c 'http_type' %>://<%= c 'fqdn' %>/#email_verify/<%= d 'token.name' %></a></div>
<div><a href="#{config.http_type}://#{config.fqdn}/#email_verify/#{token.name}">#{config.http_type}://#{config.fqdn}/#email_verify/#{token.name}</a></div>
<br>
<div>Your <%= c 'product_name' %> Team</div>
<div>Your #{config.product_name} Team</div>

View file

@ -1,9 +1,9 @@
Test Ticket!
<div>Hallo <%= d 'agent.firstname' %>,</div>
<div>Hallo #{agent.firstname},</div>
<br>
<div>dies ist ein <b>Test Ticket</b>. Ich bin ein Kunde und benötige Hilfe! :)</div>
<br>
<div><%= d 'customer.fullname' %></div>
<div>#{customer.fullname}</div>
<br>
<div>Das Zammad Projekt</div>

View file

@ -1,9 +1,9 @@
Test Ticket!
<div>Dear <%= d 'agent.firstname' %>,</div>
<div>Dear #{agent.firstname},</div>
<br>
<div>This is a <b>test ticket</b>. I'm a customer and I need some help! :)</div>
<br>
<div><%= d 'customer.fullname' %></div>
<div>#{customer.fullname}</div>
<br>
<div>The Zammad Project</div>

View file

@ -1,24 +1,24 @@
Neues Ticket (<%= d 'ticket.title' %>)
Neues Ticket (#{ticket.title})
<div>Hallo <%= d 'recipient.firstname' %>,</div>
<div>Hallo #{recipient.firstname},</div>
<br>
<div>es wurde ein neues Ticket (<%= d 'ticket.title' %>) von "<b><%= d 'current_user.longname' %></b>" erstellt.</div>
<div>es wurde ein neues Ticket (#{ticket.title}) von "<b>#{current_user.longname}</b>" erstellt.</div>
<br>
<div>
<%= t 'Group' %>: <%= d 'ticket.group.name' %><br>
<%= t 'Owner' %>: <%= d 'ticket.owner.fullname' %><br>
<%= t 'State' %>: <%= t d 'ticket.state.name' %><br>
#{t('Group')}: #{ticket.group.name}<br>
#{t('Owner')}: #{ticket.owner.fullname}<br>
#{t('State')}: #{t(ticket.state.name)}<br>
</div>
<br>
<% if @objects[:article] %>
<div>
<%= t 'Information' %>:
#{t('Information')}:
<blockquote type="cite">
<%= a_html 'article' %>
#{article.body_as_html}
</blockquote>
</div>
<% end %>
<br>
<div>
<a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>" target="zammad_app"><%= t 'View this in Zammad' %></a>
<a href="#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}" target="zammad_app">#{t('View this in Zammad')}</a>
</div>

View file

@ -1,24 +1,24 @@
New Ticket (<%= d 'ticket.title' %>)
New Ticket (#{ticket.title})
<div>Hi <%= d 'recipient.firstname' %>,</div>
<div>Hi #{recipient.firstname},</div>
<br>
<div>A new ticket (<%= d 'ticket.title' %>) has been created by "<b><%= d 'current_user.longname' %></b>".</div>
<div>A new ticket (#{ticket.title}) has been created by "<b>#{current_user.longname}</b>".</div>
<br>
<div>
<%= t 'Group' %>: <%= d 'ticket.group.name' %><br>
<%= t 'Owner' %>: <%= d 'ticket.owner.fullname' %><br>
<%= t 'State' %>: <%= t d 'ticket.state.name' %><br>
#{t('Group')}: #{ticket.group.name}<br>
#{t('Owner')}: #{ticket.owner.fullname}<br>
#{t('State')}: #{t(ticket.state.name)}<br>
</div>
<br>
<% if @objects[:article] %>
<div>
<%= t 'Information' %>:
#{t('Information')}:
<blockquote type="cite">
<%= a_html 'article' %>
#{article.body_as_html}
</blockquote>
</div>
<% end %>
<br>
<div>
<a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>" target="zammad_app"><%= t 'View this in Zammad' %></a>
<a href="#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}" target="zammad_app">#{t('View this in Zammad')}</a>
</div>

View file

@ -1,18 +1,18 @@
Ticket ist eskaliert (<%= d 'ticket.title' %>)
Ticket ist eskaliert (#{ticket.title})
<div>Hallo <%= d 'recipient.firstname' %>,</div>
<div>Hallo #{recipient.firstname},</div>
<br>
<div>Ticket (<%= d 'ticket.title' %>) von "<b><%= d 'ticket.customer.longname' %></b>" ist seit "<%= d 'ticket.escalation_at' %>" eskaliert!</div>
<div>Ticket (#{ticket.title}) von "<b>#{ticket.customer.longname}</b>" ist seit "#{ticket.escalation_at}" eskaliert!</div>
<br>
<% if @objects[:article] %>
<div>
<%= t 'Information' %>:
#{t('Information')}:
<blockquote type="cite">
<%= a_html 'article' %>
#{article.body_as_html}
</blockquote>
</div>
<% end %>
<br>
<div>
<a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>" target="zammad_app"><%= t 'View this in Zammad' %></a>
<a href="#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}" target="zammad_app">#{t('View this in Zammad')}</a>
</div>

View file

@ -1,18 +1,18 @@
Ticket is escalated (<%= d 'ticket.title' %>)
Ticket is escalated (#{ticket.title})
<div>Hi <%= d 'recipient.firstname' %>,</div>
<div>Hi #{recipient.firstname},</div>
<br>
<div>A ticket (<%= d 'ticket.title' %>) from "<b><%= d 'ticket.customer.longname' %></b>" is escalated since "<%= d 'ticket.escalation_at' %>"!</div>
<div>A ticket (#{ticket.title}) from "<b>#{ticket.customer.longname}</b>" is escalated since "#{ticket.escalation_at}"!</div>
<br>
<% if @objects[:article] %>
<div>
<%= t 'Information' %>:
#{t('Information')}:
<blockquote type="cite">
<%= a_html 'article' %>
#{article.body_as_html}
</blockquote>
</div>
<% end %>
<br>
<div>
<a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>" target="zammad_app"><%= t 'View this in Zammad' %></a>
<a href="#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}" target="zammad_app">#{t('View this in Zammad')}</a>
</div>

View file

@ -1,18 +1,18 @@
Ticket wird eskalieren (<%= d 'ticket.title' %>)
Ticket wird eskalieren (#{ticket.title})
<div>Hallo <%= d 'recipient.firstname' %>,</div>
<div>Hallo #{recipient.firstname},</div>
<br>
<div>Ticket (<%= d 'ticket.title' %>) von "<b><%= d 'ticket.customer.longname' %></b>" wird um "<%= d 'ticket.escalation_at' %>" eskalieren!</div>
<div>Ticket (#{ticket.title}) von "<b>#{ticket.customer.longname}</b>" wird um "#{ticket.escalation_at}" eskalieren!</div>
<br>
<% if @objects[:article] %>
<div>
<%= t 'Information' %>:
#{t('Information')}:
<blockquote type="cite">
<%= a_html 'article' %>
#{article.body_as_html}
</blockquote>
</div>
<% end %>
<br>
<div>
<a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>" target="zammad_app"><%= t 'View this in Zammad' %></a>
<a href="#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}" target="zammad_app">#{t('View this in Zammad')}</a>
</div>

View file

@ -1,18 +1,18 @@
Ticket will escalate (<%= d 'ticket.title' %>)
Ticket will escalate (#{ticket.title})
<div>Hi <%= d 'recipient.firstname' %>,</div>
<div>Hi #{recipient.firstname},</div>
<br>
<div>A ticket (<%= d 'ticket.title' %>) from "<b><%= d 'ticket.customer.longname' %></b>" will escalate at "<%= d 'ticket.escalation_at' %>"!</div>
<div>A ticket (#{ticket.title}) from "<b>#{ticket.customer.longname}</b>" will escalate at "#{ticket.escalation_at}"!</div>
<br>
<% if @objects[:article] %>
<div>
<%= t 'Information' %>:
#{t('Information')}:
<blockquote type="cite">
<%= a_html 'article' %>
#{article.body_as_html}
</blockquote>
</div>
<% end %>
<br>
<div>
<a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>" target="zammad_app"><%= t 'View this in Zammad' %></a>
<a href="#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}" target="zammad_app">#{t('View this in Zammad')}</a>
</div>

View file

@ -1,18 +1,18 @@
Warten auf Erinnerung erreicht! (<%= d 'ticket.title' %>)
Warten auf Erinnerung erreicht! (#{ticket.title})
<div>Hallo <%= d 'recipient.firstname' %>,</div>
<div>Hallo #{recipient.firstname},</div>
<br>
<div>dieses Ticket benötigt Deine Aufmerksamkeit, warten auf Erinnerung für (<%= d 'ticket.title' %>) mit dem Kunden "<b><%= d 'ticket.customer.longname' %></b>" ist erreicht.</div>
<div>dieses Ticket benötigt Deine Aufmerksamkeit, warten auf Erinnerung für (#{ticket.title}) mit dem Kunden "<b>#{ticket.customer.longname}</b>" ist erreicht.</div>
<br>
<% if @objects[:article] %>
<div>
<%= t 'Information' %>:
#{t('Information')}:
<blockquote type="cite">
<%= a_html 'article' %>
#{article.body_as_html}
</blockquote>
</div>
<% end %>
<br>
<div>
<a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>" target="zammad_app"><%= t 'View this in Zammad' %></a>
<a href="#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}" target="zammad_app">#{t('View this in Zammad')}</a>
</div>

View file

@ -1,18 +1,18 @@
Reminder reached (<%= d 'ticket.title' %>)
Reminder reached (#{ticket.title})
<div>Hi <%= d 'recipient.firstname' %>,</div>
<div>Hi #{recipient.firstname},</div>
<br>
<div>A ticket needs attention, reminder reached for (<%= d 'ticket.title' %>) with customer "<b><%= d 'ticket.customer.longname' %></b>".</div>
<div>A ticket needs attention, reminder reached for (#{ticket.title}) with customer "<b>#{ticket.customer.longname}</b>".</div>
<br>
<% if @objects[:article] %>
<div>
<%= t 'Information' %>:
#{t('Information')}:
<blockquote type="cite">
<%= a_html 'article' %>
#{article.body_as_html}
</blockquote>
</div>
<% end %>
<br>
<div>
<a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>" target="zammad_app"><%= t 'View this in Zammad' %></a>
<a href="#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}" target="zammad_app">#{t('View this in Zammad')}</a>
</div>

View file

@ -1,14 +1,14 @@
Ticket aktualisiert (<%= d 'ticket.title' %>)
Ticket aktualisiert (#{ticket.title})
<div>Hi <%= d 'recipient.firstname' %>,</div>
<div>Hi #{recipient.firstname},</div>
<br>
<div>
Ticket (<%= d 'ticket.title' %>) wurde von "<b><%= d 'current_user.longname' %></b>" aktualisiert.
Ticket (#{ticket.title}) wurde von "<b>#{current_user.longname}</b>" aktualisiert.
</div>
<br>
<% if @objects[:changes] && !@objects[:changes].empty? %>
<div>
<%= t 'Changes' %>:<br>
#{t('Changes')}:<br>
<% @objects[:changes].each do |key, value| %>
<%= t key %>: <%= h value[0] %> -&gt; <%= h value[1] %><br>
<% end %>
@ -17,13 +17,13 @@ Ticket (<%= d 'ticket.title' %>) wurde von "<b><%= d 'current_user.longname' %><
<br>
<% if @objects[:article] %>
<div>
<%= t 'Information' %>:
#{t('Information')}:
<blockquote type="cite">
<%= a_html 'article' %>
#{article.body_as_html}
</blockquote>
</div>
<% end %>
<br>
<div>
<a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>" target="zammad_app"><%= t 'View this in Zammad' %></a>
<a href="#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}" target="zammad_app">#{t('View this in Zammad')}</a>
</div>

View file

@ -1,14 +1,14 @@
Updated Ticket (<%= d 'ticket.title' %>)
Updated Ticket (#{ticket.title})
<div>Hi <%= d 'recipient.firstname' %>,</div>
<div>Hi #{recipient.firstname},</div>
<br>
<div>
Ticket (<%= d 'ticket.title' %>) has been updated by "<b><%= d 'current_user.longname' %></b>".
Ticket (#{ticket.title}) has been updated by "<b>#{current_user.longname}</b>".
</div>
<br>
<% if @objects[:changes] && !@objects[:changes].empty? %>
<div>
<%= t 'Changes' %>:<br>
#{t('Changes')}:<br>
<% @objects[:changes].each do |key, value| %>
<%= t key %>: <%= h value[0] %> -&gt; <%= h value[1] %><br>
<% end %>
@ -17,13 +17,13 @@ Ticket (<%= d 'ticket.title' %>) has been updated by "<b><%= d 'current_user.lon
<br>
<% if @objects[:article] %>
<div>
<%= t 'Information' %>:
#{t('Information')}:
<blockquote type="cite">
<%= a_html 'article' %>
#{article.body_as_html}
</blockquote>
</div>
<% end %>
<br>
<div>
<a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>" target="zammad_app"><%= t 'View this in Zammad' %></a>
<a href="#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}" target="zammad_app">#{t('View this in Zammad')}</a>
</div>

View file

@ -1,19 +1,19 @@
<%= c 'product_name' %>-Anmeldung erfasst von einem neuen Gerät
#{config.product_name}-Anmeldung erfasst von einem neuen Gerät
<div>Hallo <%= d 'user.firstname' %>,</div>
<div>Hallo #{user.firstname},</div>
<br>
<div>es sieht aus, als ob Du Dich mit <b>einem neuen Gerät</b> um "<%= d 'user_device.created_at' %>" angemeldet hast:</div>
<div>es sieht aus, als ob Du Dich mit <b>einem neuen Gerät</b> um "#{user_device.created_at}" angemeldet hast:</div>
<br>
<div>
Dein Gerät: <%= d 'user_device.name' %><br>
Deine Lokation (relativ): <%= d 'user_device.location' %><br>
Deine IP: <%= d 'user_device.ip' %><br>
Dein Gerät: #{user_device.name}<br>
Deine Lokation (relativ): #{user_device.location}<br>
Deine IP: #{user_device.ip}<br>
</div>
<br>
<div>Das Gerät wurde in die Liste der bekannten Geräte hinzugefügt, diese Liste kannst Du hier einsehen:</div>
<br>
<div><%= c 'http_type' %>://<%= c 'fqdn' %>/#profile/devices</div>
<div>#{config.http_type}://#{config.fqdn}/#profile/devices</div>
<br>
<div>Wenn dies nicht Du warst, entferne das Gerät aus der Liste, ändere Dein Account-Passwort und kontaktieren Deinen Administrator. Jemand könnte unberechtigten Zugriff auf Dein Konto bekommen haben.</div>
<br>
<div>Dein <%= c 'product_name' %> Team</div>
<div>Dein #{config.product_name} Team</div>

View file

@ -1,19 +1,19 @@
<%= c 'product_name' %> signin detected from a new device
#{config.product_name} signin detected from a new device
<div>Hi <%= d 'user.firstname' %>,</div>
<div>Hi #{user.firstname},</div>
<br>
<div>It looks like you signed into your account <b>using a new device</b> on "<%= d 'user_device.created_at' %>":</div>
<div>It looks like you signed into your account <b>using a new device</b> on "#{user_device.created_at}":</div>
<br>
<div>
Your device: <%= d 'user_device.name' %><br>
Your location (relative): <%= d 'user_device.location' %><br>
Your IP: <%= d 'user_device.ip' %><br>
Your device: #{user_device.name}<br>
Your location (relative): #{user_device.location}<br>
Your IP: #{user_device.ip}<br>
</div>
<br>
<div>Your device has been added to your list of known devices, which you can view here:</div>
<br>
<div><%= c 'http_type' %>://<%= c 'fqdn' %>/#profile/devices</div>
<div>#{config.http_type}://#{config.fqdn}/#profile/devices</div>
<br>
<div>If this wasn't you, remove the device, changing your account password, and contacting your administrator. Somebody might have gained unauthorized access to your account.</div>
<br>
<div>Your <%= c 'product_name' %> Team</div>
<div>Your #{config.product_name} Team</div>

View file

@ -1,19 +1,19 @@
<%= c 'product_name' %>-Anmeldung von einem anderen Land erfasst
#{config.product_name}-Anmeldung von einem anderen Land erfasst
<div>Hallo <%= d 'user.firstname' %>,</div>
<div>Hallo #{user.firstname},</div>
<br>
<div>es sieht aus, als ob Du Dich um "<%= d 'user_device.created_at' %>" von einem <b>bekannten Gerät aus einem anderen Land angemeldet hast</b>:</div>
<div>es sieht aus, als ob Du Dich um "#{user_device.created_at}" von einem <b>bekannten Gerät aus einem anderen Land angemeldet hast</b>:</div>
<br>
<div>
Dein Gerät: <%= d 'user_device.name' %><br>
Deine Lokation (relativ): <%= d 'user_device.location' %><br>
Deine IP: <%= d 'user_device.ip' %><br>
Dein Gerät: #{user_device.name}<br>
Deine Lokation (relativ): #{user_device.location}<br>
Deine IP: #{user_device.ip}<br>
</div>
<br>
<div>Das neue Land wurde in die Liste der bekannten Geräte hinzugefügt, diese Liste kannst Du hier einsehen:</div>
<br>
<div><%= c 'http_type' %>://<%= c 'fqdn' %>/#profile/devices</div>
<div>#{config.http_type}://#{config.fqdn}/#profile/devices</div>
<br>
<div>Wenn dies nicht Du warst, entferne die neue Lokation aus der Liste, ändere Dein Account-Passwort und kontaktieren Deinen Administrator. Jemand könnte unberechtigten Zugriff auf Dein Konto bekommen haben.</div>
<br>
<div>Dein <%= c 'product_name' %> Team</div>
<div>Dein #{config.product_name} Team</div>

View file

@ -1,19 +1,19 @@
<%= c 'product_name' %> signin detected from a new country
#{config.product_name} signin detected from a new country
<div>Hi <%= d 'user.firstname' %>,</div>
<div>Hi #{user.firstname},</div>
<br>
<div>It looks like you used your account with an <b>known device but from a new country</b> on "<%= d 'user_device.created_at' %>":</div>
<div>It looks like you used your account with an <b>known device but from a new country</b> on "#{user_device.created_at}":</div>
<br>
<div>
Your device: <%= d 'user_device.name' %><br>
Your location (relative): <%= d 'user_device.location' %><br>
Your IP: <%= d 'user_device.ip' %><br>
Your device: #{user_device.name}<br>
Your location (relative): #{user_device.location}<br>
Your IP: #{user_device.ip}<br>
</div>
<br>
<div>The country has been added to your list of known devices, which you can view here:</div>
<br>
<div><%= c 'http_type' %>://<%= c 'fqdn' %>/#profile/devices</div>
<div>#{config.http_type}://#{config.fqdn}/#profile/devices</div>
<br>
<div>If this wasn't you, remove the device, changing your account password, and contacting your administrator. Somebody might have gained unauthorized access to your account.</div>
<br>
<div>Your <%= c 'product_name' %> Team</div>
<div>Your #{config.product_name} Team</div>

View file

@ -1,13 +1,13 @@
Einladung zu <%= c 'product_name' %> über <%= c 'fqdn' %>
Einladung zu #{config.product_name} über #{config.fqdn}
<div>Hallo <%= d 'user.firstname' %>,</div>
<div>Hallo #{user.firstname},</div>
<br>
<div>Ich (<%= d 'current_user.firstname' %> <%= d 'current_user.lastname' %>) möchte Dich zu <%= c 'product_name' %> einladen - unsere Kundensupport / Ticket System Platform.</div>
<div>Ich (#{current_user.firstname} #{current_user.lastname}) möchte Dich zu #{config.product_name} einladen - unsere Kundensupport / Ticket System Platform.</div>
<br>
<div>Um sich anzumelden kann <a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#password_reset_verify/<%= d 'token.name' %>">hier</a> das Password gesetzt werden.</div>
<div>Um sich anzumelden kann <a href="#{config.http_type}://#{config.fqdn}/#password_reset_verify/#{token.name}">hier</a> das Password gesetzt werden.</div>
<br>
<div>Enjoy,</div>
<br>
<div><%= d 'current_user.firstname' %> <%= d 'current_user.lastname' %></div>
<div>#{current_user.firstname} #{current_user.lastname}</div>
<br>
<div>Dein <%= c 'product_name' %> Team</div>
<div>Dein #{config.product_name} Team</div>

View file

@ -1,13 +1,13 @@
Invitation to <%= c 'product_name' %> at <%= c 'fqdn' %>
Invitation to #{config.product_name} at #{config.fqdn}
<div>Hi <%= d 'user.firstname' %>,</div>
<div>Hi #{user.firstname},</div>
<br>
<div>I (<%= d 'current_user.firstname' %> <%= d 'current_user.lastname' %>) invite you to <%= c 'product_name' %> - our customer support / ticket system platform.</div>
<div>I (#{current_user.firstname} #{current_user.lastname}) invite you to #{config.product_name} - our customer support / ticket system platform.</div>
<br>
<div>Click <a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#password_reset_verify/<%= d 'token.name' %>">here</a> and set your password.</div>
<div>Click <a href="#{config.http_type}://#{config.fqdn}/#password_reset_verify/#{token.name}">here</a> and set your password.</div>
<br>
<div>Enjoy,</div>
<br>
<div><%= d 'current_user.firstname' %> <%= d 'current_user.lastname' %></div>
<div>#{current_user.firstname} #{current_user.lastname}</div>
<br>
<div>Your <%= c 'product_name' %> Team</div>
<div>Your #{config.product_name} Team</div>

View file

@ -1,9 +1,9 @@
# <%= d 'ticket.title' %>
_<<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>|Ticket#<%= d 'ticket.number' %>>: Created by <%= d 'current_user.longname' %> at <%= d 'ticket.updated_at' %>_
* <%= t 'Group' %>: <%= d 'ticket.group.name' %>
* <%= t 'Owner' %>: <%= d 'ticket.owner.fullname' %>
* <%= t 'State' %>: <%= t d 'ticket.state.name' %>
# #{ticket.title}
_<#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}|Ticket##{ticket.number}>: Created by #{current_user.longname} at #{ticket.updated_at}_
* #{t('Group')}: #{ticket.group.name}
* #{t('Owner')}: #{ticket.owner.fullname}
* #{t('State')}: #{t(ticket.state.name)}
<% if @objects[:article] %>
<%= a_text 'article' %>
#{article.body_as_text}
<% end %>

View file

@ -1,7 +1,7 @@
# <%= d 'ticket.title' %>
_<<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>|Ticket#<%= d 'ticket.number' %>>: Escalated at <%= d 'ticket.escalation_at' %>_
A ticket (<%= d 'ticket.title' %>) from "<%= d 'ticket.customer.longname' %>" is escalated since "<%= d 'ticket.escalation_at' %>"!
# #{ticket.title}
_<#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}|Ticket##{ticket.number}>: Escalated at #{ticket.escalation_at}_
A ticket (#{ticket.title}) from "#{ticket.customer.longname}" is escalated since "#{ticket.escalation_at}"!
<% if @objects[:article] %>
<%= a_text 'article' %>
#{article.body_as_text}
<% end %>

View file

@ -1,7 +1,7 @@
# <%= d 'ticket.title' %>
_<<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>|Ticket#<%= d 'ticket.number' %>>: Will escalate at <%= d 'ticket.escalation_at' %>_
A ticket (<%= d 'ticket.title' %>) from "<%= d 'ticket.customer.longname' %>" will escalate at "<%= d 'ticket.escalation_at' %>"!
# #{ticket.title}
_<#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}|Ticket##{ticket.number}>: Will escalate at #{ticket.escalation_at}_
A ticket (#{ticket.title}) from "#{ticket.customer.longname}" will escalate at "#{ticket.escalation_at}"!
<% if @objects[:article] %>
<%= a_text 'article' %>
#{article.body_as_text}
<% end %>

View file

@ -1,7 +1,7 @@
# <%= d 'ticket.title' %>
_<<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>|Ticket#<%= d 'ticket.number' %>>: Reminder reached!_
A ticket needs attention, reminder reached for (<%= d 'ticket.title' %>) with customer "*<%= d 'ticket.customer.longname' %>*".
# #{ticket.title}
_<#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}|Ticket##{ticket.number}>: Reminder reached!_
A ticket needs attention, reminder reached for (#{ticket.title}) with customer "*#{ticket.customer.longname}*".
<% if @objects[:article] %>
<%= a_text 'article' %>
#{article.body_as_text}
<% end %>

View file

@ -1,5 +1,5 @@
# <%= d 'ticket.title' %>
_<<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>|Ticket#<%= d 'ticket.number' %>>: Updated by <%= d 'current_user.longname' %> at <%= d 'ticket.updated_at' %>_
# #{ticket.title}
_<#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}|Ticket##{ticket.number}>: Updated by #{current_user.longname} at #{ticket.updated_at}_
<% if @objects[:changes] && !@objects[:changes].empty? %>
<% @objects[:changes].each do |key, value| %>
* <%= t key %>: <%= h value[0] %> -> <%= h value[1] %>
@ -7,5 +7,5 @@ _<<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>|Ticke
<% end %>
<% if @objects[:article] %>
<%= a_text 'article' %>
#{article.body_as_text}
<% end %>

View file

@ -6,7 +6,7 @@ get notification settings for user and notification type
result = NotificationFactory::Mailer.notification_settings(user, ticket, type)
type: create | update | reminder_reached | pending
type: create | update | reminder_reached | escalation (escalation_warning)
returns
@ -21,6 +21,15 @@ returns
=end
def self.notification_settings(user, ticket, type)
# map types if needed
map = {
'escalation_warning' => 'escalation'
}
if map[type]
type = map[type]
end
return if !user.preferences
return if !user.preferences['notification_config']
matrix = user.preferences['notification_config']['matrix']
@ -190,11 +199,12 @@ retunes
)
result = NotificationFactory::Mailer.template(
templateInline: "Invitation to <%= c 'product_name' %> at <%= c 'fqdn' %>",
templateInline: "Invitation to \#{config.product_name} at \#{config.fqdn}",
locale: 'en-us',
objects: {
recipient: User.find(2),
},
quote: true, # html quoting
)
only raw subject/body
@ -221,7 +231,7 @@ returns
def self.template(data)
if data[:templateInline]
return NotificationFactory::Renderer.new(data[:objects], data[:locale], data[:templateInline], false).render
return NotificationFactory::Renderer.new(data[:objects], data[:locale], data[:templateInline], data[:quote]).render
end
template = NotificationFactory.template_read(

View file

@ -9,7 +9,7 @@ examples how to use
ticket: Ticket.first,
},
'de-de',
'some template <b><%= d "ticket.title", false %></b> <%= c "fqdn", false %>',
'some template <b>#{ticket.title}</b> {config.fqdn}',
false
).render
@ -18,7 +18,7 @@ examples how to use
ticket: Ticket.first,
},
'de-de',
'some template <b><%= d "ticket.title", true %></b> <%= c "fqdn", true %>',
'some template <b>#{ticket.title}</b> #{config.fqdn}',
).render
=end
@ -26,7 +26,7 @@ examples how to use
def initialize(objects, locale, template, escape = true)
@objects = objects
@locale = locale || 'en-us'
@template = NotificationFactory::Template.new(template)
@template = NotificationFactory::Template.new(template, escape)
@escape = escape
end
@ -41,6 +41,25 @@ examples how to use
# do validaton, ignore some methodes
return "\#{#{key} / not allowed}" if !data_key_valid?(key)
# aliases
map = {
'article.body' => 'article.body_as_text_with_quote.text2html',
}
if map[key]
key = map[key]
end
# escape in html mode
if escape
no_escape = {
'article.body_as_html' => true,
'article.body_as_text_with_quote.text2html' => true,
}
if no_escape[key]
escape = false
end
end
value = nil
object_methods = key.split('.')
object_name = object_methods.shift
@ -76,7 +95,11 @@ examples how to use
value = "\#{#{object_name}.#{object_methods_s} / no such method}"
break
end
object_refs = object_refs.send(method.to_sym)
begin
object_refs = object_refs.send(method.to_sym)
rescue => e
object_refs = "\#{#{object_name}.#{object_methods_s} / e.message}"
end
}
placeholder = if !value
object_refs
@ -100,27 +123,6 @@ examples how to use
escaping(translation, escape)
end
# a_html - article body in html
# a_html(article)
def a_html(article)
content_type = d "#{article}.content_type", false
if content_type =~ /html/
return d "#{article}.body", false
end
d("#{article}.body", false).text2html
end
# a_text - article body in text
# a_text(article)
def a_text(article)
content_type = d "#{article}.content_type", false
body = d "#{article}.body", false
if content_type =~ /html/
body = body.html2text
end
(body.strip + "\n").gsub(/^(.*?)$/, '> \\1')
end
# h - htmlEscape
# h('fqdn', htmlEscape)
def h(key)
@ -137,7 +139,7 @@ examples how to use
end
def data_key_valid?(key)
return false if key =~ /`|\.(|\s*)(save|destroy|delete|remove|drop|update|create|new|all|where|find)/i
return false if key =~ /`|\.(|\s*)(save|destroy|delete|remove|drop|update|create|new|all|where|find)/i && key !~ /(update|create)d_at/i
true
end

View file

@ -33,8 +33,8 @@ returns
type: 'slack',
)
message_subject = NotificationFactory::Renderer.new(data[:objects], data[:locale], template[:subject]).render
message_body = NotificationFactory::Renderer.new(data[:objects], data[:locale], template[:body]).render
message_subject = NotificationFactory::Renderer.new(data[:objects], data[:locale], template[:subject], false).render
message_body = NotificationFactory::Renderer.new(data[:objects], data[:locale], template[:body], false).render
if !data[:raw]
application_template = NotificationFactory.application_template_read(
@ -43,7 +43,7 @@ returns
)
data[:objects][:message] = message_body
data[:objects][:standalone] = data[:standalone]
message_body = NotificationFactory::Renderer.new(data[:objects], data[:locale], application_template).render
message_body = NotificationFactory::Renderer.new(data[:objects], data[:locale], application_template, false).render
end
{
subject: message_subject.strip!,

View file

@ -5,13 +5,15 @@ class NotificationFactory::Template
examples how to use
cleaned_template = NotificationFactory::Template.new(
'some template <b><%= d "ticket.title", false %></b> <%= c "fqdn", false %>',
'some template <b>#{ticket.title}</b> #{config.fqdn}',
true,
).to_s
=end
def initialize(template)
def initialize(template, escape)
@template = template
@escape = escape
end
def to_s
@ -23,7 +25,35 @@ examples how to use
def strip_html
# some browsers start adding HTML tags
# fixes https://github.com/zammad/zammad/issues/385
@template.gsub!(%r{#\{\s*<[^>]+>([^<]+)</[^>]+>\s*\}}, '\1')
@template.gsub!(/#\{\s*<[^>]+>([^<]+)\s*\}/, '\1')
@template.gsub!(/\#\{\s*t\((.+?)\)\s*\}/m) do
content = $1
if content =~ /^'(.+?)'$/
"<%= t \"#{strip_content($1)}\", #{@escape} %>"
else
"<%= t d\"#{strip_variable(content)}\", #{@escape} %>"
end
end
@template.gsub!(/\#\{\s*config\.(.+?)\s*\}/m) do
"<%= c \"#{strip_variable($1)}\", #{@escape} %>"
end
@template.gsub!(/\#\{(.*?)\}/m) do
"<%= d \"#{strip_variable($1)}\", #{@escape} %>"
end
end
def strip_content(string)
return string if !string
string.gsub!(/\t|\r|\n/, '')
string.gsub!(/"/, '\"')
string
end
def strip_variable(string)
return string if !string
string.gsub!(/\t|\r|\n|"|'|§|;/, '')
string.gsub!(/\s*/, '')
string.gsub!(/<.+?>/, '')
string
end
end

View file

@ -3,29 +3,40 @@ require 'test_helper'
class NotificationFactoryRendererTest < ActiveSupport::TestCase
# TODO: should be mocked somehow
Translation.load('de-de')
# RSpec incoming!
def described_class
NotificationFactory::Renderer
end
Group = Struct.new(:name)
State = Struct.new(:name)
User = Struct.new(:firstname, :lastname, :longname, :fullname)
Ticket = Struct.new(:id, :title, :group, :owner, :state)
group = Group.new('Users')
state = State.new('new')
owner = User.new('Notification<b>xxx</b>', 'Agent1<b>yyy</b>', 'Notification<b>xxx</b> Agent1<b>yyy</b>', 'Notification<b>xxx</b> Agent1<b>yyy</b> (Zammad)')
current_user = User.new('CurrentUser<b>xxx</b>', 'Agent2<b>yyy</b>', 'CurrentUser<b>xxx</b> Agent2<b>yyy</b>', 'CurrentUser<b>xxx</b> Agent2<b>yyy</b> (Zammad)')
recipient = User.new('Recipient<b>xxx</b>', 'Customer1<b>yyy</b>', 'Recipient<b>xxx</b> Customer1<b>yyy</b>', 'Recipient<b>xxx</b> Customer1<b>yyy</b> (Zammad)')
ticket = Ticket.new(1, '<b>Welcome to Zammad!</b>', group, owner, state)
group = Group.new(name: 'Users')
owner = User.new(firstname: 'Notification<b>xxx</b>', lastname: 'Agent1<b>yyy</b>')
current_user = User.new(firstname: 'CurrentUser<b>xxx</b>', lastname: 'Agent2<b>yyy</b>')
recipient = User.new(firstname: 'Recipient<b>xxx</b>', lastname: 'Customer1<b>yyy</b>')
state = Ticket::State.new(name: 'new')
ticket = Ticket.new(
id: 1,
title: '<b>Welcome to Zammad!</b>',
group: group,
owner: owner,
state: state,
created_at: Time.zone.parse('2016-11-12 12:00:00 UTC'),
updated_at: Time.zone.parse('2016-11-12 14:00:00 UTC'),
)
article_html1 = Ticket::Article.new(
body: 'test <b>hello</b><br>some new line',
content_type: 'text/html',
)
article_plain1 = Ticket::Article.new(
body: "test <b>hello</b>\nsome new line",
content_type: 'text/plain',
)
article_plain2 = Ticket::Article.new(
body: "test <b>hello</b>\nsome new line",
)
test 'replace object attribute' do
template = "<%= d 'ticket.title' %>"
template = "\#{ticket.title}"
result = described_class.new(
{
ticket: ticket,
@ -35,7 +46,27 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML(ticket.title), result)
template = "<%= d 'ticket. title' %>"
template = "\#{ticket.created_at}"
result = described_class.new(
{
ticket: ticket,
},
'en-us',
template,
).render
assert_equal(ticket.created_at.to_s, result)
template = "\#{ticket.updated_at}"
result = described_class.new(
{
ticket: ticket,
},
'en-us',
template,
).render
assert_equal(ticket.updated_at.to_s, result)
template = "\#{ticket. title}"
result = described_class.new(
{
ticket: ticket,
@ -45,7 +76,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML(ticket.title), result)
template = "<%= d 'ticket.\n title' %>"
template = "\#{ticket.\n title}"
result = described_class.new(
{
ticket: ticket,
@ -55,7 +86,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML(ticket.title), result)
template = "<%= d 'ticket.\t title' %>"
template = "\#{ticket.\t title}"
result = described_class.new(
{
ticket: ticket,
@ -65,7 +96,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML(ticket.title), result)
template = "<%= d 'ticket.\t\n title\t' %>"
template = "\#{ticket.\t\n title\t}"
result = described_class.new(
{
ticket: ticket,
@ -75,13 +106,50 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML(ticket.title), result)
template = "\#{ticket.\" title\t}"
result = described_class.new(
{
ticket: ticket,
},
'en-us',
template,
).render
assert_equal(CGI.escapeHTML(ticket.title), result)
template = "some test<br>\#{article.body}"
result = described_class.new(
{
article: article_html1,
},
'en-us',
template,
).render
assert_equal('some test<br>&gt; test hello<br>&gt; some new line<br>', result)
result = described_class.new(
{
article: article_plain1,
},
'en-us',
template,
).render
assert_equal('some test<br>&gt; test &lt;b&gt;hello&lt;/b&gt;<br>&gt; some new line<br>', result)
result = described_class.new(
{
article: article_plain2,
},
'en-us',
template,
).render
assert_equal('some test<br>&gt; test &lt;b&gt;hello&lt;/b&gt;<br>&gt; some new line<br>', result)
end
test 'config' do
setting = 'fqdn'
template = "<%= c '#{setting}' %>"
setting = 'fqdn'
template = "\#{config.#{setting}}"
result = described_class.new(
{
ticket: ticket,
@ -89,13 +157,11 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
'en-us',
template,
).render
assert_equal(Setting.get(setting), result)
setting1 = 'fqdn'
setting2 = 'product_name'
template = "some <%= c '#{setting1}' %> and <%= c '#{setting2}' %>"
template = "some \#{config.#{setting1}} and \#{config.#{setting2}}"
result = described_class.new(
{
ticket: ticket,
@ -103,14 +169,25 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
'en-us',
template,
).render
assert_equal("some #{Setting.get(setting1)} and #{Setting.get(setting2)}", result)
setting1 = 'fqdn'
setting2 = 'product_name'
template = "some \#{ config.#{setting1}} and \#{\tconfig.#{setting2}}"
result = described_class.new(
{
ticket: ticket,
},
'en-us',
template,
).render
assert_equal("some #{Setting.get(setting1)} and #{Setting.get(setting2)}", result)
end
test 'translation' do
template = "<%= t 'new' %>"
#template = "<%= t 'new' %>"
template = "\#{t('new')}"
result = described_class.new(
{
ticket: ticket,
@ -118,11 +195,9 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
'de-de',
template,
).render
assert_equal('neu', result)
template = "some text <%= t 'new' %> and <%= t 'open' %>"
template = "some text \#{t('new')} and \#{t('open')}"
result = described_class.new(
{
ticket: ticket,
@ -130,14 +205,33 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
'de-de',
template,
).render
assert_equal('some text neu and offen', result)
template = "some text \#{t('new') } and \#{ t('open')}"
result = described_class.new(
{
ticket: ticket,
},
'de-de',
template,
).render
assert_equal('some text neu and offen', result)
template = "some text \#{\nt('new') } and \#{ t('open')\t}"
result = described_class.new(
{
ticket: ticket,
},
'de-de',
template,
).render
assert_equal('some text neu and offen', result)
end
test 'chained function calls' do
template = "<%= t d 'ticket.state.name' %>"
template = "\#{t(ticket.state.name)}"
result = described_class.new(
{
@ -152,7 +246,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
test 'not existing object and attribute' do
template = "<%= d '' %>"
template = "\#{}"
result = described_class.new(
{
ticket: ticket,
@ -162,7 +256,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{no such object}'), result)
template = "<%= d 'notexsiting.notexsiting' %>"
template = "\#{notexsiting.notexsiting}"
result = described_class.new(
{
ticket: ticket,
@ -172,7 +266,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{notexsiting / no such object}'), result)
template = "<%= d 'ticket.notexsiting' %>"
template = "\#{ticket.notexsiting}"
result = described_class.new(
{
ticket: ticket,
@ -182,7 +276,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket.notexsiting / no such method}'), result)
template = "<%= d 'ticket.' %>"
template = "\#{ticket.}"
result = described_class.new(
{
ticket: ticket,
@ -192,7 +286,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket. / no such method}'), result)
template = "<%= d 'ticket.title.notexsiting' %>"
template = "\#{ticket.title.notexsiting}"
result = described_class.new(
{
ticket: ticket,
@ -202,7 +296,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket.title.notexsiting / no such method}'), result)
template = "<%= d 'ticket.notexsiting.notexsiting' %>"
template = "\#{ticket.notexsiting.notexsiting}"
result = described_class.new(
{
ticket: ticket,
@ -212,7 +306,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket.notexsiting / no such method}'), result)
template = "<%= d 'notexsiting' %>"
template = "\#{notexsiting}"
result = described_class.new(
{
ticket: ticket,
@ -222,7 +316,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{notexsiting / no such object}'), result)
template = "<%= d 'notexsiting.' %>"
template = "\#{notexsiting.}"
result = described_class.new(
{
ticket: ticket,
@ -232,7 +326,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{notexsiting / no such object}'), result)
template = "<%= d 'string' %>"
template = "\#{string}"
result = described_class.new(
{
string: 'some string',
@ -242,7 +336,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('some string'), result)
template = "<%= d 'fixum' %>"
template = "\#{fixum}"
result = described_class.new(
{
fixum: 123,
@ -252,7 +346,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('123'), result)
template = "<%= d 'float' %>"
template = "\#{float}"
result = described_class.new(
{
float: 123.99,
@ -266,7 +360,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
test 'data key validation' do
template = "<%= d 'ticket.title `echo 1`' %>"
template = "\#{ticket.title `echo 1`}"
result = described_class.new(
{
ticket: ticket,
@ -274,9 +368,9 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
'en-us',
template,
).render
assert_equal(CGI.escapeHTML('#{ticket.title `echo 1` / not allowed}'), result)
assert_equal(CGI.escapeHTML('#{ticket.title`echo1` / not allowed}'), result)
template = "<%= d 'ticket.destroy' %>"
template = "\#{ticket.destroy}"
result = described_class.new(
{
ticket: ticket,
@ -286,7 +380,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket.destroy / not allowed}'), result)
template = "<%= d 'ticket.save' %>"
template = "\#{ticket.save}"
result = described_class.new(
{
ticket: ticket,
@ -296,7 +390,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket.save / not allowed}'), result)
template = "<%= d 'ticket.update' %>"
template = "\#{ticket.update}"
result = described_class.new(
{
ticket: ticket,
@ -306,37 +400,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket.update / not allowed}'), result)
template = "<%= d 'ticket.delete' %>"
result = described_class.new(
{
ticket: ticket,
},
'en-us',
template,
).render
assert_equal(CGI.escapeHTML('#{ticket.delete / not allowed}'), result)
template = "<%= d 'ticket.remove' %>"
result = described_class.new(
{
ticket: ticket,
},
'en-us',
template,
).render
assert_equal(CGI.escapeHTML('#{ticket.remove / not allowed}'), result)
template = "<%= d 'ticket.drop' %>"
result = described_class.new(
{
ticket: ticket,
},
'en-us',
template,
).render
assert_equal(CGI.escapeHTML('#{ticket.drop / not allowed}'), result)
template = "<%= d 'ticket.create' %>"
template = "\#{ticket.create}"
result = described_class.new(
{
ticket: ticket,
@ -346,7 +410,47 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket.create / not allowed}'), result)
template = "<%= d 'ticket.new' %>"
template = "\#{ticket.delete}"
result = described_class.new(
{
ticket: ticket,
},
'en-us',
template,
).render
assert_equal(CGI.escapeHTML('#{ticket.delete / not allowed}'), result)
template = "\#{ticket.remove}"
result = described_class.new(
{
ticket: ticket,
},
'en-us',
template,
).render
assert_equal(CGI.escapeHTML('#{ticket.remove / not allowed}'), result)
template = "\#{ticket.drop}"
result = described_class.new(
{
ticket: ticket,
},
'en-us',
template,
).render
assert_equal(CGI.escapeHTML('#{ticket.drop / not allowed}'), result)
template = "\#{ticket.create}"
result = described_class.new(
{
ticket: ticket,
},
'en-us',
template,
).render
assert_equal(CGI.escapeHTML('#{ticket.create / not allowed}'), result)
template = "\#{ticket.new}"
result = described_class.new(
{
ticket: ticket,
@ -356,7 +460,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket.new / not allowed}'), result)
template = "<%= d 'ticket.update_att' %>"
template = "\#{ticket.update_att}"
result = described_class.new(
{
ticket: ticket,
@ -366,7 +470,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket.update_att / not allowed}'), result)
template = "<%= d 'ticket.all' %>"
template = "\#{ticket.all}"
result = described_class.new(
{
ticket: ticket,
@ -376,7 +480,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket.all / not allowed}'), result)
template = "<%= d 'ticket.find' %>"
template = "\#{ticket.find}"
result = described_class.new(
{
ticket: ticket,
@ -386,7 +490,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket.find / not allowed}'), result)
template = "<%= d 'ticket.where' %>"
template = "\#{ticket.where}"
result = described_class.new(
{
ticket: ticket,
@ -396,7 +500,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
).render
assert_equal(CGI.escapeHTML('#{ticket.where / not allowed}'), result)
template = "<%= d 'ticket. destroy' %>"
template = "\#{ticket. destroy}"
result = described_class.new(
{
ticket: ticket,
@ -404,9 +508,9 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
'en-us',
template,
).render
assert_equal(CGI.escapeHTML('#{ticket. destroy / not allowed}'), result)
assert_equal(CGI.escapeHTML('#{ticket.destroy / not allowed}'), result)
template = "<%= d 'ticket.\n destroy' %>"
template = "\#{ticket.\n destroy}"
result = described_class.new(
{
ticket: ticket,
@ -414,9 +518,9 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
'en-us',
template,
).render
assert_equal(CGI.escapeHTML("\#{ticket.\n destroy / not allowed}"), result)
assert_equal(CGI.escapeHTML("\#{ticket.destroy / not allowed}"), result)
template = "<%= d 'ticket.\t destroy' %>"
template = "\#{ticket.\t destroy}"
result = described_class.new(
{
ticket: ticket,
@ -424,9 +528,9 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
'en-us',
template,
).render
assert_equal(CGI.escapeHTML("\#{ticket.\t destroy / not allowed}"), result)
assert_equal(CGI.escapeHTML("\#{ticket.destroy / not allowed}"), result)
template = "<%= d 'ticket.\r destroy' %>"
template = "\#{ticket.\r destroy}"
result = described_class.new(
{
ticket: ticket,
@ -434,7 +538,7 @@ class NotificationFactoryRendererTest < ActiveSupport::TestCase
'en-us',
template,
).render
assert_equal(CGI.escapeHTML("\#{ticket.\r destroy / not allowed}"), result)
assert_equal(CGI.escapeHTML("\#{ticket.destroy / not allowed}"), result)
end

View file

@ -78,7 +78,7 @@ class NotificationFactorySlackTemplateTest < ActiveSupport::TestCase
)
assert_match('# Welcome to Zammad!', result[:subject])
assert_match('User&lt;b&gt;xxx&lt;/b&gt', result[:body])
assert_match('User<b>xxx</b>', result[:body])
assert_match('Created by', result[:body])
assert_match('<b>test123</b>', result[:body])
assert_no_match('Dein', result[:body])
@ -113,7 +113,7 @@ class NotificationFactorySlackTemplateTest < ActiveSupport::TestCase
},
)
assert_match('# Welcome to Zammad!', result[:subject])
assert_match('User&lt;b&gt;xxx&lt;/b&gt', result[:body])
assert_match('User<b>xxx</b>', result[:body])
assert_match('state: aaa -> bbb', result[:body])
assert_match('group: xxx -> yyy', result[:body])
assert_no_match('Dein', result[:body])

View file

@ -11,48 +11,69 @@ class NotificationFactoryTemplateTest < ActiveSupport::TestCase
test 'regular browser html' do
# ensures https://github.com/zammad/zammad/issues/385
template_before = '<%= d "#{<a href="http://ticket.id" title="http://ticket.id" target="_blank">ticket.id</a>}" %>'
template_after = '<%= d "ticket.id" %>'
template_before = '#{<a href="http://ticket.id" title="http://ticket.id" target="_blank">ticket.id</a>}'
template_after = '<%= d "ticket.id", true %>'
result = described_class.new(template_before).to_s
result = described_class.new(template_before, true).to_s
assert_equal(template_after, result)
template_before = '#{<a href="http://ticket.id" title="http://ticket.id" target="_blank">config.fqdn</a>}'
template_after = '<%= d "config.fqdn", true %>'
result = described_class.new(template_before, true).to_s
assert_equal(template_after, result)
end
test 'spaced browser html' do
# ensures https://github.com/zammad/zammad/issues/385
template_before = '<%= d "#{ <a href="http://ticket.id" title="http://ticket.id" target="_blank">ticket.id </a>} " %>'
template_after = '<%= d "ticket.id " %>'
template_before = '#{ <a href="http://ticket.id" title="http://ticket.id" target="_blank">ticket.id </a> }'
template_after = '<%= d "ticket.id", true %>'
result = described_class.new(template_before).to_s
result = described_class.new(template_before, true).to_s
assert_equal(template_after, result)
end
test 'broken browser html' do
# ensures https://github.com/zammad/zammad/issues/385
template_before = '<%= d "#{<a href="http://ticket.id" title="http://ticket.id" target="_blank">ticket.id }" %>'
template_after = '<%= d "ticket.id " %>'
template_before = '#{<a href="http://ticket.id" title="http://ticket.id" target="_blank">ticket.id }'
template_after = '<%= d "ticket.id", true %>'
result = described_class.new(template_before).to_s
result = described_class.new(template_before, true).to_s
assert_equal(template_after, result)
end
test 'empty tag' do
template_before = '<%= d "#{}" %>'
template_after = '<%= d "#{}" %>'
template_before = '#{}'
template_after = '<%= d "", true %>'
result = described_class.new(template_before).to_s
result = described_class.new(template_before, true).to_s
assert_equal(template_after, result)
end
test 'empty tag with space' do
template_before = '<%= d "#{ }" %>'
template_after = '<%= d "#{ }" %>'
template_before = '#{ }'
template_after = '<%= d "", false %>'
result = described_class.new(template_before).to_s
result = described_class.new(template_before, false).to_s
assert_equal(template_after, result)
end
test 'translation' do
template_before = "\#{t('some text')}"
template_after = '<%= t "some text", false %>'
result = described_class.new(template_before, false).to_s
assert_equal(template_after, result)
template_before = "\#{t('some \"text\"')}"
template_after = '<%= t "some \"text\"", false %>'
result = described_class.new(template_before, false).to_s
assert_equal(template_after, result)
end

View file

@ -13,7 +13,7 @@ class TicketTriggerTest < ActiveSupport::TestCase
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}',
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'ticket_customer',
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
},
@ -60,12 +60,25 @@ class TicketTriggerTest < ActiveSupport::TestCase
created_by_id: 1,
)
assert(ticket1, 'ticket1 created')
Ticket::Article.create(
ticket_id: ticket1.id,
from: 'some_sender@example.com',
to: 'some_recipient@example.com',
subject: 'some subject',
message_id: 'some@id',
body: "some message <b>note</b>\nnew line",
internal: false,
sender: Ticket::Article::Sender.find_by(name: 'Agent'),
type: Ticket::Article::Type.find_by(name: 'note'),
updated_by_id: 1,
created_by_id: 1,
)
assert_equal('some <b>title</b> äöüß', ticket1.title, 'ticket1.title verify')
assert_equal('Users', ticket1.group.name, 'ticket1.group verify')
assert_equal('new', ticket1.state.name, 'ticket1.state verify')
assert_equal('2 normal', ticket1.priority.name, 'ticket1.priority verify')
assert_equal(0, ticket1.articles.count, 'ticket1.articles verify')
assert_equal(1, ticket1.articles.count, 'ticket1.articles verify')
assert_equal([], Tag.tag_list(object: 'Ticket', o_id: ticket1.id))
Observer::Transaction.commit
@ -75,13 +88,14 @@ class TicketTriggerTest < ActiveSupport::TestCase
assert_equal('Users', ticket1.group.name, 'ticket1.group verify')
assert_equal('new', ticket1.state.name, 'ticket1.state verify')
assert_equal('3 high', ticket1.priority.name, 'ticket1.priority verify')
assert_equal(1, ticket1.articles.count, 'ticket1.articles verify')
assert_equal(2, ticket1.articles.count, 'ticket1.articles verify')
assert_equal(%w(aa kk), Tag.tag_list(object: 'Ticket', o_id: ticket1.id))
article1 = ticket1.articles.last
assert_match('Zammad <zammad@localhost>', article1.from)
assert_match('nicole.braun@zammad.org', article1.to)
assert_match('Thanks for your inquiry (some <b>title</b> äöüß)!', article1.subject)
assert_match('Braun<br>some &lt;b&gt;title&lt;/b&gt;', article1.body)
assert_match('&gt; some message &lt;b&gt;note&lt;/b&gt;<br>&gt; new line', article1.body)
assert_equal('text/html', article1.content_type)
ticket1.priority = Ticket::Priority.lookup(name: '2 normal')
@ -93,7 +107,7 @@ class TicketTriggerTest < ActiveSupport::TestCase
assert_equal('Users', ticket1.group.name, 'ticket1.group verify')
assert_equal('new', ticket1.state.name, 'ticket1.state verify')
assert_equal('2 normal', ticket1.priority.name, 'ticket1.priority verify')
assert_equal(1, ticket1.articles.count, 'ticket1.articles verify')
assert_equal(2, ticket1.articles.count, 'ticket1.articles verify')
assert_equal(%w(aa kk), Tag.tag_list(object: 'Ticket', o_id: ticket1.id))
ticket1.state = Ticket::State.lookup(name: 'open')
@ -105,7 +119,7 @@ class TicketTriggerTest < ActiveSupport::TestCase
assert_equal('Users', ticket1.group.name, 'ticket1.group verify')
assert_equal('open', ticket1.state.name, 'ticket1.state verify')
assert_equal('2 normal', ticket1.priority.name, 'ticket1.priority verify')
assert_equal(1, ticket1.articles.count, 'ticket1.articles verify')
assert_equal(2, ticket1.articles.count, 'ticket1.articles verify')
assert_equal(%w(aa kk), Tag.tag_list(object: 'Ticket', o_id: ticket1.id))
ticket1.state = Ticket::State.lookup(name: 'new')
@ -118,7 +132,7 @@ class TicketTriggerTest < ActiveSupport::TestCase
assert_equal('Users', ticket1.group.name, 'ticket1.group verify')
assert_equal('new', ticket1.state.name, 'ticket1.state verify')
assert_equal('3 high', ticket1.priority.name, 'ticket1.priority verify')
assert_equal(2, ticket1.articles.count, 'ticket1.articles verify')
assert_equal(3, ticket1.articles.count, 'ticket1.articles verify')
assert_equal(%w(aa kk), Tag.tag_list(object: 'Ticket', o_id: ticket1.id))
article1 = ticket1.articles.last
assert_match('Zammad <zammad@localhost>', article1.from)
@ -155,6 +169,56 @@ class TicketTriggerTest < ActiveSupport::TestCase
assert_equal(0, ticket2.articles.count, 'ticket2.articles verify')
assert_equal([], Tag.tag_list(object: 'Ticket', o_id: ticket2.id))
ticket3 = Ticket.create(
title: "some <b>title</b>\n äöüß3",
group: Group.lookup(name: 'Users'),
customer: User.lookup(email: 'nicole.braun@zammad.org'),
state: Ticket::State.lookup(name: 'new'),
priority: Ticket::Priority.lookup(name: '2 normal'),
updated_by_id: 1,
created_by_id: 1,
)
assert(ticket3, 'ticket3 created')
Ticket::Article.create(
ticket_id: ticket3.id,
from: 'some_sender@example.com',
to: 'some_recipient@example.com',
subject: 'some subject',
message_id: 'some@id',
content_type: 'text/html',
body: 'some message <b>note</b><br>new line',
internal: false,
sender: Ticket::Article::Sender.find_by(name: 'Agent'),
type: Ticket::Article::Type.find_by(name: 'note'),
updated_by_id: 1,
created_by_id: 1,
)
assert_equal('some <b>title</b> äöüß3', ticket3.title, 'ticket3.title verify')
assert_equal('Users', ticket3.group.name, 'ticket3.group verify')
assert_equal('new', ticket3.state.name, 'ticket3.state verify')
assert_equal('2 normal', ticket3.priority.name, 'ticket3.priority verify')
assert_equal(1, ticket3.articles.count, 'ticket3.articles verify')
assert_equal([], Tag.tag_list(object: 'Ticket', o_id: ticket3.id))
Observer::Transaction.commit
ticket3 = Ticket.lookup(id: ticket3.id)
assert_equal('some <b>title</b> äöüß3', ticket3.title, 'ticket3.title verify')
assert_equal('Users', ticket3.group.name, 'ticket3.group verify')
assert_equal('new', ticket3.state.name, 'ticket3.state verify')
assert_equal('3 high', ticket3.priority.name, 'ticket3.priority verify')
assert_equal(2, ticket3.articles.count, 'ticket3.articles verify')
assert_equal(%w(aa kk), Tag.tag_list(object: 'Ticket', o_id: ticket3.id))
article3 = ticket3.articles.last
assert_match('Zammad <zammad@localhost>', article3.from)
assert_match('nicole.braun@zammad.org', article3.to)
assert_match('Thanks for your inquiry (some <b>title</b> äöüß3)!', article3.subject)
assert_match('Braun<br>some &lt;b&gt;title&lt;/b&gt;', article3.body)
assert_match('&gt; some message note<br>&gt; new line', article3.body)
assert_no_match('&gt; some message &lt;b&gt;note&lt;/b&gt;<br>&gt; new line', article3.body)
assert_equal('text/html', article3.content_type)
Trigger.destroy_all
end