diff --git a/app/assets/javascripts/app/controllers/signup.coffee b/app/assets/javascripts/app/controllers/signup.coffee index 4400949f0..1253c5616 100644 --- a/app/assets/javascripts/app/controllers/signup.coffee +++ b/app/assets/javascripts/app/controllers/signup.coffee @@ -43,6 +43,7 @@ class Index extends App.ControllerContent if !@params.login && @params.email @params.login = @params.email + @params.signup = true @params.role_ids = [0] @log 'notice', 'updateAttributes', @params user = new App.User diff --git a/app/assets/javascripts/app/models/user.coffee b/app/assets/javascripts/app/models/user.coffee index 61feff890..6a52d4388 100644 --- a/app/assets/javascripts/app/models/user.coffee +++ b/app/assets/javascripts/app/models/user.coffee @@ -1,5 +1,5 @@ class App.User extends App.Model - @configure 'User', 'login', 'firstname', 'lastname', 'email', 'web', 'password', 'phone', 'fax', 'mobile', 'street', 'zip', 'city', 'country', 'organization_id', 'department', 'note', 'role_ids', 'group_ids', 'active', 'invite', 'updated_at' + @configure 'User', 'login', 'firstname', 'lastname', 'email', 'web', 'password', 'phone', 'fax', 'mobile', 'street', 'zip', 'city', 'country', 'organization_id', 'department', 'note', 'role_ids', 'group_ids', 'active', 'invite', 'signup', 'updated_at' @extend Spine.Model.Ajax @url: @apiPath + '/users' diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 4f1f5279b..84b27eda8 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -135,46 +135,28 @@ class UsersController < ApplicationController # send inviteation if needed / only if session exists if params[:invite] && current_user - - # generate token token = Token.create(action: 'PasswordReset', user_id: user.id) + NotificationFactory.notification( + template: 'user_invite', + user: user, + objects: { + token: token, + user: user, + current_user: current_user, + } + ) + end - # send mail - data = {} - data[:subject] = 'Invitation to #{config.product_name} at #{config.fqdn}' - data[:body] = 'Hi #{user.firstname}, - - I (#{current_user.firstname} #{current_user.lastname}) invite you to #{config.product_name} - the customer support / ticket system platform. - - Click on the following link and set your password: - - #{config.http_type}://#{config.fqdn}/#password_reset_verify/#{token.name} - - Enjoy, - - #{current_user.firstname} #{current_user.lastname} - - Your #{config.product_name} Team - ' - - # prepare subject & body - [:subject, :body].each { |key| - data[key.to_sym] = NotificationFactory.build( - locale: user.preferences[:locale], - string: data[key.to_sym], - objects: { - token: token, - user: user, - current_user: current_user, - } - ) - } - - # send notification - NotificationFactory.send( - recipient: user, - subject: data[:subject], - body: data[:body] + # send email verify + if params[:signup] && !current_user + token = Token.create(action: 'EmailVerify', user_id: user.id) + NotificationFactory.notification( + template: 'signup', + user: user, + objects: { + token: token, + user: user, + } ) end user_new = User.find(user.id) @@ -434,12 +416,20 @@ curl http://localhost/api/v1/users/password_reset.json -v -u #{login}:#{password return end - token = User.password_reset_send(params[:username]) - if token + result = User.password_reset_new_token(params[:username]) + if result && result[:token] + + # send mail + user = result[:user] + NotificationFactory.notification( + template: 'password_reset', + user: user, + objects: result + ) # only if system is in develop mode, send token back to browser for browser tests if Setting.get('developer_mode') == true - render json: { message: 'ok', token: token.name }, status: :ok + render json: { message: 'ok', token: result[:token].name }, status: :ok return end @@ -485,6 +475,19 @@ curl http://localhost/api/v1/users/password_reset_verify.json -v -u #{login}:#{p # set new password with token user = User.password_reset_via_token(params[:token], params[:password]) + + # send mail + if user + NotificationFactory.notification( + template: 'password_change', + user: user, + objects: { + user: user, + current_user: current_user, + } + ) + end + else user = User.password_reset_check(params[:token]) end @@ -543,6 +546,16 @@ curl http://localhost/api/v1/users/password_change.json -v -u #{login}:#{passwor end user.update_attributes(password: params[:password_new]) + + NotificationFactory.notification( + template: 'password_change', + user: user, + objects: { + user: user, + current_user: current_user, + } + ) + render json: { message: 'ok', user_login: user.login }, status: :ok end diff --git a/app/models/channel/driver/mail_stdin.rb b/app/models/channel/driver/mail_stdin.rb index 3f6397048..dda2b95cb 100644 --- a/app/models/channel/driver/mail_stdin.rb +++ b/app/models/channel/driver/mail_stdin.rb @@ -10,7 +10,7 @@ process emails from STDIN e. g. -cat test/fixtures/mail1.box | rails r 'Channel::Driver::MailStdin.new' + cat test/fixtures/mail1.box | rails r 'Channel::Driver::MailStdin.new' =end diff --git a/app/models/observer/ticket/notification/background_job.rb b/app/models/observer/ticket/notification/background_job.rb index 3b44f4b64..029610c89 100644 --- a/app/models/observer/ticket/notification/background_job.rb +++ b/app/models/observer/ticket/notification/background_job.rb @@ -133,7 +133,7 @@ class Observer::Ticket::Notification::BackgroundJob created_by_id: ticket.updated_by_id || 1, user_id: user.id, ) - Rails.logger.info "send ticket online notifiaction to agent (#{@p[:type]}/#{ticket.id}/#{user.email})" + Rails.logger.debug "sent ticket online notifiaction to agent (#{@p[:type]}/#{ticket.id}/#{user.email})" end # ignore email channel notificaiton and empty emails @@ -147,39 +147,26 @@ class Observer::Ticket::Notification::BackgroundJob # get user based notification template # if create, send create message / block update messages + template = nil if @p[:type] == 'create' - template = template_create(user, ticket, article, changes) + template = 'ticket_create' elsif @p[:type] == 'update' - template = template_update(user, ticket, article, changes) + template = 'ticket_update' else fail "unknown type for notification #{@p[:type]}" end - # prepare subject & body - notification = {} - [:subject, :body].each { |key| - notification[key.to_sym] = NotificationFactory.build( - locale: user.preferences[:locale], - string: template[key], - objects: { - ticket: ticket, - article: article, - recipient: user, - } - ) - } - - # rebuild subject - notification[:subject] = ticket.subject_build(notification[:subject]) - - Rails.logger.info "send ticket email notifiaction to agent (#{@p[:type]}/#{ticket.id}/#{user.email})" - - NotificationFactory.send( - recipient: user, - subject: notification[:subject], - body: notification[:body], - content_type: 'text/html', + NotificationFactory.notification( + template: template, + user: user, + objects: { + ticket: ticket, + article: article, + recipient: user, + changes: changes, + } ) + Rails.logger.debug "sent ticket email notifiaction to agent (#{@p[:type]}/#{ticket.id}/#{user.email})" end end @@ -203,6 +190,7 @@ class Observer::Ticket::Notification::BackgroundJob def human_changes(user, record) return {} if !@p[:changes] + locale = user.preferences[:locale] || 'en-us' # only show allowed attributes attribute_list = ObjectManager::Attribute.by_object_as_hash('Ticket', user) @@ -278,7 +266,9 @@ class Observer::Ticket::Notification::BackgroundJob display = object_manager_attribute[:display].to_s end changes[display] = if object_manager_attribute && object_manager_attribute[:translate] - ["i18n(#{value_str[0]})", "i18n(#{value_str[1]})"] + from = Translation.translate(locale, value_str[0]) + to = Translation.translate(locale, value_str[1]) + [from, to] else [value_str[0].to_s, value_str[1].to_s] end @@ -286,176 +276,4 @@ class Observer::Ticket::Notification::BackgroundJob changes end - def template_create(user, ticket, article, _ticket_changes) - article_content = '' - if article - article_content = 'i18n(Information): -
-#{article.body.text2html} -
-
-
' - end - - if user.preferences[:locale] =~ /^de/i - subject = 'Neues Ticket (#{ticket.title})' - body = '
Hallo #{recipient.firstname.text2html},
-
-
-es wurde ein neues Ticket (#{ticket.title.text2html}) von "#{ticket.updated_by.fullname.text2html}" erstellt. -
-
-
-i18n(Group): #{ticket.group.name.text2html}
-i18n(Owner): #{ticket.owner.fullname.text2html}
-i18n(State): i18n(#{ticket.state.name.text2html})
-
-
-
-' + article_content + ' -
-' - else - - subject = 'New Ticket (#{ticket.title})' - body = '
Hi #{recipient.firstname.text2html},
-
-
-a new Ticket (#{ticket.title.text2html}) has been created by "#{ticket.updated_by.fullname.text2html}". -
-
-
-Group: #{ticket.group.name.text2html}
-Owner: #{ticket.owner.fullname.text2html}
-State: i18n(#{ticket.state.name.text2html})
-
-
-
-' + article_content + ' -
-' - - end - - body = template_header(user) + body - body += template_footer(user, ticket, article) - - template = { - subject: subject, - body: body, - } - template - end - - def template_update(user, ticket, article, ticket_changes) - changes = '' - ticket_changes.each {|key, value| - changes += "i18n(#{key.to_s.text2html}): #{value[0].to_s.text2html} -> #{value[1].to_s.text2html}
\n" - } - article_content = '' - if article - article_content = 'i18n(Information): -
-#{article.body.text2html} -
-
-
' - end - if user.preferences[:locale] =~ /^de/i - subject = 'Ticket aktualisiert (#{ticket.title})' - body = '
Hallo #{recipient.firstname.text2html},
-
-
-Ticket (#{ticket.title.text2html}) wurde von "#{ticket.updated_by.fullname.text2html}" aktualisiert. -
-
-
-i18n(Changes):
-' + changes + ' -
-
-
-' + article_content + ' -
-' - else - subject = 'Updated Ticket (#{ticket.title})' - body = '
Hi #{recipient.firstname.text2html},
-
-
-Ticket (#{ticket.title.text2html}) has been updated by "#{ticket.updated_by.fullname.text2html}". -
-
-
-i18n(Changes):
-' + changes + ' -
-
-
-' + article_content + ' -
-' - end - - body = template_header(user) + body - body += template_footer(user, ticket, article) - - template = { - subject: subject, - body: body, - } - template - end - - def template_header(_user) - ' - - -
- #{config.product_name} i18n(Notification) -
-' - end - - def template_footer(_user, _ticket, _article) - ' -

- i18n(View this in Zammad) -

- -' - end end diff --git a/app/models/user.rb b/app/models/user.rb index 5b49f7017..540ac04d2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -283,17 +283,20 @@ returns =begin -send reset password email with token to user +generate new token for reset password - result = User.password_reset_send(username) + result = User.password_reset_new_token(username) returns - result = token + result = { + token: token, + user: user, + } =end - def self.password_reset_send(username) + def self.password_reset_new_token(username) return if !username || username == '' # try to find user based on login @@ -311,42 +314,10 @@ returns # generate token token = Token.create(action: 'PasswordReset', user_id: user.id) - # send mail - data = {} - data[:subject] = 'Reset your #{config.product_name} password' - data[:body] = 'Forgot your password? - -We received a request to reset the password for your #{config.product_name} account (#{user.login}). - -If you want to reset your password, click on the link below (or copy and paste the URL into your browser): - -#{config.http_type}://#{config.fqdn}/#password_reset_verify/#{token.name} - -This link takes you to a page where you can change your password. - -If you don\'t want to reset your password, please ignore this message. Your password will not be reset. - -Your #{config.product_name} Team' - - # prepare subject & body - [:subject, :body].each { |key| - data[key.to_sym] = NotificationFactory.build( - locale: user.preferences[:locale], - string: data[key.to_sym], - objects: { - token: token, - user: user, - } - ) + { + token: token, + user: user, } - - # send notification - NotificationFactory.send( - recipient: user, - subject: data[:subject], - body: data[:body] - ) - token end =begin diff --git a/app/models/user_device.rb b/app/models/user_device.rb index ce5976bd9..2db2d5def 100644 --- a/app/models/user_device.rb +++ b/app/models/user_device.rb @@ -154,41 +154,13 @@ send new user device info def send_notification user = User.find(user_id) - # send mail - data = {} - data[:subject] = '#{config.product_name} signin detected from a new device' - data[:body] = 'Hi #{user.firstname}, - -it looks like you signed into your #{config.product_name} account using a new device on "#{user_device.created_at}": - -Your Location: #{user_device.location} -Your IP: #{user_device.ip} - -Your device has been added to your list of known devices, which you can view here: - -#{config.http_type}://#{config.fqdn}/#profile/devices - -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. - -Your #{config.product_name} Team' - - # prepare subject & body - [:subject, :body].each { |key| - data[key.to_sym] = NotificationFactory.build( - locale: user.preferences[:locale], - string: data[key.to_sym], - objects: { - user_device: self, - user: user, - } - ) - } - - # send notification - NotificationFactory.send( - recipient: user, - subject: data[:subject], - body: data[:body] + NotificationFactory.notification( + template: 'user_device', + user: user, + objects: { + user_device: self, + user: user, + } ) end end diff --git a/app/views/mailer/application.html.erb b/app/views/mailer/application.html.erb new file mode 100644 index 000000000..3c5d5d262 --- /dev/null +++ b/app/views/mailer/application.html.erb @@ -0,0 +1,42 @@ + + +
+ <%= c 'product_name' %> <%= t 'Notification' %> +
+ +<%= d 'message', false %> + + \ No newline at end of file diff --git a/app/views/mailer/password_change/de.html.erb b/app/views/mailer/password_change/de.html.erb new file mode 100644 index 000000000..be69b2778 --- /dev/null +++ b/app/views/mailer/password_change/de.html.erb @@ -0,0 +1,9 @@ +Dein <%= c 'product_name' %> Passwort wurde geändert + +

Hallo <%= d 'user.firstname' %>,

+
+

das Passwort für Dein <%= c 'product_name' %> Account <%= d 'user.login' %> wurde kürzlich geändert.

+
+

Diese Aktivität ist Dir nicht bekannt? In diesen Fall kontaktiere Deinen System-Administrator.

+
+

Dein <%= c 'product_name' %> Team

diff --git a/app/views/mailer/password_change/en.html.erb b/app/views/mailer/password_change/en.html.erb new file mode 100644 index 000000000..f48793398 --- /dev/null +++ b/app/views/mailer/password_change/en.html.erb @@ -0,0 +1,9 @@ +Your <%= c 'product_name' %> password has been changed + +

Hi <%= d 'user.firstname' %>,

+
+

the password for your <%= c 'product_name' %> account <%= d 'user.login' %> has been changed recently.

+
+

This activity is not known to you? If not, contact your system administrator.

+
+

Your <%= c 'product_name' %> Team

diff --git a/app/views/mailer/password_reset/de.html.erb b/app/views/mailer/password_reset/de.html.erb new file mode 100644 index 000000000..be18e9d3c --- /dev/null +++ b/app/views/mailer/password_reset/de.html.erb @@ -0,0 +1,17 @@ +Zurücksetzen Deines <%= c 'product_name' %> Passworts + +

+Hallo <%= d 'user.firstname' %>, +

+
+

wir haben eine Anfrage zum Zurücksetzen des Passworts für <%= c 'product_name' %> Account <%= d 'user.login' %> erhalten.

+
+

Wenn Sie Ihr Passwort zurückzusetzen wollen, klicken Sie auf den unten stehenden Link (oder kopieren Sie die URL in den Browser einfügen):

+
+

<%= c 'http_type' %>://<%= c 'fqdn' %>/#password_reset_verify/<%= d 'token.name' %>

+
+

Dieser Link führt Sie zu einer Seite, auf der Sie Ihr Passwort ändern können.

+
+

Wenn Sie Ihr Passwort nicht zurücksetzen wollen, ignorieren Sie diese Meldung. Das Passwort bleibt unverändert.

+
+

Dein <%= c 'product_name' %> Team

diff --git a/app/views/mailer/password_reset/en.html.erb b/app/views/mailer/password_reset/en.html.erb new file mode 100644 index 000000000..33dbecf6b --- /dev/null +++ b/app/views/mailer/password_reset/en.html.erb @@ -0,0 +1,15 @@ +Reset your <%= c 'product_name' %> password + +

Hi <%= d 'user.firstname' %>,

+
+

We received a request to reset the password for your <%= c 'product_name' %> account <%= d 'user.login' %>.

+
+

If you want to reset your password, click on the link below (or copy and paste the URL into your browser):

+
+

<%= c 'http_type' %>://<%= c 'fqdn' %>/#password_reset_verify/<%= d 'token.name' %>

+
+

This link takes you to a page where you can change your password.

+
+

If you don't want to reset your password, please ignore this message. Your password will not be reset.

+
+

Your <%= c 'product_name' %> Team

diff --git a/app/views/mailer/signup/de.html.erb b/app/views/mailer/signup/de.html.erb new file mode 100644 index 000000000..39054ac01 --- /dev/null +++ b/app/views/mailer/signup/de.html.erb @@ -0,0 +1,9 @@ +Bestätigung des <%= c 'product_name' %> Accounts, <%= d 'user.firstname' %> <%= d 'user.lastname' %> + +

Hallo <%= d 'user.firstname' %>,

+
+

bestätige Deine E-Mail-Adresse um Deine Registrierung bei <%= c 'product_name' %> abzuschließen. Es ist einfach - klick einfach auf den Link unten.

+
+

<%= c 'http_type' %>://<%= c 'fqdn' %>/#email_verify/<%= d 'token.name' %>

+
+

Dein <%= c 'product_name' %> Team

diff --git a/app/views/mailer/signup/en.html.erb b/app/views/mailer/signup/en.html.erb new file mode 100644 index 000000000..f0818eb3a --- /dev/null +++ b/app/views/mailer/signup/en.html.erb @@ -0,0 +1,9 @@ +Confirm your <%= c 'product_name' %> account, <%= d 'user.firstname' %> <%= d 'user.lastname' %> + +

Hi <%= d 'user.firstname' %>,

+
+

confirm your email address to complete your <%= c 'product_name' %> account. It's easy, just click the link below.

+
+

<%= c 'http_type' %>://<%= c 'fqdn' %>/#email_verify/<%= d 'token.name' %>

+
+

Your <%= c 'product_name' %> Team

diff --git a/app/views/mailer/ticket_create/de.html.erb b/app/views/mailer/ticket_create/de.html.erb new file mode 100644 index 000000000..5d5c07a02 --- /dev/null +++ b/app/views/mailer/ticket_create/de.html.erb @@ -0,0 +1,24 @@ +Neues Ticket (<%= d 'ticket.title' %>) + +

Hallo <%= d 'recipient.firstname' %>,

+
+

es wurde ein neues Ticket (<%= d 'ticket.title' %>) von "<%= d 'ticket.updated_by.fullname' %>" erstellt.

+
+

+<%= t 'Group' %>: <%= d 'ticket.group.name' %>
+<%= t 'Owner' %>: <%= d 'ticket.owner.fullname' %>
+<%= t 'State' %>: <%= t d 'ticket.state.name' %>
+

+
+<% if @objects[:article] %> +

+ <%= t 'Information' %>: +

+ <%= d('article.body').text2html %> +
+

+<% end %> +
+

+ <%= t 'View this in Zammad' %> +

diff --git a/app/views/mailer/ticket_create/en.html.erb b/app/views/mailer/ticket_create/en.html.erb new file mode 100644 index 000000000..78dda990c --- /dev/null +++ b/app/views/mailer/ticket_create/en.html.erb @@ -0,0 +1,24 @@ +New Ticket (<%= d 'ticket.title' %>) + +

Hi <%= d 'recipient.firstname' %>,

+
+

a new Ticket (<%= d 'ticket.title' %>) has been created by "<%= d 'ticket.updated_by.fullname' %>".

+
+

+<%= t 'Group' %>: <%= d 'ticket.group.name' %>
+<%= t 'Owner' %>: <%= d 'ticket.owner.fullname' %>
+<%= t 'State' %>: <%= t d 'ticket.state.name' %>
+

+
+<% if @objects[:article] %> +

+ <%= t 'Information' %>: +

+ <%= d('article.body').text2html %> +
+

+<% end %> +
+

+ <%= t 'View this in Zammad' %> +

diff --git a/app/views/mailer/ticket_update/de.html.erb b/app/views/mailer/ticket_update/de.html.erb new file mode 100644 index 000000000..e1ded5b70 --- /dev/null +++ b/app/views/mailer/ticket_update/de.html.erb @@ -0,0 +1,29 @@ +Ticket aktualisiert (<%= d 'ticket.title' %>) + +

Hi <%= d 'recipient.firstname' %>,

+
+
+Ticket (<%= d 'ticket.title' %>) wurde von "<%= d 'ticket.updated_by.fullname' %>" aktualisiert. +
+
+<% if @objects[:changes] && !@objects[:changes].empty? %> +

+ <%= t 'Changes' %>:
+ <% @objects[:changes].each do |key, value| %> + <%= t key %>: <%= h value[0] %> -> <%= h value[1] %>
+ <% end %> +

+<% end %> +
+<% if @objects[:article] %> +

+ <%= t 'Information' %>: +

+ <%= a 'article' %> +
+

+<% end %> +
+

+ <%= t 'View this in Zammad' %> +

diff --git a/app/views/mailer/ticket_update/en.html.erb b/app/views/mailer/ticket_update/en.html.erb new file mode 100644 index 000000000..e8ac7cd50 --- /dev/null +++ b/app/views/mailer/ticket_update/en.html.erb @@ -0,0 +1,29 @@ +Updated Ticket (<%= d 'ticket.title' %>) + +

Hi <%= d 'recipient.firstname' %>,

+
+
+Ticket (<%= d 'ticket.title' %>) has been updated by "<%= d 'ticket.updated_by.fullname' %>". +
+
+<% if @objects[:changes] && !@objects[:changes].empty? %> +

+ <%= t 'Changes' %>:
+ <% @objects[:changes].each do |key, value| %> + <%= t key %>: <%= h value[0] %> -> <%= h value[1] %>
+ <% end %> +

+<% end %> +
+<% if @objects[:article] %> +

+ <%= t 'Information' %>: +

+ <%= d('article.body').text2html %> +
+

+<% end %> +
+

+ <%= t 'View this in Zammad' %> +

diff --git a/app/views/mailer/user_device/de.html.erb b/app/views/mailer/user_device/de.html.erb new file mode 100644 index 000000000..254f1c610 --- /dev/null +++ b/app/views/mailer/user_device/de.html.erb @@ -0,0 +1,18 @@ +<%= c 'product_name' %>-Anmeldung erfasst von einem neuen Gerät + +

Hallo <%= d 'user.firstname' %>,

+
+

es sieht aus, als ob Du Dich bei <%= c 'product_name' %> mit einem neuen Gerät um "<%= d 'user_device.created_at' %>" angemeldet hast:

+
+

+Deine Lokation (relativ): <%= d 'user_device.location' %>
+Deine IP: <%= d 'user_device.ip' %>
+
+

Das Gerät wurde in die Liste der bekannten Geräte hinzugefügt, diese Liste kannst Du hier einsehen:

+
+

<%= c 'http_type' %>://<%= c 'fqdn' %>/#profile/devices

+
+

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.

+
+

Dein <%= c 'product_name' %> Team

diff --git a/app/views/mailer/user_device/en.html.erb b/app/views/mailer/user_device/en.html.erb new file mode 100644 index 000000000..57a33213b --- /dev/null +++ b/app/views/mailer/user_device/en.html.erb @@ -0,0 +1,18 @@ +<%= c 'product_name' %> signin detected from a new device + +

Hi <%= d 'user.firstname' %>,

+
+

it looks like you signed into your <%= c 'product_name' %> account using a new device on "<%= d 'user_device.created_at' %>":

+
+

+Your Location: <%= d 'user_device.location' %>
+Your IP: <%= d 'user_device.ip' %>
+
+

Your device has been added to your list of known devices, which you can view here:

+
+

<%= c 'http_type' %>://<%= c 'fqdn' %>/#profile/devices

+
+

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.

+
+

Your <%= c 'product_name' %> Team

diff --git a/app/views/mailer/user_invite/de.html.erb b/app/views/mailer/user_invite/de.html.erb new file mode 100644 index 000000000..c9f39e4e4 --- /dev/null +++ b/app/views/mailer/user_invite/de.html.erb @@ -0,0 +1,13 @@ +Einladung zu <%= c 'product_name' %> über <%= c 'fqdn' %> + +

Hallo <%= d 'user.firstname' %>,

+
+

Ich (<%= d 'current_user.firstname' %> <%= d 'current_user.lastname' %>) möchte Dich zu <%= c 'product_name' %> einladen - unsere Kundensupport / Ticket System Platform.

+
+

Um sich anzumelden kann hier das Password gesetzt werden.

+
+

Enjoy,

+
+

<%= d 'current_user.firstname' %> <%= d 'current_user.lastname' %>

+
+

Dein <%= c 'product_name' %> Team

diff --git a/app/views/mailer/user_invite/en.html.erb b/app/views/mailer/user_invite/en.html.erb new file mode 100644 index 000000000..54a09d366 --- /dev/null +++ b/app/views/mailer/user_invite/en.html.erb @@ -0,0 +1,13 @@ +Invitation to <%= c 'product_name' %> at <%= c 'fqdn' %> + +

Hi <%= d 'user.firstname' %>,

+
+

I (<%= d 'current_user.firstname' %> <%= d 'current_user.lastname' %>) invite you to <%= c 'product_name' %> - our customer support / ticket system platform.

+
+

Click here and set your password.

+
+

Enjoy,

+
+

<%= d 'current_user.firstname' %> <%= d 'current_user.lastname' %>

+
+

Your <%= c 'product_name' %> Team

diff --git a/lib/notification_factory.rb b/lib/notification_factory.rb index e393330bb..8db5e1540 100644 --- a/lib/notification_factory.rb +++ b/lib/notification_factory.rb @@ -2,6 +2,8 @@ module NotificationFactory =begin +# deprecated, will be removed with 2.0 + result_string = NotificationFactory.build( string: 'Hi #{recipient.firstname},', objects: { @@ -125,4 +127,172 @@ module NotificationFactory true ) end + +=begin + + NotificationFactory.notification( + template: 'password_reset', + user: User.find(2), + objects: { + recipient: User.find(2), + }, + ) + +=end + + def self.notification(data) + + # get subject + result = NotificationFactory.template( + template: data[:template], + locale: data[:user].preferences[:locale], + objects: data[:objects], + ) + + NotificationFactory.send( + recipient: data[:user], + subject: result[:subject], + body: result[:body], + content_type: 'text/html', + ) + end + +=begin + + result = NotificationFactory.template( + template: 'password_reset', + locale: 'en-us', + objects: { + recipient: User.find(2), + }, + ) + + result = NotificationFactory.template( + templateInline: "Invitation to <%= c 'product_name' %> at <%= c 'fqdn' %>", + locale: 'en-us', + objects: { + recipient: User.find(2), + }, + ) + +=end + + def self.template(data) + + if data[:templateInline] + return NotificationFactory::Template.new(data[:objects], data[:locale], data[:templateInline], false).render + end + + template_subject = nil + template_body = '' + locale = data[:locale] || 'en' + template = data[:template] + location = "app/views/mailer/#{template}/#{locale}.html.erb" + + # as fallback, use 2 char locale + if !File.exist?(location) + locale = locale[0, 2] + location = "app/views/mailer/#{template}/#{locale}.html.erb" + end + + # as fallback, use en + if !File.exist?(location) + location = "app/views/mailer/#{template}/en.html.erb" + end + + File.open(location, 'r:UTF-8').each do |line| + if !template_subject + template_subject = line + next + end + template_body += line + end + + message_subject = NotificationFactory::Template.new(data[:objects], data[:locale], template_subject, false).render + message_body = NotificationFactory::Template.new(data[:objects], data[:locale], template_body).render + + application_template = nil + File.open('app/views/mailer/application.html.erb', 'r:UTF-8') do |file| + application_template = file.read + end + data[:objects][:message] = message_body + message_body = NotificationFactory::Template.new(data[:objects], data[:locale], application_template).render + { + subject: message_subject, + body: message_body, + } + end + + class Template + + def initialize(objects, locale, template, escape = true) + @objects = objects + @locale = locale || 'en-us' + @template = template + @escape = escape + end + + def render + ERB.new(@template).result(binding) + end + + def d(key, escape = nil) + + # do validaton, ignore some methodes + if key =~ /(`|\.(|\s*)(save|destroy|delete|remove|drop|update\(|update_att|create\(|new|all|where|find))/i + return "#{key} (not allowed)" + end + + value = nil + object_methods = key.split('.') + object_name = object_methods.shift.to_sym + object_refs = @objects[object_name] + object_methods_s = '' + object_methods.each {|method| + if object_methods_s != '' + object_methods_s += '.' + end + object_methods_s += method + + # if method exists + if !object_refs.respond_to?( method.to_sym ) + value = "\#{#{object_name}.#{object_methods_s} / no such method}" + break + end + object_refs = object_refs.send( method.to_sym ) + } + placeholder = if !value + object_refs + else + value + end + return placeholder if escape == false || (escape.nil? && !@escape) + h placeholder + end + + def c(key, escape = nil) + config = Setting.get(key) + return config if escape == false || (escape.nil? && !@escape) + h config + end + + def t(key, escape = nil) + translation = Translation.translate(@locale, key) + return translation if escape == false || (escape.nil? && !@escape) + h translation + end + + def a(article) + content_type = d "#{article}.content_type", false + if content_type =~ /html/ + return d "#{article}.body", false + end + d("#{article}.content_type", false).text2html + end + + def h(key) + return key if !key + CGI.escapeHTML(key.to_s) + end + end end diff --git a/lib/static_assets.rb b/lib/static_assets.rb index 2ce877a28..722b27de1 100644 --- a/lib/static_assets.rb +++ b/lib/static_assets.rb @@ -122,7 +122,7 @@ returns # store hash in config if list && list[0] - file = Store.find(list[0]) + file = Store.find(list[0].id) filelocation = filename(file) Setting.set('product_logo', filelocation) return file diff --git a/test/unit/notification_factory_test.rb b/test/unit/notification_factory_test.rb index cc695ea34..b6c03e5a3 100644 --- a/test/unit/notification_factory_test.rb +++ b/test/unit/notification_factory_test.rb @@ -296,4 +296,139 @@ next line, Group: Users', ticket.destroy end + + test 'notifications template' do + groups = Group.where(name: 'Users') + roles = Role.where(name: 'Agent') + agent1 = User.create_or_update( + login: 'notification-template-agent1@example.com', + firstname: 'Notificationxxx', + lastname: 'Agent1yyy', + email: 'notification-template-agent1@example.com', + password: 'agentpw', + active: true, + roles: roles, + groups: groups, + preferences: { + locale: 'de-de', + }, + updated_by_id: 1, + created_by_id: 1, + ) + + result = NotificationFactory.template( + template: 'password_reset', + locale: 'de-de', + objects: { + user: agent1, + }, + ) + assert_match('Zurücksetzen Deines', result[:subject]) + assert_match('wir haben eine Anfrage zum Zurücksetzen', result[:body]) + assert_match('Dein', result[:body]) + assert_match('Dein', result[:body]) + assert_match('Notification<b>xxx</b>', result[:body]) + assert_no_match('Your', result[:body]) + + result = NotificationFactory.template( + template: 'password_reset', + locale: 'de', + objects: { + user: agent1, + }, + ) + assert_match('Zurücksetzen Deines', result[:subject]) + assert_match('wir haben eine Anfrage zum Zurücksetzen', result[:body]) + assert_match('Dein', result[:body]) + assert_match('Notification<b>xxx</b>', result[:body]) + assert_no_match('Your', result[:body]) + + result = NotificationFactory.template( + template: 'password_reset', + locale: 'es-us', + objects: { + user: agent1, + }, + ) + assert_match('Reset your', result[:subject]) + assert_match('We received a request to reset the password', result[:body]) + assert_match('Your', result[:body]) + assert_match('Notification<b>xxx</b>', result[:body]) + assert_no_match('Dein', result[:body]) + + ticket = Ticket.first + article = ticket.articles.first + changes = {} + result = NotificationFactory.template( + template: 'ticket_create', + locale: 'es-us', + objects: { + ticket: ticket, + article: article, + recipient: agent1, + changes: changes, + }, + ) + assert_match('New Ticket', result[:subject]) + assert_match('Notification<b>xxx</b>', result[:body]) + assert_match('has been created by', result[:body]) + assert_match('Manage your notifications settings', result[:body]) + assert_no_match('Dein', result[:body]) + + result = NotificationFactory.template( + template: 'ticket_create', + locale: 'de-de', + objects: { + ticket: ticket, + article: article, + recipient: agent1, + changes: changes, + }, + ) + assert_match('Neues Ticket', result[:subject]) + assert_match('Notification<b>xxx</b>', result[:body]) + assert_match('es wurde ein neues Ticket', result[:body]) + assert_match('Manage your notifications settings', result[:body]) + assert_no_match('Your', result[:body]) + + ticket = Ticket.first + article = ticket.articles.first + changes = { + state: %w(aaa bbb), + group: %w(xxx yyy), + } + result = NotificationFactory.template( + template: 'ticket_update', + locale: 'es-us', + objects: { + ticket: ticket, + article: article, + recipient: agent1, + changes: changes, + }, + ) + assert_match('Updated Ticket', result[:subject]) + assert_match('Notification<b>xxx</b>', result[:body]) + assert_match('has been updated by', result[:body]) + assert_match('Manage your notifications settings', result[:body]) + assert_no_match('Dein', result[:body]) + + result = NotificationFactory.template( + template: 'ticket_update', + locale: 'de-de', + objects: { + ticket: ticket, + article: article, + recipient: agent1, + changes: changes, + }, + ) + assert_match('Ticket aktualisiert', result[:subject]) + assert_match('Notification<b>xxx</b>', result[:body]) + assert_match('wurde von', result[:body]) + assert_match('Manage your notifications settings', result[:body]) + assert_no_match('Your', result[:body]) + + end + end diff --git a/test/unit/ticket_notification_test.rb b/test/unit/ticket_notification_test.rb index 4eb878893..5f0885bac 100644 --- a/test/unit/ticket_notification_test.rb +++ b/test/unit/ticket_notification_test.rb @@ -927,129 +927,142 @@ class TicketNotificationTest < ActiveSupport::TestCase ) # check changed attributes - human_changes = bg.human_changes(agent1, ticket1) + human_changes = bg.human_changes(agent2, ticket1) assert( human_changes['Priority'], 'Check if attributes translated based on ObjectManager::Attribute' ) assert( human_changes['Pending till'], 'Check if attributes translated based on ObjectManager::Attribute' ) - assert_equal( 'i18n(1 low)', human_changes['Priority'][0] ) - assert_equal( 'i18n(2 normal)', human_changes['Priority'][1] ) - assert_equal( 'i18n()', human_changes['Pending till'][0] ) - assert_equal( 'i18n(2015-01-11 23:33:47 UTC)', human_changes['Pending till'][1] ) + assert_equal( '1 low', human_changes['Priority'][0] ) + assert_equal( '2 normal', human_changes['Priority'][1] ) + assert_equal( '', human_changes['Pending till'][0].to_s ) + assert_equal( '2015-01-11 23:33:47 UTC', human_changes['Pending till'][1].to_s ) assert_not( human_changes['priority_id'] ) assert_not( human_changes['pending_time'] ) assert_not( human_changes['pending_till'] ) - # en template - template = bg.template_update(agent2, ticket1, article, human_changes) - assert( template[:subject] ) - assert( template[:body] ) - assert_match( /Priority/, template[:body] ) - assert_match( /1 low/, template[:body] ) - assert_match( /2 normal/, template[:body] ) - assert_match( /Pending till/, template[:body] ) - assert_match( /2015-01-11 23:33:47 UTC/, template[:body] ) - assert_match( /updated/i, template[:subject] ) - # en notification - subject = NotificationFactory.build( + result = NotificationFactory.template( locale: agent2.preferences[:locale], - string: template[:subject], + template: 'ticket_update', objects: { ticket: ticket1, article: article, recipient: agent2, + changes: human_changes, } ) - assert_match( /Bobs's resumé/, subject ) - body = NotificationFactory.build( - locale: agent2.preferences[:locale], - string: template[:body], - objects: { - ticket: ticket1, - article: article, - recipient: agent2, - } - ) - assert_match(/Priority/, body) - assert_match(/1 low/, body) - assert_match(/2 normal/, body) - assert_match(/Pending till/, body) - assert_match(/2015-01-11 23:33:47 UTC/, body) - assert_match(/update/, body) - assert_no_match(/pending_till/, body) - assert_no_match(/i18n/, body) + assert_match(/Bobs's resumé/, result[:subject]) + assert_match(/Priority/, result[:body]) + assert_match(/1 low/, result[:body]) + assert_match(/2 normal/, result[:body]) + assert_match(/Pending till/, result[:body]) + assert_match(/2015-01-11 23:33:47 UTC/, result[:body]) + assert_match(/update/, result[:body]) + assert_no_match(/pending_till/, result[:body]) + assert_no_match(/i18n/, result[:body]) - # de template - template = bg.template_update(agent1, ticket1, article, human_changes) - assert(template[:subject]) - assert(template[:body]) - assert_match(/Priority/, template[:body]) - assert_match(/1 low/, template[:body]) - assert_match(/2 normal/, template[:body]) - assert_match(/Pending till/, template[:body]) - assert_match(/2015-01-11 23:33:47 UTC/, template[:body]) - assert_match(/aktualis/, template[:subject]) + human_changes = bg.human_changes(agent1, ticket1) + assert( human_changes['Priority'], 'Check if attributes translated based on ObjectManager::Attribute' ) + assert( human_changes['Pending till'], 'Check if attributes translated based on ObjectManager::Attribute' ) + assert_equal( '1 niedrig', human_changes['Priority'][0] ) + assert_equal( '2 normal', human_changes['Priority'][1] ) + assert_equal( '', human_changes['Pending till'][0].to_s ) + assert_equal( '2015-01-11 23:33:47 UTC', human_changes['Pending till'][1].to_s ) + assert_not( human_changes['priority_id'] ) + assert_not( human_changes['pending_time'] ) + assert_not( human_changes['pending_till'] ) # de notification - subject = NotificationFactory.build( + result = NotificationFactory.template( locale: agent1.preferences[:locale], - string: template[:subject], - objects: { - ticket: ticket1, - article: article, - recipient: agent2, - } - ) - assert_match(/Bobs's resumé/, subject) - body = NotificationFactory.build( - locale: agent1.preferences[:locale], - string: template[:body], + template: 'ticket_update', objects: { ticket: ticket1, article: article, recipient: agent1, + changes: human_changes, } ) - assert_match(/Priorität/, body) - assert_match(/1 niedrig/, body) - assert_match(/2 normal/, body) - assert_match(/Warten/, body) - assert_match(/2015-01-11 23:33:47 UTC/, body) - assert_match(/aktualis/, body) - assert_no_match(/pending_till/, body) - assert_no_match(/i18n/, body) + assert_match(/Bobs's resumé/, result[:subject]) + assert_match(/Priorität/, result[:body]) + assert_match(/1 niedrig/, result[:body]) + assert_match(/2 normal/, result[:body]) + assert_match(/Warten/, result[:body]) + assert_match(/2015-01-11 23:33:47 UTC/, result[:body]) + assert_match(/aktualis/, result[:body]) + assert_no_match(/pending_till/, result[:body]) + assert_no_match(/i18n/, result[:body]) bg = Observer::Ticket::Notification::BackgroundJob.new( ticket_id: ticket1.id, article_id: article.id, type: 'update', changes: { - title: ['some notification template test 1', 'some notification template test 1 #2'], + title: ['some notification template test old 1', 'some notification template test 1 #2'], priority_id: [2, 3], }, ) - #puts "hc #{human_changes.inspect}" # check changed attributes human_changes = bg.human_changes(agent1, ticket1) assert(human_changes['Title'], 'Check if attributes translated based on ObjectManager::Attribute') assert(human_changes['Priority'], 'Check if attributes translated based on ObjectManager::Attribute') - assert_equal('i18n(2 normal)', human_changes['Priority'][0]) - assert_equal('i18n(3 high)', human_changes['Priority'][1]) - assert_equal('some notification template test 1', human_changes['Title'][0]) + assert_equal('2 normal', human_changes['Priority'][0]) + assert_equal('3 hoch', human_changes['Priority'][1]) + assert_equal('some notification template test old 1', human_changes['Title'][0]) assert_equal('some notification template test 1 #2', human_changes['Title'][1]) assert_not(human_changes['priority_id']) assert_not(human_changes['pending_time']) assert_not(human_changes['pending_till']) + # de notification + result = NotificationFactory.template( + locale: agent1.preferences[:locale], + template: 'ticket_update', + objects: { + ticket: ticket1, + article: article, + recipient: agent1, + changes: human_changes, + } + ) + + assert_match(/Bobs's resumé/, result[:subject]) + assert_match(/Titel/, result[:body]) + assert_no_match(/Title/, result[:body]) + assert_match(/some notification template test old 1/, result[:body]) + assert_match(/some notification template test 1 #2/, result[:body]) + assert_match(/Priorität/, result[:body]) + assert_no_match(/Priority/, result[:body]) + assert_match(/3 hoch/, result[:body]) + assert_match(/2 normal/, result[:body]) + assert_match(/aktualisier/, result[:body]) + human_changes = bg.human_changes(agent2, ticket1) - #puts "hc2 #{human_changes.inspect}" - template = bg.template_update(agent1, ticket1, article, human_changes) - #puts "t1 #{template.inspect}" + # en notification + result = NotificationFactory.template( + locale: agent2.preferences[:locale], + template: 'ticket_update', + objects: { + ticket: ticket1, + article: article, + recipient: agent2, + changes: human_changes, + } + ) - template = bg.template_update(agent2, ticket1, article, human_changes) - #puts "t2 #{template.inspect}" + assert_match(/Bobs's resumé/, result[:subject]) + assert_match(/Title/, result[:body]) + assert_match(/some notification template test old 1/, result[:body]) + assert_match(/some notification template test 1 #2/, result[:body]) + assert_match(/Priority/, result[:body]) + assert_match(/3 high/, result[:body]) + assert_match(/2 normal/, result[:body]) + assert_no_match(/Pending till/, result[:body]) + assert_no_match(/2015-01-11 23:33:47 UTC/, result[:body]) + assert_match(/update/, result[:body]) + assert_no_match(/pending_till/, result[:body]) + assert_no_match(/i18n/, result[:body]) end