Class: NotificationService

Inherits:
Object
  • Object
show all
Defined in:
app/services/notification_service.rb

Overview

NotificationService class

Used for notifying users with emails about different events

Ex.

NotificationService.new.new_issue(issue, current_user)

When calculating the recipients of a notification is expensive (for instance, in the new issue case), #async will make that calculation happen in Sidekiq instead:

NotificationService.new.async.new_issue(issue, current_user)

Defined Under Namespace

Classes: Async

Constant Summary collapse

EXCLUDED_ACTIONS =

These should not be called by the MailScheduler::NotificationServiceWorker - what would it even mean?

i[async].freeze
NEW_COMMIT_EMAIL_DISPLAY_LIMIT =
20

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.permitted_actionsObject



23
24
25
26
27
# File 'app/services/notification_service.rb', line 23

def self.permitted_actions
  @permitted_actions ||= gitlab_extensions.flat_map do |klass|
    klass.public_instance_methods(false) - EXCLUDED_ACTIONS
  end.to_set
end

Instance Method Details

#access_token_about_to_expire(user, token_names, params = {}) ⇒ Object

Notify the owner of the personal access token, when it is about to expire And mark the token with about_to_expire_delivered



126
127
128
129
130
131
132
# File 'app/services/notification_service.rb', line 126

def access_token_about_to_expire(user, token_names, params = {})
  return unless user.can?(:receive_notifications)

  log_info("Notifying User about expiring tokens", user)

  mailer.access_token_about_to_expire_email(user, token_names, params).deliver_later
end

#access_token_created(user, token_name) ⇒ Object

Notify the owner of the account when a new personal access token is created



118
119
120
121
122
# File 'app/services/notification_service.rb', line 118

def access_token_created(user, token_name)
  return unless user.can?(:receive_notifications)

  mailer.access_token_created_email(user, token_name).deliver_later
end

#access_token_expired(user, token_names = []) ⇒ Object

Notify the user when at least one of their personal access tokens has expired today



135
136
137
138
139
# File 'app/services/notification_service.rb', line 135

def access_token_expired(user, token_names = [])
  return unless user.can?(:receive_notifications)

  mailer.access_token_expired_email(user, token_names).deliver_later
end

#access_token_revoked(user, token_name, source = nil) ⇒ Object

Notify the user when one of their personal access tokens is revoked



142
143
144
145
146
# File 'app/services/notification_service.rb', line 142

def access_token_revoked(user, token_name, source = nil)
  return unless user.can?(:receive_notifications)

  mailer.access_token_revoked_email(user, token_name, source).deliver_later
end

#access_token_rotated(user, token_name) ⇒ Object

Notify the user when one of their personal access tokens is rotated



149
150
151
152
153
# File 'app/services/notification_service.rb', line 149

def access_token_rotated(user, token_name)
  return unless user.can?(:receive_notifications)

  mailer.access_token_rotated_email(user, token_name).deliver_later
end

#approve_mr(merge_request, current_user) ⇒ Object



721
722
723
# File 'app/services/notification_service.rb', line 721

def approve_mr(merge_request, current_user)
  approve_mr_email(merge_request, merge_request.target_project, current_user)
end

#asyncObject



45
46
47
# File 'app/services/notification_service.rb', line 45

def async
  @async ||= Async.new(self)
end

#autodevops_disabled(pipeline, recipients) ⇒ Object



592
593
594
595
596
597
598
# File 'app/services/notification_service.rb', line 592

def autodevops_disabled(pipeline, recipients)
  return if pipeline.project.emails_disabled?

  recipients.each do |recipient|
    mailer.autodevops_disabled_email(pipeline, recipient).deliver_later
  end
end

#bot_resource_access_token_about_to_expire(bot_user, token_name, params = {}) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'app/services/notification_service.rb', line 100

def bot_resource_access_token_about_to_expire(bot_user, token_name, params = {})
  resource = bot_user.resource_bot_resource

  bot_resource_access_token_about_to_expire_recipients(bot_user) do |recipient|
    next unless recipient.can?(:receive_notifications)

    log_info("Notifying resource access token owner about expiring tokens", recipient)

    mailer.bot_resource_access_token_about_to_expire_email(
      recipient,
      resource,
      token_name,
      params
    ).deliver_later
  end
end

#change_in_merge_request_draft_status(merge_request, current_user) ⇒ Object



313
314
315
316
317
318
319
320
321
322
323
324
325
# File 'app/services/notification_service.rb', line 313

def change_in_merge_request_draft_status(merge_request, current_user)
  recipients = NotificationRecipients::BuildService.build_recipients(merge_request, current_user, action: "draft_status_change")

  recipients.each do |recipient|
    mailer.send(
      :change_in_merge_request_draft_status_email,
      recipient.user.id,
      merge_request.id,
      current_user.id,
      recipient.reason
    ).deliver_later
  end
end

#changed_milestone(target, milestone, current_user) ⇒ Object



754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
# File 'app/services/notification_service.rb', line 754

def changed_milestone(target, milestone, current_user)
  method = case target
           when Issue
             :changed_milestone_issue_email
           when MergeRequest
             :changed_milestone_merge_request_email
           end

  recipients = NotificationRecipients::BuildService.build_recipients(
    target,
    current_user,
    action: 'changed_milestone'
  )

  recipients.each do |recipient|
    mailer.send(method, recipient.user.id, target.id, milestone, current_user.id).deliver_later
  end
end

#changed_reviewer_of_merge_request(merge_request, current_user, previous_reviewers = []) ⇒ Object

When we change reviewer in a merge_request we should send an email to:

* merge_request old reviewers if their notification level is not Disabled
* merge_request new reviewers if their notification level is not Disabled
* users with custom level checked with "change reviewer merge request"


382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'app/services/notification_service.rb', line 382

def changed_reviewer_of_merge_request(merge_request, current_user, previous_reviewers = [])
  recipients = NotificationRecipients::BuildService.build_recipients(
    merge_request,
    current_user,
    action: "change_reviewer",
    previous_assignees: previous_reviewers
  )

  previous_reviewer_ids = previous_reviewers.map(&:id)

  recipients.each do |recipient|
    mailer.changed_reviewer_of_merge_request_email(
      recipient.user.id,
      merge_request.id,
      previous_reviewer_ids,
      current_user.id,
      recipient.reason
    ).deliver_later
  end
end

#close_issue(issue, current_user, params = {}) ⇒ Object

When we close an issue we should send an email to:

* issue author if their notification level is not Disabled
* issue assignee if their notification level is not Disabled
* project team members with notification level higher then Participating
* users with custom level checked with "close issue"


233
234
235
# File 'app/services/notification_service.rb', line 233

def close_issue(issue, current_user, params = {})
  close_resource_email(issue, current_user, :closed_issue_email, closed_via: params[:closed_via])
end

#close_mr(merge_request, current_user) ⇒ Object



423
424
425
# File 'app/services/notification_service.rb', line 423

def close_mr(merge_request, current_user)
  close_resource_email(merge_request, current_user, :closed_merge_request_email)
end

#deploy_token_about_to_expire(user, token_name, project, params = {}) ⇒ Object

Notify the owner of the deploy token, when it is about to expire



156
157
158
159
160
161
162
163
# File 'app/services/notification_service.rb', line 156

def deploy_token_about_to_expire(user, token_name, project, params = {})
  return unless user.can?(:receive_notifications)
  return unless project.team.owner?(user) || project.team.maintainer?(user)

  log_info("Notifying user about expiring deploy tokens", user)

  mailer.deploy_token_about_to_expire_email(user, token_name, project, params).deliver_later
end

#disabled_two_factor(user, type = :two_factor, options = {}) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'app/services/notification_service.rb', line 62

def disabled_two_factor(user, type = :two_factor, options = {})
  return unless user.can?(:receive_notifications)

  case type
  when :passkey
    mailer.disabled_two_factor_webauthn_email(user, options[:device_name], :passkey).deliver_later
  when :webauthn
    mailer.disabled_two_factor_webauthn_email(user, options[:device_name]).deliver_later
  when :otp
    mailer.disabled_two_factor_otp_email(user).deliver_later
  else
    mailer.disabled_two_factor_email(user).deliver_later
  end
end

#email_template_name(status) ⇒ Object



558
559
560
# File 'app/services/notification_service.rb', line 558

def email_template_name(status)
  "pipeline_#{status}_email"
end

#enabled_two_factor(user, type, options = {}) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
# File 'app/services/notification_service.rb', line 49

def enabled_two_factor(user, type, options = {})
  return unless user.can?(:receive_notifications)

  case type
  when :passkey
    mailer.enabled_two_factor_webauthn_email(user, options[:device_name], :passkey).deliver_later
  when :webauthn
    mailer.enabled_two_factor_webauthn_email(user, options[:device_name]).deliver_later
  else
    mailer.enabled_two_factor_otp_email(user).deliver_later
  end
end

#group_scheduled_for_deletion(group) ⇒ Object



790
791
792
793
794
795
796
797
798
799
800
801
# File 'app/services/notification_service.rb', line 790

def group_scheduled_for_deletion(group)
  return if group.emails_disabled?

  recipients = group.members.active_without_invites_and_requests.owners.map(&:user)

  recipients.each do |recipient|
    mailer.group_scheduled_for_deletion(
      recipient.id,
      group.id
    ).deliver_later
  end
end

#group_was_exported(group, current_user) ⇒ Object



684
685
686
687
688
# File 'app/services/notification_service.rb', line 684

def group_was_exported(group, current_user)
  return true unless notifiable?(current_user, :mention, group: group)

  mailer.group_was_exported_email(current_user, group).deliver_later
end

#group_was_not_exported(group, current_user, errors) ⇒ Object



690
691
692
693
694
# File 'app/services/notification_service.rb', line 690

def group_was_not_exported(group, current_user, errors)
  return true unless notifiable?(current_user, :mention, group: group)

  mailer.group_was_not_exported_email(current_user, group, errors).deliver_later
end

#inactive_project_deletion_warning(project, deletion_date) ⇒ Object



729
730
731
732
733
# File 'app/services/notification_service.rb', line 729

def inactive_project_deletion_warning(project, deletion_date)
  owners_and_maintainers_without_invites(project).each do |recipient|
    mailer.inactive_project_deletion_warning_email(project, recipient.user, deletion_date).deliver_later
  end
end

#issue_cloned(issue, new_issue, current_user) ⇒ Object



536
537
538
539
540
541
542
543
544
# File 'app/services/notification_service.rb', line 536

def issue_cloned(issue, new_issue, current_user)
  recipients = NotificationRecipients::BuildService.build_recipients(issue, current_user, action: 'cloned')

  recipients.map do |recipient|
    email = mailer.issue_cloned_email(recipient.user, issue, new_issue, current_user, recipient.reason)
    email.deliver_later
    email
  end
end

#issue_due(issue) ⇒ Object



630
631
632
633
634
635
636
637
638
639
640
641
642
# File 'app/services/notification_service.rb', line 630

def issue_due(issue)
  recipients = NotificationRecipients::BuildService.build_recipients(
    issue,
    issue.author,
    action: 'due',
    custom_action: :issue_due,
    skip_current_user: false
  )

  recipients.each do |recipient|
    mailer.send(:issue_due_email, recipient.user.id, issue.id, recipient.reason).deliver_later
  end
end

#issue_moved(issue, new_issue, current_user) ⇒ Object



526
527
528
529
530
531
532
533
534
# File 'app/services/notification_service.rb', line 526

def issue_moved(issue, new_issue, current_user)
  recipients = NotificationRecipients::BuildService.build_recipients(issue, current_user, action: 'moved')

  recipients.map do |recipient|
    email = mailer.issue_moved_email(recipient.user, issue, new_issue, current_user, recipient.reason)
    email.deliver_later
    email
  end
end

#merge_mr(merge_request, current_user) ⇒ Object



431
432
433
434
435
436
437
438
# File 'app/services/notification_service.rb', line 431

def merge_mr(merge_request, current_user)
  close_resource_email(
    merge_request,
    current_user,
    :merged_merge_request_email,
    skip_current_user: !merge_request.auto_merge_enabled?
  )
end

#merge_request_unmergeable(merge_request) ⇒ Object

When a merge request is found to be unmergeable, we should send an email to:

* mr author
* mr merge user if set


332
333
334
# File 'app/services/notification_service.rb', line 332

def merge_request_unmergeable(merge_request)
  merge_request_unmergeable_email(merge_request)
end

#merge_when_pipeline_succeeds(merge_request, current_user) ⇒ Object



708
709
710
711
712
713
714
715
716
717
718
719
# File 'app/services/notification_service.rb', line 708

def merge_when_pipeline_succeeds(merge_request, current_user)
  recipients = ::NotificationRecipients::BuildService.build_recipients(
    merge_request,
    current_user,
    action: 'merge_when_pipeline_succeeds',
    custom_action: :merge_when_pipeline_succeeds
  )

  recipients.each do |recipient|
    mailer.merge_when_pipeline_succeeds_email(recipient.user.id, merge_request.id, current_user.id).deliver_later
  end
end

#new_achievement_email(user, achievement) ⇒ Object



773
774
775
# File 'app/services/notification_service.rb', line 773

def new_achievement_email(user, achievement)
  mailer.new_achievement_email(user, achievement)
end

#new_email_address_added(user, email) ⇒ Object

Notify a user when a new email address is added to the their account



196
197
198
199
200
# File 'app/services/notification_service.rb', line 196

def new_email_address_added(user, email)
  return unless user.can?(:receive_notifications)

  mailer.new_email_address_added_email(user, email).deliver_later
end

#new_gpg_key(gpg_key) ⇒ Object

Always notify the user about gpg key added

This is a security email so it will be sent even if the user disabled notifications



94
95
96
97
98
# File 'app/services/notification_service.rb', line 94

def new_gpg_key(gpg_key)
  if gpg_key.user&.can?(:receive_notifications)
    mailer.new_gpg_key_email(gpg_key.id).deliver_later
  end
end

#new_instance_access_request(user) ⇒ Object



495
496
497
498
499
500
501
502
503
# File 'app/services/notification_service.rb', line 495

def new_instance_access_request(user)
  recipients = User.instance_access_request_approvers_to_be_notified # https://gitlab.com/gitlab-org/gitlab/-/issues/277016 will change this

  return true if recipients.empty?

  recipients.each do |recipient|
    mailer.instance_access_request_email(user, recipient).deliver_later
  end
end

#new_issue(issue, current_user) ⇒ Object

When create an issue we should send an email to:

* issue assignee if their notification level is not Disabled
* project team members with notification level higher then Participating
* watchers of the issue's labels
* users with custom level checked with "new issue"


209
210
211
# File 'app/services/notification_service.rb', line 209

def new_issue(issue, current_user)
  new_resource_email(issue, current_user, :new_issue_email)
end

#new_key(key) ⇒ Object

Always notify user about ssh key added only if ssh key is not deploy key

This is security email so it will be sent even if user disabled notifications. However, it won’t be sent to internal users like the ghost user or the EE support bot.



84
85
86
87
88
# File 'app/services/notification_service.rb', line 84

def new_key(key)
  if key.user&.can?(:receive_notifications)
    mailer.new_ssh_key_email(key.id).deliver_later
  end
end

#new_mentions_in_issue(issue, new_mentioned_users, current_user) ⇒ Object

When issue text is updated, we should send an email to:

* newly mentioned project team members with notification level higher than Participating


217
218
219
220
221
222
223
224
# File 'app/services/notification_service.rb', line 217

def new_mentions_in_issue(issue, new_mentioned_users, current_user)
  new_mentions_in_resource_email(
    issue,
    new_mentioned_users,
    current_user,
    :new_mention_in_issue_email
  )
end

#new_mentions_in_merge_request(merge_request, new_mentioned_users, current_user) ⇒ Object

When merge request text is updated, we should send an email to:

* newly mentioned project team members with notification level higher than Participating


340
341
342
343
344
345
346
347
# File 'app/services/notification_service.rb', line 340

def new_mentions_in_merge_request(merge_request, new_mentioned_users, current_user)
  new_mentions_in_resource_email(
    merge_request,
    new_mentioned_users,
    current_user,
    :new_mention_in_merge_request_email
  )
end

#new_merge_request(merge_request, current_user) ⇒ Object

When create a merge request we should send an email to:

* mr author
* mr assignees if their notification level is not Disabled
* project team members with notification level higher then Participating
* watchers of the mr's labels
* users with custom level checked with "new merge request"

In EE, approvers of the merge request are also included



282
283
284
# File 'app/services/notification_service.rb', line 282

def new_merge_request(merge_request, current_user)
  new_resource_email(merge_request, current_user, :new_merge_request_email)
end

#new_note(note) ⇒ Object

Notify users on new note in system



469
470
471
472
473
474
475
476
477
# File 'app/services/notification_service.rb', line 469

def new_note(note)
  return true unless note.noteable_type.present?

  # ignore gitlab service messages
  return true if note.system_note_with_references?

  send_new_note_notifications(note)
  send_service_desk_notification(note)
end

#new_review(review) ⇒ Object

Notify users on new review in system



697
698
699
700
701
702
703
704
705
706
# File 'app/services/notification_service.rb', line 697

def new_review(review)
  recipients = NotificationRecipients::BuildService.build_new_review_recipients(review)
  deliver_options = new_review_deliver_options(review)

  recipients.each do |recipient|
    mailer
      .new_review_email(recipient.user.id, review.id)
      .deliver_later(deliver_options)
  end
end

#new_user(user, token = nil) ⇒ Object

Notify new user with email after creation



461
462
463
464
465
466
# File 'app/services/notification_service.rb', line 461

def new_user(user, token = nil)
  return true unless notifiable?(user, :mention)

  # Don't email omniauth created users
  mailer.new_user_email(user.id, token).deliver_later unless user.identities.any?
end

#pages_domain_auto_ssl_failed(domain) ⇒ Object



624
625
626
627
628
# File 'app/services/notification_service.rb', line 624

def pages_domain_auto_ssl_failed(domain)
  project_maintainers_recipients(domain, action: 'disabled').each do |recipient|
    mailer.pages_domain_auto_ssl_failed_email(domain, recipient.user).deliver_later
  end
end

#pages_domain_disabled(domain) ⇒ Object



618
619
620
621
622
# File 'app/services/notification_service.rb', line 618

def pages_domain_disabled(domain)
  project_maintainers_recipients(domain, action: 'disabled').each do |recipient|
    mailer.pages_domain_disabled_email(domain, recipient.user).deliver_later
  end
end

#pages_domain_enabled(domain) ⇒ Object



612
613
614
615
616
# File 'app/services/notification_service.rb', line 612

def pages_domain_enabled(domain)
  project_maintainers_recipients(domain, action: 'enabled').each do |recipient|
    mailer.pages_domain_enabled_email(domain, recipient.user).deliver_later
  end
end

#pages_domain_verification_failed(domain) ⇒ Object



606
607
608
609
610
# File 'app/services/notification_service.rb', line 606

def pages_domain_verification_failed(domain)
  project_maintainers_recipients(domain, action: 'failed').each do |recipient|
    mailer.pages_domain_verification_failed_email(domain, recipient.user).deliver_later
  end
end

#pages_domain_verification_succeeded(domain) ⇒ Object



600
601
602
603
604
# File 'app/services/notification_service.rb', line 600

def pages_domain_verification_succeeded(domain)
  project_maintainers_recipients(domain, action: 'succeeded').each do |recipient|
    mailer.pages_domain_verification_succeeded_email(domain, recipient.user).deliver_later
  end
end

#pipeline_finished(pipeline, ref_status: nil, recipients: nil) ⇒ Object



562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
# File 'app/services/notification_service.rb', line 562

def pipeline_finished(pipeline, ref_status: nil, recipients: nil)
  # Must always check project configuration since recipients could be a list of emails
  # from the PipelinesEmailService integration.
  return if pipeline.project.emails_disabled?

  # If changing the next line don't forget to do the same in EE section
  status = pipeline_notification_status(ref_status, pipeline)
  email_template = email_template_name(status)

  return unless mailer.respond_to?(email_template)

  recipients ||= notifiable_users(
    [pipeline.user], :watch,
    custom_action: :"#{status}_pipeline",
    target: pipeline
  ).map do |user|
    user.notification_email_for(pipeline.project.group)
  end

  recipients.each do |recipient|
    mailer.public_send(email_template, pipeline, recipient).deliver_later
  end
end

#pipeline_schedule_owner_unavailable(schedule) ⇒ Object



586
587
588
589
590
# File 'app/services/notification_service.rb', line 586

def pipeline_schedule_owner_unavailable(schedule)
  schedule.project.owners_and_maintainers.each do |recipient|
    mailer.pipeline_schedule_owner_unavailable_email(schedule, recipient).deliver_later
  end
end

#project_exported(project, current_user) ⇒ Object



546
547
548
549
550
# File 'app/services/notification_service.rb', line 546

def project_exported(project, current_user)
  return true unless notifiable?(current_user, :mention, project: project)

  mailer.project_was_exported_email(current_user, project).deliver_later
end

#project_not_exported(project, current_user, errors) ⇒ Object



552
553
554
555
556
# File 'app/services/notification_service.rb', line 552

def project_not_exported(project, current_user, errors)
  return true unless notifiable?(current_user, :mention, project: project)

  mailer.project_was_not_exported_email(current_user, project, errors).deliver_later
end

#project_scheduled_for_deletion(project) ⇒ Object



777
778
779
780
781
782
783
784
785
786
787
788
# File 'app/services/notification_service.rb', line 777

def project_scheduled_for_deletion(project)
  return if project.emails_disabled?

  recipients = owners_without_invites(project)

  recipients.each do |recipient|
    mailer.project_scheduled_for_deletion(
      recipient.id,
      project.id
    ).deliver_later
  end
end

#project_was_moved(project, old_path_with_namespace) ⇒ Object



513
514
515
516
517
518
519
520
521
522
523
524
# File 'app/services/notification_service.rb', line 513

def project_was_moved(project, old_path_with_namespace)
  recipients = project_moved_recipients(project)
  recipients = notifiable_users(recipients, :custom, custom_action: :moved_project, project: project)

  recipients.each do |recipient|
    mailer.project_was_moved_email(
      project.id,
      recipient.id,
      old_path_with_namespace
    ).deliver_later
  end
end

#prometheus_alerts_fired(project, alerts) ⇒ Object



676
677
678
679
680
681
682
# File 'app/services/notification_service.rb', line 676

def prometheus_alerts_fired(project, alerts)
  return if project.emails_disabled?

  owners_and_maintainers_without_invites(project).to_a.product(alerts).each do |recipient, alert|
    mailer.prometheus_alert_fired_email(project, recipient.user, alert).deliver_later
  end
end

#push_to_merge_request(merge_request, current_user, new_commits: [], existing_commits: []) ⇒ Object



287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'app/services/notification_service.rb', line 287

def push_to_merge_request(merge_request, current_user, new_commits: [], existing_commits: [])
  total_new_commits_count = new_commits.count
  truncated_new_commits = new_commits.first(NEW_COMMIT_EMAIL_DISPLAY_LIMIT).map do |commit|
    { short_id: commit.short_id, title: commit.title }
  end

  # We don't need the list of all existing commits. We need the first, the
  # last, and the total number of existing commits only.
  total_existing_commits_count = existing_commits.count
  existing_commits = [existing_commits.first, existing_commits.last] if total_existing_commits_count > 2
  existing_commits = existing_commits.map do |commit|
    { short_id: commit.short_id, title: commit.title }
  end

  recipients = NotificationRecipients::BuildService.build_recipients(merge_request, current_user, action: "push_to")

  recipients.each do |recipient|
    mailer.send(
      :push_to_merge_request_email,
      recipient.user.id, merge_request.id, current_user.id, recipient.reason,
      new_commits: truncated_new_commits, total_new_commits_count: total_new_commits_count,
      existing_commits: existing_commits, total_existing_commits_count: total_existing_commits_count
    ).deliver_later
  end
end

#reassigned_issue(issue, current_user, previous_assignees = []) ⇒ Object

When we reassign an issue we should send an email to:

* issue old assignees if their notification level is not Disabled
* issue new assignees if their notification level is not Disabled
* users with custom level checked with "reassign issue"


243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'app/services/notification_service.rb', line 243

def reassigned_issue(issue, current_user, previous_assignees = [])
  recipients = NotificationRecipients::BuildService.build_recipients(
    issue,
    current_user,
    action: "reassign",
    previous_assignees: previous_assignees
  )

  previous_assignee_ids = previous_assignees.map(&:id)

  recipients.each do |recipient|
    mailer.send(
      :reassigned_issue_email,
      recipient.user.id,
      issue.id,
      previous_assignee_ids,
      current_user.id,
      recipient.reason
    ).deliver_later
  end
end

#reassigned_merge_request(merge_request, current_user, previous_assignees = []) ⇒ Object

When we reassign a merge_request we should send an email to:

* merge_request old assignees if their notification level is not Disabled
* merge_request new assignees if their notification level is not Disabled
* users with custom level checked with "reassign merge request"


355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# File 'app/services/notification_service.rb', line 355

def reassigned_merge_request(merge_request, current_user, previous_assignees = [])
  recipients = NotificationRecipients::BuildService.build_recipients(
    merge_request,
    current_user,
    action: "reassign",
    previous_assignees: previous_assignees
  )

  previous_assignee_ids = previous_assignees.map(&:id)

  recipients.each do |recipient|
    mailer.reassigned_merge_request_email(
      recipient.user.id,
      merge_request.id,
      previous_assignee_ids,
      current_user.id,
      recipient.reason
    ).deliver_later
  end
end

#relabeled_issue(issue, added_labels, current_user) ⇒ Object

When we add labels to an issue we should send an email to:

* watchers of the issue's labels


269
270
271
# File 'app/services/notification_service.rb', line 269

def relabeled_issue(issue, added_labels, current_user)
  relabeled_resource_email(issue, added_labels, current_user, :relabeled_issue_email)
end

#relabeled_merge_request(merge_request, added_labels, current_user) ⇒ Object

When we add labels to a merge request we should send an email to:

* watchers of the mr's labels


419
420
421
# File 'app/services/notification_service.rb', line 419

def relabeled_merge_request(merge_request, added_labels, current_user)
  relabeled_resource_email(merge_request, added_labels, current_user, :relabeled_merge_request_email)
end

#remote_mirror_update_failed(remote_mirror) ⇒ Object



668
669
670
671
672
673
674
# File 'app/services/notification_service.rb', line 668

def remote_mirror_update_failed(remote_mirror)
  recipients = project_maintainers_recipients(remote_mirror, action: 'update_failed')

  recipients.each do |recipient|
    mailer.remote_mirror_update_failed_email(remote_mirror.id, recipient.user.id).deliver_later
  end
end

#removed_milestone(target, current_user) ⇒ Object



735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
# File 'app/services/notification_service.rb', line 735

def removed_milestone(target, current_user)
  method = case target
           when Issue
             :removed_milestone_issue_email
           when MergeRequest
             :removed_milestone_merge_request_email
           end

  recipients = NotificationRecipients::BuildService.build_recipients(
    target,
    current_user,
    action: 'removed_milestone'
  )

  recipients.each do |recipient|
    mailer.send(method, recipient.user.id, target.id, current_user.id).deliver_later
  end
end

#reopen_issue(issue, current_user) ⇒ Object



427
428
429
# File 'app/services/notification_service.rb', line 427

def reopen_issue(issue, current_user)
  reopen_resource_email(issue, current_user, :issue_status_changed_email, 'reopened')
end

#reopen_mr(merge_request, current_user) ⇒ Object



440
441
442
443
444
445
446
447
# File 'app/services/notification_service.rb', line 440

def reopen_mr(merge_request, current_user)
  reopen_resource_email(
    merge_request,
    current_user,
    :merge_request_status_email,
    'reopened'
  )
end

#repository_cleanup_failure(project, user, error) ⇒ Object



650
651
652
653
654
# File 'app/services/notification_service.rb', line 650

def repository_cleanup_failure(project, user, error)
  return if project.emails_disabled?

  mailer.send(:repository_cleanup_failure_email, project, user, error).deliver_later
end

#repository_cleanup_success(project, user) ⇒ Object



644
645
646
647
648
# File 'app/services/notification_service.rb', line 644

def repository_cleanup_success(project, user)
  return if project.emails_disabled?

  mailer.send(:repository_cleanup_success_email, project, user).deliver_later
end

#repository_rewrite_history_failure(project, user, error) ⇒ Object



662
663
664
665
666
# File 'app/services/notification_service.rb', line 662

def repository_rewrite_history_failure(project, user, error)
  return if project.emails_disabled?

  mailer.repository_rewrite_history_failure_email(project, user, error).deliver_later
end

#repository_rewrite_history_success(project, user) ⇒ Object



656
657
658
659
660
# File 'app/services/notification_service.rb', line 656

def repository_rewrite_history_success(project, user)
  return if project.emails_disabled?

  mailer.repository_rewrite_history_success_email(project, user).deliver_later
end

#resolve_all_discussions(merge_request, current_user) ⇒ Object



449
450
451
452
453
454
455
456
457
458
# File 'app/services/notification_service.rb', line 449

def resolve_all_discussions(merge_request, current_user)
  recipients = NotificationRecipients::BuildService.build_recipients(
    merge_request,
    current_user,
    action: "resolve_all_discussions")

  recipients.each do |recipient|
    mailer.resolved_all_discussions_email(recipient.user.id, merge_request.id, current_user.id, recipient.reason).deliver_later
  end
end

#review_requested_of_merge_request(merge_request, current_user, reviewer) ⇒ Object



403
404
405
406
407
408
409
410
411
412
413
# File 'app/services/notification_service.rb', line 403

def review_requested_of_merge_request(merge_request, current_user, reviewer)
  recipients = NotificationRecipients::BuildService.build_requested_review_recipients(merge_request, current_user, reviewer)

  deliver_option = review_request_deliver_options(merge_request.project)

  recipients.each do |recipient|
    mailer
      .request_review_merge_request_email(recipient.user.id, merge_request.id, current_user.id, recipient.reason)
      .deliver_later(deliver_option)
  end
end

#send_new_release_notifications(release) ⇒ Object

Notify users when a new release is created



480
481
482
483
484
485
486
487
488
489
490
491
492
493
# File 'app/services/notification_service.rb', line 480

def send_new_release_notifications(release)
  unless release.author&.can_trigger_notifications?
    warn_skipping_notifications(release.author, release)
    return false
  end

  recipients = NotificationRecipients::BuildService.build_recipients(release,
    release.author,
    action: "new")

  recipients.each do |recipient|
    mailer.new_release_email(recipient.user.id, release, recipient.reason).deliver_later
  end
end

#ssh_key_expired(user, fingerprints) ⇒ Object

Notify the user when at least one of their ssh key has expired today



166
167
168
169
170
# File 'app/services/notification_service.rb', line 166

def ssh_key_expired(user, fingerprints)
  return unless user.can?(:receive_notifications)

  mailer.ssh_key_expired_email(user, fingerprints).deliver_later
end

#ssh_key_expiring_soon(user, fingerprints) ⇒ Object

Notify the user when at least one of their ssh key is expiring soon



173
174
175
176
177
# File 'app/services/notification_service.rb', line 173

def ssh_key_expiring_soon(user, fingerprints)
  return unless user.can?(:receive_notifications)

  mailer.ssh_key_expiring_soon_email(user, fingerprints).deliver_later
end

#two_factor_otp_attempt_failed(user, ip) ⇒ Object

Notify a user when a wrong 2FA OTP has been entered to try to sign in to their account



189
190
191
192
193
# File 'app/services/notification_service.rb', line 189

def two_factor_otp_attempt_failed(user, ip)
  return unless user.can?(:receive_notifications)

  mailer.two_factor_otp_attempt_failed_email(user, ip).deliver_later
end

#unapprove_mr(merge_request, current_user) ⇒ Object



725
726
727
# File 'app/services/notification_service.rb', line 725

def unapprove_mr(merge_request, current_user)
  unapprove_mr_email(merge_request, merge_request.target_project, current_user)
end

#unknown_sign_in(user, ip, time, request_info) ⇒ Object

Notify a user when a previously unknown IP or device is used to sign in to their account



181
182
183
184
185
# File 'app/services/notification_service.rb', line 181

def (user, ip, time, request_info)
  return unless user.can?(:receive_notifications)

  mailer.(user, ip, time, country: request_info.country, city: request_info.city).deliver_later
end

#user_admin_rejection(name, email) ⇒ Object



505
506
507
# File 'app/services/notification_service.rb', line 505

def user_admin_rejection(name, email)
  mailer.user_admin_rejection_email(name, email).deliver_later
end

#user_deactivated(name, email) ⇒ Object



509
510
511
# File 'app/services/notification_service.rb', line 509

def user_deactivated(name, email)
  mailer.user_deactivated_email(name, email).deliver_later
end