feat: add global auth settings and pending users

This commit is contained in:
2026-07-02 06:27:32 -07:00
parent f6b7924d0c
commit 4bb4312b08
24 changed files with 2831 additions and 23 deletions

View File

@@ -0,0 +1,129 @@
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);
}