Commit 2979d3ca authored by Felipe Artur's avatar Felipe Artur

Implement custom notification level options

parent 6aefd3c3
class NotificationSetting < ActiveRecord::Base class NotificationSetting < ActiveRecord::Base
enum level: { global: 3, watch: 2, mention: 4, participating: 1, disabled: 0 } enum level: { global: 3, watch: 2, mention: 4, participating: 1, disabled: 0, custom: 5 }
default_value_for :level, NotificationSetting.levels[:global] default_value_for :level, NotificationSetting.levels[:global]
...@@ -15,6 +15,25 @@ class NotificationSetting < ActiveRecord::Base ...@@ -15,6 +15,25 @@ class NotificationSetting < ActiveRecord::Base
scope :for_groups, -> { where(source_type: 'Namespace') } scope :for_groups, -> { where(source_type: 'Namespace') }
scope :for_projects, -> { where(source_type: 'Project') } scope :for_projects, -> { where(source_type: 'Project') }
serialize :events
EMAIL_EVENTS = [
:new_issue_email,
:new_note_email,
:closed_issue_email,
:reassigned_issue_email,
:relabeled_issue_email,
:new_merge_request_email,
:reassigned_merge_request_email,
:relabeled_merge_request_email,
:closed_merge_request_email,
:issue_status_changed_email,
:merged_merge_request_email,
:merge_request_status_email
]
before_save :set_events
def self.find_or_create_for(source) def self.find_or_create_for(source)
setting = find_or_initialize_by(source: source) setting = find_or_initialize_by(source: source)
...@@ -24,4 +43,8 @@ class NotificationSetting < ActiveRecord::Base ...@@ -24,4 +43,8 @@ class NotificationSetting < ActiveRecord::Base
setting setting
end end
def set_events
self.events = EMAIL_EVENTS if level == "watch"
end
end end
...@@ -31,7 +31,7 @@ class NotificationService ...@@ -31,7 +31,7 @@ class NotificationService
# * watchers of the issue's labels # * watchers of the issue's labels
# #
def new_issue(issue, current_user) def new_issue(issue, current_user)
new_resource_email(issue, issue.project, 'new_issue_email') new_resource_email(issue, issue.project, :new_issue_email)
end end
# When we close an issue we should send an email to: # When we close an issue we should send an email to:
...@@ -41,7 +41,7 @@ class NotificationService ...@@ -41,7 +41,7 @@ class NotificationService
# * project team members with notification level higher then Participating # * project team members with notification level higher then Participating
# #
def close_issue(issue, current_user) def close_issue(issue, current_user)
close_resource_email(issue, issue.project, current_user, 'closed_issue_email') close_resource_email(issue, issue.project, current_user, :closed_issue_email)
end end
# When we reassign an issue we should send an email to: # When we reassign an issue we should send an email to:
...@@ -50,7 +50,7 @@ class NotificationService ...@@ -50,7 +50,7 @@ class NotificationService
# * issue new assignee if their notification level is not Disabled # * issue new assignee if their notification level is not Disabled
# #
def reassigned_issue(issue, current_user) def reassigned_issue(issue, current_user)
reassign_resource_email(issue, issue.project, current_user, 'reassigned_issue_email') reassign_resource_email(issue, issue.project, current_user, :reassigned_issue_email)
end end
# When we add labels to an issue we should send an email to: # When we add labels to an issue we should send an email to:
...@@ -58,7 +58,7 @@ class NotificationService ...@@ -58,7 +58,7 @@ class NotificationService
# * watchers of the issue's labels # * watchers of the issue's labels
# #
def relabeled_issue(issue, added_labels, current_user) def relabeled_issue(issue, added_labels, current_user)
relabeled_resource_email(issue, added_labels, current_user, 'relabeled_issue_email') relabeled_resource_email(issue, added_labels, current_user, :relabeled_issue_email)
end end
# When create a merge request we should send an email to: # When create a merge request we should send an email to:
...@@ -68,7 +68,7 @@ class NotificationService ...@@ -68,7 +68,7 @@ class NotificationService
# * watchers of the mr's labels # * watchers of the mr's labels
# #
def new_merge_request(merge_request, current_user) def new_merge_request(merge_request, current_user)
new_resource_email(merge_request, merge_request.target_project, 'new_merge_request_email') new_resource_email(merge_request, merge_request.target_project, :new_merge_request_email)
end end
# When we reassign a merge_request we should send an email to: # When we reassign a merge_request we should send an email to:
...@@ -77,7 +77,7 @@ class NotificationService ...@@ -77,7 +77,7 @@ class NotificationService
# * merge_request assignee if their notification level is not Disabled # * merge_request assignee if their notification level is not Disabled
# #
def reassigned_merge_request(merge_request, current_user) def reassigned_merge_request(merge_request, current_user)
reassign_resource_email(merge_request, merge_request.target_project, current_user, 'reassigned_merge_request_email') reassign_resource_email(merge_request, merge_request.target_project, current_user, :reassigned_merge_request_email)
end end
# When we add labels to a merge request we should send an email to: # When we add labels to a merge request we should send an email to:
...@@ -85,15 +85,15 @@ class NotificationService ...@@ -85,15 +85,15 @@ class NotificationService
# * watchers of the mr's labels # * watchers of the mr's labels
# #
def relabeled_merge_request(merge_request, added_labels, current_user) def relabeled_merge_request(merge_request, added_labels, current_user)
relabeled_resource_email(merge_request, added_labels, current_user, 'relabeled_merge_request_email') relabeled_resource_email(merge_request, added_labels, current_user, :relabeled_merge_request_email)
end end
def close_mr(merge_request, current_user) def close_mr(merge_request, current_user)
close_resource_email(merge_request, merge_request.target_project, current_user, 'closed_merge_request_email') close_resource_email(merge_request, merge_request.target_project, current_user, :closed_merge_request_email)
end end
def reopen_issue(issue, current_user) def reopen_issue(issue, current_user)
reopen_resource_email(issue, issue.project, current_user, 'issue_status_changed_email', 'reopened') reopen_resource_email(issue, issue.project, current_user, :issue_status_changed_email, 'reopened')
end end
def merge_mr(merge_request, current_user) def merge_mr(merge_request, current_user)
...@@ -101,7 +101,7 @@ class NotificationService ...@@ -101,7 +101,7 @@ class NotificationService
merge_request, merge_request,
merge_request.target_project, merge_request.target_project,
current_user, current_user,
'merged_merge_request_email' :merged_merge_request_email
) )
end end
...@@ -110,7 +110,7 @@ class NotificationService ...@@ -110,7 +110,7 @@ class NotificationService
merge_request, merge_request,
merge_request.target_project, merge_request.target_project,
current_user, current_user,
'merge_request_status_email', :merge_request_status_email,
'reopened' 'reopened'
) )
end end
...@@ -248,6 +248,15 @@ class NotificationService ...@@ -248,6 +248,15 @@ class NotificationService
protected protected
def add_project_custom_notifications(recipients, project, action)
user_ids = []
user_ids += project_member_notification(project, :custom, action)
user_ids += group_member_notification(project, :custom, action)
recipients.concat(User.find(user_ids))
end
# Get project users with WATCH notification level # Get project users with WATCH notification level
def project_watchers(project) def project_watchers(project)
project_members = project_member_notification(project) project_members = project_member_notification(project)
...@@ -262,17 +271,21 @@ class NotificationService ...@@ -262,17 +271,21 @@ class NotificationService
User.where(id: users_with_project_setting.concat(users_with_group_setting).uniq).to_a User.where(id: users_with_project_setting.concat(users_with_group_setting).uniq).to_a
end end
def project_member_notification(project, notification_level=nil) def project_member_notification(project, notification_level=nil, action=nil)
if notification_level if notification_level
project.notification_settings.where(level: NotificationSetting.levels[notification_level]).pluck(:user_id) settings = project.notification_settings.where(level: NotificationSetting.levels[notification_level])
settings = settings.where(events: action.to_yaml) if action.present?
settings.pluck(:user_id)
else else
project.notification_settings.pluck(:user_id) project.notification_settings.pluck(:user_id)
end end
end end
def group_member_notification(project, notification_level) def group_member_notification(project, notification_level, action=nil)
if project.group if project.group
project.group.notification_settings.where(level: NotificationSetting.levels[notification_level]).pluck(:user_id) settings = project.group.notification_settings.where(level: NotificationSetting.levels[notification_level])
settings = settings.where(events: action.to_yaml) if action.present?
settings.pluck(:user_id)
else else
[] []
end end
...@@ -323,7 +336,7 @@ class NotificationService ...@@ -323,7 +336,7 @@ class NotificationService
end end
def add_project_watchers(recipients, project) def add_project_watchers(recipients, project)
recipients.concat(project_watchers(project)).compact.uniq recipients.concat(project_watchers(project)).compact
end end
# Remove users with disabled notifications from array # Remove users with disabled notifications from array
...@@ -408,7 +421,7 @@ class NotificationService ...@@ -408,7 +421,7 @@ class NotificationService
end end
def new_resource_email(target, project, method) def new_resource_email(target, project, method)
recipients = build_recipients(target, project, target.author, action: :new) recipients = build_recipients(target, project, target.author, action: method)
recipients.each do |recipient| recipients.each do |recipient|
mailer.send(method, recipient.id, target.id).deliver_later mailer.send(method, recipient.id, target.id).deliver_later
...@@ -416,7 +429,7 @@ class NotificationService ...@@ -416,7 +429,7 @@ class NotificationService
end end
def close_resource_email(target, project, current_user, method) def close_resource_email(target, project, current_user, method)
recipients = build_recipients(target, project, current_user) recipients = build_recipients(target, project, current_user, action: method)
recipients.each do |recipient| recipients.each do |recipient|
mailer.send(method, recipient.id, target.id, current_user.id).deliver_later mailer.send(method, recipient.id, target.id, current_user.id).deliver_later
...@@ -427,7 +440,7 @@ class NotificationService ...@@ -427,7 +440,7 @@ class NotificationService
previous_assignee_id = previous_record(target, 'assignee_id') previous_assignee_id = previous_record(target, 'assignee_id')
previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
recipients = build_recipients(target, project, current_user, action: :reassign, previous_assignee: previous_assignee) recipients = build_recipients(target, project, current_user, action: method, previous_assignee: previous_assignee)
recipients.each do |recipient| recipients.each do |recipient|
mailer.send( mailer.send(
...@@ -450,7 +463,7 @@ class NotificationService ...@@ -450,7 +463,7 @@ class NotificationService
end end
def reopen_resource_email(target, project, current_user, method, status) def reopen_resource_email(target, project, current_user, method, status)
recipients = build_recipients(target, project, current_user) recipients = build_recipients(target, project, current_user, action: method)
recipients.each do |recipient| recipients.each do |recipient|
mailer.send(method, recipient.id, target.id, status, current_user.id).deliver_later mailer.send(method, recipient.id, target.id, status, current_user.id).deliver_later
...@@ -460,12 +473,15 @@ class NotificationService ...@@ -460,12 +473,15 @@ class NotificationService
def build_recipients(target, project, current_user, action: nil, previous_assignee: nil) def build_recipients(target, project, current_user, action: nil, previous_assignee: nil)
recipients = target.participants(current_user) recipients = target.participants(current_user)
recipients = add_project_watchers(recipients, project) recipients = add_project_watchers(recipients, project)
recipients = add_project_custom_notifications(recipients, project, action)
recipients = reject_mention_users(recipients, project) recipients = reject_mention_users(recipients, project)
recipients = recipients.uniq
# Re-assign is considered as a mention of the new assignee so we add the # Re-assign is considered as a mention of the new assignee so we add the
# new assignee to the list of recipients after we rejected users with # new assignee to the list of recipients after we rejected users with
# the "on mention" notification level # the "on mention" notification level
if action == :reassign if [:reassigned_merge_request_email, :reassigned_issue_email].include?(action)
recipients << previous_assignee if previous_assignee recipients << previous_assignee if previous_assignee
recipients << target.assignee recipients << target.assignee
end end
...@@ -473,7 +489,7 @@ class NotificationService ...@@ -473,7 +489,7 @@ class NotificationService
recipients = reject_muted_users(recipients, project) recipients = reject_muted_users(recipients, project)
recipients = add_subscribed_users(recipients, target) recipients = add_subscribed_users(recipients, target)
if action == :new if [:new_issue_email, :new_merge_request_email].include?(action)
recipients = add_labels_subscribers(recipients, target) recipients = add_labels_subscribers(recipients, target)
end end
......
class AddEventsToNotificationSettings < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
def change
add_column :notification_settings, :events, :text
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment