-
Notifications
You must be signed in to change notification settings - Fork 672
Add plugin owner menu with publish, delete, and verification actions. #405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| "use server"; | ||
|
|
||
| import { revalidatePath } from "next/cache"; | ||
| import { z } from "zod"; | ||
| import { createClient } from "@/utils/supabase/server"; | ||
| import { ActionError, authActionClient } from "./safe-action"; | ||
|
|
||
| export const deletePluginAction = authActionClient | ||
| .metadata({ | ||
| actionName: "delete-plugin", | ||
| }) | ||
| .schema( | ||
| z.object({ | ||
| id: z.string().uuid(), | ||
| }), | ||
| ) | ||
| .action(async ({ parsedInput: { id }, ctx: { userId } }) => { | ||
| const supabase = await createClient(); | ||
|
|
||
| const { data: existing, error: fetchError } = await supabase | ||
| .from("plugins") | ||
| .select("id, owner_id, slug, active") | ||
| .eq("id", id) | ||
| .single(); | ||
|
|
||
| if (fetchError || !existing) { | ||
| throw new ActionError("Plugin not found."); | ||
| } | ||
|
|
||
| if (existing.owner_id !== userId) { | ||
| throw new ActionError("You do not have permission to delete this plugin."); | ||
| } | ||
|
|
||
| const { error } = await supabase | ||
| .from("plugins") | ||
| .delete() | ||
| .eq("id", id) | ||
| .eq("owner_id", userId); | ||
|
|
||
| if (error) { | ||
| throw new ActionError(`Failed to delete plugin: ${error.message}`); | ||
| } | ||
|
|
||
| revalidatePath("/"); | ||
| revalidatePath("/admin/plugins"); | ||
|
|
||
| return { slug: existing.slug }; | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| "use server"; | ||
|
|
||
| import { revalidatePath } from "next/cache"; | ||
| import { z } from "zod"; | ||
| import { createClient } from "@/utils/supabase/server"; | ||
| import { ActionError, authActionClient } from "./safe-action"; | ||
|
|
||
| export const togglePluginListingAction = authActionClient | ||
| .metadata({ | ||
| actionName: "toggle-plugin-listing", | ||
| }) | ||
| .schema( | ||
| z.object({ | ||
| id: z.string().uuid(), | ||
| active: z.boolean(), | ||
| }), | ||
| ) | ||
| .action(async ({ parsedInput: { id, active }, ctx: { userId } }) => { | ||
| const supabase = await createClient(); | ||
|
|
||
| const { data: existing, error: fetchError } = await supabase | ||
| .from("plugins") | ||
| .select("id, owner_id, slug, permanently_blocked") | ||
| .eq("id", id) | ||
| .single(); | ||
|
|
||
| if (fetchError || !existing) { | ||
| throw new ActionError("Plugin not found."); | ||
| } | ||
|
|
||
| if (existing.owner_id !== userId) { | ||
| throw new ActionError("You do not have permission to update this plugin."); | ||
| } | ||
|
|
||
| if (active && existing.permanently_blocked) { | ||
| throw new ActionError( | ||
| "This plugin cannot be published. Contact support if you believe this is a mistake.", | ||
| ); | ||
| } | ||
|
|
||
| const { data, error } = await supabase | ||
| .from("plugins") | ||
| .update({ active }) | ||
| .eq("id", id) | ||
| .eq("owner_id", userId) | ||
| .select("slug") | ||
| .single(); | ||
|
|
||
| if (error) { | ||
| throw new ActionError(error.message); | ||
| } | ||
|
|
||
| revalidatePath("/"); | ||
| revalidatePath(`/plugins/${data.slug}`); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing null check after updateMedium Severity · Logic Bug After the listing update, the action only checks Supabase Reviewed by Cursor Bugbot for commit 5e1c31e. Configure here. |
||
|
|
||
| return data; | ||
| }); | ||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Publish ignores scan status
High Severity · Logic Bug
togglePluginListingActionsetsactiveto true for owners with only apermanently_blockedcheck, so plugins stillpending,scanning,flagged, orerrorcan be published and appear in directory queries that filter onactive.Additional Locations (1)
apps/cursor/src/components/plugins/plugin-owner-menu.tsx#L128-L192Reviewed by Cursor Bugbot for commit 5e1c31e. Configure here.