2025-06-30 18:58:24 +02:00
|
|
|
/*
|
|
|
|
SPDX-FileCopyrightText: © 2025 Hornwitser <code@hornwitser.no>
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
*/
|
2025-06-28 01:23:52 +02:00
|
|
|
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, "/");
|
|
|
|
})
|