owltide/server/utils/session.ts
Hornwitser e52972853d License under AGPL version 3 or later
I firmly believe in free software.

The application I'm making here have capabilities that I've not seen in
any system.  It presents itself as an opportunity to collaborate on a
tool that serves the people rather than corporations.  Whose incentives
are to help people rather, not make the most money.  And whose terms
ensure that these freedoms and incentives cannot be taken back or
subverted.

I license this software under the AGPL.
2025-06-30 18:58:24 +02:00

87 lines
2.7 KiB
TypeScript

/*
SPDX-FileCopyrightText: © 2025 Hornwitser <code@hornwitser.no>
SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type { H3Event } from "h3";
import { nextSessionId, readSessions, readSubscriptions, type ServerSession, type ServerUser, writeSessions, writeSubscriptions } from "~/server/database";
const oneYearSeconds = 365 * 24 * 60 * 60;
async function removeSessionSubscription(sessionId: number) {
const subscriptions = await readSubscriptions();
const index = subscriptions.findIndex(subscription => subscription.sessionId === sessionId);
if (index !== -1) {
subscriptions.splice(index, 1);
await writeSubscriptions(subscriptions);
}
}
async function clearServerSessionInternal(event: H3Event, sessions: ServerSession[]) {
const existingSessionCookie = await getSignedCookie(event, "session");
if (existingSessionCookie) {
const sessionId = parseInt(existingSessionCookie, 10);
const sessionIndex = sessions.findIndex(session => session.id === sessionId);
if (sessionIndex !== -1) {
sessions.splice(sessionIndex, 1);
await removeSessionSubscription(sessionId);
return true;
}
}
return false;
}
export async function clearServerSession(event: H3Event) {
const sessions = await readSessions();
if (await clearServerSessionInternal(event, sessions)) {
await writeSessions(sessions);
}
deleteCookie(event, "session");
}
export async function setServerSession(event: H3Event, account: ServerUser) {
const sessions = await readSessions();
await clearServerSessionInternal(event, sessions);
const newSession: ServerSession = {
account,
id: await nextSessionId(),
};
sessions.push(newSession);
await writeSessions(sessions);
await setSignedCookie(event, "session", String(newSession.id), oneYearSeconds)
}
export async function refreshServerSession(event: H3Event, session: ServerSession) {
await setSignedCookie(event, "session", String(session.id), oneYearSeconds)
}
export async function getServerSession(event: H3Event) {
const sessionCookie = await getSignedCookie(event, "session");
if (sessionCookie) {
const sessionId = parseInt(sessionCookie, 10);
const sessions = await readSessions();
return sessions.find(session => session.id === sessionId);
}
}
export async function requireServerSession(event: H3Event) {
const session = await getServerSession(event);
if (!session)
throw createError({
status: 401,
message: "Account session required",
});
return session;
}
export async function requireServerSessionWithAdmin(event: H3Event) {
const session = await requireServerSession(event);
if (session.account.type !== "admin") {
throw createError({
statusCode: 403,
statusMessage: "Forbidden",
});
}
return session;
}