templates2.Base.Next/lib/server/auth.ts

65 lines
2 KiB
TypeScript
Raw Permalink Normal View History

2026-10-11 20:23:30 +00:00
import 'server-only';
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';
import { randomBytes } from 'node:crypto';
import { db } from './db';
export { hashPassword, verifyPassword } from '@/lib/password';
export const SESSION_COOKIE = 'w4c_session';
const TTL_MS = 30 * 24 * 60 * 60 * 1000;
export type SessionUser = {
id: string;
email: string;
name: string | null;
role: string;
};
/** Create a session row and set the httpOnly cookie (works in Route Handlers and Server Actions). */
export async function createSession(userId: string): Promise<string> {
const token = randomBytes(32).toString('hex');
const expiresAt = new Date(Date.now() + TTL_MS);
await db.session.create({ data: { token, userId, expiresAt } });
const store = await cookies();
store.set(SESSION_COOKIE, token, {
httpOnly: true,
sameSite: 'lax',
secure: process.env.NODE_ENV === 'production',
path: '/',
expires: expiresAt,
});
return token;
}
export async function destroySession(): Promise<void> {
const store = await cookies();
const token = store.get(SESSION_COOKIE)?.value;
if (token) await db.session.deleteMany({ where: { token } });
store.delete(SESSION_COOKIE);
}
export async function getCurrentUser(): Promise<SessionUser | null> {
const store = await cookies();
const token = store.get(SESSION_COOKIE)?.value;
if (!token) return null;
const session = await db.session.findUnique({ where: { token }, include: { user: true } });
if (!session || session.expiresAt < new Date()) return null;
const { id, email, name, role } = session.user;
return { id, email, name, role };
}
/** Page guard: redirect to /login when unauthenticated. */
export async function requireUser(): Promise<SessionUser> {
const user = await getCurrentUser();
if (!user) redirect('/login');
return user;
}
/** Page guard: require the admin role. */
export async function requireAdmin(): Promise<SessionUser> {
const user = await requireUser();
if (user.role !== 'admin') redirect('/dashboard');
return user;
}