owltide/server/utils/session.ts
Hornwitser 52dfde95d1 Tie push subscriptions to current session
If a user logs out from a device the expectation should be that device
no longer having any association with the user's account.  Any existing
push notifications should thefore be removed on server.  For this reason
tie push notifications to a session, and remove them when the session is
deleted.
2025-03-07 15:47:48 +01:00

67 lines
2.1 KiB
TypeScript

import type { H3Event } from "h3";
import { nextSessionId, readSessions, readSubscriptions, writeSessions, writeSubscriptions } from "~/server/database";
import { Session } from "~/shared/types/account";
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 clearAccountSessionInternal(event: H3Event, sessions: Session[]) {
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 clearAccountSession(event: H3Event) {
const sessions = await readSessions();
if (await clearAccountSessionInternal(event, sessions)) {
await writeSessions(sessions);
}
setCookie(event, "session", "")
}
export async function setAccountSession(event: H3Event, accountId: number) {
const sessions = await readSessions();
await clearAccountSessionInternal(event, sessions);
const newSession: Session = {
accountId,
id: await nextSessionId(),
};
sessions.push(newSession);
await writeSessions(sessions);
await setSignedCookie(event, "session", String(newSession.id))
}
export async function getAccountSession(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 requireAccountSession(event: H3Event) {
const session = await getAccountSession(event);
if (!session)
throw createError({
status: 401,
message: "Account session required",
});
return session;
}