diff --git a/src/app.module.ts b/src/app.module.ts index d9a09f527..416a3e813 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -25,9 +25,13 @@ import hstsConfig from './config/hsts.config'; import cspConfig from './config/csp.config'; import databaseConfig from './config/database.config'; import authConfig from './config/auth.config'; +import customizationConfig from './config/customization.config'; +import externalConfig from './config/external-services.config'; import { PrivateApiModule } from './api/private/private-api.module'; import { ScheduleModule } from '@nestjs/schedule'; import { RouterModule, Routes } from 'nest-router'; +import { FrontendConfigService } from './frontend-config/frontend-config.service'; +import { FrontendConfigModule } from './frontend-config/frontend-config.module'; const routes: Routes = [ { @@ -53,6 +57,8 @@ const routes: Routes = [ cspConfig, databaseConfig, authConfig, + customizationConfig, + externalConfig, ], isGlobal: true, }), diff --git a/src/config/customization.config.ts b/src/config/customization.config.ts new file mode 100644 index 000000000..401e3e2b2 --- /dev/null +++ b/src/config/customization.config.ts @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { registerAs } from '@nestjs/config'; +import * as Joi from 'joi'; +import { buildErrorMessage } from './utils'; + +export interface CustomizationConfig { + branding: { + customName: string; + customLogo: string; + }; + specialUrls: { + privacy: string; + termsOfUse: string; + imprint: string; + }; +} + +const schema = Joi.object({ + branding: Joi.object({ + customName: Joi.string().optional().label('HD_CUSTOM_NAME'), + customLogo: Joi.string() + .uri({ + scheme: [/https?/], + }) + .optional() + .label('HD_CUSTOM_LOGO'), + }), + specialUrls: Joi.object({ + privacy: Joi.string() + .uri({ + scheme: /https?/, + }) + .optional() + .label('HD_PRIVACY_URL'), + termsOfUse: Joi.string() + .uri({ + scheme: /https?/, + }) + .optional() + .label('HD_TERMS_OF_USE_URL'), + imprint: Joi.string() + .uri({ + scheme: /https?/, + }) + .optional() + .label('HD_IMPRINT_URL'), + }), +}); + +export default registerAs('customizationConfig', () => { + const customizationConfig = schema.validate( + { + branding: { + customName: process.env.HD_CUSTOM_NAME, + customLogo: process.env.HD_CUSTOM_LOGO, + }, + specialUrls: { + privacy: process.env.HD_PRIVACY_URL, + termsOfUse: process.env.HD_TERMS_OF_USE_URL, + imprint: process.env.HD_IMPRINT_URL, + }, + }, + { + abortEarly: false, + presence: 'required', + }, + ); + if (customizationConfig.error) { + const errorMessages = customizationConfig.error.details.map( + (detail) => detail.message, + ); + throw new Error(buildErrorMessage(errorMessages)); + } + return customizationConfig.value as CustomizationConfig; +}); diff --git a/src/config/external-services.config.ts b/src/config/external-services.config.ts new file mode 100644 index 000000000..406633a4e --- /dev/null +++ b/src/config/external-services.config.ts @@ -0,0 +1,49 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { registerAs } from '@nestjs/config'; +import * as Joi from 'joi'; +import { buildErrorMessage } from './utils'; + +export interface ExternalServicesConfig { + plantUmlServer: string; + imageProxy: string; +} + +const schema = Joi.object({ + plantUmlServer: Joi.string() + .uri({ + scheme: /https?/, + }) + .optional() + .label('HD_PLANTUML_SERVER'), + imageProxy: Joi.string() + .uri({ + scheme: /https?/, + }) + .optional() + .label('HD_IMAGE_PROXY'), +}); + +export default registerAs('externalServicesConfig', () => { + const externalConfig = schema.validate( + { + plantUmlServer: process.env.HD_PLANTUML_SERVER, + imageProxy: process.env.HD_IMAGE_PROXY, + }, + { + abortEarly: false, + presence: 'required', + }, + ); + if (externalConfig.error) { + const errorMessages = externalConfig.error.details.map( + (detail) => detail.message, + ); + throw new Error(buildErrorMessage(errorMessages)); + } + return externalConfig.value as ExternalServicesConfig; +});