- Plan/Product/Infrastructure: empty states now suggest a concrete AI
prompt so non-technical users know exactly what to type rather than
staring at a blank category ("Try: Add a Postgres database…")
- Workspace settings danger zone: wired Delete Workspace to a new
POST /api/workspaces/delete endpoint (deletes projects + chat
threads; Coolify resources intentionally untouched)
Made-with: Cursor
72 lines
2.1 KiB
TypeScript
72 lines
2.1 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { authSession } from "@/lib/auth/session-server";
|
|
import { query } from "@/lib/db-postgres";
|
|
|
|
/**
|
|
* POST /api/workspaces/delete
|
|
* Body: { slug: string }
|
|
*
|
|
* Deletes the workspace record and all associated projects/threads.
|
|
* Coolify resources (services, databases) are NOT deleted — the user
|
|
* must clean those up manually or via the AI. This only removes Vibn's
|
|
* knowledge of the workspace.
|
|
*
|
|
* Ownership check: the workspace's owner_user_id must match the
|
|
* authenticated user.
|
|
*/
|
|
export async function POST(request: Request) {
|
|
try {
|
|
const session = await authSession();
|
|
if (!session?.user?.email) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
|
|
const { slug } = await request.json();
|
|
if (!slug) {
|
|
return NextResponse.json({ error: "slug is required" }, { status: 400 });
|
|
}
|
|
|
|
// Find the workspace and verify ownership
|
|
const wsRows = await query<{ id: string; slug: string }>(
|
|
`SELECT vw.id, vw.slug
|
|
FROM vibn_workspaces vw
|
|
JOIN fs_users u ON u.id = vw.owner_user_id
|
|
WHERE vw.slug = $1 AND u.data->>'email' = $2
|
|
LIMIT 1`,
|
|
[slug, session.user.email],
|
|
);
|
|
|
|
if (!wsRows.length) {
|
|
return NextResponse.json({ error: "Workspace not found or unauthorized" }, { status: 404 });
|
|
}
|
|
|
|
const workspaceId = wsRows[0].id;
|
|
|
|
// Delete all chat threads scoped to the workspace
|
|
await query(
|
|
`DELETE FROM fs_chat_threads WHERE workspace = $1`,
|
|
[slug],
|
|
);
|
|
|
|
// Delete all projects in the workspace
|
|
await query(
|
|
`DELETE FROM fs_projects WHERE workspace = $1`,
|
|
[slug],
|
|
);
|
|
|
|
// Delete the workspace itself
|
|
await query(
|
|
`DELETE FROM vibn_workspaces WHERE id = $1`,
|
|
[workspaceId],
|
|
);
|
|
|
|
return NextResponse.json({ success: true, message: "Workspace deleted" });
|
|
} catch (error) {
|
|
console.error("[POST /api/workspaces/delete]", error);
|
|
return NextResponse.json(
|
|
{ error: error instanceof Error ? error.message : "Delete failed" },
|
|
{ status: 500 },
|
|
);
|
|
}
|
|
}
|