Expose notifications on work items REST API

What does this MR do and why?

  • Adds support for the notifications widget in the work items REST API.

References

Screenshots or screen recordings

Not provided

How to set up and validate locally

  1. Enable the work_item_rest_api feature flag

  2. Set up test data

user = User.find_by_username('root')
project = Project.find_by(name: "Flight")
pat = user.personal_access_tokens.create!(name: 'test', scopes: [:api], expires_at: 1.day.from_now)
puts "PAT: #{pat.token}"
 
wi = WorkItem.where(project: project).first
puts "Work item IID: #{wi.iid}"
  1. Verify listing endpoint with explicit subscription (cache path)

Create an explicit subscription row so the bulk-load cache path is exercised:

Subscription.create!(user: user, subscribable: wi, subscribed: true)
curl --header "PRIVATE-TOKEN: <PAT>" \
  "http://localhost:3000/api/v4/projects/7/-/work_items?features=notifications&fields=web_url"

Expected: Each work item in the response includes a features.notifications object. The work item with the explicit subscription shows:

"notifications": { "subscribed": true }
  1. Verify listing endpoint with author fallback (no subscription row)

Create a work item authored by the current user with no subscription row:

authored = WorkItem.create!(
  project: project,
  work_item_type: WorkItems::TypesFramework::Provider.new(project).default_issue_type,
  title: 'Authored by me',
  author: user,
  namespace: project.project_namespace
)
puts "Authored IID: #{authored.iid}"

Re-run the listing request from step 2.

Expected: The authored work item shows "notifications": { "subscribed": true } via the author fallback. No explicit subscription row needed.

  1. Verify listing endpoint with assignee fallback (no subscription row)
assigned = WorkItem.create!(
  project: project,
  work_item_type: WorkItems::TypesFramework::Provider.new(project).default_issue_type,
  title: 'Assigned to me',
  author: User.find(2), # any other user
  namespace: project.project_namespace
)
IssueAssignee.create!(issue: assigned, assignee: user)
puts "Assigned IID: #{assigned.iid}"

Re-run the listing request from step 2.

Expected: The assigned work item shows "notifications": { "subscribed": true } via the assignee fallback.

  1. Verify listing endpoint with non-participant returns false

Any work item where the current user is not the author, not an assignee, and has no subscription row should show:

"notifications": { "subscribed": false }
  1. Verify listing endpoint — explicit unsubscribe wins over fallback
# Unsubscribe from the authored work item
Subscription.create!(user: user, subscribable: authored, subscribed: false)

Re-run the listing request from step 2.

Expected: Even though the user is the author, the explicit unsubscribe row takes precedence:

"notifications": { "subscribed": false }
  1. Verify update endpoint with subscription toggle
curl --request PATCH \
  --header "PRIVATE-TOKEN: <PAT>" \
  --header "Content-Type: application/json" \
  --data '{"features": {"notifications": {"subscribed": true}}}' \
  "http://gdk.test:3000/api/v4/projects/7/-/work_items/#{wi.iid}"

Expected: Response returns 200 with "notifications": { "subscribed": true }. Confirm in console:

Subscription.find_by(user: user, subscribable: wi).subscribed
# => true

Toggle it off:

curl --request PATCH \
  --header "PRIVATE-TOKEN: <PAT>" \
  --header "Content-Type: application/json" \
  --data '{"features": {"notifications": {"subscribed": false}}}' \
  "http://gdk.test:3000/api/v4/projects/7/-/work_items/#{wi.iid}"

Expected: Response returns 200 with "notifications": { "subscribed": false }.

9. Verify update endpoint with error handling when update fails

curl --request PATCH \
  --header "PRIVATE-TOKEN: <PAT>" \
  --header "Content-Type: application/json" \
  --data '{"features": {"notifications": {"subscribed": true}, "time_tracking": {"time_estimate": "not a duration"}}}' \
  "http://gdk.test:3000/api/v4/projects/7/-/work_items/#{wi.iid}"

Expected: 422 Unprocessable Entity — the NoMethodError guard in render_work_item_update handles the nil work item gracefully.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Related to #601133 (closed)

Edited by Matt D'Angelo

Merge request reports

Loading