import { cookies } from 'next/headers' import { createHash, randomBytes } from 'crypto' import bcrypt from 'bcryptjs' import { prisma } from './prisma' import type { User, Session } from '@prisma/client' const COOKIE_NAME = 'session_token' const SESSION_EXPIRY_DAYS = 30 const BCRYPT_COST = 12 export function hashToken(token: string): string { return createHash('sha256').update(token).digest('hex') } export async function hashPassword(password: string): Promise { return bcrypt.hash(password, BCRYPT_COST) } export async function verifyPassword(password: string, hash: string): Promise { return bcrypt.compare(password, hash) } export function validatePasswordStrength(password: string): string | null { if (password.length < 12) return 'Password must be at least 12 characters' if (!/[A-Z]/.test(password)) return 'Password must contain at least one uppercase letter' if (!/[a-z]/.test(password)) return 'Password must contain at least one lowercase letter' if (!/[0-9]/.test(password)) return 'Password must contain at least one number' if (!/[^A-Za-z0-9]/.test(password)) return 'Password must contain at least one symbol' return null } export async function createSession(userId: string): Promise { const token = randomBytes(32).toString('hex') const tokenHash = hashToken(token) const expiresAt = new Date(Date.now() + SESSION_EXPIRY_DAYS * 24 * 60 * 60 * 1000) await prisma.session.create({ data: { userId, tokenHash, expiresAt, }, }) return token } export async function setSessionCookie(token: string): Promise { const cookieStore = cookies() const isProd = process.env.NODE_ENV === 'production' cookieStore.set(COOKIE_NAME, token, { httpOnly: true, secure: isProd, sameSite: 'lax', expires: new Date(Date.now() + SESSION_EXPIRY_DAYS * 24 * 60 * 60 * 1000), path: '/', }) } export async function clearSessionCookie(): Promise { const cookieStore = cookies() cookieStore.delete(COOKIE_NAME) } export async function getSessionToken(): Promise { const cookieStore = cookies() const cookie = cookieStore.get(COOKIE_NAME) return cookie?.value ?? null } export async function getSession(): Promise<(Session & { user: User }) | null> { const token = await getSessionToken() if (!token) return null const tokenHash = hashToken(token) const session = await prisma.session.findUnique({ where: { tokenHash }, include: { user: true }, }) if (!session) return null if (session.expiresAt < new Date()) { await prisma.session.delete({ where: { id: session.id } }) return null } return session } export async function getCurrentUser(): Promise { const session = await getSession() return session?.user ?? null } export async function deleteSession(token: string): Promise { const tokenHash = hashToken(token) await prisma.session.deleteMany({ where: { tokenHash } }) } export async function deleteAllUserSessions(userId: string): Promise { await prisma.session.deleteMany({ where: { userId } }) }