import { getUserByUsername, writeAuthAudit } from "@/lib/store"; import { parseHy2Userpass, verifyNodeToken, evaluateUserForAuth } from "@/lib/hy2"; import { verifyPassword } from "@/lib/password"; type AuthRequest = { addr?: string; auth?: string; tx?: number; }; function deny(id = "") { return Response.json({ ok: false, id }); } export async function POST( request: Request, context: RouteContext<"/api/hy2/nodes/[slug]/auth">, ) { const { slug } = await context.params; const requestUrl = new URL(request.url); const token = requestUrl.searchParams.get("token") || request.headers.get("authorization")?.replace(/^Bearer\s+/i, "") || request.headers.get("x-node-token"); const nodeResult = await verifyNodeToken(slug, token); if (!nodeResult.ok) { await writeAuthAudit({ nodeId: nodeResult.node?.id ?? null, ok: false, reason: nodeResult.reason, }); return deny(); } const node = nodeResult.node; if (!node) { return deny(); } let payload: AuthRequest; try { payload = (await request.json()) as AuthRequest; } catch { await writeAuthAudit({ nodeId: node.id, addr: null, requestedTx: null, ok: false, reason: "bad_json", }); return deny(); } if (!payload.auth) { await writeAuthAudit({ nodeId: node.id, addr: payload.addr ?? null, requestedTx: payload.tx ?? null, ok: false, reason: "missing_auth", }); return deny(); } const parsed = parseHy2Userpass(payload.auth); if (!parsed) { await writeAuthAudit({ nodeId: node.id, addr: payload.addr ?? null, requestedTx: payload.tx ?? null, ok: false, reason: "bad_auth_format", }); return deny(); } const user = await getUserByUsername(parsed.username); if (!user) { await writeAuthAudit({ nodeId: node.id, username: parsed.username, addr: payload.addr ?? null, requestedTx: payload.tx ?? null, ok: false, reason: "user_not_found", }); return deny(); } const passwordOk = await verifyPassword(parsed.password, user.password_hash); if (!passwordOk) { await writeAuthAudit({ nodeId: node.id, userId: user.id, authId: user.auth_id, username: user.username, addr: payload.addr ?? null, requestedTx: payload.tx ?? null, ok: false, reason: "password_invalid", }); return deny(); } const access = evaluateUserForAuth(user); if (!access.ok) { await writeAuthAudit({ nodeId: node.id, userId: user.id, authId: user.auth_id, username: user.username, addr: payload.addr ?? null, requestedTx: payload.tx ?? null, ok: false, reason: access.reason, }); return deny(); } await writeAuthAudit({ nodeId: node.id, userId: user.id, authId: user.auth_id, username: user.username, addr: payload.addr ?? null, requestedTx: payload.tx ?? null, ok: true, reason: "ok", }); return Response.json({ ok: true, id: user.auth_id }); }