first commit
This commit is contained in:
+63
@@ -0,0 +1,63 @@
|
||||
import { cookies } from "next/headers";
|
||||
import crypto from "crypto";
|
||||
|
||||
const COOKIE_NAME = "admin_session";
|
||||
const ADMIN_SECRET = process.env.ADMIN_SECRET || "fallback-admin-secret-2026";
|
||||
const ADMIN_USERNAME = process.env.ADMIN_USERNAME || "admin";
|
||||
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || "password123";
|
||||
|
||||
/**
|
||||
* Generate a signed session token for the admin
|
||||
*/
|
||||
export function createSessionToken(username: string): string {
|
||||
const timestamp = Date.now();
|
||||
const data = `${username}.${timestamp}`;
|
||||
const signature = crypto
|
||||
.createHmac("sha256", ADMIN_SECRET)
|
||||
.update(data)
|
||||
.digest("hex");
|
||||
return `${data}.${signature}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if a session token is valid and signed properly
|
||||
*/
|
||||
export function verifySessionToken(token?: string | null): boolean {
|
||||
if (!token) return false;
|
||||
const parts = token.split(".");
|
||||
if (parts.length !== 3) return false;
|
||||
|
||||
const [username, timestamp, signature] = parts;
|
||||
if (username !== ADMIN_USERNAME) return false;
|
||||
|
||||
// Optional: Check if token is older than 7 days
|
||||
const tokenTime = parseInt(timestamp, 10);
|
||||
if (isNaN(tokenTime) || Date.now() - tokenTime > 7 * 24 * 60 * 60 * 1000) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const expectedSignature = crypto
|
||||
.createHmac("sha256", ADMIN_SECRET)
|
||||
.update(`${username}.${timestamp}`)
|
||||
.digest("hex");
|
||||
|
||||
return signature === expectedSignature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to validate admin credentials
|
||||
*/
|
||||
export function validateCredentials(username?: string, password?: string): boolean {
|
||||
return username === ADMIN_USERNAME && password === ADMIN_PASSWORD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for Server Routes to check if caller is authenticated
|
||||
*/
|
||||
export async function isAdminAuthenticated(): Promise<boolean> {
|
||||
const cookieStore = await cookies();
|
||||
const token = cookieStore.get(COOKIE_NAME)?.value;
|
||||
return verifySessionToken(token);
|
||||
}
|
||||
|
||||
export { COOKIE_NAME, ADMIN_USERNAME };
|
||||
@@ -0,0 +1,13 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const globalForPrisma = globalThis as unknown as {
|
||||
prisma: PrismaClient | undefined;
|
||||
};
|
||||
|
||||
export const prisma =
|
||||
globalForPrisma.prisma ??
|
||||
new PrismaClient({
|
||||
log: process.env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"],
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
|
||||
Reference in New Issue
Block a user