import { NextRequest, NextResponse } from "next/server"; import { prisma } from "@/lib/db"; import { requireAuth, withOrgScope } from "@/lib/auth"; import { PermissionError } from "@/lib/permissions"; export async function GET() { try { const user = await requireAuth("users.invite"); const scope = withOrgScope(user); const invitations = await prisma.invitation.findMany({ where: { ...scope, acceptedAt: null }, orderBy: { createdAt: "desc" }, }); return NextResponse.json(invitations); } catch (error) { if (error instanceof PermissionError) { return NextResponse.json({ error: error.message }, { status: 403 }); } return NextResponse.json({ error: "Failed to fetch invitations" }, { status: 500 }); } } export async function POST(req: NextRequest) { try { const user = await requireAuth("users.invite"); if (!user.orgId) { return NextResponse.json( { error: "No organization found" }, { status: 400 } ); } const body = await req.json(); const { email, role } = body; if (!email) { return NextResponse.json( { error: "Email is required" }, { status: 400 } ); } const validRoles = ["admin", "editor", "reviewer", "viewer"]; if (role && !validRoles.includes(role)) { return NextResponse.json( { error: "Invalid role" }, { status: 400 } ); } const existing = await prisma.invitation.findFirst({ where: { email, organizationId: user.orgId, acceptedAt: null, expiresAt: { gt: new Date() }, }, }); if (existing) { return NextResponse.json( { error: "An active invitation already exists for this email" }, { status: 409 } ); } const invitation = await prisma.invitation.create({ data: { email, role: role || "viewer", organizationId: user.orgId, invitedById: user.id, expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days }, }); return NextResponse.json({ invitation, inviteUrl: `/signup?token=${invitation.token}`, }); } catch (error) { if (error instanceof PermissionError) { return NextResponse.json({ error: error.message }, { status: 403 }); } console.error("[invitations] Error:", error); return NextResponse.json( { error: "Failed to create invitation" }, { status: 500 } ); } }