import { randomBytes } from "node:crypto"; import { and, eq, gt } from "drizzle-orm"; import { db } from "~/lib/db"; import { sessions } from "~/lib/schema"; export const SESSION_COOKIE_NAME = "askimut_session"; /** @deprecated use SESSION_COOKIE_NAME */ export const SESSION_COOKIE = SESSION_COOKIE_NAME; const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000; export async function createSession(did: string): Promise { const id = randomBytes(32).toString("hex"); const expiresAt = new Date(Date.now() + THIRTY_DAYS_MS); console.log("[createSession] Creating new session:", { did, sessionId: `${id.slice(0, 8)}...`, expiresAt, timestamp: new Date().toISOString() }); await db.insert(sessions).values({ id, did, expiresAt }); return id; } export async function getSession(sessionId: string) { console.log("[getSession] Looking up session:", { sessionId: sessionId ? `${sessionId.slice(0, 8)}...` : null, timestamp: new Date().toISOString() }); const row = await db.query.sessions.findFirst({ where: and(eq(sessions.id, sessionId), gt(sessions.expiresAt, new Date())), with: { user: true }, }); console.log("[getSession] Database result:", { found: !!row, hasUser: !!row?.user, expired: row ? row.expiresAt < new Date() : null, expiresAt: row?.expiresAt, userHandle: row?.user?.handle, timestamp: new Date().toISOString() }); return row ?? null; } export async function deleteSession(sessionId: string): Promise { await db.delete(sessions).where(eq(sessions.id, sessionId)); } export function buildSessionCookie(sessionId: string): string { const maxAgeSec = Math.floor(THIRTY_DAYS_MS / 1000); const secure = process.env.APP_URL?.startsWith("https://") ? "; Secure" : ""; return `${SESSION_COOKIE_NAME}=${sessionId}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${maxAgeSec}${secure}`; } export function parseSessionCookie(cookieHeader: string | null): string | undefined { console.log("[parseSessionCookie] Parsing cookie header:", { hasCookieHeader: !!cookieHeader, cookieHeader: cookieHeader ? `${cookieHeader.slice(0, 50)}...` : null, timestamp: new Date().toISOString() }); if (!cookieHeader) return undefined; for (const part of cookieHeader.split(";")) { const [name, ...rest] = part.trim().split("="); if (name === SESSION_COOKIE_NAME && rest.length > 0) { const sessionId = decodeURIComponent(rest.join("=").trim()); console.log("[parseSessionCookie] Found session cookie:", { sessionId: `${sessionId.slice(0, 8)}...`, timestamp: new Date().toISOString() }); return sessionId; } } console.log("[parseSessionCookie] No session cookie found"); return undefined; }