Skip to content

fix(api): validate assignees/labels in IssueSerializer instead of silently dropping invalid ids - #9526

Open
houssaineamzil wants to merge 1 commit into
makeplane:previewfrom
houssaineamzil:fix/issue-9517-assignee-label-validation
Open

fix(api): validate assignees/labels in IssueSerializer instead of silently dropping invalid ids#9526
houssaineamzil wants to merge 1 commit into
makeplane:previewfrom
houssaineamzil:fix/issue-9517-assignee-label-validation

Conversation

@houssaineamzil

@houssaineamzil houssaineamzil commented Aug 2, 2026

Copy link
Copy Markdown

Summary

Fixes #9517.

Creating or updating a work item through the external API (POST/PATCH /api/v1/.../issues/) with an assignees or labels list returned 200/201 even when some of those ids weren't valid for the project (not an active project member with role >= 15, or a label from a different project). The invalid ids were silently filtered out in IssueSerializer.validate() — no error, and the work item just came back unassigned/unlabeled.

This matches the same silent-narrowing pattern already fixed for state/parent, which raise a ValidationError when the id isn't valid for the project. Assignees and labels were the odd ones out.

Change

In apps/api/plane/api/serializers/issue.py, IssueSerializer.validate():

  • Compute which submitted assignee/label ids are actually valid for the project (same querysets as before).
  • If any submitted id isn't in that valid set, raise a ValidationError naming the offending ids, instead of quietly dropping them.
  • Valid ids continue to be passed through as a plain list to create()/update(), which already just iterate over them — no change needed there.

A partially-valid list (some valid, some invalid ids) now rejects the whole request rather than silently keeping only the valid subset.

Test plan

  • New unit tests (apps/api/plane/tests/unit/serializers/test_issue_serializer_api.py) covering the serializer directly: rejects a non-member assignee, rejects a foreign-project label, still accepts a valid active project member.
  • New end-to-end contract tests (apps/api/plane/tests/contract/api/test_issue_assignee_label_validation.py) hitting the real /api/v1/.../issues/ endpoint via APIClient, covering the exact repro steps from the issue: POST with a non-member assignee, POST with a foreign label, PATCH adding a non-member assignee, a mixed valid+invalid assignee list, and a regression guard that a genuinely valid assignee still works.
  • Verified true RED before the fix (reproduced the bug end-to-end: 201/200 responses instead of 400) and GREEN after.
  • Full existing unit test suite passes with no regressions.

Summary by CodeRabbit

  • Bug Fixes

    • Issue creation and updates now reject assignees who aren’t active members of the project.
    • Labels from other projects are rejected.
    • Mixed valid and invalid assignee lists are rejected instead of partially applied.
    • Valid project members and labels continue to work as expected.
  • Tests

    • Added coverage for invalid assignments, cross-project labels, update preservation, and valid issue creation.

…ently dropping invalid ids

Work item create/update via the external API returned 200/201 even
when assignees or labels didn't belong to the project, quietly
filtering the invalid ids out with no error. Now raises the same kind
of ValidationError already used for state/parent, matching the pattern
of makeplane#9517.
@CLAassistant

CLAassistant commented Aug 2, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

IssueSerializer now rejects assignees outside the current project or without sufficient membership, and labels outside the project. Unit and contract tests cover invalid, mixed, update, and valid assignment cases.

Changes

Issue relationship validation

Layer / File(s) Summary
Serializer relationship validation
apps/api/plane/api/serializers/issue.py, apps/api/plane/tests/unit/serializers/test_issue_serializer_api.py
IssueSerializer validates active project-member assignees and project-owned labels. Unit tests cover rejected relationships and valid project members.
REST API contract coverage
apps/api/plane/tests/contract/api/test_issue_assignee_label_validation.py
Contract tests verify HTTP 400 responses for invalid relationships, preservation during invalid updates, rejection of mixed assignee lists, and successful valid assignment.

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

Possibly related issues

Suggested reviewers: dheeru0198

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: IssueSerializer now validates assignees and labels instead of silently dropping invalid IDs.
Description check ✅ Passed The description explains the problem, implementation, issue reference, and test coverage; it omits the template headings but includes the required information.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

Warning

⚠️ This pull request shows signs of AI-generated slop (redundant_comments). It has been flagged by CodeRabbit slop detection and should be reviewed carefully.

@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: 1

🤖 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/tests/contract/api/test_issue_assignee_label_validation.py`:
- Around line 19-23: Update the fixture teardown around the task_always_eager
setup to capture the original celery_app.conf.task_eager_propagates value before
changing it, then restore that value after yield alongside task_always_eager.
Preserve the fixture’s existing eager-task configuration behavior.
🪄 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 Plus

Run ID: 01fbfb6e-5b4a-4384-bdac-a914e6e89d4c

📥 Commits

Reviewing files that changed from the base of the PR and between 1ed664e and 92fc8f9.

📒 Files selected for processing (3)
  • apps/api/plane/api/serializers/issue.py
  • apps/api/plane/tests/contract/api/test_issue_assignee_label_validation.py
  • apps/api/plane/tests/unit/serializers/test_issue_serializer_api.py

Comment on lines +19 to +23
original = celery_app.conf.task_always_eager
celery_app.conf.task_always_eager = True
celery_app.conf.task_eager_propagates = False
yield
celery_app.conf.task_always_eager = original

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Restore task_eager_propagates during fixture teardown.

The fixture changes task_eager_propagates on Line 21 but does not restore it. Later tests can observe False instead of their prior configuration.

Proposed fix
     original = celery_app.conf.task_always_eager
+    original_propagates = celery_app.conf.task_eager_propagates
     celery_app.conf.task_always_eager = True
     celery_app.conf.task_eager_propagates = False
     yield
     celery_app.conf.task_always_eager = original
+    celery_app.conf.task_eager_propagates = original_propagates
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
original = celery_app.conf.task_always_eager
celery_app.conf.task_always_eager = True
celery_app.conf.task_eager_propagates = False
yield
celery_app.conf.task_always_eager = original
original = celery_app.conf.task_always_eager
original_propagates = celery_app.conf.task_eager_propagates
celery_app.conf.task_always_eager = True
celery_app.conf.task_eager_propagates = False
yield
celery_app.conf.task_always_eager = original
celery_app.conf.task_eager_propagates = original_propagates
🤖 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_issue_assignee_label_validation.py`
around lines 19 - 23, Update the fixture teardown around the task_always_eager
setup to capture the original celery_app.conf.task_eager_propagates value before
changing it, then restore that value after yield alongside task_always_eager.
Preserve the fixture’s existing eager-task configuration behavior.

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.

🐛 Bug: Work item create/update via API silently drops assignees who aren't active project members (returns 200/201, no error)

2 participants