Bootstrap configured admin users
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@
|
||||
"dev": "next dev",
|
||||
"build": "prisma generate && next build",
|
||||
"start": "next start",
|
||||
"start:deploy": "prisma db push && tsx prisma/seed-if-empty.ts && next start",
|
||||
"start:deploy": "prisma db push && tsx prisma/seed-if-empty.ts && tsx prisma/bootstrap-admins.ts && next start",
|
||||
"lint": "next lint",
|
||||
"db:generate": "prisma generate",
|
||||
"db:migrate": "prisma migrate dev",
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { PrismaClient, SubscriptionStatus, UserRole } from "@prisma/client";
|
||||
import { getConfiguredAdminEmails } from "../src/lib/admin-emails";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
const adminEmails = getConfiguredAdminEmails();
|
||||
if (adminEmails.length === 0) {
|
||||
console.log("No ADMIN_EMAILS configured. Skipping admin bootstrap.");
|
||||
return;
|
||||
}
|
||||
|
||||
const premiumPlan = await prisma.plan.findUnique({ where: { code: "PREMIUM" } });
|
||||
if (!premiumPlan) {
|
||||
throw new Error("PREMIUM plan is not seeded.");
|
||||
}
|
||||
|
||||
for (const email of adminEmails) {
|
||||
const user = await prisma.user.findUnique({ where: { email } });
|
||||
if (!user) {
|
||||
console.log(`Admin email ${email} is configured but user does not exist yet.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
await prisma.user.update({
|
||||
where: { id: user.id },
|
||||
data: { role: UserRole.ADMIN }
|
||||
});
|
||||
|
||||
await prisma.subscription.upsert({
|
||||
where: { userId: user.id },
|
||||
update: {
|
||||
planId: premiumPlan.id,
|
||||
status: SubscriptionStatus.ACTIVE,
|
||||
cancelAtPeriodEnd: false
|
||||
},
|
||||
create: {
|
||||
userId: user.id,
|
||||
planId: premiumPlan.id,
|
||||
status: SubscriptionStatus.ACTIVE
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Admin access ensured for ${email}.`);
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
@@ -1,8 +1,10 @@
|
||||
import bcrypt from "bcryptjs";
|
||||
import { UserRole } from "@prisma/client";
|
||||
import { NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { createSession } from "@/lib/auth/session";
|
||||
import { isConfiguredAdminEmail } from "@/lib/admin-emails";
|
||||
|
||||
const schema = z.object({
|
||||
email: z.string().email(),
|
||||
@@ -12,18 +14,21 @@ const schema = z.object({
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const body = schema.parse(await req.json());
|
||||
const free = await prisma.plan.findUnique({ where: { code: "FREE" } });
|
||||
if (!free) return NextResponse.json({ error: "PLAN_NOT_SEEDED" }, { status: 500 });
|
||||
const email = body.email.trim().toLowerCase();
|
||||
const isAdmin = isConfiguredAdminEmail(email);
|
||||
const plan = await prisma.plan.findUnique({ where: { code: isAdmin ? "PREMIUM" : "FREE" } });
|
||||
if (!plan) return NextResponse.json({ error: "PLAN_NOT_SEEDED" }, { status: 500 });
|
||||
|
||||
const exists = await prisma.user.findUnique({ where: { email: body.email } });
|
||||
const exists = await prisma.user.findUnique({ where: { email } });
|
||||
if (exists) return NextResponse.json({ error: "EMAIL_EXISTS" }, { status: 409 });
|
||||
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
email: body.email,
|
||||
name: body.name || body.email.split("@")[0],
|
||||
email,
|
||||
name: body.name || email.split("@")[0],
|
||||
passwordHash: await bcrypt.hash(body.password, 10),
|
||||
subscription: { create: { planId: free.id, status: "ACTIVE" } }
|
||||
role: isAdmin ? UserRole.ADMIN : UserRole.USER,
|
||||
subscription: { create: { planId: plan.id, status: "ACTIVE" } }
|
||||
}
|
||||
});
|
||||
await createSession(user.id);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
export function getConfiguredAdminEmails() {
|
||||
return (process.env.ADMIN_EMAILS || "")
|
||||
.split(/[\s,;]+/)
|
||||
.map((email) => email.trim().toLowerCase())
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
export function isConfiguredAdminEmail(email: string) {
|
||||
return getConfiguredAdminEmails().includes(email.trim().toLowerCase());
|
||||
}
|
||||
Reference in New Issue
Block a user