fix: server 审查修复——member_id 校验、访问日志 finally、静默初始化并发

非法 member_id 不再以 NaN 入库;HTTP 访问日志覆盖异常路径;setup-state 静默建管理员遇唯一冲突视为已初始化。
This commit is contained in:
2026-10-06 12:55:18 +08:00
parent fa5b3a8942
commit 54ea686f44
4 changed files with 41 additions and 17 deletions
+5 -2
View File
@@ -40,8 +40,11 @@ export function createApp(opts: CreateAppOptions) {
app.use("*", async (c, next) => {
const start = Date.now();
await next();
appLogger("http").info`${c.req.method} ${c.req.path} → ${c.res.status} · ${Date.now() - start}ms`;
try {
await next();
} finally {
appLogger("http").info`${c.req.method} ${c.req.path} → ${c.res.status} · ${Date.now() - start}ms`;
}
});
app.use("*", async (c, next) => {
c.set("repos", repos);
+24 -6
View File
@@ -133,10 +133,18 @@ export function adminKeyRoutes() {
if (guard) return guard;
const body = await c.req.json().catch(() => null);
const sk_key = typeof body?.sk_key === "string" ? body.sk_key.trim() : "";
const member_id =
body?.member_id === undefined || body?.member_id === null
? null
: Number(body.member_id);
let member_id: number | null = null;
if (body?.member_id !== undefined && body?.member_id !== null) {
const n = Number(body.member_id);
if (!Number.isInteger(n) || n <= 0) {
return jsonError(
c,
422,
ERR.validation_failed({ member_id: "成员 id 无效" }),
);
}
member_id = n;
}
if (!sk_key || !sk_key.startsWith("sk-")) {
return jsonError(
c,
@@ -276,8 +284,18 @@ export function adminKeyRoutes() {
}
}
if (body && "member_id" in body) {
const nextMember =
body.member_id == null ? null : Number(body.member_id);
let nextMember: number | null = null;
if (body.member_id != null) {
const n = Number(body.member_id);
if (!Number.isInteger(n) || n <= 0) {
return jsonError(
c,
422,
ERR.validation_failed({ member_id: "成员 id 无效" }),
);
}
nextMember = n;
}
if (nextMember !== before.member_id) {
patch.member_id = nextMember;
actions.push({
+12 -8
View File
@@ -74,14 +74,18 @@ export function adminSessionRoutes() {
const initUser = c.get("adminInitUsername");
const initPass = c.get("adminInitPassword");
if (initUser && initPass) {
const password_hash = await hashPassword(initPass);
await repos.users.insert(initUser, password_hash);
await repos.audit.insert({
operator: null,
domain: "account",
action: "account.init",
summary: "空库 env 静默重建管理员",
});
try {
const password_hash = await hashPassword(initPass);
await repos.users.insert(initUser, password_hash);
await repos.audit.insert({
operator: null,
domain: "account",
action: "account.init",
summary: "空库 env 静默重建管理员",
});
} catch {
// 并发/重复初始化:唯一约束冲突时视为已初始化
}
return c.json({ initialized: true }, 200);
}
return c.json({ initialized: false }, 200);
-1
View File
@@ -15,7 +15,6 @@ import {
err401,
err422,
logPageSchema,
keyItemSchema,
} from "../api-schemas.ts";
import { z } from "zod";