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: 'wta__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 requireAdminUserId( request: Request, redirectTo: string = new URL(request.url).pathname ) { const user = await getUser(request); if (!user || !user.admin) { const searchParams = new URLSearchParams([['redirectTo', redirectTo]]); throw redirect(`/login?${searchParams}`); } return user.id; } 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) } }); }