Files
new-api/web/src/features/system-settings/maintenance/config.ts
T
Calcium-Ion 31d70fca39 refactor(auth): replace dashboard sessions with stateless tokens and session control (#6329)
* refactor(auth): replace dashboard sessions with stateless tokens

* feat(auth): harden session issuance and distributed enforcement

* fix(proxy): preserve trusted proxy compatibility defaults

* refactor: address dashboard auth review feedback

* refactor: remove classic frontend and flatten web app
2026-07-20 16:48:43 +08:00

243 lines
6.1 KiB
TypeScript

/*
Copyright (C) 2023-2026 QuantumNous
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
export type HeaderNavAccessConfig = {
enabled: boolean
requireAuth: boolean
}
export type HeaderNavModulesConfig = {
home: boolean
console: boolean
pricing: HeaderNavAccessConfig
rankings: HeaderNavAccessConfig
docs: boolean
about: boolean
[key: string]: boolean | HeaderNavAccessConfig
}
export type SidebarSectionConfig = {
enabled: boolean
[key: string]: boolean
}
export type SidebarModulesAdminConfig = Record<string, SidebarSectionConfig>
export const HEADER_NAV_DEFAULT: HeaderNavModulesConfig = {
home: true,
console: true,
pricing: {
enabled: true,
requireAuth: false,
},
rankings: {
enabled: true,
requireAuth: false,
},
docs: true,
about: true,
}
export const SIDEBAR_MODULES_DEFAULT: SidebarModulesAdminConfig = {
chat: {
enabled: true,
playground: true,
chat: true,
},
console: {
enabled: true,
detail: true,
token: true,
log: true,
midjourney: true,
task: true,
},
personal: {
enabled: true,
topup: true,
personal: true,
},
admin: {
enabled: true,
channel: true,
models: true,
redemption: true,
user: true,
setting: true,
subscription: true,
},
}
const toBoolean = (value: unknown, fallback: boolean): boolean => {
if (typeof value === 'boolean') return value
if (typeof value === 'number') return value === 1
if (typeof value === 'string') {
const normalized = value.trim().toLowerCase()
if (normalized === 'true' || normalized === '1') return true
if (normalized === 'false' || normalized === '0') return false
}
return fallback
}
const cloneHeaderNavDefault = (): HeaderNavModulesConfig => ({
...HEADER_NAV_DEFAULT,
pricing: { ...HEADER_NAV_DEFAULT.pricing },
rankings: { ...HEADER_NAV_DEFAULT.rankings },
})
const parseAccessModule = (
raw: unknown,
fallback: HeaderNavAccessConfig
): HeaderNavAccessConfig => {
if (
typeof raw === 'boolean' ||
typeof raw === 'string' ||
typeof raw === 'number'
) {
return {
enabled: toBoolean(raw, fallback.enabled),
requireAuth: fallback.requireAuth,
}
}
if (raw && typeof raw === 'object') {
const record = raw as Record<string, unknown>
return {
enabled: toBoolean(record.enabled, fallback.enabled),
requireAuth: toBoolean(record.requireAuth, fallback.requireAuth),
}
}
return { ...fallback }
}
const cloneSidebarDefault = (): SidebarModulesAdminConfig =>
Object.entries(SIDEBAR_MODULES_DEFAULT).reduce<SidebarModulesAdminConfig>(
(acc, [section, config]) => {
acc[section] = { ...config }
return acc
},
{}
)
export function parseHeaderNavModules(
value: string | null | undefined
): HeaderNavModulesConfig {
const base = cloneHeaderNavDefault()
if (!value) {
return base
}
try {
const parsed = JSON.parse(value) as Record<string, unknown>
const result: HeaderNavModulesConfig = {
...base,
pricing: { ...base.pricing },
rankings: { ...base.rankings },
}
Object.entries(parsed).forEach(([key, raw]) => {
if (key === 'pricing') {
result.pricing = parseAccessModule(raw, base.pricing)
return
}
if (key === 'rankings') {
result.rankings = parseAccessModule(raw, base.rankings)
return
}
if (typeof raw === 'boolean') {
result[key] = raw
return
}
if (typeof raw === 'string' || typeof raw === 'number') {
result[key] = toBoolean(raw, Boolean(base[key]))
return
}
})
return result
} catch {
return base
}
}
export function serializeHeaderNavModules(
config: HeaderNavModulesConfig
): string {
return JSON.stringify(config)
}
export function parseSidebarModulesAdmin(
value: string | null | undefined
): SidebarModulesAdminConfig {
const defaults = cloneSidebarDefault()
// If empty string, null, or undefined, use default config
if (!value || value.trim() === '') return defaults
try {
const parsed = JSON.parse(value) as Record<string, unknown>
const result: SidebarModulesAdminConfig = {}
Object.entries(parsed).forEach(([sectionKey, raw]) => {
if (!raw || typeof raw !== 'object') return
const defaultSection = defaults[sectionKey] ?? { enabled: true }
const sectionConfig: SidebarSectionConfig = {
enabled: toBoolean(
(raw as Record<string, unknown>).enabled,
defaultSection.enabled ?? true
),
}
Object.entries(raw as Record<string, unknown>).forEach(
([moduleKey, moduleValue]) => {
if (moduleKey === 'enabled') return
sectionConfig[moduleKey] = toBoolean(
moduleValue,
defaultSection[moduleKey] ?? true
)
}
)
result[sectionKey] = sectionConfig
})
// Merge defaults to ensure expected sections exist
Object.entries(defaults).forEach(([sectionKey, config]) => {
if (!result[sectionKey]) {
result[sectionKey] = { ...config }
return
}
Object.entries(config).forEach(([moduleKey, moduleValue]) => {
if (!(moduleKey in result[sectionKey])) {
result[sectionKey][moduleKey] = moduleValue
}
})
})
return result
} catch {
return defaults
}
}
export function serializeSidebarModulesAdmin(
config: SidebarModulesAdminConfig
): string {
return JSON.stringify(config)
}