150 lines
4.5 KiB
TypeScript
150 lines
4.5 KiB
TypeScript
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 }
|
|
);
|
|
}
|
|
}
|