Skip to content

Add admin moderation actions to the plugin detail page - #434

Merged
leerob merged 3 commits into
cursor:mainfrom
ericzakariasson:feat/plugin-page-admin-actions
Sep 11, 2026
Merged

Add admin moderation actions to the plugin detail page#434
leerob merged 3 commits into
cursor:mainfrom
ericzakariasson:feat/plugin-page-admin-actions

Conversation

@ericzakariasson

@ericzakariasson ericzakariasson commented Sep 11, 2026

Copy link
Copy Markdown
Member

Summary

Admins can now moderate a plugin directly from its public page (e.g. /plugins/bulkpublish) instead of round-tripping through /admin/plugins.

A PluginAdminPanel card renders at the top of PluginDetailView for admins only. It shows the plugin's moderation state (Live/Hidden, scan: <status>, flag severity, verdict, Blocked), surfaces the scanner's flag_summary and reasons (which the public banner hides from non-owners), links to the queue, and offers the same actions as the queue, picked for the plugin's state:

Plugin state Buttons
Hidden, not flagged Approve · Re-scan · Delete
Live, not flagged Unpublish · Re-scan · Delete
Flagged (hidden or live-with-warning) Approve anyway · Re-scan · Confirm flag · Delete
Permanently blocked Approve anyway (clears the block) · Re-scan · Delete
Scan error Approve · Re-scan · Delete, plus the error message

Delete goes through an AlertDialog confirmation and then redirects to /admin/plugins. The other actions toast and router.refresh() inside a transition so the buttons stay disabled until the fresh row has rendered.

Changes

  • New apps/cursor/src/components/plugins/plugin-admin-panel.tsx — the panel. Rendering is gated client-side via isAdminClient (same pattern as VerifyControls); every action is enforced server-side by adminActionClient.
  • apps/cursor/src/actions/review-plugin.ts — adds unpublishPluginAction (admin-gated, active: false, same revalidation as its siblings). Previously an admin had no way to take a live plugin down short of permanently blocking (confirmFlagAction) or deleting it.
  • apps/cursor/src/components/plugins/plugin-detail.tsx — mounts the panel above ScanStatusBanner.

Flagged/blocked plugins route through approveFlaggedPluginAction rather than approvePluginAction, so approving also clears permanently_blocked; plain approve would leave the block in place and the next scan's short-circuit would hide the plugin again.

Notes

  • NEXT_PUBLIC_ADMIN_USER_IDS must mirror ADMIN_USER_IDS for the panel to appear (existing requirement for VerifyControls).
  • Non-admins see the page exactly as before; the component returns null.

Verification

  • bunx biome ci . and tsc --noEmit pass.
  • Rendered the component in a throwaway happy-dom harness with the server actions mocked, covering every state in the table above plus the non-admin case and the delete-confirmation flow (dispatches declinePluginAction, then navigates to /admin/plugins). Harness not committed.

Note

Medium Risk
Adds admin-only moderation paths on public pages (unpublish, approve, delete); server enforcement via adminActionClient limits exposure, but mistakes affect directory visibility and plugin records.

Overview
Adds in-context admin moderation on public plugin detail pages so reviewers don’t have to use /admin/plugins for every action.

A new PluginAdminPanel (admin-only via isAdminClient, actions via adminActionClient) sits at the top of PluginDetailView. It shows live/hidden, scan status, flag severity, blocked state, and admin-visible flag_summary/reasons, with state-dependent actions: approve, unpublish, re-scan, confirm flag, and delete (with confirmation + redirect to the queue).

Introduces unpublishPluginAction, which sets active: false without permanent block or delete—distinct from confirm-flag/delete. Flagged or permanently blocked plugins use approveFlaggedPluginAction so approval clears the block; successful actions toast and router.refresh() in a transition until fresh data loads.

Reviewed by Cursor Bugbot for commit fc456ef. Bugbot is set up for automated code reviews on this repo. Configure here.

Admins can now approve, re-scan, confirm a flag, unpublish, or delete a
plugin directly from /plugins/[slug] instead of going through
/admin/plugins. The panel mirrors the queue's actions and picks the
right one for the plugin's state (hidden vs live, flagged, blocked,
scan error) and surfaces the scanner's summary and reasons, which the
public banner hides from non-owners.

Adds an admin-gated unpublishPluginAction so a live plugin can be taken
down without permanently blocking or deleting it.

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

@ericzakariasson is attempting to deploy a commit to the Anysphere Team on Vercel.

A member of the Team first needs to authorize it.

ericzakariasson and others added 2 commits September 11, 2026 11:36
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@leerob
leerob merged commit 8ff3631 into cursor:main Sep 11, 2026
2 of 3 checks passed
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.

2 participants