Skip to content

feat(api): expose work item subscribers on the public v1 API#9397

Open
clwluvw wants to merge 1 commit into
makeplane:previewfrom
clwluvw:watchers
Open

feat(api): expose work item subscribers on the public v1 API#9397
clwluvw wants to merge 1 commit into
makeplane:previewfrom
clwluvw:watchers

Conversation

@clwluvw

@clwluvw clwluvw commented Jul 11, 2026

Copy link
Copy Markdown

Description

Add token-authenticated endpoints to list, add, and remove the subscribers (watchers) of a work item on the public /api/v1 API, mirroring the internal IssueSubscriberViewSet but following the public API's conventions (APIKeyAuthentication, the public BaseAPIView, cursor pagination, and the ProjectEntityPermission used by sibling public issue endpoints).

Endpoints (under the work-items prefix):

  GET    .../work-items/{issue_id}/subscribers/           list subscribers
  POST   .../work-items/{issue_id}/subscribers/           add by subscriber_id
  DELETE .../work-items/{issue_id}/subscribers/{user_id}/ remove by user id

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring
  • Performance improvements
  • Documentation update

Summary by CodeRabbit

  • New Features
    • Added API support for managing work-item subscribers (watchers) on issues, including list/create and delete endpoints.
    • Subscriber responses include embedded member details, including when using expand=member.
    • Subscriptions are restricted to active project members and prevent duplicate subscriptions.
  • Documentation
    • Added OpenAPI documentation helpers and a reusable subscriber_id path parameter for the new endpoints.
  • Tests
    • Added contract tests covering listing, creation validation (missing/invalid/duplicate), permissions, and deletion (including missing records).

Copilot AI review requested due to automatic review settings July 11, 2026 19:42
@CLAassistant

CLAassistant commented Jul 11, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5c3ed658-58bf-4bba-8693-b25532ebed2c

📥 Commits

Reviewing files that changed from the base of the PR and between 1b0b14e and d55b51f.

📒 Files selected for processing (9)
  • apps/api/plane/api/serializers/__init__.py
  • apps/api/plane/api/serializers/issue.py
  • apps/api/plane/api/urls/work_item.py
  • apps/api/plane/api/views/__init__.py
  • apps/api/plane/api/views/issue.py
  • apps/api/plane/tests/contract/api/test_subscribers.py
  • apps/api/plane/utils/openapi/__init__.py
  • apps/api/plane/utils/openapi/decorators.py
  • apps/api/plane/utils/openapi/parameters.py
🚧 Files skipped from review as they are similar to previous changes (9)
  • apps/api/plane/api/views/init.py
  • apps/api/plane/api/serializers/init.py
  • apps/api/plane/utils/openapi/parameters.py
  • apps/api/plane/utils/openapi/init.py
  • apps/api/plane/api/serializers/issue.py
  • apps/api/plane/tests/contract/api/test_subscribers.py
  • apps/api/plane/api/urls/work_item.py
  • apps/api/plane/utils/openapi/decorators.py
  • apps/api/plane/api/views/issue.py

📝 Walkthrough

Walkthrough

Adds issue subscriber serializers, list/create/delete API endpoints, work-item routes, OpenAPI metadata, and contract tests covering validation, authorization, persistence, and removal.

Changes

Issue Subscriber API

Layer / File(s) Summary
Subscriber serializers and OpenAPI contracts
apps/api/plane/api/serializers/issue.py, apps/api/plane/api/serializers/__init__.py, apps/api/plane/utils/openapi/*
Adds serializers for subscriber responses and creation payloads, plus reusable subscriber path-parameter and endpoint documentation exports.
Subscriber endpoint flow
apps/api/plane/api/views/issue.py, apps/api/plane/api/views/__init__.py, apps/api/plane/api/urls/work_item.py
Adds list/create and delete endpoints, validates project membership and duplicate subscriptions, and exposes the new work-item routes.
Subscriber contract validation
apps/api/plane/tests/contract/api/test_subscribers.py
Tests listing, creation, validation failures, authentication, missing issues, duplicate subscriptions, and deletion behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant APIClient
  participant IssueSubscriberListCreateAPIEndpoint
  participant IssueSubscriberCreateSerializer
  participant IssueSubscriber
  APIClient->>IssueSubscriberListCreateAPIEndpoint: POST subscriber_id
  IssueSubscriberListCreateAPIEndpoint->>IssueSubscriberCreateSerializer: validate payload
  IssueSubscriberCreateSerializer-->>IssueSubscriberListCreateAPIEndpoint: validated subscriber_id
  IssueSubscriberListCreateAPIEndpoint->>IssueSubscriber: create subscription
  IssueSubscriber-->>IssueSubscriberListCreateAPIEndpoint: created subscription
  IssueSubscriberListCreateAPIEndpoint-->>APIClient: serialized subscriber
Loading

Suggested reviewers: pablohashescobar, dheeru0198, Saurabhkmr98, sangeethailango

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the change and type, but it omits required Test Scenarios and References sections. Add a Test Scenarios section describing verification steps and a References section with related issues or links; include Screenshots only if relevant.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: exposing work item subscribers in the public API.
Docstring Coverage ✅ Passed Docstring coverage is 84.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds public API support for managing “subscribers/watchers” on work items under /api/v1, aligning the feature with existing public API conventions (API key auth, BaseAPIView, cursor pagination, and ProjectEntityPermission).

Changes:

  • Introduces public list/add/remove subscriber endpoints for work items and wires them into the v1 URL config.
  • Adds public serializers for subscriber responses and the create payload (subscriber_id).
  • Extends OpenAPI helpers (parameter + decorator) and adds contract tests for the new endpoints.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
apps/api/plane/utils/openapi/parameters.py Adds SUBSCRIBER_ID_PARAMETER for path documentation.
apps/api/plane/utils/openapi/decorators.py Adds work_item_subscriber_docs decorator to standardize OpenAPI docs for subscriber endpoints.
apps/api/plane/utils/openapi/init.py Exports new OpenAPI parameter and decorator.
apps/api/plane/api/serializers/issue.py Adds IssueSubscriberSerializer and IssueSubscriberCreateSerializer for the public API.
apps/api/plane/api/serializers/init.py Re-exports the new subscriber serializers.
apps/api/plane/api/views/issue.py Implements list/create and delete subscriber endpoints under public v1 work-items.
apps/api/plane/api/views/init.py Exposes new views from the API views package.
apps/api/plane/api/urls/work_item.py Registers the new subscriber URL routes under the work-items prefix.
apps/api/plane/tests/contract/api/test_subscribers.py Adds contract tests covering list/add/remove subscriber behavior.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
apps/api/plane/tests/contract/api/test_subscribers.py (1)

164-173: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Auth test only covers the list endpoint.

test_list_requires_authentication validates auth for GET, but there are no equivalent tests for POST (create) or DELETE. Adding unauthenticated tests for those endpoints would ensure auth enforcement is consistent across all subscriber operations.

🛡️ Suggested auth tests for create and delete
     `@pytest.mark.django_db`
     def test_list_requires_authentication(self, api_client, workspace, project, issue):
         """Without an API key the endpoint rejects the request."""
         url = self.get_url(workspace.slug, project.id, issue.id)
         response = api_client.get(url)

         assert response.status_code in (
             status.HTTP_401_UNAUTHORIZED,
             status.HTTP_403_FORBIDDEN,
         )
+
+    `@pytest.mark.django_db`
+    def test_create_requires_authentication(self, api_client, workspace, project, issue, member_user):
+        """Without an API key the create endpoint rejects the request."""
+        url = self.get_url(workspace.slug, project.id, issue.id)
+        response = api_client.post(url, {"subscriber_id": str(member_user.id)}, format="json")
+
+        assert response.status_code in (
+            status.HTTP_401_UNAUTHORIZED,
+            status.HTTP_403_FORBIDDEN,
+        )
+    `@pytest.mark.django_db`
+    def test_remove_requires_authentication(self, api_client, workspace, project, issue, member_user):
+        """Without an API key the delete endpoint rejects the request."""
+        url = self.get_url(workspace.slug, project.id, issue.id, member_user.id)
+        response = api_client.delete(url)
+
+        assert response.status_code in (
+            status.HTTP_401_UNAUTHORIZED,
+            status.HTTP_403_FORBIDDEN,
+        )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/plane/tests/contract/api/test_subscribers.py` around lines 164 -
173, Extend the subscriber authentication coverage alongside
test_list_requires_authentication by adding unauthenticated tests for the POST
create and DELETE endpoints. Build each request with the existing api_client and
test fixtures, then assert the response returns either HTTP 401 or HTTP 403,
matching the list test’s accepted authentication outcomes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/plane/api/serializers/issue.py`:
- Around line 484-528: Update the generic expansion logic used with
IssueSubscriberSerializer so the member field is excluded from the fallback
expansion path and cannot overwrite the embedded UserLiteSerializer output.
Preserve member’s serialized subscriber profile when expand=member is requested,
while leaving other expandable fields unchanged.

In `@apps/api/plane/api/views/issue.py`:
- Around line 2628-2640: Update the GET method in the issue subscriber view to
verify the requested issue exists before calling paginate, using the same issue
lookup and not-found behavior already implemented by post(). Preserve the
existing queryset, serializer, and pagination flow for valid issues, while
returning the established 404 response for nonexistent issues.

---

Nitpick comments:
In `@apps/api/plane/tests/contract/api/test_subscribers.py`:
- Around line 164-173: Extend the subscriber authentication coverage alongside
test_list_requires_authentication by adding unauthenticated tests for the POST
create and DELETE endpoints. Build each request with the existing api_client and
test fixtures, then assert the response returns either HTTP 401 or HTTP 403,
matching the list test’s accepted authentication outcomes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b0670e57-f7b0-4888-98d8-cd76c0b4f108

📥 Commits

Reviewing files that changed from the base of the PR and between dc9d80b and 1b0b14e.

📒 Files selected for processing (9)
  • apps/api/plane/api/serializers/__init__.py
  • apps/api/plane/api/serializers/issue.py
  • apps/api/plane/api/urls/work_item.py
  • apps/api/plane/api/views/__init__.py
  • apps/api/plane/api/views/issue.py
  • apps/api/plane/tests/contract/api/test_subscribers.py
  • apps/api/plane/utils/openapi/__init__.py
  • apps/api/plane/utils/openapi/decorators.py
  • apps/api/plane/utils/openapi/parameters.py

Comment thread apps/api/plane/api/serializers/issue.py
Comment thread apps/api/plane/api/views/issue.py
Add token-authenticated endpoints to list, add, and remove the subscribers
(watchers) of a work item on the public /api/v1 API, mirroring the internal
IssueSubscriberViewSet but following the public API's conventions
(APIKeyAuthentication, the public BaseAPIView, cursor pagination, and the
ProjectEntityPermission used by sibling public issue endpoints).

Endpoints (under the work-items prefix):
  GET    .../work-items/{issue_id}/subscribers/           list subscribers
  POST   .../work-items/{issue_id}/subscribers/           add by subscriber_id
  DELETE .../work-items/{issue_id}/subscribers/{user_id}/ remove by user id

- IssueSubscriberSerializer / IssueSubscriberCreateSerializer reuse the
  IssueSubscriber through-model and embed the subscriber user as `member`.
- New BaseAPIView endpoints enforce project membership, validate the target
  user is an active project member, reject duplicates, and 404 cleanly.
- Routes registered in the work-items URL module; an OpenAPI decorator and
  path parameter are added so the endpoints appear in the generated schema.
- Contract tests mirror the existing public-API issue tests (10 cases).

Signed-off-by: Seena Fallah <seenafallah@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants