- P2.9: VNCtalk video meeting — create/update meeting from event modal, 'Join Meeting' link in event detail. Admin config vnctalkServerUrl. - P2.10: Collabora online editing — 'Edit with Collabora' for office files, WOPI discovery + edit URL. Admin config collaboraServerUrl. - P2.11: Calendar enhancements — clickable links in descriptions, participant contact popover, Reply/Reply All from event, timezone picker, map links for locations. - P2.13: VNCdirectory IDP admin panel — Connection, SAML/IDP, LDAP, Authentication, Federated Apps configuration. Secret masking on display.
50 lines
1.5 KiB
TypeScript
50 lines
1.5 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { createVncMeeting } from "@/lib/vnctalk/client";
|
|
import { logger } from "@/lib/logger";
|
|
|
|
function getClientIP(request: NextRequest): string {
|
|
const forwarded = request.headers.get("x-forwarded-for");
|
|
if (forwarded) return forwarded.split(",")[0].trim();
|
|
return "127.0.0.1";
|
|
}
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const body = await request.json();
|
|
|
|
if (!body.name || !body.start || !body.end) {
|
|
return NextResponse.json(
|
|
{ error: "Missing required fields: name, start, end" },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
const invitees: string[] = Array.isArray(body.invitees) ? body.invitees : [];
|
|
|
|
const result = await createVncMeeting({
|
|
name: String(body.name),
|
|
start: String(body.start),
|
|
end: String(body.end),
|
|
invitees,
|
|
password: body.password ? String(body.password) : undefined,
|
|
description: body.description ? String(body.description) : undefined,
|
|
});
|
|
|
|
logger.info("VNCtalk meeting created", {
|
|
meetingId: result.meetingId,
|
|
ip: getClientIP(request),
|
|
});
|
|
|
|
return NextResponse.json(result, { status: 201 });
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
logger.error("VNCtalk meeting creation failed", { error: message });
|
|
|
|
if (message.includes("not configured")) {
|
|
return NextResponse.json({ error: message }, { status: 503 });
|
|
}
|
|
|
|
return NextResponse.json({ error: message }, { status: 500 });
|
|
}
|
|
}
|