fix(admin): secure proxied model mutations
This commit is contained in:
@@ -28,7 +28,6 @@ const providerSchema = z.object({
|
||||
baseUrl: z.string().url().startsWith("https://").nullable().optional(),
|
||||
apiKey: z.string().max(4096).optional(),
|
||||
enabled: z.boolean(),
|
||||
reason: z.string().trim().min(1).max(500),
|
||||
}).strict();
|
||||
const settingsSchema = z.record(z.string(), z.unknown()).superRefine((value, context) => {
|
||||
if (modelSettingsContainSecrets(value)) {
|
||||
@@ -52,20 +51,26 @@ const draftSchema = z.object({
|
||||
isDefault: z.boolean(),
|
||||
fallbackModelId: z.string().regex(/^[a-z0-9][a-z0-9._-]{0,63}$/).nullable().optional(),
|
||||
settings: settingsSchema.default({}),
|
||||
reason: z.string().trim().min(1).max(500),
|
||||
}).strict();
|
||||
const actionSchema = z.discriminatedUnion("action", [
|
||||
providerSchema,
|
||||
draftSchema,
|
||||
z.object({ action: z.literal("test"), versionId: z.string().uuid() }).strict(),
|
||||
z.object({ action: z.literal("publish"), versionId: z.string().uuid(), reason: z.string().trim().min(1).max(500) }).strict(),
|
||||
z.object({ action: z.literal("rollback"), configId: z.string().uuid(), targetVersion: z.number().int().positive(), reason: z.string().trim().min(1).max(500) }).strict(),
|
||||
z.object({ action: z.literal("publish"), versionId: z.string().uuid() }).strict(),
|
||||
z.object({ action: z.literal("rollback"), configId: z.string().uuid(), targetVersion: z.number().int().positive() }).strict(),
|
||||
]).superRefine((value, context) => {
|
||||
if (value.action === "saveDraft" && value.isDefault && !value.enabled) {
|
||||
context.addIssue({ code: "custom", path: ["isDefault"], message: "默认模型必须启用" });
|
||||
}
|
||||
});
|
||||
|
||||
const modelMutationAuditReasons = {
|
||||
saveProvider: "保存模型供应商",
|
||||
saveDraft: "保存模型草稿",
|
||||
publish: "发布模型版本",
|
||||
rollback: "回滚模型版本",
|
||||
} as const;
|
||||
|
||||
type ProviderRow = {
|
||||
id: string;
|
||||
code: string;
|
||||
@@ -178,8 +183,11 @@ export async function POST(request: Request) {
|
||||
: "models.write";
|
||||
const session = await requireAdminMutation(request, permission);
|
||||
const rid = requestId(request);
|
||||
const mutation: AdminModelMutation = body.data.action === "test"
|
||||
? body.data
|
||||
: { ...body.data, reason: modelMutationAuditReasons[body.data.action] };
|
||||
return await handleAdminModelMutation(
|
||||
body.data as AdminModelMutation,
|
||||
mutation,
|
||||
{ actorUserId: session.user.id, requestId: rid },
|
||||
{
|
||||
queryRows: (sql, values) => queryAdminRows<Record<string, unknown>>(sql, values),
|
||||
|
||||
Reference in New Issue
Block a user