130 lines
3.7 KiB
TypeScript
130 lines
3.7 KiB
TypeScript
import { eq } from "drizzle-orm";
|
|
|
|
import { getDatabase } from "@/modules/core/server/db";
|
|
import { systemSettings } from "@/modules/core/server/schema";
|
|
import type { SystemSettings } from "@/modules/core/types";
|
|
|
|
const GLOBAL_SETTINGS_ID = "global";
|
|
|
|
type SystemSettingsRow = typeof systemSettings.$inferSelect;
|
|
|
|
export type SystemSettingsUpdate = {
|
|
registrationEnabled?: boolean;
|
|
oidcEnabled?: boolean;
|
|
oidcIssuerUrl?: string;
|
|
oidcClientId?: string;
|
|
oidcClientSecret?: string;
|
|
oidcScopes?: string;
|
|
oidcRedirectUri?: string;
|
|
oidcAvatarClaim?: string;
|
|
oidcAutoProvision?: boolean;
|
|
};
|
|
|
|
function toSystemSettings(row: SystemSettingsRow): SystemSettings {
|
|
return {
|
|
id: row.id,
|
|
registrationEnabled: row.registrationEnabled,
|
|
oidcEnabled: row.oidcEnabled,
|
|
oidcIssuerUrl: row.oidcIssuerUrl,
|
|
oidcClientId: row.oidcClientId,
|
|
oidcHasClientSecret: row.oidcClientSecret.length > 0,
|
|
oidcScopes: row.oidcScopes,
|
|
oidcRedirectUri: row.oidcRedirectUri,
|
|
oidcAvatarClaim: row.oidcAvatarClaim,
|
|
oidcAutoProvision: row.oidcAutoProvision,
|
|
updatedAt: row.updatedAt.toISOString(),
|
|
};
|
|
}
|
|
|
|
async function ensureSystemSettingsRow(): Promise<SystemSettingsRow> {
|
|
const database = getDatabase();
|
|
const existingRows = await database
|
|
.select()
|
|
.from(systemSettings)
|
|
.where(eq(systemSettings.id, GLOBAL_SETTINGS_ID))
|
|
.limit(1);
|
|
const existing = existingRows[0];
|
|
if (existing) {
|
|
return existing;
|
|
}
|
|
|
|
const createdRows = await database
|
|
.insert(systemSettings)
|
|
.values({ id: GLOBAL_SETTINGS_ID })
|
|
.onConflictDoNothing()
|
|
.returning();
|
|
const created = createdRows[0];
|
|
if (created) {
|
|
return created;
|
|
}
|
|
|
|
const fallbackRows = await database
|
|
.select()
|
|
.from(systemSettings)
|
|
.where(eq(systemSettings.id, GLOBAL_SETTINGS_ID))
|
|
.limit(1);
|
|
const fallback = fallbackRows[0];
|
|
if (!fallback) {
|
|
throw new Error("系统配置初始化失败");
|
|
}
|
|
|
|
return fallback;
|
|
}
|
|
|
|
export async function ensureSystemSettings(): Promise<void> {
|
|
await ensureSystemSettingsRow();
|
|
}
|
|
|
|
export async function getSystemSettings(): Promise<SystemSettings> {
|
|
const row = await ensureSystemSettingsRow();
|
|
return toSystemSettings(row);
|
|
}
|
|
|
|
export async function updateSystemSettings(input: SystemSettingsUpdate): Promise<SystemSettings> {
|
|
const database = getDatabase();
|
|
await ensureSystemSettingsRow();
|
|
|
|
const updateValues: SystemSettingsUpdate & { updatedAt: Date } = {
|
|
updatedAt: new Date(),
|
|
};
|
|
if (input.registrationEnabled !== undefined) {
|
|
updateValues.registrationEnabled = input.registrationEnabled;
|
|
}
|
|
if (input.oidcEnabled !== undefined) {
|
|
updateValues.oidcEnabled = input.oidcEnabled;
|
|
}
|
|
if (input.oidcIssuerUrl !== undefined) {
|
|
updateValues.oidcIssuerUrl = input.oidcIssuerUrl;
|
|
}
|
|
if (input.oidcClientId !== undefined) {
|
|
updateValues.oidcClientId = input.oidcClientId;
|
|
}
|
|
if (input.oidcClientSecret !== undefined && input.oidcClientSecret.length > 0) {
|
|
updateValues.oidcClientSecret = input.oidcClientSecret;
|
|
}
|
|
if (input.oidcScopes !== undefined) {
|
|
updateValues.oidcScopes = input.oidcScopes;
|
|
}
|
|
if (input.oidcRedirectUri !== undefined) {
|
|
updateValues.oidcRedirectUri = input.oidcRedirectUri;
|
|
}
|
|
if (input.oidcAvatarClaim !== undefined) {
|
|
updateValues.oidcAvatarClaim = input.oidcAvatarClaim;
|
|
}
|
|
if (input.oidcAutoProvision !== undefined) {
|
|
updateValues.oidcAutoProvision = input.oidcAutoProvision;
|
|
}
|
|
|
|
const rows = await database
|
|
.update(systemSettings)
|
|
.set(updateValues)
|
|
.where(eq(systemSettings.id, GLOBAL_SETTINGS_ID))
|
|
.returning();
|
|
const row = rows[0];
|
|
if (!row) {
|
|
throw new Error("系统配置不存在");
|
|
}
|
|
|
|
return toSystemSettings(row);
|
|
}
|