/* SPDX-FileCopyrightText: © 2025 Hornwitser SPDX-License-Identifier: AGPL-3.0-or-later */ import { readNextSessionId, readNextUserId, readSessions, type ServerSession, type ServerUser, writeNextSessionId, writeNextUserId, writeSchedule, writeSessions, writeSubscriptions, writeUsers } from "~/server/database"; import type { ApiSchedule, ApiSubscription } from "~/shared/types/api"; export default defineEventHandler(async (event) => { await requireServerSessionWithAdmin(event); const formData = await readMultipartFormData(event); let snapshot: undefined | { nextUserId: number, users: ServerUser[], nextSessionId: number, sessions: ServerSession[], subscriptions: ApiSubscription[], schedule: ApiSchedule, }; for (const part of formData ?? []) { if (part.name === "snapshot") { snapshot = JSON.parse(part.data.toString("utf-8")); } } if (!snapshot) { throw createError({ statusCode: 400, statusMessage: "Bad Request", message: "snapshot missing." }); } const currentNextUserId = await readNextUserId(); await writeNextUserId(Math.max(currentNextUserId, snapshot.nextUserId)); await writeUsers(snapshot.users); const currentNextSessionId = await readNextSessionId(); await writeNextSessionId(Math.max(currentNextSessionId, snapshot.nextSessionId)); const currentSessions = new Map((await readSessions()).map(session => [session.id, session])); await writeSessions(snapshot.sessions.filter(session => { const current = currentSessions.get(session.id); // Only keep sessions that match the account id in both sets to avoid // resurrecting deleted sessions. This will still cause session cross // pollution if a snapshot from another instance is loaded here. return current && current.account.id === session.account.id; })); await writeSubscriptions(snapshot.subscriptions); await writeSchedule(snapshot.schedule); await sendRedirect(event, "/"); })