import { NextResponse } from "next/server"; import { z } from "zod"; import { getEnv } from "@/lib/env"; import { timingSafeStringEqual } from "@/lib/auth/timing-safe-compare"; import { createSessionToken, sessionCookieOptions } from "@/lib/auth/session"; import { withRouteLogging } from "@/lib/api/with-route-logging"; import { createLogger } from "@/lib/logger"; const log = createLogger("auth"); const bodySchema = z.object({ secret: z.string().min(1) }); export const POST = withRouteLogging("auth.login", async (req: Request) => { const parsed = bodySchema.safeParse(await req.json().catch(() => null)); if (!parsed.success) { return NextResponse.json({ error: "secret is required" }, { status: 400 }); } if (!timingSafeStringEqual(parsed.data.secret, getEnv().ACCESS_PASSWORD)) { log.warn("login attempt with invalid secret"); return NextResponse.json({ error: "invalid secret" }, { status: 401 }); } log.info("login succeeded"); const token = await createSessionToken(); const res = NextResponse.json({ ok: true }); res.cookies.set({ ...sessionCookieOptions, value: token }); return res; });