import { encodeHexLowerCase, } from "@oslojs/encoding"; import { sha256 } from "@oslojs/crypto/sha2"; import { Newt, newts, newtSessions, NewtSession } from "@server/db/schemas"; import db from "@server/db"; import { eq } from "drizzle-orm"; export const EXPIRES = 1000 * 60 * 60 * 24 * 30; export async function createNewtSession( token: string, newtId: string, ): Promise { const sessionId = encodeHexLowerCase( sha256(new TextEncoder().encode(token)), ); const session: NewtSession = { sessionId: sessionId, newtId, expiresAt: new Date(Date.now() + EXPIRES).getTime(), }; await db.insert(newtSessions).values(session); return session; } export async function validateNewtSessionToken( token: string, ): Promise { const sessionId = encodeHexLowerCase( sha256(new TextEncoder().encode(token)), ); const result = await db .select({ newt: newts, session: newtSessions }) .from(newtSessions) .innerJoin(newts, eq(newtSessions.newtId, newts.newtId)) .where(eq(newtSessions.sessionId, sessionId)); if (result.length < 1) { return { session: null, newt: null }; } const { newt, session } = result[0]; if (Date.now() >= session.expiresAt) { await db .delete(newtSessions) .where(eq(newtSessions.sessionId, session.sessionId)); return { session: null, newt: null }; } if (Date.now() >= session.expiresAt - (EXPIRES / 2)) { session.expiresAt = new Date( Date.now() + EXPIRES, ).getTime(); await db .update(newtSessions) .set({ expiresAt: session.expiresAt, }) .where(eq(newtSessions.sessionId, session.sessionId)); } return { session, newt }; } export async function invalidateNewtSession(sessionId: string): Promise { await db.delete(newtSessions).where(eq(newtSessions.sessionId, sessionId)); } export async function invalidateAllNewtSessions(newtId: string): Promise { await db.delete(newtSessions).where(eq(newtSessions.newtId, newtId)); } export type SessionValidationResult = | { session: NewtSession; newt: Newt } | { session: null; newt: null };