55 lines
2.6 KiB
TypeScript
55 lines
2.6 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { getPayload } from "payload";
|
|
import config from "@payload-config";
|
|
import { createLiveKitToken, getLiveKitClientUrl } from "@/lib/meeting/livekit";
|
|
import { isMeetingParticipantKicked } from "@/lib/meeting/kicks";
|
|
import { verifyMeetingToken } from "@/lib/meeting/token";
|
|
import { authorizeMeeting } from "@/lib/meeting/access";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
type Args = { params: Promise<{ slug: string }> };
|
|
|
|
/** Exchanges the app's short-lived meeting credential for a LiveKit token. */
|
|
export async function POST(request: Request, { params }: Args) {
|
|
const { slug } = await params;
|
|
const authorization = request.headers.get("authorization") ?? "";
|
|
const appToken = authorization.startsWith("Bearer ") ? authorization.slice(7) : "";
|
|
const meetingToken = verifyMeetingToken(appToken);
|
|
if (!meetingToken || meetingToken.eventSlug !== slug) {
|
|
return NextResponse.json({ error: "Die Meeting-Sitzung ist ungültig." }, { status: 401 });
|
|
}
|
|
if (isMeetingParticipantKicked(slug, meetingToken.participantId, meetingToken.clientId)) {
|
|
return NextResponse.json({ error: "Du wurdest aus diesem Meeting entfernt." }, { status: 403 });
|
|
}
|
|
|
|
try {
|
|
let expiresAt = meetingToken.exp;
|
|
const isAdminTestRoom = meetingToken.role === "host" && meetingToken.testRoom === true && slug.startsWith("test-");
|
|
if (!isAdminTestRoom) {
|
|
const payload = await getPayload({ config });
|
|
const { docs } = await payload.find({ collection: "events", where: { slug: { equals: slug } }, limit: 1 });
|
|
if (!docs[0]?.isOnline) return NextResponse.json({ error: "Dieser Online-Termin wurde nicht gefunden." }, { status: 404 });
|
|
const access = await authorizeMeeting(payload, docs[0], meetingToken.role);
|
|
if (!access || access.accessVersion !== meetingToken.accessVersion) {
|
|
return NextResponse.json({ error: "Dieser Meeting-Zugang ist nicht mehr gültig. Bitte tritt erneut bei." }, { status: 403 });
|
|
}
|
|
expiresAt = Math.min(expiresAt, access.expiresAt);
|
|
}
|
|
|
|
const participantToken = await createLiveKitToken({
|
|
eventSlug: slug,
|
|
participantId: meetingToken.participantId,
|
|
name: meetingToken.name,
|
|
role: meetingToken.role,
|
|
clientId: meetingToken.clientId,
|
|
accessVersion: meetingToken.accessVersion,
|
|
expiresAt,
|
|
});
|
|
return NextResponse.json({ serverUrl: getLiveKitClientUrl(), participantToken });
|
|
} catch (error) {
|
|
console.error("meeting LiveKit connect failed", error);
|
|
return NextResponse.json({ error: "Der Video-Server ist gerade nicht erreichbar." }, { status: 503 });
|
|
}
|
|
}
|