feat(api): expose work item subscribers on the public v1 API#9397
feat(api): expose work item subscribers on the public v1 API#9397clwluvw wants to merge 1 commit into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (9)
🚧 Files skipped from review as they are similar to previous changes (9)
📝 WalkthroughWalkthroughAdds issue subscriber serializers, list/create/delete API endpoints, work-item routes, OpenAPI metadata, and contract tests covering validation, authorization, persistence, and removal. ChangesIssue Subscriber API
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
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
apps/api/plane/tests/contract/api/test_subscribers.py (1)
164-173: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winAuth test only covers the list endpoint.
test_list_requires_authenticationvalidates 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
📒 Files selected for processing (9)
apps/api/plane/api/serializers/__init__.pyapps/api/plane/api/serializers/issue.pyapps/api/plane/api/urls/work_item.pyapps/api/plane/api/views/__init__.pyapps/api/plane/api/views/issue.pyapps/api/plane/tests/contract/api/test_subscribers.pyapps/api/plane/utils/openapi/__init__.pyapps/api/plane/utils/openapi/decorators.pyapps/api/plane/utils/openapi/parameters.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>
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):
Type of Change
Summary by CodeRabbit
expand=member.subscriber_idpath parameter for the new endpoints.