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.
67 lines
2.1 KiB
TypeScript
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;
|
|
}
|