owltide/server/api/admin/database-import.post.ts

49 lines
1.9 KiB
TypeScript
Raw Normal View History

/*
SPDX-FileCopyrightText: © 2025 Hornwitser <code@hornwitser.no>
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, "/");
})