Merge branch '19359-api-for-notification-settings' into 'master'
Add notification_settings API calls ## What does this MR do? It adds API calls to get/update notification settings, globally and at the group/project level. ## Are there points in the code the reviewer needs to double check? None ## Why was this MR needed? Notification settings were updated, but related API calls were never created. ## What are the relevant issue numbers? gitlab-org/gitlab-ce#19359 ## Does this MR meet the acceptance criteria? - [x] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added - [x] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md) - [x] API support added - Tests - [x] Added for this feature/bug - [x] All builds are passing - [x] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides) - [x] Branch has no merge conflicts with `master` (if you do - rebase it please) - [x] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) Closes #19359 See merge request !5632
This commit is contained in:
commit
3a59efd562
|
@ -116,6 +116,7 @@ v 8.12.0 (unreleased)
|
||||||
- Use default clone protocol on "check out, review, and merge locally" help page URL
|
- Use default clone protocol on "check out, review, and merge locally" help page URL
|
||||||
- API for Ci Lint !5953 (Katarzyna Kobierska Urszula Budziszewska)
|
- API for Ci Lint !5953 (Katarzyna Kobierska Urszula Budziszewska)
|
||||||
- Allow bulk update merge requests from merge requests index page
|
- Allow bulk update merge requests from merge requests index page
|
||||||
|
- Add notification_settings API calls !5632 (mahcsig)
|
||||||
|
|
||||||
v 8.11.6 (unreleased)
|
v 8.11.6 (unreleased)
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ following locations:
|
||||||
- [Open source license templates](licenses.md)
|
- [Open source license templates](licenses.md)
|
||||||
- [Namespaces](namespaces.md)
|
- [Namespaces](namespaces.md)
|
||||||
- [Notes](notes.md) (comments)
|
- [Notes](notes.md) (comments)
|
||||||
|
- [Notification settings](notification_settings.md)
|
||||||
- [Pipelines](pipelines.md)
|
- [Pipelines](pipelines.md)
|
||||||
- [Projects](projects.md) including setting Webhooks
|
- [Projects](projects.md) including setting Webhooks
|
||||||
- [Project Access Requests](access_requests.md)
|
- [Project Access Requests](access_requests.md)
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
# Notification settings
|
||||||
|
|
||||||
|
>**Note:** This feature was [introduced][ce-5632] in GitLab 8.12.
|
||||||
|
|
||||||
|
**Valid notification levels**
|
||||||
|
|
||||||
|
The notification levels are defined in the `NotificationSetting::level` model enumeration. Currently, these levels are recognized:
|
||||||
|
|
||||||
|
```
|
||||||
|
disabled
|
||||||
|
participating
|
||||||
|
watch
|
||||||
|
global
|
||||||
|
mention
|
||||||
|
custom
|
||||||
|
```
|
||||||
|
|
||||||
|
If the `custom` level is used, specific email events can be controlled. Notification email events are defined in the `NotificationSetting::EMAIL_EVENTS` model variable. Currently, these events are recognized:
|
||||||
|
|
||||||
|
```
|
||||||
|
new_note
|
||||||
|
new_issue
|
||||||
|
reopen_issue
|
||||||
|
close_issue
|
||||||
|
reassign_issue
|
||||||
|
new_merge_request
|
||||||
|
reopen_merge_request
|
||||||
|
close_merge_request
|
||||||
|
reassign_merge_request
|
||||||
|
merge_merge_request
|
||||||
|
```
|
||||||
|
|
||||||
|
## Global notification settings
|
||||||
|
|
||||||
|
Get current notification settings and email address.
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /notification_settings
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/notification_settings
|
||||||
|
```
|
||||||
|
|
||||||
|
Example response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"level": "participating",
|
||||||
|
"notification_email": "admin@example.com"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Update global notification settings
|
||||||
|
|
||||||
|
Update current notification settings and email address.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /notification_settings
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/notification_settings?level=watch
|
||||||
|
```
|
||||||
|
|
||||||
|
| Attribute | Type | Required | Description |
|
||||||
|
| --------- | ---- | -------- | ----------- |
|
||||||
|
| `level` | string | no | The global notification level |
|
||||||
|
| `notification_email` | string | no | The email address to send notifications |
|
||||||
|
| `new_note` | boolean | no | Enable/disable this notification |
|
||||||
|
| `new_issue` | boolean | no | Enable/disable this notification |
|
||||||
|
| `reopen_issue` | boolean | no | Enable/disable this notification |
|
||||||
|
| `close_issue` | boolean | no | Enable/disable this notification |
|
||||||
|
| `reassign_issue` | boolean | no | Enable/disable this notification |
|
||||||
|
| `new_merge_request` | boolean | no | Enable/disable this notification |
|
||||||
|
| `reopen_merge_request` | boolean | no | Enable/disable this notification |
|
||||||
|
| `close_merge_request` | boolean | no | Enable/disable this notification |
|
||||||
|
| `reassign_merge_request` | boolean | no | Enable/disable this notification |
|
||||||
|
| `merge_merge_request` | boolean | no | Enable/disable this notification |
|
||||||
|
|
||||||
|
Example response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"level": "watch",
|
||||||
|
"notification_email": "admin@example.com"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Group / project level notification settings
|
||||||
|
|
||||||
|
Get current group or project notification settings.
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /groups/:id/notification_settings
|
||||||
|
GET /projects/:id/notification_settings
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/5/notification_settings
|
||||||
|
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/8/notification_settings
|
||||||
|
```
|
||||||
|
|
||||||
|
| Attribute | Type | Required | Description |
|
||||||
|
| --------- | ---- | -------- | ----------- |
|
||||||
|
| `id` | integer/string | yes | The group/project ID or path |
|
||||||
|
|
||||||
|
Example response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"level": "global"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Update group/project level notification settings
|
||||||
|
|
||||||
|
Update current group/project notification settings.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /groups/:id/notification_settings
|
||||||
|
PUT /projects/:id/notification_settings
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/5/notification_settings?level=watch
|
||||||
|
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/8/notification_settings?level=custom&new_note=true
|
||||||
|
```
|
||||||
|
|
||||||
|
| Attribute | Type | Required | Description |
|
||||||
|
| --------- | ---- | -------- | ----------- |
|
||||||
|
| `id` | integer/string | yes | The group/project ID or path |
|
||||||
|
| `level` | string | no | The global notification level |
|
||||||
|
| `new_note` | boolean | no | Enable/disable this notification |
|
||||||
|
| `new_issue` | boolean | no | Enable/disable this notification |
|
||||||
|
| `reopen_issue` | boolean | no | Enable/disable this notification |
|
||||||
|
| `close_issue` | boolean | no | Enable/disable this notification |
|
||||||
|
| `reassign_issue` | boolean | no | Enable/disable this notification |
|
||||||
|
| `new_merge_request` | boolean | no | Enable/disable this notification |
|
||||||
|
| `reopen_merge_request` | boolean | no | Enable/disable this notification |
|
||||||
|
| `close_merge_request` | boolean | no | Enable/disable this notification |
|
||||||
|
| `reassign_merge_request` | boolean | no | Enable/disable this notification |
|
||||||
|
| `merge_merge_request` | boolean | no | Enable/disable this notification |
|
||||||
|
|
||||||
|
Example responses:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"level": "watch"
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
"level": "custom",
|
||||||
|
"events": {
|
||||||
|
"new_note": true,
|
||||||
|
"new_issue": false,
|
||||||
|
"reopen_issue": false,
|
||||||
|
"close_issue": false,
|
||||||
|
"reassign_issue": false,
|
||||||
|
"new_merge_request": false,
|
||||||
|
"reopen_merge_request": false,
|
||||||
|
"close_merge_request": false,
|
||||||
|
"reassign_merge_request": false,
|
||||||
|
"merge_merge_request": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[ce-5632]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5632
|
|
@ -51,6 +51,7 @@ module API
|
||||||
mount ::API::Milestones
|
mount ::API::Milestones
|
||||||
mount ::API::Namespaces
|
mount ::API::Namespaces
|
||||||
mount ::API::Notes
|
mount ::API::Notes
|
||||||
|
mount ::API::NotificationSettings
|
||||||
mount ::API::Pipelines
|
mount ::API::Pipelines
|
||||||
mount ::API::ProjectHooks
|
mount ::API::ProjectHooks
|
||||||
mount ::API::ProjectSnippets
|
mount ::API::ProjectSnippets
|
||||||
|
|
|
@ -375,7 +375,7 @@ module API
|
||||||
expose :access_level
|
expose :access_level
|
||||||
expose :notification_level do |member, options|
|
expose :notification_level do |member, options|
|
||||||
if member.notification_setting
|
if member.notification_setting
|
||||||
NotificationSetting.levels[member.notification_setting.level]
|
::NotificationSetting.levels[member.notification_setting.level]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -386,6 +386,21 @@ module API
|
||||||
class GroupAccess < MemberAccess
|
class GroupAccess < MemberAccess
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class NotificationSetting < Grape::Entity
|
||||||
|
expose :level
|
||||||
|
expose :events, if: ->(notification_setting, _) { notification_setting.custom? } do
|
||||||
|
::NotificationSetting::EMAIL_EVENTS.each do |event|
|
||||||
|
expose event
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class GlobalNotificationSetting < NotificationSetting
|
||||||
|
expose :notification_email do |notification_setting, options|
|
||||||
|
notification_setting.user.notification_email
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class ProjectService < Grape::Entity
|
class ProjectService < Grape::Entity
|
||||||
expose :id, :title, :created_at, :updated_at, :active
|
expose :id, :title, :created_at, :updated_at, :active
|
||||||
expose :push_events, :issues_events, :merge_requests_events
|
expose :push_events, :issues_events, :merge_requests_events
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
module API
|
||||||
|
# notification_settings API
|
||||||
|
class NotificationSettings < Grape::API
|
||||||
|
before { authenticate! }
|
||||||
|
|
||||||
|
helpers ::API::Helpers::MembersHelpers
|
||||||
|
|
||||||
|
resource :notification_settings do
|
||||||
|
desc 'Get global notification level settings and email, defaults to Participate' do
|
||||||
|
detail 'This feature was introduced in GitLab 8.12'
|
||||||
|
success Entities::GlobalNotificationSetting
|
||||||
|
end
|
||||||
|
get do
|
||||||
|
notification_setting = current_user.global_notification_setting
|
||||||
|
|
||||||
|
present notification_setting, with: Entities::GlobalNotificationSetting
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Update global notification level settings and email, defaults to Participate' do
|
||||||
|
detail 'This feature was introduced in GitLab 8.12'
|
||||||
|
success Entities::GlobalNotificationSetting
|
||||||
|
end
|
||||||
|
params do
|
||||||
|
optional :level, type: String, desc: 'The global notification level'
|
||||||
|
optional :notification_email, type: String, desc: 'The email address to send notifications'
|
||||||
|
NotificationSetting::EMAIL_EVENTS.each do |event|
|
||||||
|
optional event, type: Boolean, desc: 'Enable/disable this notification'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
put do
|
||||||
|
notification_setting = current_user.global_notification_setting
|
||||||
|
|
||||||
|
begin
|
||||||
|
notification_setting.transaction do
|
||||||
|
new_notification_email = params.delete(:notification_email)
|
||||||
|
declared_params = declared(params, include_missing: false).to_h
|
||||||
|
|
||||||
|
current_user.update(notification_email: new_notification_email) if new_notification_email
|
||||||
|
notification_setting.update(declared_params)
|
||||||
|
end
|
||||||
|
rescue ArgumentError => e # catch level enum error
|
||||||
|
render_api_error! e.to_s, 400
|
||||||
|
end
|
||||||
|
|
||||||
|
render_validation_error! current_user
|
||||||
|
render_validation_error! notification_setting
|
||||||
|
present notification_setting, with: Entities::GlobalNotificationSetting
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%w[group project].each do |source_type|
|
||||||
|
resource source_type.pluralize do
|
||||||
|
desc "Get #{source_type} level notification level settings, defaults to Global" do
|
||||||
|
detail 'This feature was introduced in GitLab 8.12'
|
||||||
|
success Entities::NotificationSetting
|
||||||
|
end
|
||||||
|
params do
|
||||||
|
requires :id, type: String, desc: 'The group ID or project ID or project NAMESPACE/PROJECT_NAME'
|
||||||
|
end
|
||||||
|
get ":id/notification_settings" do
|
||||||
|
source = find_source(source_type, params[:id])
|
||||||
|
|
||||||
|
notification_setting = current_user.notification_settings_for(source)
|
||||||
|
|
||||||
|
present notification_setting, with: Entities::NotificationSetting
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Update #{source_type} level notification level settings, defaults to Global" do
|
||||||
|
detail 'This feature was introduced in GitLab 8.12'
|
||||||
|
success Entities::NotificationSetting
|
||||||
|
end
|
||||||
|
params do
|
||||||
|
requires :id, type: String, desc: 'The group ID or project ID or project NAMESPACE/PROJECT_NAME'
|
||||||
|
optional :level, type: String, desc: "The #{source_type} notification level"
|
||||||
|
NotificationSetting::EMAIL_EVENTS.each do |event|
|
||||||
|
optional event, type: Boolean, desc: 'Enable/disable this notification'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
put ":id/notification_settings" do
|
||||||
|
source = find_source(source_type, params.delete(:id))
|
||||||
|
notification_setting = current_user.notification_settings_for(source)
|
||||||
|
|
||||||
|
begin
|
||||||
|
declared_params = declared(params, include_missing: false).to_h
|
||||||
|
|
||||||
|
notification_setting.update(declared_params)
|
||||||
|
rescue ArgumentError => e # catch level enum error
|
||||||
|
render_api_error! e.to_s, 400
|
||||||
|
end
|
||||||
|
|
||||||
|
render_validation_error! notification_setting
|
||||||
|
present notification_setting, with: Entities::NotificationSetting
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,89 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe API::API, api: true do
|
||||||
|
include ApiHelpers
|
||||||
|
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
let!(:group) { create(:group) }
|
||||||
|
let!(:project) { create(:project, :public, creator_id: user.id, namespace: group) }
|
||||||
|
|
||||||
|
describe "GET /notification_settings" do
|
||||||
|
it "returns global notification settings for the current user" do
|
||||||
|
get api("/notification_settings", user)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(json_response).to be_a Hash
|
||||||
|
expect(json_response['notification_email']).to eq(user.notification_email)
|
||||||
|
expect(json_response['level']).to eq(user.global_notification_setting.level)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "PUT /notification_settings" do
|
||||||
|
let(:email) { create(:email, user: user) }
|
||||||
|
|
||||||
|
it "updates global notification settings for the current user" do
|
||||||
|
put api("/notification_settings", user), { level: 'watch', notification_email: email.email }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(json_response['notification_email']).to eq(email.email)
|
||||||
|
expect(user.reload.notification_email).to eq(email.email)
|
||||||
|
expect(json_response['level']).to eq(user.reload.global_notification_setting.level)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "PUT /notification_settings" do
|
||||||
|
it "fails on non-user email address" do
|
||||||
|
put api("/notification_settings", user), { notification_email: 'invalid@example.com' }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(400)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET /groups/:id/notification_settings" do
|
||||||
|
it "returns group level notification settings for the current user" do
|
||||||
|
get api("/groups/#{group.id}/notification_settings", user)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(json_response).to be_a Hash
|
||||||
|
expect(json_response['level']).to eq(user.notification_settings_for(group).level)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "PUT /groups/:id/notification_settings" do
|
||||||
|
it "updates group level notification settings for the current user" do
|
||||||
|
put api("/groups/#{group.id}/notification_settings", user), { level: 'watch' }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(json_response['level']).to eq(user.reload.notification_settings_for(group).level)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET /projects/:id/notification_settings" do
|
||||||
|
it "returns project level notification settings for the current user" do
|
||||||
|
get api("/projects/#{project.id}/notification_settings", user)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(json_response).to be_a Hash
|
||||||
|
expect(json_response['level']).to eq(user.notification_settings_for(project).level)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "PUT /projects/:id/notification_settings" do
|
||||||
|
it "updates project level notification settings for the current user" do
|
||||||
|
put api("/projects/#{project.id}/notification_settings", user), { level: 'custom', new_note: true }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(json_response['level']).to eq(user.reload.notification_settings_for(project).level)
|
||||||
|
expect(json_response['events']['new_note']).to eq(true)
|
||||||
|
expect(json_response['events']['new_issue']).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "PUT /projects/:id/notification_settings" do
|
||||||
|
it "fails on invalid level" do
|
||||||
|
put api("/projects/#{project.id}/notification_settings", user), { level: 'invalid' }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(400)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue