import { UserModel } from './models/user.ts'; import { Config, OptionalApp } from './types.ts'; export class AppConfig { private static config: Config; private static getDefaultConfig(): Config { return { auth: { baseUrl: 'http://localhost:8000', allowSignups: false, enableEmailVerification: false, enableForeverSignup: true, enableMultiFactor: false, allowedCookieDomains: [], skipCookieDomainSecurity: false, enableSingleSignOn: false, singleSignOnUrl: '', singleSignOnEmailAttribute: 'email', singleSignOnScopes: ['openid', 'email'], }, files: { rootPath: 'data-files', allowPublicSharing: false, }, core: { enabledApps: ['news', 'notes', 'photos', 'expenses', 'contacts', 'calendar'], }, visuals: { title: '', description: '', helpEmail: 'help@bewcloud.com', }, email: { from: 'help@bewcloud.com', host: 'localhost', port: 465, }, contacts: { enableCardDavServer: true, cardDavUrl: 'http://radicale:5232', }, calendar: { enableCalDavServer: true, calDavUrl: 'http://radicale:5232', }, }; } private static async loadConfig(): Promise { if (this.config) { return; } const initialConfig = this.getDefaultConfig(); const config: Config = { ...initialConfig, }; try { const configFromFile: Config = (await import(`${Deno.cwd()}/bewcloud.config.ts`)).default; this.config = { ...config, auth: { ...config.auth, ...configFromFile.auth, }, files: { ...config.files, ...configFromFile.files, }, core: { ...config.core, ...configFromFile.core, }, visuals: { ...config.visuals, ...configFromFile.visuals, }, email: { ...config.email, ...configFromFile.email, }, contacts: { ...config.contacts, ...configFromFile.contacts, }, calendar: { ...config.calendar, ...configFromFile.calendar, }, }; console.info('\nConfig loaded from bewcloud.config.ts', JSON.stringify(this.config, null, 2), '\n'); return; } catch (error) { console.error('Error loading config from bewcloud.config.ts. Using default config instead.', error); } this.config = config; } static async getConfig(): Promise { await this.loadConfig(); return this.config; } static async isSignupAllowed(): Promise { await this.loadConfig(); const areSignupsAllowed = this.config.auth.allowSignups; const areThereAdmins = await UserModel.isThereAnAdmin(); if (areSignupsAllowed || !areThereAdmins) { return true; } return false; } static async isAppEnabled(app: OptionalApp): Promise { await this.loadConfig(); const enabledApps = this.config.core.enabledApps; return enabledApps.includes(app); } static async isCookieDomainAllowed(domain: string): Promise { await this.loadConfig(); const allowedDomains = this.config.auth.allowedCookieDomains; if (allowedDomains.length === 0) { return true; } return allowedDomains.includes(domain); } static async isCookieDomainSecurityDisabled(): Promise { await this.loadConfig(); return this.config.auth.skipCookieDomainSecurity; } static async isEmailVerificationEnabled(): Promise { await this.loadConfig(); return this.config.auth.enableEmailVerification; } static async isForeverSignupEnabled(): Promise { await this.loadConfig(); return this.config.auth.enableForeverSignup; } static async isMultiFactorAuthEnabled(): Promise { await this.loadConfig(); return this.config.auth.enableMultiFactor; } static async isSingleSignOnEnabled(): Promise { await this.loadConfig(); return this.config.auth.enableSingleSignOn; } static async isPublicFileSharingAllowed(): Promise { await this.loadConfig(); return this.config.files.allowPublicSharing; } static async getFilesRootPath(): Promise { await this.loadConfig(); const filesRootPath = `${Deno.cwd()}/${this.config.files.rootPath}`; return filesRootPath; } static async getEmailConfig(): Promise { await this.loadConfig(); return this.config.email; } static async getContactsConfig(): Promise { await this.loadConfig(); return this.config.contacts; } static async getCalendarConfig(): Promise { await this.loadConfig(); return this.config.calendar; } }