init
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
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 });
|
||||
}
|
||||
Reference in New Issue
Block a user