Commit 03e08ab7 authored by Wei-Meng Lee's avatar Wei-Meng Lee

Guarantee order of notification settings

parent 31775ad8
...@@ -82,16 +82,8 @@ class Notify < BaseMailer ...@@ -82,16 +82,8 @@ class Notify < BaseMailer
group_notification_email = nil group_notification_email = nil
if notification_group if notification_group
# Get notification group's and ancestors' notification settings notification_settings = notification_group.notification_settings(hierarchy_order: :asc).where(user: @current_user) # rubocop: disable CodeReuse/ActiveRecord
group_ids = notification_group.self_and_ancestors_ids group_notification_email = notification_settings.find { |n| n.notification_email.present? }&.notification_email
notification_settings = notification_group.notification_settings.where(user: @current_user) # rubocop: disable CodeReuse/ActiveRecord
# Exploit notification_group.self_and_ancestors_ids being ordered from
# most nested to least nested to iterate through group ancestors
group_ids.each do |group_id|
group_notification_email = notification_settings.find { |ns| ns.source_id == group_id }&.notification_email
break if group_notification_email.present?
end
end end
# Return group-specific email address if present, otherwise return global # Return group-specific email address if present, otherwise return global
......
...@@ -126,10 +126,16 @@ class Group < Namespace ...@@ -126,10 +126,16 @@ class Group < Namespace
# Overrides notification_settings has_many association # Overrides notification_settings has_many association
# This allows to apply notification settings from parent groups # This allows to apply notification settings from parent groups
# to child groups and projects. # to child groups and projects.
def notification_settings def notification_settings(hierarchy_order: nil)
source_type = self.class.base_class.name source_type = self.class.base_class.name
settings = NotificationSetting.where(source_type: source_type, source_id: self_and_ancestors_ids)
NotificationSetting.where(source_type: source_type, source_id: self_and_ancestors_ids) return settings unless hierarchy_order && self_and_ancestors_ids.length > 1
settings
.joins("LEFT JOIN (#{self_and_ancestors(hierarchy_order: hierarchy_order).to_sql}) AS ordered_groups ON notification_settings.source_id = ordered_groups.id")
.select('notification_settings.*, ordered_groups.depth AS depth')
.order("ordered_groups.depth #{hierarchy_order}")
end end
def to_reference(_from = nil, full: nil) def to_reference(_from = nil, full: nil)
......
...@@ -206,12 +206,12 @@ class Namespace < ApplicationRecord ...@@ -206,12 +206,12 @@ class Namespace < ApplicationRecord
.ancestors(upto: top, hierarchy_order: hierarchy_order) .ancestors(upto: top, hierarchy_order: hierarchy_order)
end end
def self_and_ancestors def self_and_ancestors(hierarchy_order: nil)
return self.class.where(id: id) unless parent_id return self.class.where(id: id) unless parent_id
Gitlab::ObjectHierarchy Gitlab::ObjectHierarchy
.new(self.class.where(id: id)) .new(self.class.where(id: id))
.base_and_ancestors .base_and_ancestors(hierarchy_order: hierarchy_order)
end end
# Returns all the descendants of the current namespace. # Returns all the descendants of the current namespace.
......
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