Files

43 lines
2.2 KiB
TypeScript

import { createHmac } from "node:crypto";
import type { Payload } from "payload";
import type { Event, MeetingSetting } from "@/payload-types";
import { canJoinMeeting, combineDateAndTime, getMeetingStatus } from "./status";
import type { MeetingRole } from "./token";
export function meetingAccessVersion(event: Event): string {
const secret = process.env.MEETING_SESSION_SECRET;
if (!secret) throw new Error("MEETING_SESSION_SECRET is not set");
return createHmac("sha256", secret).update(JSON.stringify([
event.id, event.slug, event.meetingPassword, event.date, event.startTime,
event.endTime, event.isOnline, event._status, event.isPrivateBooking,
])).digest("hex");
}
export function meetingWindow(event: Event, settings: MeetingSetting, role: MeetingRole, now = new Date()) {
const start = combineDateAndTime(event.date, event.startTime);
const end = event.endTime ? combineDateAndTime(event.date, event.endTime) : new Date(start.getTime() + 3600000);
const closeAt = end.getTime() + settings.meetingCloseAfterMinutes * 60000;
const status = getMeetingStatus({ start, end,
joinWindowMinutes: role === "host" ? settings.hostJoinWindowMinutes : settings.participantJoinWindowMinutes,
closeAfterMinutes: settings.meetingCloseAfterMinutes, now });
return { allowed: Number.isFinite(closeAt) && end > start && canJoinMeeting(status), closeAt, status };
}
/** Shared by every issuer: existing credentials are not a substitute for current access. */
export async function authorizeMeeting(payload: Payload, event: Event, role: MeetingRole) {
if (!event.isOnline || (!event.isPrivateBooking && event._status !== "published" && role !== "host")) return null;
if (event.isPrivateBooking) {
const { docs } = await payload.find({ collection: "booking-requests", depth: 0, limit: 1,
where: { and: [
{ linkedEvent: { equals: event.id } }, { status: { equals: "confirmed" } },
{ appointmentType: { equals: "online" } },
] },
});
if (!docs[0]) return null;
}
const settings = await payload.findGlobal({ slug: "meeting-settings" });
const window = meetingWindow(event, settings, role);
if (!window.allowed) return null;
return { accessVersion: meetingAccessVersion(event), expiresAt: window.closeAt };
}