Map model provider configuration errors

This commit is contained in:
Jesse_Chen
2026-08-08 11:01:56 +08:00
parent 99e2abe9bc
commit 0676b6c402
2 changed files with 39 additions and 0 deletions
@@ -7,10 +7,30 @@ function isPostgresError(error: unknown): error is { code: string } {
&& typeof (error as { code?: unknown }).code === "string";
}
function errorMessage(error: unknown) {
return typeof error === "object" && error !== null && "message" in error
&& typeof (error as { message?: unknown }).message === "string"
? (error as { message: string }).message
: "";
}
export function adminErrorResponse(error: unknown) {
if (error instanceof AdminAuthorizationError) {
return NextResponse.json({ error: error.message }, { status: error.status });
}
const message = errorMessage(error);
if (message.includes("模型供应商地址不在服务器允许列表中")) {
return NextResponse.json({ error: message }, { status: 400 });
}
if (message.includes("网关地址不允许")) {
return NextResponse.json({ error: message }, { status: 400 });
}
if (message.includes("model_provider_url_unsafe")) {
return NextResponse.json({ error: "模型供应商地址不安全或解析到内网" }, { status: 400 });
}
if (message.includes("模型供应商密钥未配置") || message.includes("model_provider_key_required")) {
return NextResponse.json({ error: "模型供应商密钥未配置" }, { status: 409 });
}
if (isPostgresError(error)) {
if (error.code === "42501") return NextResponse.json({ error: "无权执行此操作" }, { status: 403 });
if (error.code === "40001") return NextResponse.json({ error: "资源已被其他管理员修改,请刷新后重试" }, { status: 409 });
+19
View File
@@ -168,6 +168,25 @@ test("configuration, identity reader, and RBAC query failures become sanitized 5
}
});
test("adminErrorResponse maps model provider configuration failures without exposing details", async () => {
for (const [error, status, message] of [
[new Error("模型供应商地址不在服务器允许列表中"), 400, "模型供应商地址不在服务器允许列表中"],
[new Error("网关地址不允许解析到本机、内网或保留地址"), 400, "网关地址不允许解析到本机、内网或保留地址"],
[new Error("model_provider_url_unsafe"), 400, "模型供应商地址不安全或解析到内网"],
[new Error("model_provider_key_required"), 409, "模型供应商密钥未配置"],
] as const) {
const response = adminErrorResponse(error);
assert.equal(response.status, status);
assert.deepEqual(await response.json(), { error: message });
}
for (const error of [new Error("model_provider_runtime_immutable"), new Error("model_provider_code_immutable")]) {
const response = adminErrorResponse(error);
assert.equal(response.status, 500);
assert.deepEqual(await response.json(), { error: "后台服务暂时不可用" });
}
});
test("adminErrorResponse preserves the sanitized authorization 503", async () => {
const response = adminErrorResponse(
new AdminAuthorizationError("后台服务暂时不可用", 503),