import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; import { db } from "@/lib/db"; import { authSettings } from "@/lib/db/schema"; import { eq } from "drizzle-orm"; import { auth } from "@/app/(auth)/auth"; // GET /api/auth-settings - 获取认证配置 export async function GET() { try { const session = await auth(); const isAdmin = session?.user?.type === "admin"; const [settings] = await db.select().from(authSettings).limit(1); // 如果没有配置记录,返回默认值 if (!settings) { return NextResponse.json({ dingTalkAppKey: "", dingTalkAppSecret: "", // 即使是空的,非管理员也不应该看到这个字段名,但因为是空字符串,问题不大 dingTalkOrganizations: [], isDingTalkEnabled: false, isRegistrationEnabled: true, }); } if (isAdmin) { return NextResponse.json({ ...settings, dingTalkOrganizations: settings.dingTalkOrganizations ?? [], }); } // 非管理员,脱敏返回,只暴露组织名称 const organizations = settings.dingTalkOrganizations?.map((org) => ({ name: org.name, })) ?? []; return NextResponse.json({ dingTalkAppKey: settings.dingTalkAppKey, isDingTalkEnabled: settings.isDingTalkEnabled, isRegistrationEnabled: settings.isRegistrationEnabled, organizations, // 不返回 dingTalkAppSecret 以及各组织的密钥 }); } catch (error) { console.error("[Auth Settings API] Get error:", error); return NextResponse.json( { error: "Failed to fetch auth settings" }, { status: 500 } ); } } const orgSchema = z.object({ name: z.string().min(1), appKey: z.string().min(1), appSecret: z.string().min(1), }); const updateSchema = z.object({ dingTalkAppKey: z.string().optional(), dingTalkAppSecret: z.string().optional(), dingTalkOrganizations: z.array(orgSchema).optional(), isDingTalkEnabled: z.boolean().optional(), isRegistrationEnabled: z.boolean().optional(), }); // PUT /api/auth-settings - 更新认证配置(仅管理员) export async function PUT(request: NextRequest) { try { const session = await auth(); if (!session?.user) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } if (session.user.type !== "admin") { return NextResponse.json({ error: "Forbidden" }, { status: 403 }); } const body = await request.json(); const data = updateSchema.parse(body); // 查找现有配置 const [existing] = await db.select().from(authSettings).limit(1); const organizations = data.dingTalkOrganizations ?? existing?.dingTalkOrganizations ?? []; const primaryOrg = organizations[0] as | { name: string; appKey: string; appSecret: string } | undefined; const resolvedAppKey = data.dingTalkAppKey ?? primaryOrg?.appKey ?? existing?.dingTalkAppKey ?? null; const resolvedAppSecret = data.dingTalkAppSecret ?? primaryOrg?.appSecret ?? existing?.dingTalkAppSecret ?? null; if (existing) { // 更新现有配置 const [updated] = await db .update(authSettings) .set({ dingTalkAppKey: resolvedAppKey, dingTalkAppSecret: resolvedAppSecret, dingTalkOrganizations: organizations, isDingTalkEnabled: data.isDingTalkEnabled ?? existing.isDingTalkEnabled, isRegistrationEnabled: data.isRegistrationEnabled ?? existing.isRegistrationEnabled, updatedAt: new Date(), updatedBy: session.user.id, }) .where(eq(authSettings.id, existing.id)) .returning(); return NextResponse.json(updated); } // 创建新配置 const [created] = await db .insert(authSettings) .values({ dingTalkAppKey: resolvedAppKey, dingTalkAppSecret: resolvedAppSecret, dingTalkOrganizations: organizations, isDingTalkEnabled: data.isDingTalkEnabled || false, isRegistrationEnabled: data.isRegistrationEnabled ?? true, updatedBy: session.user.id, }) .returning(); return NextResponse.json(created); } catch (error) { console.error("[Auth Settings API] Update error:", error); if (error instanceof z.ZodError) { return NextResponse.json( { error: "Invalid request data", details: error.errors }, { status: 400 } ); } return NextResponse.json( { error: "Failed to update auth settings" }, { status: 500 } ); } }