104 lines
3.0 KiB
TypeScript
104 lines
3.0 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { auth, clerkClient } from "@clerk/nextjs/server";
|
|
import { getAuthContext } from "@/lib/auth/context";
|
|
import log from "@/lib/logger";
|
|
|
|
/**
|
|
* POST /api/invitations/[id]/resend
|
|
*
|
|
* Resend an invitation with same parameters
|
|
*/
|
|
export async function POST(
|
|
request: NextRequest,
|
|
{ params }: { params: Promise<{ id: string }> },
|
|
) {
|
|
try {
|
|
const { userId } = await auth();
|
|
if (!userId) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
|
|
const { id: invitationId } = await params;
|
|
const authContext = await getAuthContext();
|
|
|
|
// Fetch pending invitations to find the one being resent
|
|
const client = await clerkClient();
|
|
const invitationList = await client.invitations.getInvitationList({
|
|
status: "pending",
|
|
});
|
|
|
|
// Find the invitation
|
|
const invitation = invitationList.data.find(
|
|
(inv) => inv.id === invitationId,
|
|
);
|
|
|
|
if (!invitation) {
|
|
return NextResponse.json(
|
|
{ error: "Invitation not found or already processed" },
|
|
{ status: 404 },
|
|
);
|
|
}
|
|
|
|
const metadata = invitation.publicMetadata as any;
|
|
const invitationGymId =
|
|
(metadata?.gymId as string | null | undefined) ?? null;
|
|
const createdBy = (metadata?.createdBy as string | undefined) ?? undefined;
|
|
|
|
const canManageByRole =
|
|
authContext.role === "superAdmin" ||
|
|
(authContext.role === "admin" &&
|
|
authContext.gymId !== null &&
|
|
invitationGymId === authContext.gymId);
|
|
|
|
// Check if current user created this invitation
|
|
if (createdBy !== userId && !canManageByRole) {
|
|
return NextResponse.json(
|
|
{
|
|
error:
|
|
"Forbidden - You can only resend invitations you created or manage within your scope",
|
|
},
|
|
{ status: 403 },
|
|
);
|
|
}
|
|
|
|
// Create new invitation with same parameters
|
|
const role = metadata?.role;
|
|
|
|
// Determine redirect URL based on role
|
|
const isStaffRole = ["admin", "trainer", "superAdmin"].includes(role);
|
|
const redirectUrl = isStaffRole
|
|
? `${process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000"}/sign-up`
|
|
: undefined;
|
|
|
|
const newInvitation = await client.invitations.createInvitation({
|
|
emailAddress: invitation.emailAddress,
|
|
publicMetadata: invitation.publicMetadata || undefined,
|
|
redirectUrl,
|
|
ignoreExisting: true,
|
|
});
|
|
|
|
log.info("Invitation resent", {
|
|
originalId: invitationId,
|
|
newId: newInvitation.id,
|
|
email: invitation.emailAddress,
|
|
resentBy: userId,
|
|
});
|
|
|
|
return NextResponse.json({
|
|
data: {
|
|
invitation: {
|
|
id: newInvitation.id,
|
|
email: newInvitation.emailAddress,
|
|
status: newInvitation.status,
|
|
},
|
|
},
|
|
});
|
|
} catch (error) {
|
|
log.error("POST /api/invitations/[id]/resend error:", error);
|
|
return NextResponse.json(
|
|
{ error: "Failed to resend invitation" },
|
|
{ status: 500 },
|
|
);
|
|
}
|
|
}
|