Feature #36162 » 0001-Add-notification-reason.patch
| app/models/issue.rb | ||
|---|---|---|
| 1120 | 1120 |
notified = notified.map {|n| n.is_a?(Group) ? n.users : n}.flatten
|
| 1121 | 1121 |
notified.uniq! |
| 1122 | 1122 |
notified = notified.select {|u| u.active? && u.notify_about?(self)}
|
| 1123 |
notified.map {|user| user.notification_reason = UserNotificationReason::INVOLVED}
|
|
| 1123 | 1124 | |
| 1124 | 1125 |
notified += project.notified_users |
| 1125 | 1126 |
notified += project.users.preload(:preference).select(&:notify_about_high_priority_issues?) if priority.high? |
| app/models/mailer.rb | ||
|---|---|---|
| 78 | 78 |
end |
| 79 | 79 | |
| 80 | 80 |
# Builds a mail for notifying user about a new issue |
| 81 |
def issue_add(user, issue) |
|
| 81 |
def issue_add(user, issue, reason = nil)
|
|
| 82 | 82 |
redmine_headers 'Project' => issue.project.identifier, |
| 83 | 83 |
'Issue-Tracker' => issue.tracker.name, |
| 84 | 84 |
'Issue-Id' => issue.id, |
| 85 | 85 |
'Issue-Author' => issue.author.login, |
| 86 | 86 |
'Issue-Assignee' => assignee_for_header(issue) |
| 87 | 87 |
redmine_headers 'Issue-Priority' => issue.priority.name if issue.priority |
| 88 |
redmine_headers 'Reason' => reason if reason |
|
| 88 | 89 |
message_id issue |
| 89 | 90 |
references issue |
| 90 | 91 |
@author = issue.author |
| 91 | 92 |
@issue = issue |
| 92 | 93 |
@user = user |
| 94 |
@reason = reason |
|
| 93 | 95 |
@issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue) |
| 94 | 96 |
subject = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]"
|
| 95 | 97 |
subject += " (#{issue.status.name})" if Setting.show_status_changes_in_mail_subject?
|
| ... | ... | |
| 103 | 105 |
# Example: |
| 104 | 106 |
# Mailer.deliver_issue_add(issue) |
| 105 | 107 |
def self.deliver_issue_add(issue) |
| 106 |
users = issue.notified_users | issue.notified_watchers | issue.notified_mentions |
|
| 108 |
users = issue.notified_users + issue.notified_watchers + issue.notified_mentions |
|
| 109 |
users = UserNotificationReason.reorder_by_priority(users) |
|
| 110 | ||
| 107 | 111 |
users.each do |user| |
| 108 |
issue_add(user, issue).deliver_later |
|
| 112 |
issue_add(user, issue, user.notification_reason).deliver_later
|
|
| 109 | 113 |
end |
| 110 | 114 |
end |
| 111 | 115 | |
| 112 | 116 |
# Builds a mail for notifying user about an issue update |
| 113 |
def issue_edit(user, journal) |
|
| 117 |
def issue_edit(user, journal, reason = nil)
|
|
| 114 | 118 |
issue = journal.journalized |
| 115 | 119 |
redmine_headers 'Project' => issue.project.identifier, |
| 116 | 120 |
'Issue-Tracker' => issue.tracker.name, |
| ... | ... | |
| 118 | 122 |
'Issue-Author' => issue.author.login, |
| 119 | 123 |
'Issue-Assignee' => assignee_for_header(issue) |
| 120 | 124 |
redmine_headers 'Issue-Priority' => issue.priority.name if issue.priority |
| 125 |
redmine_headers 'Reason' => reason if reason |
|
| 121 | 126 |
message_id journal |
| 122 | 127 |
references issue |
| 123 | 128 |
@author = journal.user |
| ... | ... | |
| 126 | 131 |
s += issue.subject |
| 127 | 132 |
@issue = issue |
| 128 | 133 |
@user = user |
| 134 |
@reason = reason |
|
| 129 | 135 |
@journal = journal |
| 130 | 136 |
@journal_details = journal.visible_details |
| 131 | 137 |
@issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
|
| ... | ... | |
| 139 | 145 |
# Example: |
| 140 | 146 |
# Mailer.deliver_issue_edit(journal) |
| 141 | 147 |
def self.deliver_issue_edit(journal) |
| 142 |
users = journal.notified_users | journal.notified_watchers | journal.notified_mentions | journal.journalized.notified_mentions |
|
| 148 |
users = journal.notified_users + journal.notified_mentions + journal.journalized.notified_mentions + journal.notified_watchers |
|
| 149 |
users = UserNotificationReason.reorder_by_priority(users) |
|
| 150 | ||
| 143 | 151 |
users.select! do |user| |
| 144 | 152 |
journal.notes? || journal.visible_details(user).any? |
| 145 | 153 |
end |
| 146 | 154 |
users.each do |user| |
| 147 |
issue_edit(user, journal).deliver_later |
|
| 155 |
issue_edit(user, journal, user.notification_reason).deliver_later
|
|
| 148 | 156 |
end |
| 149 | 157 |
end |
| 150 | 158 | |
| 151 | 159 |
# Builds a mail to user about a new document. |
| 152 |
def document_added(user, document, author) |
|
| 160 |
def document_added(user, document, author, reason = nil)
|
|
| 153 | 161 |
redmine_headers 'Project' => document.project.identifier |
| 162 |
redmine_headers 'Reason' => reason if reason |
|
| 154 | 163 |
@author = author |
| 155 | 164 |
@document = document |
| 156 | 165 |
@user = user |
| 166 |
@reason = reason |
|
| 157 | 167 |
@document_url = url_for(:controller => 'documents', :action => 'show', :id => document) |
| 158 | 168 |
mail :to => user, |
| 159 | 169 |
:subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
|
| ... | ... | |
| 166 | 176 |
def self.deliver_document_added(document, author) |
| 167 | 177 |
users = document.notified_users |
| 168 | 178 |
users.each do |user| |
| 169 |
document_added(user, document, author).deliver_later |
|
| 179 |
document_added(user, document, author, user.notification_reason).deliver_later
|
|
| 170 | 180 |
end |
| 171 | 181 |
end |
| 172 | 182 | |
| 173 | 183 |
# Builds a mail to user about new attachements. |
| 174 |
def attachments_added(user, attachments) |
|
| 184 |
def attachments_added(user, attachments, reason = nil)
|
|
| 175 | 185 |
container = attachments.first.container |
| 176 | 186 |
added_to = '' |
| 177 | 187 |
added_to_url = '' |
| ... | ... | |
| 188 | 198 |
added_to = "#{l(:label_document)}: #{container.title}"
|
| 189 | 199 |
end |
| 190 | 200 |
redmine_headers 'Project' => container.project.identifier |
| 201 |
redmine_headers 'Reason' => reason if reason |
|
| 191 | 202 |
@attachments = attachments |
| 192 | 203 |
@user = user |
| 204 |
@reason = reason |
|
| 193 | 205 |
@added_to = added_to |
| 194 | 206 |
@added_to_url = added_to_url |
| 195 | 207 |
mail :to => user, |
| ... | ... | |
| 210 | 222 |
end |
| 211 | 223 | |
| 212 | 224 |
users.each do |user| |
| 213 |
attachments_added(user, attachments).deliver_later |
|
| 225 |
attachments_added(user, attachments, user.notification_reason).deliver_later
|
|
| 214 | 226 |
end |
| 215 | 227 |
end |
| 216 | 228 | |
| 217 | 229 |
# Builds a mail to user about a new news. |
| 218 |
def news_added(user, news) |
|
| 230 |
def news_added(user, news, reason = nil)
|
|
| 219 | 231 |
redmine_headers 'Project' => news.project.identifier |
| 232 |
redmine_headers 'Reason' => reason if reason |
|
| 220 | 233 |
@author = news.author |
| 221 | 234 |
message_id news |
| 222 | 235 |
references news |
| 223 | 236 |
@news = news |
| 224 | 237 |
@user = user |
| 238 |
@reason = reason |
|
| 225 | 239 |
@news_url = url_for(:controller => 'news', :action => 'show', :id => news) |
| 226 | 240 |
mail :to => user, |
| 227 | 241 |
:subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
|
| ... | ... | |
| 232 | 246 |
# Example: |
| 233 | 247 |
# Mailer.deliver_news_added(news) |
| 234 | 248 |
def self.deliver_news_added(news) |
| 235 |
users = news.notified_users | news.notified_watchers_for_added_news |
|
| 249 |
users = news.notified_users + news.notified_watchers_for_added_news |
|
| 250 |
users = UserNotificationReason.reorder_by_priority(users) |
|
| 251 | ||
| 236 | 252 |
users.each do |user| |
| 237 |
news_added(user, news).deliver_later |
|
| 253 |
news_added(user, news, user.notification_reason).deliver_later
|
|
| 238 | 254 |
end |
| 239 | 255 |
end |
| 240 | 256 | |
| 241 | 257 |
# Builds a mail to user about a new news comment. |
| 242 |
def news_comment_added(user, comment) |
|
| 258 |
def news_comment_added(user, comment, reason = nil)
|
|
| 243 | 259 |
news = comment.commented |
| 244 | 260 |
redmine_headers 'Project' => news.project.identifier |
| 261 |
redmine_headers 'Reason' => reason if reason |
|
| 245 | 262 |
@author = comment.author |
| 246 | 263 |
message_id comment |
| 247 | 264 |
references news |
| 248 | 265 |
@news = news |
| 249 | 266 |
@comment = comment |
| 250 | 267 |
@user = user |
| 268 |
@reason = reason |
|
| 251 | 269 |
@news_url = url_for(:controller => 'news', :action => 'show', :id => news) |
| 252 | 270 |
mail :to => user, |
| 253 | 271 |
:subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
|
| ... | ... | |
| 259 | 277 |
# Mailer.deliver_news_comment_added(comment) |
| 260 | 278 |
def self.deliver_news_comment_added(comment) |
| 261 | 279 |
news = comment.commented |
| 262 |
users = news.notified_users | news.notified_watchers |
|
| 280 |
users = news.notified_users + news.notified_watchers |
|
| 281 |
users = UserNotificationReason.reorder_by_priority(users) |
|
| 282 | ||
| 263 | 283 |
users.each do |user| |
| 264 |
news_comment_added(user, comment).deliver_later |
|
| 284 |
news_comment_added(user, comment, user.notification_reason).deliver_later
|
|
| 265 | 285 |
end |
| 266 | 286 |
end |
| 267 | 287 | |
| 268 | 288 |
# Builds a mail to user about a new message. |
| 269 |
def message_posted(user, message) |
|
| 289 |
def message_posted(user, message, reason = nil)
|
|
| 270 | 290 |
redmine_headers 'Project' => message.project.identifier, |
| 271 | 291 |
'Topic-Id' => (message.parent_id || message.id) |
| 292 |
redmine_headers 'Reason' => reason if reason |
|
| 272 | 293 |
@author = message.author |
| 273 | 294 |
message_id message |
| 274 | 295 |
references message.root |
| 275 | 296 |
@message = message |
| 276 | 297 |
@user = user |
| 298 |
@reason = reason |
|
| 277 | 299 |
@message_url = url_for(message.event_url) |
| 278 | 300 |
mail :to => user, |
| 279 | 301 |
:subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
|
| ... | ... | |
| 285 | 307 |
# Mailer.deliver_message_posted(message) |
| 286 | 308 |
def self.deliver_message_posted(message) |
| 287 | 309 |
users = message.notified_users |
| 288 |
users |= message.root.notified_watchers |
|
| 289 |
users |= message.board.notified_watchers |
|
| 310 |
users += message.root.notified_watchers |
|
| 311 |
users += message.board.notified_watchers |
|
| 312 |
users = UserNotificationReason.reorder_by_priority(users) |
|
| 290 | 313 | |
| 291 | 314 |
users.each do |user| |
| 292 |
message_posted(user, message).deliver_later |
|
| 315 |
message_posted(user, message, user.notification_reason).deliver_later
|
|
| 293 | 316 |
end |
| 294 | 317 |
end |
| 295 | 318 | |
| 296 | 319 |
# Builds a mail to user about a new wiki content. |
| 297 |
def wiki_content_added(user, wiki_content) |
|
| 320 |
def wiki_content_added(user, wiki_content, reason = nil)
|
|
| 298 | 321 |
redmine_headers 'Project' => wiki_content.project.identifier, |
| 299 | 322 |
'Wiki-Page-Id' => wiki_content.page.id |
| 323 |
redmine_headers 'Reason' => reason if reason |
|
| 300 | 324 |
@author = wiki_content.author |
| 301 | 325 |
message_id wiki_content |
| 302 | 326 |
@wiki_content = wiki_content |
| 303 | 327 |
@user = user |
| 328 |
@reason = reason |
|
| 304 | 329 |
@wiki_content_url = url_for(:controller => 'wiki', :action => 'show', |
| 305 | 330 |
:project_id => wiki_content.project, |
| 306 | 331 |
:id => wiki_content.page.title) |
| ... | ... | |
| 316 | 341 |
# Example: |
| 317 | 342 |
# Mailer.deliver_wiki_content_added(wiki_content) |
| 318 | 343 |
def self.deliver_wiki_content_added(wiki_content) |
| 319 |
users = wiki_content.notified_users | wiki_content.page.wiki.notified_watchers | wiki_content.notified_mentions |
|
| 344 |
users = wiki_content.notified_users + wiki_content.page.wiki.notified_watchers + wiki_content.notified_mentions |
|
| 345 |
users = UserNotificationReason.reorder_by_priority(users) |
|
| 346 | ||
| 320 | 347 |
users.each do |user| |
| 321 |
wiki_content_added(user, wiki_content).deliver_later |
|
| 348 |
wiki_content_added(user, wiki_content, user.notification_reason).deliver_later
|
|
| 322 | 349 |
end |
| 323 | 350 |
end |
| 324 | 351 | |
| 325 | 352 |
# Builds a mail to user about an update of the specified wiki content. |
| 326 |
def wiki_content_updated(user, wiki_content) |
|
| 353 |
def wiki_content_updated(user, wiki_content, reason = nil)
|
|
| 327 | 354 |
redmine_headers 'Project' => wiki_content.project.identifier, |
| 328 | 355 |
'Wiki-Page-Id' => wiki_content.page.id |
| 356 |
redmine_headers 'Reason' => reason if reason |
|
| 329 | 357 |
@author = wiki_content.author |
| 330 | 358 |
message_id wiki_content |
| 331 | 359 |
@wiki_content = wiki_content |
| 332 | 360 |
@user = user |
| 361 |
@reason = reason |
|
| 333 | 362 |
@wiki_content_url = |
| 334 | 363 |
url_for(:controller => 'wiki', :action => 'show', |
| 335 | 364 |
:project_id => wiki_content.project, |
| ... | ... | |
| 351 | 380 |
# Mailer.deliver_wiki_content_updated(wiki_content) |
| 352 | 381 |
def self.deliver_wiki_content_updated(wiki_content) |
| 353 | 382 |
users = wiki_content.notified_users |
| 354 |
users |= wiki_content.page.notified_watchers |
|
| 355 |
users |= wiki_content.page.wiki.notified_watchers |
|
| 356 |
users |= wiki_content.notified_mentions |
|
| 383 |
users += wiki_content.page.notified_watchers |
|
| 384 |
users += wiki_content.page.wiki.notified_watchers |
|
| 385 |
users += wiki_content.notified_mentions |
|
| 386 |
users = UserNotificationReason.reorder_by_priority(users) |
|
| 357 | 387 | |
| 358 | 388 |
users.each do |user| |
| 359 |
wiki_content_updated(user, wiki_content).deliver_later |
|
| 389 |
wiki_content_updated(user, wiki_content, user.notification_reason).deliver_later
|
|
| 360 | 390 |
end |
| 361 | 391 |
end |
| 362 | 392 | |
| ... | ... | |
| 485 | 515 |
field: (options[:field] && l(options[:field])), |
| 486 | 516 |
value: options[:value]) |
| 487 | 517 |
@title = options[:title] && l(options[:title]) |
| 518 |
@reason = UserNotificationReason::ADMIN |
|
| 488 | 519 |
@remote_ip = options[:remote_ip] || @sender.remote_ip |
| 489 | 520 |
@url = options[:url] && (options[:url].is_a?(Hash) ? url_for(options[:url]) : options[:url]) |
| 490 | 521 |
redmine_headers 'Url' => @url |
| ... | ... | |
| 521 | 552 |
# Build a mail to user about application settings changes made by sender. |
| 522 | 553 |
def settings_updated(user, sender, changes, options={})
|
| 523 | 554 |
@sender = sender |
| 555 |
@reason = UserNotificationReason::ADMIN |
|
| 524 | 556 |
redmine_headers 'Sender' => sender.login |
| 525 | 557 |
@changes = changes |
| 526 | 558 |
@remote_ip = options[:remote_ip] || @sender.remote_ip |
| app/models/news.rb | ||
|---|---|---|
| 56 | 56 |
end |
| 57 | 57 | |
| 58 | 58 |
def notified_users |
| 59 |
project.users.select {|user| user.notify_about?(self) && user.allowed_to?(:view_news, project)}
|
|
| 59 |
users = project.users.select {|user| user.notify_about?(self) && user.allowed_to?(:view_news, project)}
|
|
| 60 |
users.map {|user| user.notification_reason = UserNotificationReason::SUBSCRIBED}
|
|
| 61 |
users |
|
| 60 | 62 |
end |
| 61 | 63 | |
| 62 | 64 |
def recipients |
| app/models/project.rb | ||
|---|---|---|
| 626 | 626 | |
| 627 | 627 |
# Returns the users that should be notified on project events |
| 628 | 628 |
def notified_users |
| 629 |
users.where('members.mail_notification = ? OR users.mail_notification = ?', true, 'all')
|
|
| 629 |
notified_users = users.where('members.mail_notification = ? OR users.mail_notification = ?', true, 'all')
|
|
| 630 |
notified_users.map {|user| user.notification_reason = UserNotificationReason::SUBSCRIBED}
|
|
| 631 |
notified_users |
|
| 630 | 632 |
end |
| 631 | 633 | |
| 632 | 634 |
# Returns a scope of all custom fields enabled for project issues |
| app/models/user.rb | ||
|---|---|---|
| 102 | 102 |
attr_accessor :password, :password_confirmation, :generate_password |
| 103 | 103 |
attr_accessor :last_before_login_on |
| 104 | 104 |
attr_accessor :remote_ip |
| 105 |
attr_accessor :notification_reason |
|
| 105 | 106 | |
| 106 | 107 |
LOGIN_LENGTH_LIMIT = 60 |
| 107 | 108 |
MAIL_LENGTH_LIMIT = 254 |
| app/models/user_notification_reason.rb | ||
|---|---|---|
| 1 |
# frozen_string_literal: true |
|
| 2 | ||
| 3 |
# Redmine - project management software |
|
| 4 |
# Copyright (C) 2006-2023 Jean-Philippe Lang |
|
| 5 |
# |
|
| 6 |
# This program is free software; you can redistribute it and/or |
|
| 7 |
# modify it under the terms of the GNU General Public License |
|
| 8 |
# as published by the Free Software Foundation; either version 2 |
|
| 9 |
# of the License, or (at your option) any later version. |
|
| 10 |
# |
|
| 11 |
# This program is distributed in the hope that it will be useful, |
|
| 12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 14 |
# GNU General Public License for more details. |
|
| 15 |
# |
|
| 16 |
# You should have received a copy of the GNU General Public License |
|
| 17 |
# along with this program; if not, write to the Free Software |
|
| 18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 19 | ||
| 20 |
class UserNotificationReason |
|
| 21 |
INVOLVED = 'involved' |
|
| 22 |
MENTIONED = 'mentioned' |
|
| 23 |
WATCHER = 'watcher' |
|
| 24 |
SUBSCRIBED = 'subscribed' |
|
| 25 |
ADMIN = 'admin' |
|
| 26 | ||
| 27 |
REASON_PRIORITY = [ |
|
| 28 |
INVOLVED, |
|
| 29 |
MENTIONED, |
|
| 30 |
WATCHER, |
|
| 31 |
SUBSCRIBED, |
|
| 32 |
ADMIN |
|
| 33 |
].freeze |
|
| 34 | ||
| 35 |
def self.reorder_by_priority(users) |
|
| 36 |
users = users.sort_by { |r| priority(r.notification_reason) }
|
|
| 37 |
users.uniq! |
|
| 38 |
users |
|
| 39 |
end |
|
| 40 | ||
| 41 |
def self.priority(reason) |
|
| 42 |
REASON_PRIORITY.index(reason) || REASON_PRIORITY.length + 1 |
|
| 43 |
end |
|
| 44 |
end |
|
| app/views/layouts/mailer.html.erb | ||
|---|---|---|
| 75 | 75 |
<% end -%> |
| 76 | 76 |
<%= yield %> |
| 77 | 77 |
<hr /> |
| 78 |
<% if Setting.emails_footer.present? -%> |
|
| 79 |
<span class="footer"><%= Redmine::WikiFormatting.to_html(Setting.text_formatting, Setting.emails_footer).html_safe %></span> |
|
| 80 |
<% end -%> |
|
| 78 |
<span class="footer"> |
|
| 79 |
<% if @reason %> |
|
| 80 |
<span><%= l("text_notification_reason.#{@reason}") %></span> <br />
|
|
| 81 |
<% end %> |
|
| 82 |
<span><%= l(:text_notification_settings, link: link_to(nil, url_for(controller: 'my', action: 'account'))).html_safe %></span> |
|
| 83 |
<% if Setting.emails_footer.present? -%> |
|
| 84 |
<%= Redmine::WikiFormatting.to_html(Setting.text_formatting, Setting.emails_footer).html_safe %> |
|
| 85 |
<% end -%> |
|
| 86 |
</span> |
|
| 81 | 87 |
</body> |
| 82 | 88 |
</html> |
| app/views/layouts/mailer.text.erb | ||
|---|---|---|
| 2 | 2 |
<%= Setting.emails_header %> |
| 3 | 3 |
<% end -%> |
| 4 | 4 |
<%= yield %> |
| 5 |
<% if Setting.emails_footer.present? -%> |
|
| 6 | 5 |
-- |
| 6 |
<% if @reason %> |
|
| 7 |
<%= l("text_notification_reason.#{@reason}") %>
|
|
| 8 |
<% end %> |
|
| 9 |
<%= l(:text_notification_settings, link: url_for(controller: 'my', action: 'account')) %> |
|
| 10 |
<% if Setting.emails_footer.present? -%> |
|
| 7 | 11 |
<%= Setting.emails_footer %> |
| 8 | 12 |
<% end -%> |
| config/locales/en.yml | ||
|---|---|---|
| 1414 | 1414 |
text_user_destroy_confirmation: "Are you sure you want to delete this user and remove all references to them? This cannot be undone. Often, locking a user instead of deleting them is the better solution. To confirm, please enter their login (%{login}) below."
|
| 1415 | 1415 |
text_project_destroy_enter_identifier: "To confirm, please enter the project's identifier (%{identifier}) below."
|
| 1416 | 1416 |
field_name_or_email_or_login: Name, email or login |
| 1417 |
text_notification_reason: |
|
| 1418 |
admin: You have received this security notification because you are an administrator. |
|
| 1419 |
subscribed: You have received this notification because you have subscribed to it. |
|
| 1420 |
involved: You have received this notification because you are involved in. |
|
| 1421 |
watcher: You have received this notification because you are watching it. |
|
| 1422 |
mentioned: You have received this notification because you have been mentioned in. |
|
| 1423 |
text_notification_settings: "To change your notification preferences, please click here: %{link}."
|
|
| config/settings.yml | ||
|---|---|---|
| 298 | 298 |
ui_theme: |
| 299 | 299 |
default: '' |
| 300 | 300 |
emails_footer: |
| 301 |
default: |- |
|
| 302 |
You have received this notification because you have either subscribed to it, or are involved in it. |
|
| 303 |
To change your notification preferences, please click here: http://hostname/my/account |
|
| 301 |
default: '' |
|
| 304 | 302 |
gravatar_enabled: |
| 305 | 303 |
default: 0 |
| 306 | 304 |
gravatar_default: |
| lib/plugins/acts_as_watchable/lib/acts_as_watchable.rb | ||
|---|---|---|
| 118 | 118 |
if respond_to?(:visible?) |
| 119 | 119 |
notified.reject! {|user| !visible?(user)}
|
| 120 | 120 |
end |
| 121 |
notified.map {|user| user.notification_reason = UserNotificationReason::WATCHER}
|
|
| 121 | 122 |
notified |
| 122 | 123 |
end |
| 123 | 124 | |
| lib/redmine/acts/mentionable.rb | ||
|---|---|---|
| 48 | 48 |
if respond_to?(:visible?) |
| 49 | 49 |
notified.select! {|user| visible?(user)}
|
| 50 | 50 |
end |
| 51 |
notified.map {|user| user.notification_reason = UserNotificationReason::MENTIONED}
|
|
| 51 | 52 |
notified |
| 52 | 53 |
end |
| 53 | 54 | |
| test/test_helper.rb | ||
|---|---|---|
| 285 | 285 |
(mail.multipart? ? mail.parts.first : mail).body.encoded |
| 286 | 286 |
end |
| 287 | 287 | |
| 288 |
# Verifies mail notification deliveries match the expected deliveries and the reasons |
|
| 289 |
def assert_mail_deliveries_reasons(expected, deliveries) |
|
| 290 |
# First assert that number of deliveries match the number of expected deliveries |
|
| 291 |
assert_equal expected.size, deliveries.size |
|
| 292 | ||
| 293 |
deliveries.each do |mail| |
|
| 294 |
assert_not_nil mail |
|
| 295 | ||
| 296 |
# Assert that the email is sent to only one recipient |
|
| 297 |
assert_equal 1, mail.to.size |
|
| 298 | ||
| 299 |
recipient = mail.to.first |
|
| 300 | ||
| 301 |
# Assert that the actual recipient is part of the expected recipients |
|
| 302 |
assert expected[recipient] |
|
| 303 | ||
| 304 |
# Get expected notification reason |
|
| 305 |
reason = expected[recipient] |
|
| 306 |
# Remove recipient from the expected hash |
|
| 307 |
expected.delete(recipient) |
|
| 308 | ||
| 309 |
mail_html_part = mail.parts.detect {|part| part.content_type.include?('text/html')}
|
|
| 310 |
mail_text_part = mail.parts.detect {|part| part.content_type.include?('text/html')}
|
|
| 311 | ||
| 312 |
# Assert mail body contains the expected notification reason for both parts (html / text) |
|
| 313 |
assert_include l("text_notification_reason.#{reason}"), mail_html_part.body.encoded
|
|
| 314 |
assert_include l("text_notification_reason.#{reason}"), mail_text_part.body.encoded
|
|
| 315 | ||
| 316 |
# Assert reason header |
|
| 317 |
assert_equal reason, mail.header['X-Redmine-Reason'].to_s |
|
| 318 |
end |
|
| 319 | ||
| 320 |
# Assert that we iterate through all the expected recipients |
|
| 321 |
assert_equal 0, expected.size |
|
| 322 |
end |
|
| 323 | ||
| 288 | 324 |
# Returns the lft value for a new root issue |
| 289 | 325 |
def new_issue_lft |
| 290 | 326 |
1 |
| test/unit/comment_test.rb | ||
|---|---|---|
| 20 | 20 |
require_relative '../test_helper' |
| 21 | 21 | |
| 22 | 22 |
class CommentTest < ActiveSupport::TestCase |
| 23 |
include Redmine::I18n |
|
| 23 | 24 |
fixtures :users, :email_addresses, :news, :comments, :projects, :enabled_modules, |
| 24 | 25 |
:user_preferences, :roles, :members, :member_roles |
| 25 | 26 | |
| ... | ... | |
| 44 | 45 |
Comment.create!(:commented => @news, :author => @jsmith, :comments => "my comment") |
| 45 | 46 |
end |
| 46 | 47 |
end |
| 48 | ||
| 49 |
recipients = {
|
|
| 50 |
"jsmith@somenet.foo" => "watcher", |
|
| 51 |
"dlopper@somenet.foo" => "subscribed", |
|
| 52 |
} |
|
| 53 | ||
| 54 |
assert_mail_deliveries_reasons(recipients, ActionMailer::Base.deliveries) |
|
| 47 | 55 |
end |
| 48 | 56 | |
| 49 | 57 |
def test_validate |
| test/unit/mailer_test.rb | ||
|---|---|---|
| 486 | 486 |
# @jsmith and @dlopper are members of the project |
| 487 | 487 |
# admin is mentioned |
| 488 | 488 |
# @dlopper won't receive duplicated notifications |
| 489 |
assert_equal 3, ActionMailer::Base.deliveries.size |
|
| 490 |
assert_include User.find(1).mail, recipients |
|
| 491 | 489 |
end |
| 492 | 490 | |
| 493 | 491 |
def test_issue_add_should_include_enabled_fields |
| ... | ... | |
| 543 | 541 |
end |
| 544 | 542 |
end |
| 545 | 543 | |
| 544 |
def test_issue_add_should_contain_notification_reason |
|
| 545 |
issue = Issue.find(1) |
|
| 546 |
assert Mailer.deliver_issue_add(issue) |
|
| 547 | ||
| 548 |
recipients = {
|
|
| 549 |
"jsmith@somenet.foo" => "involved", |
|
| 550 |
"dlopper@somenet.foo" => "subscribed", |
|
| 551 |
} |
|
| 552 |
assert_mail_deliveries_reasons(recipients, ActionMailer::Base.deliveries) |
|
| 553 |
end |
|
| 554 | ||
| 546 | 555 |
def test_issue_edit_subject_should_include_status_changes_if_setting_is_enabled |
| 547 | 556 |
with_settings :show_status_changes_in_mail_subject => 1 do |
| 548 | 557 |
issue = Issue.find(2) |
| ... | ... | |
| 645 | 654 |
ActionMailer::Base.deliveries.clear |
| 646 | 655 |
Mailer.deliver_issue_edit(journal) |
| 647 | 656 | |
| 648 |
# @jsmith and @dlopper are members of the project |
|
| 649 |
# admin is mentioned in the updated description |
|
| 650 |
# @dlopper won't receive duplicated notifications |
|
| 651 |
assert_equal 3, ActionMailer::Base.deliveries.size |
|
| 652 |
assert_include User.find(1).mail, recipients |
|
| 657 |
recipients = {
|
|
| 658 |
"jsmith@somenet.foo" => "involved", |
|
| 659 |
"dlopper@somenet.foo" => "involved", |
|
| 660 |
"admin@somenet.foo" => "mentioned", |
|
| 661 |
} |
|
| 662 |
assert_mail_deliveries_reasons(recipients, ActionMailer::Base.deliveries) |
|
| 653 | 663 |
end |
| 654 | 664 | |
| 655 | 665 |
def test_issue_edit_should_notify_mentioned_users_in_notes |
| ... | ... | |
| 665 | 675 |
# @dlopper won't receive duplicated notifications |
| 666 | 676 |
assert_equal 3, ActionMailer::Base.deliveries.size |
| 667 | 677 |
assert_include User.find(1).mail, recipients |
| 678 | ||
| 679 |
recipients = {
|
|
| 680 |
"jsmith@somenet.foo" => "involved", |
|
| 681 |
"dlopper@somenet.foo" => "involved", |
|
| 682 |
"admin@somenet.foo" => "mentioned", |
|
| 683 |
} |
|
| 684 |
assert_mail_deliveries_reasons(recipients, ActionMailer::Base.deliveries) |
|
| 685 |
end |
|
| 686 | ||
| 687 |
def test_issue_edit_should_contain_notification_reason |
|
| 688 |
journal = Journal.generate!(journalized: Issue.find(2), user: User.find(1), notes: 'Hello') |
|
| 689 | ||
| 690 |
ActionMailer::Base.deliveries.clear |
|
| 691 |
Mailer.deliver_issue_edit(journal) |
|
| 692 | ||
| 693 |
# assert notification reason |
|
| 694 |
assert_include "You have received this notification because you are watching it.", text_part.body.encoded |
|
| 695 |
assert_include "You have received this notification because you are watching it.", html_part.body.encoded |
|
| 696 | ||
| 697 |
# Assert notification reason |
|
| 698 |
assert_equal 'watcher', last_email.header['X-Redmine-Reason'].to_s |
|
| 668 | 699 |
end |
| 669 | 700 | |
| 670 | 701 |
def test_issue_should_send_email_notification_with_suppress_empty_fields |
| ... | ... | |
| 714 | 745 |
assert last_email.to.any? |
| 715 | 746 |
assert_select_email do |
| 716 | 747 |
assert_select "a[href=?]", "http://localhost:3000/projects/ecookbook/files" |
| 748 |
assert_select "span[class=?] span", "footer", text: "You have received this notification because you have subscribed to it." |
|
| 717 | 749 |
end |
| 750 |
assert_include "You have received this notification because you have subscribed to it.", text_part.body.encoded |
|
| 751 | ||
| 752 |
# Assert notification reason header |
|
| 753 |
assert_equal 'subscribed', last_email.header['X-Redmine-Reason'].to_s |
|
| 718 | 754 |
end |
| 719 | 755 | |
| 720 | 756 |
def test_project_file_added |
| ... | ... | |
| 724 | 760 |
assert last_email.to.any? |
| 725 | 761 |
assert_select_email do |
| 726 | 762 |
assert_select "a[href=?]", "http://localhost:3000/projects/ecookbook/files" |
| 763 |
assert_select "span[class=?] span", "footer", text: "You have received this notification because you have subscribed to it." |
|
| 727 | 764 |
end |
| 765 |
assert_include "You have received this notification because you have subscribed to it.", text_part.body.encoded |
|
| 766 | ||
| 767 |
# Assert notification reason header |
|
| 768 |
assert_equal 'subscribed', last_email.header['X-Redmine-Reason'].to_s |
|
| 769 |
end |
|
| 770 | ||
| 771 |
def test_document_file_added |
|
| 772 |
attachements = [Attachment.find_by_container_type('Document')]
|
|
| 773 | ||
| 774 |
assert Mailer.deliver_attachments_added(attachements) |
|
| 775 |
assert_not_nil last_email.to |
|
| 776 |
assert last_email.to.any? |
|
| 777 |
assert_select_email do |
|
| 778 |
assert_select "a[href=?]", "http://localhost:3000/documents/1" |
|
| 779 |
assert_select "span[class=?] span", "footer", text: "You have received this notification because you have subscribed to it." |
|
| 780 |
end |
|
| 781 |
assert_include "You have received this notification because you have subscribed to it.", text_part.body.encoded |
|
| 782 | ||
| 783 |
# Assert notification reason header |
|
| 784 |
assert_equal 'subscribed', last_email.header['X-Redmine-Reason'].to_s |
|
| 785 |
end |
|
| 786 | ||
| 787 |
def test_document_added |
|
| 788 |
project = Project.find(1) |
|
| 789 |
doc = Document.new(:project => project, :title => 'New document', :category => Enumeration.find_by_name('User documentation'))
|
|
| 790 |
doc.save |
|
| 791 | ||
| 792 |
assert Mailer.deliver_document_added(doc, User.find_by_id(3)) |
|
| 793 |
assert_not_nil last_email.to |
|
| 794 |
assert last_email.to.any? |
|
| 795 |
assert_select_email do |
|
| 796 |
assert_select "a[href=?]", "http://localhost:3000/documents/#{doc.id}"
|
|
| 797 |
assert_select "span[class=?] span", "footer", text: "You have received this notification because you have subscribed to it." |
|
| 798 |
end |
|
| 799 |
assert_include "You have received this notification because you have subscribed to it.", text_part.body.encoded |
|
| 800 | ||
| 801 |
# Assert headers |
|
| 802 |
assert_equal project.identifier, last_email.header['X-Redmine-Project'].to_s |
|
| 803 |
assert_equal 'subscribed', last_email.header['X-Redmine-Reason'].to_s |
|
| 728 | 804 |
end |
| 729 | 805 | |
| 730 | 806 |
def test_news_added_should_notify_project_news_watchers |
| ... | ... | |
| 759 | 835 |
assert_select 'a[href=?]', |
| 760 | 836 |
'http://localhost:3000/projects/ecookbook/wiki/CookBook_documentation', |
| 761 | 837 |
:text => 'CookBook documentation' |
| 838 |
assert_select "span[class=?] span", 'footer', text: "You have received this notification because you have subscribed to it." |
|
| 762 | 839 |
end |
| 840 | ||
| 841 |
assert_include "You have received this notification because you have subscribed to it.", text_part.body.encoded |
|
| 842 | ||
| 843 |
# Assert headers |
|
| 844 |
assert_equal 'subscribed', last_email.header['X-Redmine-Reason'].to_s |
|
| 763 | 845 |
end |
| 764 | 846 |
end |
| 765 | 847 | |
| ... | ... | |
| 785 | 867 |
'http://localhost:3000/projects/ecookbook/wiki/CookBook_documentation', |
| 786 | 868 |
:text => 'CookBook documentation' |
| 787 | 869 |
end |
| 870 | ||
| 871 |
recipients = {
|
|
| 872 |
"admin@somenet.foo" => "watcher", |
|
| 873 |
"jsmith@somenet.foo" => "subscribed", |
|
| 874 |
"dlopper@somenet.foo" => "subscribed", |
|
| 875 |
} |
|
| 876 | ||
| 877 |
assert_mail_deliveries_reasons(recipients, ActionMailer::Base.deliveries) |
|
| 788 | 878 |
end |
| 789 | 879 | |
| 790 | 880 |
def test_wiki_content_updated_should_notify_mentioned_users_in_updated_content |
| ... | ... | |
| 981 | 1071 | |
| 982 | 1072 |
def test_security_notification |
| 983 | 1073 |
set_language_if_valid User.find(1).language |
| 984 |
with_settings :emails_footer => "footer without link" do |
|
| 1074 |
with_settings :emails_footer => "footer without extra link" do
|
|
| 985 | 1075 |
sender = User.find(2) |
| 986 | 1076 |
sender.remote_ip = '192.168.1.1' |
| 987 | 1077 |
assert( |
| ... | ... | |
| 996 | 1086 |
assert_mail_body_match '192.168.1.1', mail |
| 997 | 1087 |
assert_mail_body_match I18n.t(:notice_account_password_updated), mail |
| 998 | 1088 |
assert_select_email do |
| 999 |
assert_select "h1", false |
|
| 1000 |
assert_select "a", false |
|
| 1089 |
assert_select 'span[class=?]', 'footer' do |
|
| 1090 |
assert_select 'span', text: 'You have received this security notification because you are an administrator.' |
|
| 1091 |
assert_select 'a', true |
|
| 1092 |
assert_select 'p', text: "footer without extra link" |
|
| 1093 |
end |
|
| 1001 | 1094 |
end |
| 1002 | 1095 |
end |
| 1003 | 1096 |
end |
| ... | ... | |
| 1031 | 1124 |
) |
| 1032 | 1125 |
) |
| 1033 | 1126 |
assert_select_email do |
| 1034 |
assert_select "a", false
|
|
| 1127 |
assert_select "a", true
|
|
| 1035 | 1128 |
assert_select "h1", :text => I18n.t(:label_my_account) |
| 1036 | 1129 |
end |
| 1037 | 1130 |
end |
| ... | ... | |
| 1117 | 1210 |
with_settings :plain_text_mail => 0 do |
| 1118 | 1211 |
assert Mailer.test_email(User.find(1)).deliver_now |
| 1119 | 1212 |
assert_select_email do |
| 1120 |
assert_select ".footer" do
|
|
| 1213 |
assert_select "span[class=?]", "footer" do
|
|
| 1121 | 1214 |
assert_select "strong", :text => "Footer content" |
| 1122 | 1215 |
end |
| 1123 | 1216 |
end |
| ... | ... | |
| 1126 | 1219 |
assert Mailer.test_email(User.find(1)).deliver_now |
| 1127 | 1220 |
mail = last_email |
| 1128 | 1221 |
assert_include "\n-- \n", mail.body.decoded |
| 1222 |
assert_include "To change your notification preferences, please click here: http://localhost:3000/my/account.", mail.body.decoded |
|
| 1129 | 1223 |
assert_include "*Footer content*", mail.body.decoded |
| 1130 | 1224 |
end |
| 1131 | 1225 |
end |
| ... | ... | |
| 1136 | 1230 |
with_settings :plain_text_mail => 0 do |
| 1137 | 1231 |
assert Mailer.test_email(User.find(1)).deliver_now |
| 1138 | 1232 |
assert_select_email do |
| 1139 |
assert_select ".footer", false |
|
| 1233 |
assert_select 'span[class=?]', 'footer' do |
|
| 1234 |
assert_select 'p', false |
|
| 1235 |
end |
|
| 1140 | 1236 |
end |
| 1141 | 1237 |
end |
| 1142 | 1238 |
with_settings :plain_text_mail => 1 do |
| 1143 | 1239 |
assert Mailer.test_email(User.find(1)).deliver_now |
| 1144 |
mail = last_email
|
|
| 1145 |
assert_not_include "\n-- \n", mail.body.decoded
|
|
| 1240 |
assert_equal "This is a test email sent by Redmine.\nRedmine URL: http://localhost:3000/\n\n-- \nTo change your notification preferences, please click here: http://localhost:3000/my/account.\n",
|
|
| 1241 |
last_email.body.decoded
|
|
| 1146 | 1242 |
end |
| 1147 | 1243 |
end |
| 1148 | 1244 |
end |
| test/unit/message_test.rb | ||
|---|---|---|
| 20 | 20 |
require_relative '../test_helper' |
| 21 | 21 | |
| 22 | 22 |
class MessageTest < ActiveSupport::TestCase |
| 23 |
include Redmine::I18n |
|
| 23 | 24 |
fixtures :projects, :roles, :members, :member_roles, :boards, :messages, |
| 24 | 25 |
:users, :watchers, :enabled_modules |
| 25 | 26 | |
| ... | ... | |
| 36 | 37 |
message = Message.new(:board => @board, :subject => 'Test message', |
| 37 | 38 |
:content => 'Test message content', |
| 38 | 39 |
:author => @user) |
| 39 |
assert message.save |
|
| 40 | ||
| 41 |
with_settings :notified_events => %w(message_posted) do |
|
| 42 |
assert message.save |
|
| 43 |
end |
|
| 44 | ||
| 40 | 45 |
@board.reload |
| 41 | 46 |
# topics count incremented |
| 42 | 47 |
assert_equal topics_count + 1, @board[:topics_count] |
| ... | ... | |
| 45 | 50 |
assert_equal message, @board.last_message |
| 46 | 51 |
# author should be watching the message |
| 47 | 52 |
assert message.watched_by?(@user) |
| 53 | ||
| 54 |
expected = {
|
|
| 55 |
"admin@somenet.foo" => "watcher", |
|
| 56 |
"jsmith@somenet.foo" => "subscribed", |
|
| 57 |
"dlopper@somenet.foo" => "subscribed" |
|
| 58 |
} |
|
| 59 | ||
| 60 |
assert_mail_deliveries_reasons(expected, ActionMailer::Base.deliveries) |
|
| 48 | 61 |
end |
| 49 | 62 | |
| 50 | 63 |
def test_reply |
| test/unit/news_test.rb | ||
|---|---|---|
| 20 | 20 |
require_relative '../test_helper' |
| 21 | 21 | |
| 22 | 22 |
class NewsTest < ActiveSupport::TestCase |
| 23 |
include Redmine::I18n |
|
| 23 | 24 |
fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, :enabled_modules, :news |
| 24 | 25 | |
| 25 | 26 |
def valid_news |
| ... | ... | |
| 38 | 39 |
assert news.save |
| 39 | 40 |
end |
| 40 | 41 |
assert_equal 2, ActionMailer::Base.deliveries.size |
| 42 | ||
| 43 |
expected = {
|
|
| 44 |
"jsmith@somenet.foo" => "subscribed", |
|
| 45 |
"dlopper@somenet.foo" => "subscribed" |
|
| 46 |
} |
|
| 47 |
assert_mail_deliveries_reasons(expected, ActionMailer::Base.deliveries) |
|
| 41 | 48 |
end |
| 42 | 49 | |
| 43 | 50 |
def test_should_include_news_for_projects_with_news_enabled |