Atproto AMA app
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 84 lines 2.8 kB view raw
1import { randomBytes } from "node:crypto"; 2import { and, eq, gt } from "drizzle-orm"; 3 4import { db } from "~/lib/db"; 5import { sessions } from "~/lib/schema"; 6 7export const SESSION_COOKIE_NAME = "askimut_session"; 8/** @deprecated use SESSION_COOKIE_NAME */ 9export const SESSION_COOKIE = SESSION_COOKIE_NAME; 10 11const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000; 12 13export async function createSession(did: string): Promise<string> { 14 const id = randomBytes(32).toString("hex"); 15 const expiresAt = new Date(Date.now() + THIRTY_DAYS_MS); 16 17 console.log("[createSession] Creating new session:", { 18 did, 19 sessionId: `${id.slice(0, 8)}...`, 20 expiresAt, 21 timestamp: new Date().toISOString() 22 }); 23 24 await db.insert(sessions).values({ id, did, expiresAt }); 25 return id; 26} 27 28export async function getSession(sessionId: string) { 29 console.log("[getSession] Looking up session:", { 30 sessionId: sessionId ? `${sessionId.slice(0, 8)}...` : null, 31 timestamp: new Date().toISOString() 32 }); 33 34 const row = await db.query.sessions.findFirst({ 35 where: and(eq(sessions.id, sessionId), gt(sessions.expiresAt, new Date())), 36 with: { user: true }, 37 }); 38 39 console.log("[getSession] Database result:", { 40 found: !!row, 41 hasUser: !!row?.user, 42 expired: row ? row.expiresAt < new Date() : null, 43 expiresAt: row?.expiresAt, 44 userHandle: row?.user?.handle, 45 timestamp: new Date().toISOString() 46 }); 47 48 return row ?? null; 49} 50 51export async function deleteSession(sessionId: string): Promise<void> { 52 await db.delete(sessions).where(eq(sessions.id, sessionId)); 53} 54 55export function buildSessionCookie(sessionId: string): string { 56 const maxAgeSec = Math.floor(THIRTY_DAYS_MS / 1000); 57 const secure = process.env.APP_URL?.startsWith("https://") ? "; Secure" : ""; 58 return `${SESSION_COOKIE_NAME}=${sessionId}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${maxAgeSec}${secure}`; 59} 60 61export function parseSessionCookie(cookieHeader: string | null): string | undefined { 62 console.log("[parseSessionCookie] Parsing cookie header:", { 63 hasCookieHeader: !!cookieHeader, 64 cookieHeader: cookieHeader ? `${cookieHeader.slice(0, 50)}...` : null, 65 timestamp: new Date().toISOString() 66 }); 67 68 if (!cookieHeader) return undefined; 69 70 for (const part of cookieHeader.split(";")) { 71 const [name, ...rest] = part.trim().split("="); 72 if (name === SESSION_COOKIE_NAME && rest.length > 0) { 73 const sessionId = decodeURIComponent(rest.join("=").trim()); 74 console.log("[parseSessionCookie] Found session cookie:", { 75 sessionId: `${sessionId.slice(0, 8)}...`, 76 timestamp: new Date().toISOString() 77 }); 78 return sessionId; 79 } 80 } 81 82 console.log("[parseSessionCookie] No session cookie found"); 83 return undefined; 84}