Commit 17aa580c authored by Stan Hu's avatar Stan Hu

Add ability to turn off "project moved" notifications

By default project and group maintainers/owners receive a "project
moved" e-mails, but this can now be configured. These same users
watching or participating in a project will also receive a notification
unless the setting is explicitly disabled.

Closes https://gitlab.com/gitlab-org/gitlab/-/issues/30371
parent ac510e71
...@@ -52,10 +52,9 @@ class NotificationRecipient ...@@ -52,10 +52,9 @@ class NotificationRecipient
when :mention when :mention
@type == :mention @type == :mention
when :participating when :participating
%i[failed_pipeline fixed_pipeline].include?(@custom_action) || participating_custom_action? || participating_or_mention?
%i[participating mention].include?(@type)
when :custom when :custom
custom_enabled? || %i[participating mention].include?(@type) custom_enabled? || participating_or_mention?
when :watch when :watch
!excluded_watcher_action? !excluded_watcher_action?
else else
...@@ -175,4 +174,12 @@ class NotificationRecipient ...@@ -175,4 +174,12 @@ class NotificationRecipient
.where.not(level: NotificationSetting.levels[:global]) .where.not(level: NotificationSetting.levels[:global])
.first .first
end end
def participating_custom_action?
%i[failed_pipeline fixed_pipeline moved_project].include?(@custom_action)
end
def participating_or_mention?
%i[participating mention].include?(@type)
end
end end
...@@ -46,7 +46,8 @@ class NotificationSetting < ApplicationRecord ...@@ -46,7 +46,8 @@ class NotificationSetting < ApplicationRecord
:merge_merge_request, :merge_merge_request,
:failed_pipeline, :failed_pipeline,
:fixed_pipeline, :fixed_pipeline,
:success_pipeline :success_pipeline,
:moved_project
].freeze ].freeze
# Update unfound_translations.rb when events are changed # Update unfound_translations.rb when events are changed
......
...@@ -425,7 +425,7 @@ class NotificationService ...@@ -425,7 +425,7 @@ class NotificationService
def project_was_moved(project, old_path_with_namespace) def project_was_moved(project, old_path_with_namespace)
recipients = project_moved_recipients(project) recipients = project_moved_recipients(project)
recipients = notifiable_users(recipients, :mention, project: project) recipients = notifiable_users(recipients, :custom, custom_action: :moved_project, project: project)
recipients.each do |recipient| recipients.each do |recipient|
mailer.project_was_moved_email( mailer.project_was_moved_email(
......
---
title: Add ability to turn off "project moved" notifications
merge_request: 37269
author:
type: added
# frozen_string_literal: true
class AddMovedProjectToNotificationSettings < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
add_column :notification_settings, :moved_project, :boolean, default: true, null: false
end
end
40b9ece83b05dc3ec2c69db2298a051b085d645d2b60719eef4a55d7838ba1fb
\ No newline at end of file
...@@ -13425,7 +13425,8 @@ CREATE TABLE public.notification_settings ( ...@@ -13425,7 +13425,8 @@ CREATE TABLE public.notification_settings (
new_epic boolean, new_epic boolean,
notification_email character varying, notification_email character varying,
fixed_pipeline boolean, fixed_pipeline boolean,
new_release boolean new_release boolean,
moved_project boolean DEFAULT true NOT NULL
); );
CREATE SEQUENCE public.notification_settings_id_seq CREATE SEQUENCE public.notification_settings_id_seq
......
...@@ -32,6 +32,7 @@ If the `custom` level is used, specific email events can be controlled. Availabl ...@@ -32,6 +32,7 @@ If the `custom` level is used, specific email events can be controlled. Availabl
- `failed_pipeline` - `failed_pipeline`
- `fixed_pipeline` - `fixed_pipeline`
- `success_pipeline` - `success_pipeline`
- `moved_project`
- `new_epic` **(ULTIMATE)** - `new_epic` **(ULTIMATE)**
## Global notification settings ## Global notification settings
...@@ -86,6 +87,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab ...@@ -86,6 +87,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
| `failed_pipeline` | boolean | no | Enable/disable this notification | | `failed_pipeline` | boolean | no | Enable/disable this notification |
| `fixed_pipeline` | boolean | no | Enable/disable this notification | | `fixed_pipeline` | boolean | no | Enable/disable this notification |
| `success_pipeline` | boolean | no | Enable/disable this notification | | `success_pipeline` | boolean | no | Enable/disable this notification |
| `moved_project` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37269) in 13.3)|
| `new_epic` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6626) in 11.3) **(ULTIMATE)** | | `new_epic` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6626) in 11.3) **(ULTIMATE)** |
Example response: Example response:
...@@ -156,6 +158,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab ...@@ -156,6 +158,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
| `failed_pipeline` | boolean | no | Enable/disable this notification | | `failed_pipeline` | boolean | no | Enable/disable this notification |
| `fixed_pipeline` | boolean | no | Enable/disable this notification | | `fixed_pipeline` | boolean | no | Enable/disable this notification |
| `success_pipeline` | boolean | no | Enable/disable this notification | | `success_pipeline` | boolean | no | Enable/disable this notification |
| `moved_project` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37269) in 13.3)|
| `new_epic` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6626) in 11.3) **(ULTIMATE)** | | `new_epic` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6626) in 11.3) **(ULTIMATE)** |
Example responses: Example responses:
......
...@@ -28,6 +28,7 @@ RSpec.describe NotificationSetting do ...@@ -28,6 +28,7 @@ RSpec.describe NotificationSetting do
:failed_pipeline, :failed_pipeline,
:fixed_pipeline, :fixed_pipeline,
:success_pipeline, :success_pipeline,
:moved_project,
:new_epic :new_epic
] ]
) )
...@@ -55,7 +56,8 @@ RSpec.describe NotificationSetting do ...@@ -55,7 +56,8 @@ RSpec.describe NotificationSetting do
:merge_merge_request, :merge_merge_request,
:failed_pipeline, :failed_pipeline,
:fixed_pipeline, :fixed_pipeline,
:success_pipeline :success_pipeline,
:moved_project
] ]
) )
end end
...@@ -83,6 +85,7 @@ RSpec.describe NotificationSetting do ...@@ -83,6 +85,7 @@ RSpec.describe NotificationSetting do
:failed_pipeline, :failed_pipeline,
:fixed_pipeline, :fixed_pipeline,
:success_pipeline, :success_pipeline,
:moved_project,
:new_epic :new_epic
] ]
) )
......
...@@ -52,7 +52,8 @@ RSpec.describe 'Projects > Show > User manages notifications', :js do ...@@ -52,7 +52,8 @@ RSpec.describe 'Projects > Show > User manages notifications', :js do
:merge_merge_request, :merge_merge_request,
:failed_pipeline, :failed_pipeline,
:fixed_pipeline, :fixed_pipeline,
:success_pipeline :success_pipeline,
:moved_project
] ]
end end
......
...@@ -22,6 +22,7 @@ RSpec.describe NotificationsHelper do ...@@ -22,6 +22,7 @@ RSpec.describe NotificationsHelper do
it { expect(notification_event_name(:success_pipeline)).to match('Successful pipeline') } it { expect(notification_event_name(:success_pipeline)).to match('Successful pipeline') }
it { expect(notification_event_name(:failed_pipeline)).to match('Failed pipeline') } it { expect(notification_event_name(:failed_pipeline)).to match('Failed pipeline') }
it { expect(notification_event_name(:fixed_pipeline)).to match('Fixed pipeline') } it { expect(notification_event_name(:fixed_pipeline)).to match('Fixed pipeline') }
it { expect(notification_event_name(:moved_project)).to match('Moved project') }
end end
describe '#notification_icon_level' do describe '#notification_icon_level' do
......
...@@ -138,7 +138,8 @@ RSpec.describe NotificationSetting do ...@@ -138,7 +138,8 @@ RSpec.describe NotificationSetting do
:merge_merge_request, :merge_merge_request,
:failed_pipeline, :failed_pipeline,
:success_pipeline, :success_pipeline,
:fixed_pipeline :fixed_pipeline,
:moved_project
) )
end end
......
...@@ -70,12 +70,13 @@ RSpec.describe API::NotificationSettings do ...@@ -70,12 +70,13 @@ RSpec.describe API::NotificationSettings do
describe "PUT /projects/:id/notification_settings" do describe "PUT /projects/:id/notification_settings" do
it "updates project level notification settings for the current user" do it "updates project level notification settings for the current user" do
put api("/projects/#{project.id}/notification_settings", user), params: { level: 'custom', new_note: true } put api("/projects/#{project.id}/notification_settings", user), params: { level: 'custom', new_note: true, moved_project: true }
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(json_response['level']).to eq(user.reload.notification_settings_for(project).level) expect(json_response['level']).to eq(user.reload.notification_settings_for(project).level)
expect(json_response['events']['new_note']).to be_truthy expect(json_response['events']['new_note']).to be_truthy
expect(json_response['events']['new_issue']).to be_falsey expect(json_response['events']['new_issue']).to be_falsey
expect(json_response['events']['moved_project']).to be_truthy
end end
end end
......
...@@ -2054,6 +2054,18 @@ RSpec.describe NotificationService, :mailer do ...@@ -2054,6 +2054,18 @@ RSpec.describe NotificationService, :mailer do
end end
describe '#project_was_moved' do describe '#project_was_moved' do
context 'when notifications are disabled' do
before do
@u_custom_global.global_notification_setting.update!(moved_project: false)
end
it 'does not send a notification' do
notification.project_was_moved(project, "gitlab/gitlab")
should_not_email(@u_custom_global)
end
end
context 'with users at both project and group level' do context 'with users at both project and group level' do
let(:maintainer) { create(:user) } let(:maintainer) { create(:user) }
let(:developer) { create(:user) } let(:developer) { create(:user) }
......
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