import { eq } from "drizzle-orm"; import { jsonFailure, jsonSuccess, readJsonBody } from "@/modules/core/server/api"; import { recordAuditLog } from "@/modules/core/server/audit"; import { requirePermission } from "@/modules/core/server/auth"; import { getDatabase } from "@/modules/core/server/db"; import { organizations } from "@/modules/core/server/schema"; import type { OrganizationStatus } from "@/modules/core/types"; type RouteContext = { params: Promise<{ id: string; }>; }; const ORGANIZATION_STATUSES: OrganizationStatus[] = ["active", "disabled"]; function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null && !Array.isArray(value); } function readString(source: Record, key: string): string { const value = source[key]; return typeof value === "string" ? value.trim() : ""; } function readBoolean(source: Record, key: string): boolean | null { const value = source[key]; return typeof value === "boolean" ? value : null; } function readStatus(value: unknown): OrganizationStatus | null { if (typeof value !== "string") { return null; } return ORGANIZATION_STATUSES.find((status) => status === value) ?? null; } export async function PATCH(request: Request, context: RouteContext): Promise { const { id } = await context.params; const auth = await requirePermission("organization:manage", { action: "organization.update", targetType: "organization", targetId: id, }); if (!auth.success) { return auth.response; } const body = await readJsonBody(request); if (!isRecord(body)) { return jsonFailure("请求数据格式无效"); } const name = readString(body, "name"); const slug = readString(body, "slug"); const oidcIssuerUrl = readString(body, "oidcIssuerUrl"); const oidcClientId = readString(body, "oidcClientId"); const oidcClientSecret = readString(body, "oidcClientSecret"); const oidcScopes = readString(body, "oidcScopes"); const oidcRedirectUri = readString(body, "oidcRedirectUri"); const status = "status" in body ? readStatus(body.status) : null; if ("status" in body && !status) { return jsonFailure("机构状态无效"); } const registrationEnabled = "registrationEnabled" in body ? readBoolean(body, "registrationEnabled") : null; const oidcEnabled = "oidcEnabled" in body ? readBoolean(body, "oidcEnabled") : null; const oidcAutoProvision = "oidcAutoProvision" in body ? readBoolean(body, "oidcAutoProvision") : null; if ("registrationEnabled" in body && registrationEnabled === null) { return jsonFailure("注册开关无效"); } if ("oidcEnabled" in body && oidcEnabled === null) { return jsonFailure("OIDC开关无效"); } if ("oidcAutoProvision" in body && oidcAutoProvision === null) { return jsonFailure("OIDC自动开户配置无效"); } if ( !name && !slug && !status && registrationEnabled === null && oidcEnabled === null && !oidcIssuerUrl && !oidcClientId && !oidcClientSecret && !oidcScopes && !oidcRedirectUri && oidcAutoProvision === null ) { return jsonFailure("请至少填写一个要更新的字段"); } const updateValues: { name?: string; slug?: string; status?: OrganizationStatus; registrationEnabled?: boolean; oidcEnabled?: boolean; oidcIssuerUrl?: string; oidcClientId?: string; oidcClientSecret?: string; oidcScopes?: string; oidcRedirectUri?: string; oidcAutoProvision?: boolean; updatedAt: Date; } = { updatedAt: new Date(), }; if (name) { updateValues.name = name; } if (slug) { updateValues.slug = slug; } if (status) { updateValues.status = status; } if (registrationEnabled !== null) { updateValues.registrationEnabled = registrationEnabled; } if (oidcEnabled !== null) { updateValues.oidcEnabled = oidcEnabled; } if (oidcIssuerUrl) { updateValues.oidcIssuerUrl = oidcIssuerUrl; } if (oidcClientId) { updateValues.oidcClientId = oidcClientId; } if (oidcClientSecret) { updateValues.oidcClientSecret = oidcClientSecret; } if (oidcScopes) { updateValues.oidcScopes = oidcScopes; } if (oidcRedirectUri) { updateValues.oidcRedirectUri = oidcRedirectUri; } if (oidcAutoProvision !== null) { updateValues.oidcAutoProvision = oidcAutoProvision; } const database = getDatabase(); try { const rows = await database.update(organizations).set(updateValues).where(eq(organizations.id, id)).returning(); const organization = rows[0]; if (!organization) { return jsonFailure("机构不存在", 404); } await recordAuditLog({ actor: auth.context.account, organizationId: organization.id, action: "organization.update", targetType: "organization", targetId: organization.id, result: "success", reason: `更新机构:${organization.name}`, }); return jsonSuccess("机构已更新", { organization }); } catch (error) { const message = error instanceof Error ? error.message : ""; if (message.includes("organizations_slug_unique")) { return jsonFailure("机构标识已存在", 409); } return jsonFailure("机构更新失败", 500); } } export async function DELETE(_request: Request, context: RouteContext): Promise { const { id } = await context.params; const auth = await requirePermission("organization:manage", { action: "organization.disable", targetType: "organization", targetId: id, }); if (!auth.success) { return auth.response; } const database = getDatabase(); const rows = await database .update(organizations) .set({ status: "disabled", updatedAt: new Date() }) .where(eq(organizations.id, id)) .returning(); const organization = rows[0]; if (!organization) { return jsonFailure("机构不存在", 404); } await recordAuditLog({ actor: auth.context.account, organizationId: organization.id, action: "organization.disable", targetType: "organization", targetId: organization.id, result: "success", reason: `停用机构:${organization.name}`, }); return jsonSuccess("机构已停用", { organization }); }