import { cookies } from "next/headers"; import { SignJWT, jwtVerify } from "jose"; import bcrypt from "bcryptjs"; import { prisma } from "./db"; const SESSION_COOKIE_NAME = "ftp_session"; const SESSION_MAX_AGE = 60 * 60 * 24 * 7; // 7 days type SessionPayload = { userId: string; email: string; }; function getJwtSecret() { const secret = process.env.JWT_SECRET; if (!secret) { throw new Error("JWT_SECRET is not set"); } return new TextEncoder().encode(secret); } export async function hashPassword(password: string) { return bcrypt.hash(password, 10); } export async function verifyPassword(password: string, hash: string) { return bcrypt.compare(password, hash); } export async function createSessionToken(payload: SessionPayload) { const secret = getJwtSecret(); return new SignJWT(payload) .setProtectedHeader({ alg: "HS256" }) .setIssuedAt() .setExpirationTime(`${SESSION_MAX_AGE}s`) .sign(secret); } export async function verifySessionToken(token: string) { try { const { payload } = await jwtVerify(token, getJwtSecret()); return payload; } catch { return null; } } export async function setSessionCookie(token: string) { const store = await cookies(); store.set(SESSION_COOKIE_NAME, token, { httpOnly: true, sameSite: "lax", secure: process.env.NODE_ENV === "production", path: "/", maxAge: SESSION_MAX_AGE, }); } export async function clearSessionCookie() { const store = await cookies(); store.delete(SESSION_COOKIE_NAME); } export async function getSessionUser() { const store = await cookies(); const token = store.get(SESSION_COOKIE_NAME)?.value; if (!token) return null; const payload = await verifySessionToken(token); if (!payload) return null; return payload; } export async function getCurrentUserRecord() { const session = await getSessionUser(); if (!session) return null; return prisma.user.findUnique({ where: { id: session.userId } }); } export { SESSION_COOKIE_NAME, SESSION_MAX_AGE };