From 14d26c765aa4f270f783d6ca810a7c997dd6cfaa Mon Sep 17 00:00:00 2001 From: flym Date: Thu, 10 Sep 2026 01:18:20 +0800 Subject: [PATCH] feat: add controlled one-shot CMS admin seed route --- apps/cms/src/app/api/seed-admin/route.ts | 32 ++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 apps/cms/src/app/api/seed-admin/route.ts diff --git a/apps/cms/src/app/api/seed-admin/route.ts b/apps/cms/src/app/api/seed-admin/route.ts new file mode 100644 index 0000000..44f26ab --- /dev/null +++ b/apps/cms/src/app/api/seed-admin/route.ts @@ -0,0 +1,32 @@ +import { getPayload } from "payload"; +import config from "@payload-config"; +import { headers } from "next/headers"; + +export const POST = async () => { + const h = await headers(); + const token = h.get("x-cms-seed-token"); + if (!process.env.CMS_SEED_TOKEN || token !== process.env.CMS_SEED_TOKEN) { + return Response.json({ ok: false, error: "unauthorized" }, { status: 401 }); + } + + const email = process.env.CMS_ADMIN_EMAIL; + const password = process.env.CMS_ADMIN_PASSWORD; + if (!email || !password) { + return Response.json({ ok: false, error: "seed env not set" }, { status: 400 }); + } + + const payload = await getPayload({ config }); + const existing = await payload.find({ collection: "users", limit: 1, pagination: false }); + if (existing.totalDocs > 0) { + await payload.destroy(); + return Response.json({ ok: false, error: "user exists" }, { status: 409 }); + } + + await payload.create({ + collection: "users", + data: { email, password, displayName: "CMS Admin" }, + overrideAccess: true, + }); + await payload.destroy(); + return Response.json({ ok: true }); +};