feat: some changes and admin
This commit is contained in:
88
nextjs/src/lib/auth/session.ts
Normal file
88
nextjs/src/lib/auth/session.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { createHash, randomBytes } from 'crypto';
|
||||
import type { RowDataPacket } from 'mysql2';
|
||||
import { cookies } from 'next/headers';
|
||||
|
||||
import { getPool } from '@/lib/db';
|
||||
|
||||
export const SESSION_COOKIE = 'admin_session';
|
||||
const SESSION_MAX_AGE_SEC = 60 * 60 * 24 * 7; // 7 days
|
||||
|
||||
export type AdminUserRow = {
|
||||
id: number;
|
||||
email: string;
|
||||
password_hash: string;
|
||||
is_approved: boolean;
|
||||
is_admin: boolean;
|
||||
};
|
||||
|
||||
function hashToken(token: string): string {
|
||||
return createHash('sha256').update(token, 'utf8').digest('hex');
|
||||
}
|
||||
|
||||
export async function createSession(userId: number): Promise<string> {
|
||||
const token = randomBytes(32).toString('hex');
|
||||
const tokenHash = hashToken(token);
|
||||
const expiresAt = new Date(Date.now() + SESSION_MAX_AGE_SEC * 1000);
|
||||
|
||||
const pool = getPool();
|
||||
await pool.query(
|
||||
`INSERT INTO admin_sessions (user_id, token_hash, expires_at) VALUES (?, ?, ?)`,
|
||||
[userId, tokenHash, expiresAt]
|
||||
);
|
||||
|
||||
const cookieStore = await cookies();
|
||||
cookieStore.set(SESSION_COOKIE, token, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
maxAge: SESSION_MAX_AGE_SEC,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
export async function destroySession(): Promise<void> {
|
||||
const cookieStore = await cookies();
|
||||
const token = cookieStore.get(SESSION_COOKIE)?.value;
|
||||
if (token) {
|
||||
const pool = getPool();
|
||||
await pool.query(
|
||||
'DELETE FROM admin_sessions WHERE token_hash = ?',
|
||||
[hashToken(token)]
|
||||
);
|
||||
}
|
||||
cookieStore.delete(SESSION_COOKIE);
|
||||
}
|
||||
|
||||
export async function getSessionUser(): Promise<AdminUserRow | null> {
|
||||
const cookieStore = await cookies();
|
||||
const token = cookieStore.get(SESSION_COOKIE)?.value;
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tokenHash = hashToken(token);
|
||||
const pool = getPool();
|
||||
const [rows] = await pool.query<RowDataPacket[]>(
|
||||
`SELECT u.id, u.email, u.password_hash, u.is_approved, u.is_admin
|
||||
FROM admin_sessions s
|
||||
JOIN admin_users u ON u.id = s.user_id
|
||||
WHERE s.token_hash = ? AND s.expires_at > NOW()`,
|
||||
[tokenHash]
|
||||
);
|
||||
|
||||
if (rows.length === 0) {
|
||||
cookieStore.delete(SESSION_COOKIE);
|
||||
return null;
|
||||
}
|
||||
|
||||
const row = rows[0] as Record<string, unknown>;
|
||||
return {
|
||||
id: row.id as number,
|
||||
email: row.email as string,
|
||||
password_hash: row.password_hash as string,
|
||||
is_approved: Boolean(row.is_approved),
|
||||
is_admin: Boolean(row.is_admin),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user