Files
kycnotme/web/src/lib/userCookies.ts

81 lines
2.1 KiB
TypeScript
Raw Normal View History

2025-05-19 10:23:36 +00:00
import { stopImpersonating } from './impersonation'
import { prisma } from './prisma'
import { redisSessions } from './redis/redisSessions'
import type { APIContext, AstroCookies, AstroCookieSetOptions } from 'astro'
const COOKIE_NAME = 'user_session_id'
const COOKIE_MAX_AGE = 60 * 60 * 24 * 7 // 1 week
const defaultCookieOptions = {
path: '/',
secure: true,
httpOnly: true,
sameSite: 'strict',
maxAge: COOKIE_MAX_AGE,
} as const satisfies AstroCookieSetOptions
export function getUserSessionIdCookie(cookies: AstroCookies) {
return cookies.get(COOKIE_NAME)?.value
}
export async function getUserFromCookies(cookies: AstroCookies) {
const userSessionId = getUserSessionIdCookie(cookies)
if (!userSessionId) return null
const userSecretTokenHash = await redisSessions.getUserBySessionId(userSessionId)
if (!userSecretTokenHash) return null
return prisma.user.findFirst({
where: {
secretTokenHash: userSecretTokenHash,
},
})
}
export async function setUserSessionIdCookie(
cookies: AstroCookies,
userSecretTokenHash: string,
options: AstroCookieSetOptions = {}
) {
const sessId = await redisSessions.createSession(userSecretTokenHash)
cookies.set(COOKIE_NAME, sessId, {
...defaultCookieOptions,
...options,
})
}
export async function removeUserSessionIdCookie(cookies: AstroCookies) {
const sessionId = cookies.get(COOKIE_NAME)?.value
if (sessionId) {
await redisSessions.deleteSession(sessionId)
}
cookies.delete(COOKIE_NAME, { path: '/' })
}
export async function logout(context: Pick<APIContext, 'cookies' | 'locals'>) {
await stopImpersonating(context)
await removeUserSessionIdCookie(context.cookies)
context.locals.user = null
context.locals.actualUser = null
}
export async function login(
context: Pick<APIContext, 'cookies' | 'locals'>,
user: NonNullable<APIContext['locals']['user']>
) {
await stopImpersonating(context)
await setUserSessionIdCookie(context.cookies, user.secretTokenHash)
await prisma.user.update({
where: { id: user.id },
data: { lastLoginAt: new Date() },
})
context.locals.user = user
context.locals.actualUser = null
}