Repository navigation
fix(plugin-forms): let editors star and mark submissions read, hide delete and export from them - #4756
fix(plugin-forms): let editors star and mark submissions read, hide delete and export from them#4756marks-zyz wants to merge 2 commits into
Conversation
…refuses The Submissions page renders star, mark read, delete and export for every role, but submissions/update, submissions/delete and submissions/export fall back to plugins:manage. Renders the page as an Editor against the real route permissions and handlers, and fails for all five controls.
…elete and export from them submissions/update declared no permission, so it fell back to plugins:manage while the Submissions page offered star and mark read to every role. It now takes content:edit_any (the editor tier, as ai-search entry/sync does). Delete and export stay plugins:manage; submissions/list returns canManage so the page stops showing editors those two controls. Export stays admin-only because its JSON carries the IP, user agent and referer that list and get already hide from editors.
🦋 Changeset detectedLatest commit: 148d57f The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Letting Editors triage submissions while delete and export stay Admin-only is a sound, scoped approach. The page uses canManage from submissions/list to hide the Admin-only controls. Both reviewers found one blocking problem: opening submissions/update to Editors lets them read the submitter metadata (IP, user agent, referer) that the list and get routes redact. That should be fixed before merge. The second reviewer also raised a test fixture type error and two repository-convention issues (a literal permission assertion and redundant comments). The first reviewer did not mention these.
Reviewed by anthropic/claude-opus-5-5 and openai/gpt-6.1-sol.
Findings
-
[needs fixing]
packages/plugins/forms/src/handlers/submissions.ts:94Now that
submissions/updateacceptscontent:edit_any(Editor tier), this line returns the full storedSubmissionto Editors, includingmeta.ip,meta.userAgentandmeta.referer.submissions/listandsubmissions/gethide those from Editors throughvisibleTo(#4294).submissionUpdateSchemamakesstatus,starredandnotesoptional. An Editor can therefore post{ id }with no changes and read the submitter details for any submission. That undoes the redaction this PR claims to keep. The admin page ignores the response body, so redacting it breaks nothing:return { id: input.id, ...visibleTo(ctx, updated) };Please add a test that calls the update handler as an Editor (role 40) and asserts the result has no
ip,userAgentorreferer. Both reviewers flagged this issue. The second one anchored it on the route permission atindex.ts:177and also asked for Admin update-response coverage. -
[needs fixing]
packages/plugins/forms/tests/submissions-editor-controls.test.tsx:144This fixture is declared to return
Submission, but itsmetaomits the requiredSubmissionMeta.refererfield. Vitest transpilation does not catch this, and the package typecheck excludes tests. Add the missing field:meta: { ip: "203.0.113.7", userAgent: "Mozilla/5.0", referer: null, country: "DE" }, -
[needs fixing]
packages/plugins/forms/tests/route-permissions.test.ts:44-46This test asserts the exact permission literal added to the route table instead of testing behavior (an Editor can triage, a lower role is refused). AGENTS.md prohibits this config-pin pattern. Remove it or replace it with authorization coverage through the real dispatcher, including a denied lower-role request.
-
[needs fixing]
packages/plugins/forms/src/handlers/submissions.ts:59This new comment restates the field's UI use and the permission policy, which the adjacent
canManageexpression and conditional rendering already show. The same redundant comment is added above the state declaration inadmin.tsx(~line 1145). AGENTS.md prohibits comments that narrate the change or restate clear code. Remove both.
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/auth-atproto
@emdash-cms/blocks
@emdash-cms/cloudflare
@emdash-cms/contentful-to-portable-text
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/plugin-cli
@emdash-cms/plugin-test
@emdash-cms/plugin-types
@emdash-cms/registry-client
@emdash-cms/registry-lexicons
@emdash-cms/registry-loader
@emdash-cms/registry-moderation
@emdash-cms/registry-verification
upgrade-emdash
@emdash-cms/sandbox-workerd
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-ai-search
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-field-kit
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
|
Closing as superseded by #4762, which merged as Checked this PR's test file Not released yet: the latest Tested by an AI agent on behalf of the maintainer. |
What does this PR do?
Lets an Editor star a submission and change its status on the Submissions page of
@emdash-cms/plugin-forms, and stops showing Editors the Delete and export controls they cannot use.The page renders star, "Toggle status", Delete, CSV and JSON for every role. After #3373 an Editor can read, but
submissions/update,submissions/deleteandsubmissions/exportdeclare nopermission, so they fall back toplugins:manage(packages/core/src/plugins/http-route-dispatch.ts:55). Clicking the star or the eye as an Editor shows "You don't have permission to do this." This is the follow-up #3373 listed under "Left for a maintainer call".index.ts:submissions/updategetspermission: "content:edit_any"(Editor tier).submissions/deleteandsubmissions/exportkeep theplugins:managedefault. The route-table comment now says which writes editors have.handlers/submissions.ts:submissions/listreturnscanManage(role >= ADMIN_ROLE, the same check that already redacts the webhook URL and the submitter details). The header comment is updated.admin.tsx: the Submissions page keepscanManagefrom the list response and renders Delete, CSV and JSON only when it is true. Star and "Toggle status" stay for everyone who can open the page.tests/submissions-editor-controls.test.tsxrenders the page as an Editor and as an Admin against the real route permissions and handlers, and clicks every control (first commit, fails onmain).tests/route-permissions.test.tsmovessubmissions/updateto a new editor-triage group and still fails if a route is left unclassified.tests/submissions-list-can-manage.test.tscovers admin, editor and no-user.Closes #4755
Decisions for a maintainer
content:edit_anyfollowsai-search(entry/sync) and the plugin route docs ("a narrower RBAC permission when the operation belongs to an existing capability").plugins:readalso passes the new tests and is one line to swap; I did not use it because it names a read capability.content:edit_anyexists at theemdash0.11.0 peer floor.exportHandlerreturnsitem.dataincludingmeta(IP, user agent, referer), which fix(plugin-forms): hide submitter IP, user agent and referer from editors #4294 hides from Editors in list and get.permissionline and also hide star and "Toggle status" behindcanManage; the tests only need the expectation flipped.Not in this PR
canManageapproach would apply. Say if you want it here.Type of change
Checklist
tsc --noEmit -p packages/plugins/forms, exit 0;tsgowas not installed in my checkout)oxlint --deny-warningsonpackages/plugins/forms/srcandtestsis clean; the type-aware pass (--type-aware) did not run locally because thetsgolintbinary was missing, so CI is the check for itpnpm testpasses (targeted:packages/plugins/forms)oxfmt --checkrun onpackages/plugins/forms/src,packages/plugins/forms/testsand the changeset: correct formatAI-generated code disclosure
mainand the full plugin suite with the fix.Screenshots / test output
mainat b4a845b, first commit only (the new test, no fix):With the fix (
packages/plugins/forms):The Admin case in the same test file asserts that star, "Toggle status", Delete, CSV and JSON are all still rendered for role 50 and that starring works.