import { NextRequest, NextResponse } from "next/server"; import { db } from "@/lib/db"; import { invitations, users } from "@/lib/db/schema"; import { auth } from "@/lib/auth"; import { eq } from "drizzle-orm"; import { z } from "zod"; import { nanoid } from "nanoid"; const AcceptSchema = z.object({ token: z.string().min(1), name: z.string().min(2).max(100), password: z.string().min(8).max(128), }); export async function POST(req: NextRequest) { let body: z.infer; try { body = AcceptSchema.parse(await req.json()); } catch { return NextResponse.json({ error: "Invalid request" }, { status: 400 }); } const invitation = await db .select() .from(invitations) .where(eq(invitations.token, body.token)) .get(); if (!invitation) { return NextResponse.json({ error: "Invalid invitation token" }, { status: 404 }); } if (invitation.acceptedAt) { return NextResponse.json({ error: "Invitation already used" }, { status: 409 }); } if (Number(invitation.expiresAt) < Date.now()) { return NextResponse.json({ error: "Invitation has expired" }, { status: 410 }); } // Check if email already registered const existing = await db.select().from(users).where(eq(users.email, invitation.email)).get(); if (existing) { return NextResponse.json({ error: "Email already registered" }, { status: 409 }); } // Create user via Better Auth try { await auth.api.signUpEmail({ body: { email: invitation.email, password: body.password, name: body.name, }, }); } catch (err) { const message = err instanceof Error ? err.message : "Failed to create account"; return NextResponse.json({ error: message }, { status: 500 }); } // Mark invitation as accepted and set role await db .update(invitations) .set({ acceptedAt: Date.now() }) .where(eq(invitations.token, body.token)); await db .update(users) .set({ role: invitation.role }) .where(eq(users.email, invitation.email)); return NextResponse.json({ success: true }); }