Skip to content

fix: scope draft publish to the draft's owner - #9811

Open
CaptainAni187 wants to merge 1 commit into
makeplane:previewfrom
CaptainAni187:fix-draft-to-issue-ownership
Open

fix: scope draft publish to the draft's owner#9811
CaptainAni187 wants to merge 1 commit into
makeplane:previewfrom
CaptainAni187:fix-draft-to-issue-ownership

Conversation

@CaptainAni187

@CaptainAni187 CaptainAni187 commented Sep 10, 2026

Copy link
Copy Markdown

Description

Draft work items are personal. list, retrieve and partial_update in WorkspaceDraftIssueViewSet all resolve them with created_by=request.user, but create_draft_to_issue looked the draft up by id alone:

draft_issue = self.get_queryset().filter(pk=draft_id).first()

get_queryset() only filters by workspace, so any workspace member holding a draft's UUID could publish another user's draft. Publishing also deletes the original, so the author loses the draft with nothing in the activity trail naming who did it.

Worth noting why the decorator does not already cover this: allow_permission(..., creator=True, model=...) checks kwargs["pk"], and this route receives draft_id. That is why destroy is protected and this action is not, and why the fix belongs in the query rather than on the decorator.

The unresolved case now returns 404 instead of raising AttributeError on None.project_id, matching how retrieve handles a draft that is not there.

Test

plane/tests/unit/views/test_workspace_draft.py asserts the lookup carries created_by, that a draft the caller does not own never reaches IssueCreateSerializer, and that a missing draft returns 404. Reverting the fix fails all three, the last with the AttributeError the guard removes.

$ pytest plane/tests/unit/views/test_workspace_draft.py -q
3 passed

ruff check and ruff format --check are clean on both files.

Fixes #9363

Summary by CodeRabbit

  • Bug Fixes

    • Restricted draft-to-issue publishing to drafts owned by the requesting user.
    • Drafts belonging to another user can no longer be published.
    • Missing or inaccessible drafts now return a clear 404 response instead of causing an error.
  • Tests

    • Added regression coverage for ownership checks and missing-draft handling.

Drafts are personal, and list, retrieve and partial_update all look them up with
created_by=request.user. create_draft_to_issue looked up by id alone, so any
workspace member with a draft's UUID could publish someone else's draft, which
also deletes the original as part of the conversion.

The decorator's creator check cannot cover this route because it reads
kwargs["pk"] and this one receives draft_id, so scope the query instead, the way
the neighbouring actions already do. A draft that does not resolve now returns
404 rather than raising AttributeError on None.

Fixes makeplane#9363
@coldtea-pr-lens

coldtea-pr-lens Bot commented Sep 10, 2026

Copy link
Copy Markdown

◈ PR Lens

🟢 +0 new · 🟠 ~1 changed · 🔴 -0 removed · 1 flow · 2 files · commit e8a496d


Architecture

Architecture diagram for makeplane/plane at e8a496d

1 component touched across 5 lanes.

Open the interactive canvas


Inside the changed components — 1 view

Component view — Draft issue conversion

The workspace draft viewset enforces user isolation by scoping draft lookups to the creator before issue creation.

Architecture view of Component view — Draft issue conversion in makeplane/plane

Data flow

Data flow diagram for makeplane/plane at e8a496d

Publishing draft issue to issue

Open the interactive canvas


View

  • Architecture lens
  • Data flow lens
  • Expand every detail

Tip

The CLI's render reads .github/pr-lens.yml and applies your renames, exclusions and lane pins at draw time.

🪧 More tips
  • Run npx skills add coldteadotai/pr-lens, then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Run npx @coldtea/pr-lens-cli analyze --base origin/main on a branch, then npx @coldtea/pr-lens-cli render .pr-lens/graph.json. Same lenses, your own model key, before the pull request exists.
  • Untick Architecture lens or Data flow lens under View to hide a diagram, or tick Expand every detail to open every section. The comment redraws in a few seconds.
  • Click the link under each diagram to open it on a canvas you can zoom, pan and step through.
  • The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change.
  • Open a diagram on the canvas, then press W or click play to walk through the change one step at a time.
  • Set github.comment.collapsed: true in .github/pr-lens.yml to fold the comment behind one View architecture and data flow row. Drawing still runs on every push.
  • Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and your model provider's key as its api-key to run PR Lens from your own CI. Any /chat/completions endpoint works.
  • Push a commit and the comment redraws for the new head. A slow older run never overwrites a newer one.
  • Switch GitHub to dark mode and the diagrams follow. The moving dots are this pull request's data in motion.

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

❤️ Share

@CLAassistant

CLAassistant commented Sep 10, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 43d4ea61-76d2-44dc-87f5-c8f019eda606

📥 Commits

Reviewing files that changed from the base of the PR and between 2f895b8 and e8a496d.

📒 Files selected for processing (2)
  • apps/api/plane/app/views/workspace/draft.py
  • apps/api/plane/tests/unit/views/test_workspace_draft.py

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

The draft-to-issue endpoint now limits publication to drafts created by the requesting user. It returns 404 for unauthorized or missing drafts. New unit tests validate query scoping, serializer exclusion, and missing-draft handling.

Changes

Draft publication security

Layer / File(s) Summary
Ownership-scoped draft publication and regression tests
apps/api/plane/app/views/workspace/draft.py, apps/api/plane/tests/unit/views/test_workspace_draft.py
The draft lookup now filters by created_by=request.user. The endpoint returns 404 when no matching draft exists. Tests verify ownership filtering, unauthorized publication behavior, serializer exclusion, and missing-draft handling.

Estimated code review effort: 2 (Simple) | ~10 minutes

Severity of issue fixed: High

Merge Risk: ⚪ Minimal · up to e8a49

Draft publication now requires ownership, preventing other workspace members from publishing or deleting someone else’s draft. Unauthorized and missing drafts return 404, with regression coverage for these cases and no concrete merge-blocking risk remaining.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: limiting draft publishing to the draft owner.
Description check ✅ Passed The description explains the vulnerability, implementation rationale, behavior change, tests, formatting checks, and linked issue. It is sufficiently complete, although the Type of Change checkbox is …
Linked Issues check ✅ Passed The changes satisfy issue #9363 by restricting draft lookup to created_by=request.user, preventing unauthorized publishing and deletion. The 404 handling and regression tests support the required beha…
Out of Scope Changes check ✅ Passed The code and tests are directly related to the ownership check and missing-draft handling required by issue #9363. No unrelated changes are evident.
  • Fix all pre-merge checks with AI
✨ 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.

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.

Any workspace member can publish (and delete) another user's private draft

2 participants