fix: server 审查修复——member_id 校验、访问日志 finally、静默初始化并发
非法 member_id 不再以 NaN 入库;HTTP 访问日志覆盖异常路径;setup-state 静默建管理员遇唯一冲突视为已初始化。
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
err401,
|
||||
err422,
|
||||
logPageSchema,
|
||||
keyItemSchema,
|
||||
} from "../api-schemas.ts";
|
||||
import { z } from "zod";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user