diff --git a/src/api/public/media/media.controller.spec.ts b/src/api/public/media/media.controller.spec.ts index 5319a3bb9..2e5180993 100644 --- a/src/api/public/media/media.controller.spec.ts +++ b/src/api/public/media/media.controller.spec.ts @@ -8,6 +8,7 @@ import { ConfigModule } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import appConfigMock from '../../../config/app.config.mock'; +import mediaConfigMock from '../../../config/media.config.mock'; import { LoggerModule } from '../../../logger/logger.module'; import { MediaUpload } from '../../../media/media-upload.entity'; import { MediaModule } from '../../../media/media.module'; @@ -31,7 +32,7 @@ describe('Media Controller', () => { imports: [ ConfigModule.forRoot({ isGlobal: true, - load: [appConfigMock], + load: [appConfigMock, mediaConfigMock], }), LoggerModule, MediaModule, diff --git a/src/app.module.ts b/src/app.module.ts index 54a22ece5..06e5bb281 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -19,6 +19,11 @@ import { PermissionsModule } from './permissions/permissions.module'; import { RevisionsModule } from './revisions/revisions.module'; import { UsersModule } from './users/users.module'; import appConfig from './config/app.config'; +import mediaConfig from './config/media.config'; +import hstsConfig from './config/hsts.config'; +import cspConfig from './config/csp.config'; +import databaseConfig from './config/database.config'; +import authConfig from './config/auth.config'; @Module({ imports: [ @@ -29,7 +34,14 @@ import appConfig from './config/app.config'; synchronize: true, }), ConfigModule.forRoot({ - load: [appConfig], + load: [ + appConfig, + mediaConfig, + hstsConfig, + cspConfig, + databaseConfig, + authConfig, + ], isGlobal: true, }), NotesModule, diff --git a/src/config/app.config.mock.ts b/src/config/app.config.mock.ts index 825a0b90d..9b013a75c 100644 --- a/src/config/app.config.mock.ts +++ b/src/config/app.config.mock.ts @@ -8,12 +8,4 @@ import { registerAs } from '@nestjs/config'; export default registerAs('appConfig', () => ({ port: 3000, - media: { - backend: { - use: 'filesystem', - filesystem: { - uploadPath: 'uploads', - }, - }, - }, })); diff --git a/src/config/app.config.ts b/src/config/app.config.ts index bfd687325..980eabfe3 100644 --- a/src/config/app.config.ts +++ b/src/config/app.config.ts @@ -7,46 +7,11 @@ import { registerAs } from '@nestjs/config'; import * as Joi from 'joi'; import { Loglevel } from './loglevel.enum'; -import { appConfigHsts, HstsConfig, hstsSchema } from './hsts-config'; -import { appConfigCsp, CspConfig, cspSchema } from './csp-config'; -import { appConfigMedia, MediaConfig, mediaSchema } from './media-config'; -import { - appConfigDatabase, - DatabaseConfig, - databaseSchema, -} from './database-config'; -import { appConfigAuth, AuthConfig, authSchema } from './auth-config'; - -// import { LinkifyHeaderStyle } from './linkify-header-style'; export interface AppConfig { domain: string; port: number; loglevel: Loglevel; - /*linkifyHeaderStyle: LinkifyHeaderStyle; - sourceURL: string; - urlPath: string; - host: string; - path: string; - urlAddPort: boolean; - cookiePolicy: string; - protocolUseSSL: boolean; - allowOrigin: string[]; - useCDN: boolean; - enableAnonymous: boolean; - enableAnonymousEdits: boolean; - enableFreeURL: boolean; - forbiddenNoteIDs: string[]; - defaultPermission: string; - sessionSecret: string; - sessionLife: number; - tooBusyLag: number; - enableGravatar: boolean;*/ - hsts: HstsConfig; - csp: CspConfig; - media: MediaConfig; - database: DatabaseConfig; - auth: AuthConfig; } const schema = Joi.object({ @@ -56,30 +21,6 @@ const schema = Joi.object({ .valid(...Object.values(Loglevel)) .default(Loglevel.WARN) .optional(), - /*linkifyHeaderStyle: Joi.string().valid(...Object.values(LinkifyHeaderStyle)).default(LinkifyHeaderStyle.GFM).optional(), - sourceURL: Joi.string(), - urlPath: Joi.string(), - host: Joi.string().default('::').optional(), - path: Joi.string(), - urlAddPort: Joi.boolean().default(false).optional(), - cookiePolicy: Joi.string(), - protocolUseSSL: Joi.boolean().default(true).optional(), - allowOrigin: Joi.array().items(Joi.string()), - useCDN: Joi.boolean().default(false).optional(), - enableAnonymous: Joi.boolean().default(true).optional(), - enableAnonymousEdits: Joi.boolean().default(false).optional(), - enableFreeURL: Joi.boolean().default(false).optional(), - forbiddenNoteIDs: Joi.array().items(Joi.string()), - defaultPermission: Joi.string(), - sessionSecret: Joi.string(), - sessionLife: Joi.number().default(14 * 24 * 60 * 60 * 1000).optional(), - tooBusyLag: Joi.number().default(70).optional(), - enableGravatar: Joi.boolean().default(true).optional(),*/ - hsts: hstsSchema, - csp: cspSchema, - media: mediaSchema, - database: databaseSchema, - auth: authSchema, }); export default registerAs('appConfig', async () => { @@ -87,31 +28,7 @@ export default registerAs('appConfig', async () => { { domain: process.env.HD_DOMAIN, port: parseInt(process.env.PORT) || undefined, - loglevel: process.env.HD_LOGLEVEL, //|| Loglevel.WARN, - /*linkifyHeaderStyle: process.env.HD_LINKIFY_HEADER_STYLE, - sourceURL: process.env.HD_SOURCE_URL, - urlPath: process.env.HD_URL_PATH, - host: process.env.HD_HOST || '::', - path: process.env.HD_PATH, - urlAddPort: process.env.HD_URL_ADDPORT, - cookiePolicy: process.env.HD_COOKIE_POLICY, - protocolUseSSL: process.env.HD_PROTOCOL_USESSL || true, - allowOrigin: toArrayConfig(process.env.HD_ALLOW_ORIGIN), - useCDN: process.env.HD_USECDN, - enableAnonymous: process.env.HD_ENABLE_ANONYMOUS || true, - enableAnonymousEdits: process.env.HD_ENABLE_ANONYMOUS_EDITS, - enableFreeURL: process.env.HD_ENABLE_FREEURL, - forbiddenNoteIDs: toArrayConfig(process.env.HD_FORBIDDEN_NOTE_IDS), - defaultPermission: process.env.HD_DEFAULT_PERMISSION, - sessionSecret: process.env.HD_SESSION_SECRET, - sessionLife: parseInt(process.env.HD_SESSION_LIFE) || 14 * 24 * 60 * 60 * 1000, - tooBusyLag: parseInt(process.env.HD_TOOBUSY_LAG) || 70, - enableGravatar: process.env.HD_ENABLE_GRAVATAR || true,*/ - hsts: appConfigHsts, - csp: appConfigCsp, - media: appConfigMedia, - database: appConfigDatabase, - auth: appConfigAuth, + loglevel: process.env.HD_LOGLEVEL, }, { abortEarly: false, diff --git a/src/config/auth-config.ts b/src/config/auth.config.ts similarity index 87% rename from src/config/auth-config.ts rename to src/config/auth.config.ts index d8ab34fcd..b722b5b50 100644 --- a/src/config/auth-config.ts +++ b/src/config/auth.config.ts @@ -7,6 +7,7 @@ import * as Joi from 'joi'; import { GitlabScope, GitlabVersion } from './gitlab.enum'; import { toArrayConfig } from './utils'; +import { registerAs } from '@nestjs/config'; export interface AuthConfig { email: { @@ -99,7 +100,7 @@ export interface AuthConfig { ]; } -export const authSchema = Joi.object({ +const authSchema = Joi.object({ email: { enableLogin: Joi.boolean().default(false).optional(), enableRegister: Joi.boolean().default(false).optional(), @@ -297,35 +298,47 @@ const oauth2s = oauth2Names.map((oauth2Name) => { }; }); -export const appConfigAuth = { - email: { - enableLogin: process.env.HD_AUTH_EMAIL_ENABLE_LOGIN, - enableRegister: process.env.HD_AUTH_EMAIL_ENABLE_REGISTER, - }, - facebook: { - clientID: process.env.HD_AUTH_FACEBOOK_CLIENT_ID, - clientSecret: process.env.HD_AUTH_FACEBOOK_CLIENT_SECRET, - }, - twitter: { - consumerKey: process.env.HD_AUTH_TWITTER_CONSUMER_KEY, - consumerSecret: process.env.HD_AUTH_TWITTER_CONSUMER_SECRET, - }, - github: { - clientID: process.env.HD_AUTH_GITHUB_CLIENT_ID, - clientSecret: process.env.HD_AUTH_GITHUB_CLIENT_SECRET, - }, - dropbox: { - clientID: process.env.HD_AUTH_DROPBOX_CLIENT_ID, - clientSecret: process.env.HD_AUTH_DROPBOX_CLIENT_SECRET, - appKey: process.env.HD_AUTH_DROPBOX_APP_KEY, - }, - google: { - clientID: process.env.HD_AUTH_GOOGLE_CLIENT_ID, - clientSecret: process.env.HD_AUTH_GOOGLE_CLIENT_SECRET, - apiKey: process.env.HD_AUTH_GOOGLE_APP_KEY, - }, - gitlab: gitlabs, - ldap: ldaps, - saml: samls, - oauth2: oauth2s, -}; +export default registerAs('authConfig', async () => { + const authConfig = authSchema.validate( + { + email: { + enableLogin: process.env.HD_AUTH_EMAIL_ENABLE_LOGIN, + enableRegister: process.env.HD_AUTH_EMAIL_ENABLE_REGISTER, + }, + facebook: { + clientID: process.env.HD_AUTH_FACEBOOK_CLIENT_ID, + clientSecret: process.env.HD_AUTH_FACEBOOK_CLIENT_SECRET, + }, + twitter: { + consumerKey: process.env.HD_AUTH_TWITTER_CONSUMER_KEY, + consumerSecret: process.env.HD_AUTH_TWITTER_CONSUMER_SECRET, + }, + github: { + clientID: process.env.HD_AUTH_GITHUB_CLIENT_ID, + clientSecret: process.env.HD_AUTH_GITHUB_CLIENT_SECRET, + }, + dropbox: { + clientID: process.env.HD_AUTH_DROPBOX_CLIENT_ID, + clientSecret: process.env.HD_AUTH_DROPBOX_CLIENT_SECRET, + appKey: process.env.HD_AUTH_DROPBOX_APP_KEY, + }, + google: { + clientID: process.env.HD_AUTH_GOOGLE_CLIENT_ID, + clientSecret: process.env.HD_AUTH_GOOGLE_CLIENT_SECRET, + apiKey: process.env.HD_AUTH_GOOGLE_APP_KEY, + }, + gitlab: gitlabs, + ldap: ldaps, + saml: samls, + oauth2: oauth2s, + }, + { + abortEarly: false, + presence: 'required', + }, + ); + if (authConfig.error) { + throw new Error(authConfig.error.toString()); + } + return authConfig.value; +}); diff --git a/src/config/csp-config.ts b/src/config/csp-config.ts deleted file mode 100644 index ab699673a..000000000 --- a/src/config/csp-config.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import * as Joi from 'joi'; - -export interface CspConfig { - enable: boolean; - maxAgeSeconds: number; - includeSubdomains: boolean; - preload: boolean; -} - -export const cspSchema = Joi.object({ - enable: Joi.boolean().default(true).optional(), - reportURI: Joi.string().optional(), -}); - -export const appConfigCsp = { - enable: process.env.HD_CSP_ENABLE || true, - reportURI: process.env.HD_CSP_REPORTURI, -}; diff --git a/src/config/csp.config.ts b/src/config/csp.config.ts new file mode 100644 index 000000000..a6de092d6 --- /dev/null +++ b/src/config/csp.config.ts @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import * as Joi from 'joi'; +import { registerAs } from '@nestjs/config'; + +export interface CspConfig { + enable: boolean; + maxAgeSeconds: number; + includeSubdomains: boolean; + preload: boolean; +} + +const cspSchema = Joi.object({ + enable: Joi.boolean().default(true).optional(), + reportURI: Joi.string().optional(), +}); + +export default registerAs('cspConfig', async () => { + const cspConfig = cspSchema.validate( + { + enable: process.env.HD_CSP_ENABLE || true, + reportURI: process.env.HD_CSP_REPORTURI, + }, + { + abortEarly: false, + presence: 'required', + }, + ); + if (cspConfig.error) { + throw new Error(cspConfig.error.toString()); + } + return cspConfig.value; +}); diff --git a/src/config/database-config.ts b/src/config/database-config.ts deleted file mode 100644 index 59397321e..000000000 --- a/src/config/database-config.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import * as Joi from 'joi'; -import { DatabaseDialect } from './database-dialect.enum'; - -export interface DatabaseConfig { - username: string; - password: string; - database: string; - host: string; - port: number; - storage: string; - dialect: DatabaseDialect; -} - -export const databaseSchema = Joi.object({ - username: Joi.string(), - password: Joi.string(), - database: Joi.string(), - host: Joi.string(), - port: Joi.number(), - storage: Joi.when('...dialect', { - is: Joi.valid(DatabaseDialect.SQLITE), - then: Joi.string(), - otherwise: Joi.optional(), - }), - dialect: Joi.string().valid(...Object.values(DatabaseDialect)), -}); - -export const appConfigDatabase = { - username: process.env.HD_DATABASE_USER, - password: process.env.HD_DATABASE_PASS, - database: process.env.HD_DATABASE_NAME, - host: process.env.HD_DATABASE_HOST, - port: parseInt(process.env.HD_DATABASE_PORT) || undefined, - storage: process.env.HD_DATABASE_STORAGE, - dialect: process.env.HD_DATABASE_DIALECT, -}; diff --git a/src/config/database.config.ts b/src/config/database.config.ts new file mode 100644 index 000000000..24575128d --- /dev/null +++ b/src/config/database.config.ts @@ -0,0 +1,75 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import * as Joi from 'joi'; +import { DatabaseDialect } from './database-dialect.enum'; +import { registerAs } from '@nestjs/config'; + +export interface DatabaseConfig { + username: string; + password: string; + database: string; + host: string; + port: number; + storage: string; + dialect: DatabaseDialect; +} + +const databaseSchema = Joi.object({ + username: Joi.when('dialect', { + is: Joi.invalid(DatabaseDialect.SQLITE), + then: Joi.string(), + otherwise: Joi.optional(), + }), + password: Joi.when('dialect', { + is: Joi.invalid(DatabaseDialect.SQLITE), + then: Joi.string(), + otherwise: Joi.optional(), + }), + database: Joi.when('dialect', { + is: Joi.invalid(DatabaseDialect.SQLITE), + then: Joi.string(), + otherwise: Joi.optional(), + }), + host: Joi.when('dialect', { + is: Joi.invalid(DatabaseDialect.SQLITE), + then: Joi.string(), + otherwise: Joi.optional(), + }), + port: Joi.when('dialect', { + is: Joi.invalid(DatabaseDialect.SQLITE), + then: Joi.number(), + otherwise: Joi.optional(), + }), + storage: Joi.when('dialect', { + is: Joi.valid(DatabaseDialect.SQLITE), + then: Joi.string(), + otherwise: Joi.optional(), + }), + dialect: Joi.string().valid(...Object.values(DatabaseDialect)), +}); + +export default registerAs('databaseConfig', async () => { + const databaseConfig = databaseSchema.validate( + { + username: process.env.HD_DATABASE_USER, + password: process.env.HD_DATABASE_PASS, + database: process.env.HD_DATABASE_NAME, + host: process.env.HD_DATABASE_HOST, + port: parseInt(process.env.HD_DATABASE_PORT) || undefined, + storage: process.env.HD_DATABASE_STORAGE, + dialect: process.env.HD_DATABASE_DIALECT, + }, + { + abortEarly: false, + presence: 'required', + }, + ); + if (databaseConfig.error) { + throw new Error(databaseConfig.error.toString()); + } + return databaseConfig.value; +}); diff --git a/src/config/hsts-config.ts b/src/config/hsts-config.ts deleted file mode 100644 index a15ccd32b..000000000 --- a/src/config/hsts-config.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import * as Joi from 'joi'; - -export interface HstsConfig { - enable: boolean; - maxAgeSeconds: number; - includeSubdomains: boolean; - preload: boolean; -} - -export const hstsSchema = Joi.object({ - enable: Joi.boolean().default(true).optional(), - maxAgeSeconds: Joi.number() - .default(60 * 60 * 24 * 365) - .optional(), - includeSubdomains: Joi.boolean().default(true).optional(), - preload: Joi.boolean().default(true).optional(), -}); - -export const appConfigHsts = { - enable: process.env.HD_HSTS_ENABLE, - maxAgeSeconds: parseInt(process.env.HD_HSTS_MAX_AGE) || undefined, - includeSubdomains: process.env.HD_HSTS_INCLUDE_SUBDOMAINS, - preload: process.env.HD_HSTS_PRELOAD, -}; diff --git a/src/config/hsts.config.ts b/src/config/hsts.config.ts new file mode 100644 index 000000000..08d5bdc66 --- /dev/null +++ b/src/config/hsts.config.ts @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import * as Joi from 'joi'; +import { registerAs } from '@nestjs/config'; + +export interface HstsConfig { + enable: boolean; + maxAgeSeconds: number; + includeSubdomains: boolean; + preload: boolean; +} + +const hstsSchema = Joi.object({ + enable: Joi.boolean().default(true).optional(), + maxAgeSeconds: Joi.number() + .default(60 * 60 * 24 * 365) + .optional(), + includeSubdomains: Joi.boolean().default(true).optional(), + preload: Joi.boolean().default(true).optional(), +}); + +export default registerAs('hstsConfig', async () => { + const hstsConfig = hstsSchema.validate( + { + enable: process.env.HD_HSTS_ENABLE, + maxAgeSeconds: parseInt(process.env.HD_HSTS_MAX_AGE) || undefined, + includeSubdomains: process.env.HD_HSTS_INCLUDE_SUBDOMAINS, + preload: process.env.HD_HSTS_PRELOAD, + }, + { + abortEarly: false, + presence: 'required', + }, + ); + if (hstsConfig.error) { + throw new Error(hstsConfig.error.toString()); + } + return hstsConfig.value; +}); diff --git a/src/config/linkify-header-style.enum.ts b/src/config/linkify-header-style.enum.ts deleted file mode 100644 index 7c7ab088c..000000000 --- a/src/config/linkify-header-style.enum.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ - -export enum LinkifyHeaderStyle { - KEEP_CASE = 'keep-case', - LOWER_CASE = 'lower-case', - GFM = 'gfm', -} diff --git a/src/config/media.config.mock.ts b/src/config/media.config.mock.ts new file mode 100644 index 000000000..3f729d34c --- /dev/null +++ b/src/config/media.config.mock.ts @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { registerAs } from '@nestjs/config'; + +export default registerAs('mediaConfig', () => ({ + backend: { + use: 'filesystem', + filesystem: { + uploadPath: 'uploads', + }, + }, +})); diff --git a/src/config/media-config.ts b/src/config/media.config.ts similarity index 57% rename from src/config/media-config.ts rename to src/config/media.config.ts index d94d86def..4a78a9ed0 100644 --- a/src/config/media-config.ts +++ b/src/config/media.config.ts @@ -6,6 +6,7 @@ import * as Joi from 'joi'; import { BackendType } from '../media/backends/backend-type.enum'; +import { registerAs } from '@nestjs/config'; export interface MediaConfig { backend: { @@ -30,7 +31,7 @@ export interface MediaConfig { }; } -export const mediaSchema = Joi.object({ +const mediaSchema = Joi.object({ backend: { use: Joi.string().valid(...Object.values(BackendType)), filesystem: { @@ -69,25 +70,38 @@ export const mediaSchema = Joi.object({ }, }); -export const appConfigMedia = { - backend: { - use: process.env.HD_MEDIA_BACKEND, - filesystem: { - uploadPath: process.env.HD_MEDIA_BACKEND_FILESYSTEM_UPLOAD_PATH, +export default registerAs('mediaConfig', async () => { + const mediaConfig = mediaSchema.validate( + { + backend: { + use: process.env.HD_MEDIA_BACKEND, + filesystem: { + uploadPath: process.env.HD_MEDIA_BACKEND_FILESYSTEM_UPLOAD_PATH, + }, + s3: { + accessKey: process.env.HD_MEDIA_BACKEND_S3_ACCESS_KEY, + secretKey: process.env.HD_MEDIA_BACKEND_S3_ACCESS_KEY, + endPoint: process.env.HD_MEDIA_BACKEND_S3_ENDPOINT, + secure: process.env.HD_MEDIA_BACKEND_S3_SECURE, + port: parseInt(process.env.HD_MEDIA_BACKEND_S3_PORT) || undefined, + }, + azure: { + connectionString: + process.env.HD_MEDIA_BACKEND_AZURE_CONNECTION_STRING, + container: process.env.HD_MEDIA_BACKEND_AZURE_CONTAINER, + }, + imgur: { + clientID: process.env.HD_MEDIA_BACKEND_IMGUR_CLIENTID, + }, + }, }, - s3: { - accessKey: process.env.HD_MEDIA_BACKEND_S3_ACCESS_KEY, - secretKey: process.env.HD_MEDIA_BACKEND_S3_ACCESS_KEY, - endPoint: process.env.HD_MEDIA_BACKEND_S3_ENDPOINT, - secure: process.env.HD_MEDIA_BACKEND_S3_SECURE, - port: parseInt(process.env.HD_MEDIA_BACKEND_S3_PORT) || undefined, + { + abortEarly: false, + presence: 'required', }, - azure: { - connectionString: process.env.HD_MEDIA_BACKEND_AZURE_CONNECTION_STRING, - container: process.env.HD_MEDIA_BACKEND_AZURE_CONTAINER, - }, - imgur: { - clientID: process.env.HD_MEDIA_BACKEND_IMGUR_CLIENTID, - }, - }, -}; + ); + if (mediaConfig.error) { + throw new Error(mediaConfig.error.toString()); + } + return mediaConfig.value; +}); diff --git a/src/main.ts b/src/main.ts index a50657fbc..1dbce7ac3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -12,6 +12,7 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { AppModule } from './app.module'; import { AppConfig } from './config/app.config'; import { NestConsoleLoggerService } from './logger/nest-console-logger.service'; +import { MediaConfig } from './config/media.config'; async function bootstrap() { const app = await NestFactory.create(AppModule); @@ -20,6 +21,7 @@ async function bootstrap() { app.useLogger(logger); const configService = app.get(ConfigService); const appConfig = configService.get('appConfig'); + const mediaConfig = configService.get('mediaConfig'); const swaggerOptions = new DocumentBuilder() .setTitle('HedgeDoc') @@ -35,9 +37,9 @@ async function bootstrap() { transform: true, }), ); - if (appConfig.media.backend.use === 'filesystem') { + if (mediaConfig.backend.use === 'filesystem') { app.useStaticAssets('uploads', { - prefix: appConfig.media.backend.filesystem.uploadPath, + prefix: mediaConfig.backend.filesystem.uploadPath, }); } await app.listen(appConfig.port); diff --git a/src/media/backends/filesystem-backend.ts b/src/media/backends/filesystem-backend.ts index cbad1109b..505b94ea6 100644 --- a/src/media/backends/filesystem-backend.ts +++ b/src/media/backends/filesystem-backend.ts @@ -7,10 +7,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { promises as fs } from 'fs'; import { join } from 'path'; -import applicationConfig, { AppConfig } from '../../config/app.config'; +import mediaConfiguration from '../../config/media.config'; import { ConsoleLoggerService } from '../../logger/console-logger.service'; import { MediaBackend } from '../media-backend.interface'; import { BackendData } from '../media-upload.entity'; +import { MediaConfig } from '../../config/media.config'; @Injectable() export class FilesystemBackend implements MediaBackend { @@ -18,11 +19,11 @@ export class FilesystemBackend implements MediaBackend { constructor( private readonly logger: ConsoleLoggerService, - @Inject(applicationConfig.KEY) - private appConfig: AppConfig, + @Inject(mediaConfiguration.KEY) + private mediaConfig: MediaConfig, ) { this.logger.setContext(FilesystemBackend.name); - this.uploadDirectory = appConfig.media.backend.filesystem.uploadPath; + this.uploadDirectory = mediaConfig.backend.filesystem.uploadPath; } async saveFile( diff --git a/src/media/media.service.spec.ts b/src/media/media.service.spec.ts index d6c804f87..6eb99deb1 100644 --- a/src/media/media.service.spec.ts +++ b/src/media/media.service.spec.ts @@ -7,7 +7,7 @@ import { ConfigModule } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import appConfigMock from '../config/app.config.mock'; +import mediaConfigMock from '../config/media.config.mock'; import { LoggerModule } from '../logger/logger.module'; import { AuthorColor } from '../notes/author-color.entity'; import { Note } from '../notes/note.entity'; @@ -39,7 +39,7 @@ describe('MediaService', () => { imports: [ ConfigModule.forRoot({ isGlobal: true, - load: [appConfigMock], + load: [mediaConfigMock], }), LoggerModule, NotesModule, diff --git a/src/media/media.service.ts b/src/media/media.service.ts index e3c449095..8b5dfdecb 100644 --- a/src/media/media.service.ts +++ b/src/media/media.service.ts @@ -9,7 +9,7 @@ import { ModuleRef } from '@nestjs/core'; import { InjectRepository } from '@nestjs/typeorm'; import * as FileType from 'file-type'; import { Repository } from 'typeorm'; -import applicationConfig, { AppConfig } from '../config/app.config'; +import mediaConfiguration, { MediaConfig } from '../config/media.config'; import { ClientError, NotInDBError, PermissionError } from '../errors/errors'; import { ConsoleLoggerService } from '../logger/console-logger.service'; import { NotesService } from '../notes/notes.service'; @@ -31,8 +31,8 @@ export class MediaService { private notesService: NotesService, private usersService: UsersService, private moduleRef: ModuleRef, - @Inject(applicationConfig.KEY) - private appConfig: AppConfig, + @Inject(mediaConfiguration.KEY) + private mediaConfig: MediaConfig, ) { this.logger.setContext(MediaService.name); this.mediaBackendType = this.chooseBackendType(); @@ -120,7 +120,7 @@ export class MediaService { } private chooseBackendType(): BackendType { - switch (this.appConfig.media.backend.use) { + switch (this.mediaConfig.backend.use) { case 'filesystem': return BackendType.FILESYSTEM; } diff --git a/test/public-api/media.e2e-spec.ts b/test/public-api/media.e2e-spec.ts index daa6e60de..6d1c3d14d 100644 --- a/test/public-api/media.e2e-spec.ts +++ b/test/public-api/media.e2e-spec.ts @@ -4,14 +4,14 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { ConfigModule, registerAs } from '@nestjs/config'; +import { ConfigModule } from '@nestjs/config'; import { NestExpressApplication } from '@nestjs/platform-express'; import { Test } from '@nestjs/testing'; import { TypeOrmModule } from '@nestjs/typeorm'; import { promises as fs } from 'fs'; import * as request from 'supertest'; import { PublicApiModule } from '../../src/api/public/public-api.module'; -import appConfigMock from '../../src/config/app.config.mock'; +import mediaConfigMock from '../../src/config/media.config.mock'; import { GroupsModule } from '../../src/groups/groups.module'; import { LoggerModule } from '../../src/logger/logger.module'; import { NestConsoleLoggerService } from '../../src/logger/nest-console-logger.service'; @@ -31,7 +31,7 @@ describe('Notes', () => { imports: [ ConfigModule.forRoot({ isGlobal: true, - load: [appConfigMock], + load: [mediaConfigMock], }), PublicApiModule, MediaModule, diff --git a/test/public-api/notes.e2e-spec.ts b/test/public-api/notes.e2e-spec.ts index 38b2db779..500e880c3 100644 --- a/test/public-api/notes.e2e-spec.ts +++ b/test/public-api/notes.e2e-spec.ts @@ -5,12 +5,12 @@ */ import { INestApplication } from '@nestjs/common'; -import { ConfigModule, registerAs } from '@nestjs/config'; +import { ConfigModule } from '@nestjs/config'; import { Test } from '@nestjs/testing'; import { TypeOrmModule } from '@nestjs/typeorm'; import * as request from 'supertest'; import { PublicApiModule } from '../../src/api/public/public-api.module'; -import appConfigMock from '../../src/config/app.config.mock'; +import mediaConfigMock from '../../src/config/media.config.mock'; import { NotInDBError } from '../../src/errors/errors'; import { GroupsModule } from '../../src/groups/groups.module'; import { LoggerModule } from '../../src/logger/logger.module'; @@ -27,7 +27,7 @@ describe('Notes', () => { imports: [ ConfigModule.forRoot({ isGlobal: true, - load: [appConfigMock], + load: [mediaConfigMock], }), PublicApiModule, NotesModule,