import { createCookieSessionStorage, redirect } from '@remix-run/node' import invariant from 'tiny-invariant' import type { User } from '~/models/user.server' import { getUserById } from '~/models/user.server' invariant(process.env.SESSION_SECRET, 'SESSION_SECRET must be set') const SESSION_SECRET = process.env.SESSION_SECRET export const sessionStorage = createCookieSessionStorage({ cookie: { name: '__session', httpOnly: true, path: '/', sameSite: 'lax', secrets: [SESSION_SECRET], secure: process.env.NODE_ENV === 'production' } }) const USER_SESSION_KEY = 'userId' export async function getSession(request: Request) { const cookie = request.headers.get('Cookie') return sessionStorage.getSession(cookie) } export async function getUserId(request: Request): Promise { const session = await getSession(request) const userId = session.get(USER_SESSION_KEY) return userId } export async function getUser(request: Request) { const userId = await getUserId(request) if (userId === undefined) return null const user = await getUserById(userId) if (user) return user throw await logout(request) } export async function requireUserId(request: Request, redirectTo: string = new URL(request.url).pathname) { const userId = await getUserId(request) if (!userId) { const searchParams = new URLSearchParams([['redirectTo', redirectTo]]) throw redirect(`/login?${searchParams}`) } return userId } export async function requireUser(request: Request) { const userId = await requireUserId(request) const user = await getUserById(userId) if (user) return user throw await logout(request) } export async function createUserSession({ request, userId, remember, redirectTo }: { request: Request userId: string remember: boolean redirectTo: string }) { const session = await getSession(request) session.set(USER_SESSION_KEY, userId) return redirect(redirectTo, { headers: { 'Set-Cookie': await sessionStorage.commitSession(session, { maxAge: remember ? 60 * 60 * 24 * 14 // 14 days : undefined }) } }) } export async function logout(request: Request) { const session = await getSession(request) return redirect('/', { headers: { 'Set-Cookie': await sessionStorage.destroySession(session) } }) }