feat: 添加注册开关功能,优化系统配置与注册接口
ocs-nuxt / deploy (push) Failing after 11s

This commit is contained in:
2026-05-23 23:48:30 +08:00
parent bc785ac1ce
commit 5e99e28e8b
15 changed files with 371 additions and 48 deletions
+24 -20
View File
@@ -7,27 +7,31 @@
// - 此接口不返回任何用户数据
import { setResponseStatus } from "h3";
import { getSysConfig, maskApiKey } from "~~/server/utils/sysConfig";
import { apiErr, apiOk } from "~~/server/utils/response";
import { getSysConfig, maskApiKey } from "~~/server/utils/sysConfig";
import type { ISystemConfigResponse } from "~~/shared/types/settings";
export default defineEventHandler(async (event): Promise<ISystemConfigResponse> => {
// 二次校验:必须是 superadmin 才能访问系统配置
const role = (event.context.auth?.user as { role?: string } | undefined)
?.role;
if (role !== "superadmin") {
setResponseStatus(event, 403);
return apiErr(403, "权限不足") as ISystemConfigResponse;
export default defineEventHandler(
async (event): Promise<ISystemConfigResponse> => {
// 二次校验:必须是 superadmin 才能访问系统配置
const role = (event.context.auth?.user as { role?: string } | undefined)
?.role;
if (role !== "superadmin") {
setResponseStatus(event, 403);
return apiErr(403, "权限不足") as unknown as ISystemConfigResponse;
}
const cfg = await getSysConfig();
return apiOk({
openAiApiBase: cfg.openAiApiBase,
openAiApiKeyPreview: maskApiKey(cfg.openAiApiKey),
openAiModel: cfg.openAiModel,
maxTokens: cfg.maxTokens,
temperature: cfg.temperature,
maxSseLineBytes: cfg.maxSseLineBytes,
allowRegistration: cfg.allowRegistration
});
}
const cfg = await getSysConfig();
return apiOk({
openAiApiBase: cfg.openAiApiBase,
openAiApiKeyPreview: maskApiKey(cfg.openAiApiKey),
openAiModel: cfg.openAiModel,
maxTokens: cfg.maxTokens,
temperature: cfg.temperature,
maxSseLineBytes: cfg.maxSseLineBytes
});
});
);
+17 -6
View File
@@ -7,12 +7,11 @@
// - 更新成功后立即失效系统配置缓存,下次请求即生效
import { readBody, setResponseStatus } from "h3";
import { prisma } from "~~/server/utils/db";
import { createApiLogger, toSafeLogError } from "~~/server/utils/logging";
import { apiErr, apiOk } from "~~/server/utils/response";
import {
invalidateSysConfigCache
} from "~~/server/utils/sysConfig";
import { invalidateSysConfigCache } from "~~/server/utils/sysConfig";
import type { ISystemConfigUpdateRequest } from "~~/shared/types/settings";
const isRecord = (v: unknown): v is Record<string, unknown> =>
@@ -25,7 +24,8 @@ const SYS_KEY = {
openAiModel: "openai_model",
maxTokens: "max_tokens",
temperature: "temperature",
maxSseLineBytes: "openai_stream_max_sse_line_bytes"
maxSseLineBytes: "openai_stream_max_sse_line_bytes",
allowRegistration: "allow_registration"
} as const;
export default defineEventHandler(async (event) => {
@@ -63,6 +63,9 @@ export default defineEventHandler(async (event) => {
if (typeof body.maxSseLineBytes === "number") {
req.maxSseLineBytes = body.maxSseLineBytes;
}
if (typeof body.allowRegistration === "boolean") {
req.allowRegistration = body.allowRegistration;
}
// 构建需要写入的 KV 对(key 为空时跳过)
type SysKv = { key: string; value: string };
@@ -90,13 +93,19 @@ export default defineEventHandler(async (event) => {
value: String(req.maxSseLineBytes)
});
}
if (req.allowRegistration !== undefined) {
upserts.push({
key: SYS_KEY.allowRegistration,
value: String(req.allowRegistration)
});
}
if (upserts.length === 0) {
return apiOk(null);
}
try {
await prisma.$transaction(
await Promise.all(
upserts.map((item) =>
prisma.systemConfig.upsert({
where: { key: item.key },
@@ -115,7 +124,9 @@ export default defineEventHandler(async (event) => {
return apiOk(null);
} catch (error) {
logger.error("system_config_update_failed", { error: toSafeLogError(error) });
logger.error("system_config_update_failed", {
error: toSafeLogError(error)
});
setResponseStatus(event, 500);
return apiErr(500, "服务器内部错误");
}
+16
View File
@@ -0,0 +1,16 @@
// server/api/auth/register-open.get.ts - 公开接口:查询当前是否开放注册
//
// 该接口无需登录,供前端注册页面展示禁用提示使用。
// 路径位于 /api/auth/** 公开区内,不经过鉴权中间件。
// 不返回任何用户数据或系统敏感信息。
import { apiOk } from "~~/server/utils/response";
import { getSysConfig } from "~~/server/utils/sysConfig";
import type { IRegisterStatusResponse } from "~~/shared/types/settings";
export default defineEventHandler(
async (): Promise<IRegisterStatusResponse> => {
const cfg = await getSysConfig();
return apiOk({ allowRegistration: cfg.allowRegistration });
}
);