fix: harden booking and meeting flows
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
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 };
|
||||
}
|
||||
Reference in New Issue
Block a user