Spaces:
Runtime error
Runtime error
| import crypto from "node:crypto"; | |
| import type { User } from "@prisma/client"; | |
| import { cookies } from "next/headers"; | |
| import { redirect } from "next/navigation"; | |
| import { SESSION_COOKIE_NAME, SESSION_TTL_DAYS } from "@/lib/constants"; | |
| import { db } from "@/server/db"; | |
| import { AppError } from "@/server/errors"; | |
| const sessionTtlMs = SESSION_TTL_DAYS * 24 * 60 * 60 * 1000; | |
| function hashSessionToken(token: string) { | |
| return crypto.createHash("sha256").update(token).digest("hex"); | |
| } | |
| function createSessionToken() { | |
| return crypto.randomBytes(32).toString("hex"); | |
| } | |
| export async function createSession(userId: string) { | |
| const token = createSessionToken(); | |
| const expiresAt = new Date(Date.now() + sessionTtlMs); | |
| await db.session.create({ | |
| data: { | |
| userId, | |
| tokenHash: hashSessionToken(token), | |
| expiresAt, | |
| }, | |
| }); | |
| return { token, expiresAt }; | |
| } | |
| export async function setSessionCookie(token: string, expiresAt: Date) { | |
| const cookieStore = await cookies(); | |
| cookieStore.set(SESSION_COOKIE_NAME, token, { | |
| httpOnly: true, | |
| sameSite: "lax", | |
| secure: process.env.NODE_ENV === "production", | |
| path: "/", | |
| expires: expiresAt, | |
| }); | |
| } | |
| export async function clearSessionCookie() { | |
| const cookieStore = await cookies(); | |
| cookieStore.set(SESSION_COOKIE_NAME, "", { | |
| httpOnly: true, | |
| sameSite: "lax", | |
| secure: process.env.NODE_ENV === "production", | |
| path: "/", | |
| expires: new Date(0), | |
| }); | |
| } | |
| export async function getSessionToken() { | |
| const cookieStore = await cookies(); | |
| return cookieStore.get(SESSION_COOKIE_NAME)?.value; | |
| } | |
| export async function getCurrentSession() { | |
| const token = await getSessionToken(); | |
| if (!token) { | |
| return null; | |
| } | |
| const session = await db.session.findUnique({ | |
| where: { | |
| tokenHash: hashSessionToken(token), | |
| }, | |
| include: { | |
| user: true, | |
| }, | |
| }); | |
| if (!session) { | |
| return null; | |
| } | |
| if (session.expiresAt <= new Date()) { | |
| await db.session.delete({ | |
| where: { | |
| id: session.id, | |
| }, | |
| }); | |
| return null; | |
| } | |
| return session; | |
| } | |
| export async function getCurrentUser(): Promise<User | null> { | |
| const session = await getCurrentSession(); | |
| return session?.user ?? null; | |
| } | |
| export async function requireCurrentUser() { | |
| const user = await getCurrentUser(); | |
| if (!user) { | |
| redirect("/login"); | |
| } | |
| return user; | |
| } | |
| export async function requireApiUser() { | |
| const user = await getCurrentUser(); | |
| if (!user) { | |
| throw new AppError("أنت محتاج تسجل الدخول الأول.", 401); | |
| } | |
| return user; | |
| } | |
| export async function redirectIfAuthenticated() { | |
| const user = await getCurrentUser(); | |
| if (user) { | |
| redirect("/dashboard/customers"); | |
| } | |
| } | |
| export async function destroyCurrentSession() { | |
| const token = await getSessionToken(); | |
| if (token) { | |
| const tokenHash = hashSessionToken(token); | |
| await db.session.deleteMany({ | |
| where: { | |
| tokenHash, | |
| }, | |
| }); | |
| } | |
| await clearSessionCookie(); | |
| } | |