Files
ecommerce-platform/app/src/lib/auth.ts
T
2026-05-18 15:25:38 +02:00

104 lines
3.1 KiB
TypeScript

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<string> {
return bcrypt.hash(password, BCRYPT_COST)
}
export async function verifyPassword(password: string, hash: string): Promise<boolean> {
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<string> {
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<void> {
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<void> {
const cookieStore = cookies()
cookieStore.delete(COOKIE_NAME)
}
export async function getSessionToken(): Promise<string | null> {
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<User | null> {
const session = await getSession()
return session?.user ?? null
}
export async function deleteSession(token: string): Promise<void> {
const tokenHash = hashToken(token)
await prisma.session.deleteMany({ where: { tokenHash } })
}
export async function deleteAllUserSessions(userId: string): Promise<void> {
await prisma.session.deleteMany({ where: { userId } })
}