Update NotificationService to use NotificationSettings instead of membership

Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
This commit is contained in:
Dmitriy Zaporozhets 2016-03-28 20:31:36 +02:00
parent 7ea1bcab45
commit b8f3843790
8 changed files with 40 additions and 67 deletions

View File

@ -1,15 +0,0 @@
# == Notifiable concern
#
# Contains notification functionality
#
module Notifiable
extend ActiveSupport::Concern
included do
validates :notification_level, inclusion: { in: Notification.project_notification_levels }, presence: true
end
def notification
@notification ||= Notification.new(self)
end
end

View File

@ -27,6 +27,7 @@ class Group < Namespace
has_many :users, through: :group_members
has_many :project_group_links, dependent: :destroy
has_many :shared_projects, through: :project_group_links, source: :project
has_many :notification_settings, dependent: :destroy, as: :source
validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? }
validate :visibility_level_allowed_by_projects

View File

@ -19,7 +19,6 @@
class Member < ActiveRecord::Base
include Sortable
include Notifiable
include Gitlab::Access
attr_accessor :raw_invite_token
@ -170,6 +169,10 @@ class Member < ActiveRecord::Base
end
end
def notification
@notification ||= user.notification_settings.find_by(source: source)
end
private
def send_invite

View File

@ -30,30 +30,12 @@ class Notification
end
end
delegate :disabled?, :participating?, :watch?, :global?, :mention?, to: :target
def initialize(target)
@target = target
end
def disabled?
target.notification_level == N_DISABLED
end
def participating?
target.notification_level == N_PARTICIPATING
end
def watch?
target.notification_level == N_WATCH
end
def global?
target.notification_level == N_GLOBAL
end
def mention?
target.notification_level == N_MENTION
end
def level
target.notification_level
end

View File

@ -154,6 +154,7 @@ class Project < ActiveRecord::Base
has_many :project_group_links, dependent: :destroy
has_many :invited_groups, through: :project_group_links, source: :group
has_many :todos, dependent: :destroy
has_many :notification_settings, dependent: :destroy, as: :source
has_one :import_data, dependent: :destroy, class_name: "ProjectImportData"

View File

@ -193,6 +193,9 @@ class User < ActiveRecord::Base
# Notification level
# Note: When adding an option, it MUST go on the end of the array.
#
# TODO: Add '_prefix: :notification' to enum when update to Rails 5. https://github.com/rails/rails/pull/19813
# Because user.notification_disabled? is much better than user.disabled?
enum notification_level: [:disabled, :participating, :watch, :global, :mention]
alias_attribute :private_token, :authentication_token

View File

@ -253,8 +253,8 @@ class NotificationService
def project_watchers(project)
project_members = project_member_notification(project)
users_with_project_level_global = project_member_notification(project, Notification::N_GLOBAL)
users_with_group_level_global = group_member_notification(project, Notification::N_GLOBAL)
users_with_project_level_global = project_member_notification(project, :global)
users_with_group_level_global = group_member_notification(project, :global)
users = users_with_global_level_watch([users_with_project_level_global, users_with_group_level_global].flatten.uniq)
users_with_project_setting = select_project_member_setting(project, users_with_project_level_global, users)
@ -264,18 +264,16 @@ class NotificationService
end
def project_member_notification(project, notification_level=nil)
project_members = project.project_members
if notification_level
project_members.where(notification_level: notification_level).pluck(:user_id)
project.notification_settings.where(level: NotificationSetting.levels[notification_level]).pluck(:user_id)
else
project_members.pluck(:user_id)
project.notification_settings.pluck(:user_id)
end
end
def group_member_notification(project, notification_level)
if project.group
project.group.group_members.where(notification_level: notification_level).pluck(:user_id)
project.group.notification_settings.where(level: NotificationSetting.levels[notification_level]).pluck(:user_id)
else
[]
end
@ -284,13 +282,13 @@ class NotificationService
def users_with_global_level_watch(ids)
User.where(
id: ids,
notification_level: Notification::N_WATCH
notification_level: NotificationSetting.levels[:watch]
).pluck(:id)
end
# Build a list of users based on project notifcation settings
def select_project_member_setting(project, global_setting, users_global_level_watch)
users = project_member_notification(project, Notification::N_WATCH)
users = project_member_notification(project, :watch)
# If project setting is global, add to watch list if global setting is watch
global_setting.each do |user_id|
@ -304,7 +302,7 @@ class NotificationService
# Build a list of users based on group notification settings
def select_group_member_setting(project, project_members, global_setting, users_global_level_watch)
uids = group_member_notification(project, Notification::N_WATCH)
uids = group_member_notification(project, :watch)
# Group setting is watch, add to users list if user is not project member
users = []
@ -351,20 +349,20 @@ class NotificationService
users.reject do |user|
next user.notification.send(method_name) unless project
member = project.project_members.find_by(user_id: user.id)
setting = user.notification_settings.find_by(source: project)
if !member && project.group
member = project.group.group_members.find_by(user_id: user.id)
if !setting && project.group
setting = user.notification_settings.find_by(source: group)
end
# reject users who globally set mention notification and has no membership
next user.notification.send(method_name) unless member
# reject users who globally set mention notification and has no setting per project/group
next user.notification.send(method_name) unless setting
# reject users who set mention notification in project
next true if member.notification.send(method_name)
next true if setting.send(method_name)
# reject users who have N_MENTION in project and disabled in global settings
member.notification.global? && user.notification.send(method_name)
# reject users who have mention level in project and disabled in global settings
setting.global? && user.notification.send(method_name)
end
end

View File

@ -89,11 +89,11 @@ describe NotificationService, services: true do
note.project.group.add_user(@u_watcher, GroupMember::MASTER)
note.project.save
user_project = note.project.project_members.find_by_user_id(@u_watcher.id)
user_project.notification_level = Notification::N_PARTICIPATING
user_project.notification.level = :participating
user_project.save
group_member = note.project.group.group_members.find_by_user_id(@u_watcher.id)
group_member.notification_level = Notification::N_GLOBAL
group_member.save
group_member.notification.level = :global
group_member.notification.save
ActionMailer::Base.deliveries.clear
end
@ -215,7 +215,7 @@ describe NotificationService, services: true do
end
it do
@u_committer.update_attributes(notification_level: Notification::N_MENTION)
@u_committer.update_attributes(notification_level: :mention)
notification.new_note(note)
should_not_email(@u_committer)
end
@ -246,7 +246,7 @@ describe NotificationService, services: true do
end
it do
issue.assignee.update_attributes(notification_level: Notification::N_MENTION)
issue.assignee.update_attributes(notification_level: :mention)
notification.new_issue(issue, @u_disabled)
should_not_email(issue.assignee)
@ -596,13 +596,13 @@ describe NotificationService, services: true do
end
def build_team(project)
@u_watcher = create(:user, notification_level: Notification::N_WATCH)
@u_participating = create(:user, notification_level: Notification::N_PARTICIPATING)
@u_participant_mentioned = create(:user, username: 'participant', notification_level: Notification::N_PARTICIPATING)
@u_disabled = create(:user, notification_level: Notification::N_DISABLED)
@u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_MENTION)
@u_watcher = create(:user, notification_level: :watch)
@u_participating = create(:user, notification_level: :participating)
@u_participant_mentioned = create(:user, username: 'participant', notification_level: :participating)
@u_disabled = create(:user, notification_level: :disabled)
@u_mentioned = create(:user, username: 'mention', notification_level: :mention)
@u_committer = create(:user, username: 'committer')
@u_not_mentioned = create(:user, username: 'regular', notification_level: Notification::N_PARTICIPATING)
@u_not_mentioned = create(:user, username: 'regular', notification_level: :participating)
@u_outsider_mentioned = create(:user, username: 'outsider')
project.team << [@u_watcher, :master]
@ -617,8 +617,8 @@ describe NotificationService, services: true do
def add_users_with_subscription(project, issuable)
@subscriber = create :user
@unsubscriber = create :user
@subscribed_participant = create(:user, username: 'subscribed_participant', notification_level: Notification::N_PARTICIPATING)
@watcher_and_subscriber = create(:user, notification_level: Notification::N_WATCH)
@subscribed_participant = create(:user, username: 'subscribed_participant', notification_level: :participating)
@watcher_and_subscriber = create(:user, notification_level: :watch)
project.team << [@subscribed_participant, :master]
project.team << [@subscriber, :master]