mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-29 19:14:25 -05:00
config: splits config in multiple files
splits the big appConfig in multiple configs adds media.config.mock.ts Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
parent
d59ccaba54
commit
072ef223e0
18 changed files with 287 additions and 174 deletions
|
@ -8,6 +8,7 @@ import { ConfigModule } from '@nestjs/config';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
import appConfigMock from '../../../config/app.config.mock';
|
import appConfigMock from '../../../config/app.config.mock';
|
||||||
|
import mediaConfigMock from '../../../config/media.config.mock';
|
||||||
import { LoggerModule } from '../../../logger/logger.module';
|
import { LoggerModule } from '../../../logger/logger.module';
|
||||||
import { MediaUpload } from '../../../media/media-upload.entity';
|
import { MediaUpload } from '../../../media/media-upload.entity';
|
||||||
import { MediaModule } from '../../../media/media.module';
|
import { MediaModule } from '../../../media/media.module';
|
||||||
|
@ -31,7 +32,7 @@ describe('Media Controller', () => {
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
load: [appConfigMock],
|
load: [appConfigMock, mediaConfigMock],
|
||||||
}),
|
}),
|
||||||
LoggerModule,
|
LoggerModule,
|
||||||
MediaModule,
|
MediaModule,
|
||||||
|
|
|
@ -19,6 +19,11 @@ import { PermissionsModule } from './permissions/permissions.module';
|
||||||
import { RevisionsModule } from './revisions/revisions.module';
|
import { RevisionsModule } from './revisions/revisions.module';
|
||||||
import { UsersModule } from './users/users.module';
|
import { UsersModule } from './users/users.module';
|
||||||
import appConfig from './config/app.config';
|
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({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -29,7 +34,14 @@ import appConfig from './config/app.config';
|
||||||
synchronize: true,
|
synchronize: true,
|
||||||
}),
|
}),
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
load: [appConfig],
|
load: [
|
||||||
|
appConfig,
|
||||||
|
mediaConfig,
|
||||||
|
hstsConfig,
|
||||||
|
cspConfig,
|
||||||
|
databaseConfig,
|
||||||
|
authConfig,
|
||||||
|
],
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
}),
|
}),
|
||||||
NotesModule,
|
NotesModule,
|
||||||
|
|
|
@ -8,12 +8,4 @@ import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
export default registerAs('appConfig', () => ({
|
export default registerAs('appConfig', () => ({
|
||||||
port: 3000,
|
port: 3000,
|
||||||
media: {
|
|
||||||
backend: {
|
|
||||||
use: 'filesystem',
|
|
||||||
filesystem: {
|
|
||||||
uploadPath: 'uploads',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import * as Joi from 'joi';
|
import * as Joi from 'joi';
|
||||||
import { GitlabScope, GitlabVersion } from './gitlab.enum';
|
import { GitlabScope, GitlabVersion } from './gitlab.enum';
|
||||||
import { toArrayConfig } from './utils';
|
import { toArrayConfig } from './utils';
|
||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
export interface AuthConfig {
|
export interface AuthConfig {
|
||||||
email: {
|
email: {
|
||||||
|
@ -99,7 +100,7 @@ export interface AuthConfig {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const authSchema = Joi.object({
|
const authSchema = Joi.object({
|
||||||
email: {
|
email: {
|
||||||
enableLogin: Joi.boolean().default(false).optional(),
|
enableLogin: Joi.boolean().default(false).optional(),
|
||||||
enableRegister: Joi.boolean().default(false).optional(),
|
enableRegister: Joi.boolean().default(false).optional(),
|
||||||
|
@ -297,35 +298,47 @@ const oauth2s = oauth2Names.map((oauth2Name) => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export const appConfigAuth = {
|
export default registerAs('authConfig', async () => {
|
||||||
email: {
|
const authConfig = authSchema.validate(
|
||||||
enableLogin: process.env.HD_AUTH_EMAIL_ENABLE_LOGIN,
|
{
|
||||||
enableRegister: process.env.HD_AUTH_EMAIL_ENABLE_REGISTER,
|
email: {
|
||||||
},
|
enableLogin: process.env.HD_AUTH_EMAIL_ENABLE_LOGIN,
|
||||||
facebook: {
|
enableRegister: process.env.HD_AUTH_EMAIL_ENABLE_REGISTER,
|
||||||
clientID: process.env.HD_AUTH_FACEBOOK_CLIENT_ID,
|
},
|
||||||
clientSecret: process.env.HD_AUTH_FACEBOOK_CLIENT_SECRET,
|
facebook: {
|
||||||
},
|
clientID: process.env.HD_AUTH_FACEBOOK_CLIENT_ID,
|
||||||
twitter: {
|
clientSecret: process.env.HD_AUTH_FACEBOOK_CLIENT_SECRET,
|
||||||
consumerKey: process.env.HD_AUTH_TWITTER_CONSUMER_KEY,
|
},
|
||||||
consumerSecret: process.env.HD_AUTH_TWITTER_CONSUMER_SECRET,
|
twitter: {
|
||||||
},
|
consumerKey: process.env.HD_AUTH_TWITTER_CONSUMER_KEY,
|
||||||
github: {
|
consumerSecret: process.env.HD_AUTH_TWITTER_CONSUMER_SECRET,
|
||||||
clientID: process.env.HD_AUTH_GITHUB_CLIENT_ID,
|
},
|
||||||
clientSecret: process.env.HD_AUTH_GITHUB_CLIENT_SECRET,
|
github: {
|
||||||
},
|
clientID: process.env.HD_AUTH_GITHUB_CLIENT_ID,
|
||||||
dropbox: {
|
clientSecret: process.env.HD_AUTH_GITHUB_CLIENT_SECRET,
|
||||||
clientID: process.env.HD_AUTH_DROPBOX_CLIENT_ID,
|
},
|
||||||
clientSecret: process.env.HD_AUTH_DROPBOX_CLIENT_SECRET,
|
dropbox: {
|
||||||
appKey: process.env.HD_AUTH_DROPBOX_APP_KEY,
|
clientID: process.env.HD_AUTH_DROPBOX_CLIENT_ID,
|
||||||
},
|
clientSecret: process.env.HD_AUTH_DROPBOX_CLIENT_SECRET,
|
||||||
google: {
|
appKey: process.env.HD_AUTH_DROPBOX_APP_KEY,
|
||||||
clientID: process.env.HD_AUTH_GOOGLE_CLIENT_ID,
|
},
|
||||||
clientSecret: process.env.HD_AUTH_GOOGLE_CLIENT_SECRET,
|
google: {
|
||||||
apiKey: process.env.HD_AUTH_GOOGLE_APP_KEY,
|
clientID: process.env.HD_AUTH_GOOGLE_CLIENT_ID,
|
||||||
},
|
clientSecret: process.env.HD_AUTH_GOOGLE_CLIENT_SECRET,
|
||||||
gitlab: gitlabs,
|
apiKey: process.env.HD_AUTH_GOOGLE_APP_KEY,
|
||||||
ldap: ldaps,
|
},
|
||||||
saml: samls,
|
gitlab: gitlabs,
|
||||||
oauth2: oauth2s,
|
ldap: ldaps,
|
||||||
};
|
saml: samls,
|
||||||
|
oauth2: oauth2s,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
abortEarly: false,
|
||||||
|
presence: 'required',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (authConfig.error) {
|
||||||
|
throw new Error(authConfig.error.toString());
|
||||||
|
}
|
||||||
|
return authConfig.value;
|
||||||
|
});
|
|
@ -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,
|
|
||||||
};
|
|
37
src/config/csp.config.ts
Normal file
37
src/config/csp.config.ts
Normal file
|
@ -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;
|
||||||
|
});
|
|
@ -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,
|
|
||||||
};
|
|
75
src/config/database.config.ts
Normal file
75
src/config/database.config.ts
Normal file
|
@ -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;
|
||||||
|
});
|
|
@ -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,
|
|
||||||
};
|
|
43
src/config/hsts.config.ts
Normal file
43
src/config/hsts.config.ts
Normal file
|
@ -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;
|
||||||
|
});
|
16
src/config/media.config.mock.ts
Normal file
16
src/config/media.config.mock.ts
Normal file
|
@ -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',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
import * as Joi from 'joi';
|
import * as Joi from 'joi';
|
||||||
import { BackendType } from '../media/backends/backend-type.enum';
|
import { BackendType } from '../media/backends/backend-type.enum';
|
||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
export interface MediaConfig {
|
export interface MediaConfig {
|
||||||
backend: {
|
backend: {
|
||||||
|
@ -30,7 +31,7 @@ export interface MediaConfig {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mediaSchema = Joi.object({
|
const mediaSchema = Joi.object({
|
||||||
backend: {
|
backend: {
|
||||||
use: Joi.string().valid(...Object.values(BackendType)),
|
use: Joi.string().valid(...Object.values(BackendType)),
|
||||||
filesystem: {
|
filesystem: {
|
||||||
|
@ -69,25 +70,38 @@ export const mediaSchema = Joi.object({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const appConfigMedia = {
|
export default registerAs('mediaConfig', async () => {
|
||||||
backend: {
|
const mediaConfig = mediaSchema.validate(
|
||||||
use: process.env.HD_MEDIA_BACKEND,
|
{
|
||||||
filesystem: {
|
backend: {
|
||||||
uploadPath: process.env.HD_MEDIA_BACKEND_FILESYSTEM_UPLOAD_PATH,
|
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,
|
abortEarly: false,
|
||||||
secretKey: process.env.HD_MEDIA_BACKEND_S3_ACCESS_KEY,
|
presence: 'required',
|
||||||
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,
|
if (mediaConfig.error) {
|
||||||
container: process.env.HD_MEDIA_BACKEND_AZURE_CONTAINER,
|
throw new Error(mediaConfig.error.toString());
|
||||||
},
|
}
|
||||||
imgur: {
|
return mediaConfig.value;
|
||||||
clientID: process.env.HD_MEDIA_BACKEND_IMGUR_CLIENTID,
|
});
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -12,6 +12,7 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
import { AppConfig } from './config/app.config';
|
import { AppConfig } from './config/app.config';
|
||||||
import { NestConsoleLoggerService } from './logger/nest-console-logger.service';
|
import { NestConsoleLoggerService } from './logger/nest-console-logger.service';
|
||||||
|
import { MediaConfig } from './config/media.config';
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
||||||
|
@ -20,6 +21,7 @@ async function bootstrap() {
|
||||||
app.useLogger(logger);
|
app.useLogger(logger);
|
||||||
const configService = app.get(ConfigService);
|
const configService = app.get(ConfigService);
|
||||||
const appConfig = configService.get<AppConfig>('appConfig');
|
const appConfig = configService.get<AppConfig>('appConfig');
|
||||||
|
const mediaConfig = configService.get<MediaConfig>('mediaConfig');
|
||||||
|
|
||||||
const swaggerOptions = new DocumentBuilder()
|
const swaggerOptions = new DocumentBuilder()
|
||||||
.setTitle('HedgeDoc')
|
.setTitle('HedgeDoc')
|
||||||
|
@ -35,9 +37,9 @@ async function bootstrap() {
|
||||||
transform: true,
|
transform: true,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
if (appConfig.media.backend.use === 'filesystem') {
|
if (mediaConfig.backend.use === 'filesystem') {
|
||||||
app.useStaticAssets('uploads', {
|
app.useStaticAssets('uploads', {
|
||||||
prefix: appConfig.media.backend.filesystem.uploadPath,
|
prefix: mediaConfig.backend.filesystem.uploadPath,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await app.listen(appConfig.port);
|
await app.listen(appConfig.port);
|
||||||
|
|
|
@ -7,10 +7,11 @@
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { join } from 'path';
|
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 { ConsoleLoggerService } from '../../logger/console-logger.service';
|
||||||
import { MediaBackend } from '../media-backend.interface';
|
import { MediaBackend } from '../media-backend.interface';
|
||||||
import { BackendData } from '../media-upload.entity';
|
import { BackendData } from '../media-upload.entity';
|
||||||
|
import { MediaConfig } from '../../config/media.config';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FilesystemBackend implements MediaBackend {
|
export class FilesystemBackend implements MediaBackend {
|
||||||
|
@ -18,11 +19,11 @@ export class FilesystemBackend implements MediaBackend {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly logger: ConsoleLoggerService,
|
private readonly logger: ConsoleLoggerService,
|
||||||
@Inject(applicationConfig.KEY)
|
@Inject(mediaConfiguration.KEY)
|
||||||
private appConfig: AppConfig,
|
private mediaConfig: MediaConfig,
|
||||||
) {
|
) {
|
||||||
this.logger.setContext(FilesystemBackend.name);
|
this.logger.setContext(FilesystemBackend.name);
|
||||||
this.uploadDirectory = appConfig.media.backend.filesystem.uploadPath;
|
this.uploadDirectory = mediaConfig.backend.filesystem.uploadPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveFile(
|
async saveFile(
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { ConfigModule } from '@nestjs/config';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
import appConfigMock from '../config/app.config.mock';
|
import appConfigMock from '../config/app.config.mock';
|
||||||
|
import mediaConfigMock from '../config/media.config.mock';
|
||||||
import { LoggerModule } from '../logger/logger.module';
|
import { LoggerModule } from '../logger/logger.module';
|
||||||
import { AuthorColor } from '../notes/author-color.entity';
|
import { AuthorColor } from '../notes/author-color.entity';
|
||||||
import { Note } from '../notes/note.entity';
|
import { Note } from '../notes/note.entity';
|
||||||
|
@ -39,7 +40,7 @@ describe('MediaService', () => {
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
load: [appConfigMock],
|
load: [appConfigMock, mediaConfigMock],
|
||||||
}),
|
}),
|
||||||
LoggerModule,
|
LoggerModule,
|
||||||
NotesModule,
|
NotesModule,
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { ModuleRef } from '@nestjs/core';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import * as FileType from 'file-type';
|
import * as FileType from 'file-type';
|
||||||
import { Repository } from 'typeorm';
|
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 { ClientError, NotInDBError, PermissionError } from '../errors/errors';
|
||||||
import { ConsoleLoggerService } from '../logger/console-logger.service';
|
import { ConsoleLoggerService } from '../logger/console-logger.service';
|
||||||
import { NotesService } from '../notes/notes.service';
|
import { NotesService } from '../notes/notes.service';
|
||||||
|
@ -31,8 +31,8 @@ export class MediaService {
|
||||||
private notesService: NotesService,
|
private notesService: NotesService,
|
||||||
private usersService: UsersService,
|
private usersService: UsersService,
|
||||||
private moduleRef: ModuleRef,
|
private moduleRef: ModuleRef,
|
||||||
@Inject(applicationConfig.KEY)
|
@Inject(mediaConfiguration.KEY)
|
||||||
private appConfig: AppConfig,
|
private mediaConfig: MediaConfig,
|
||||||
) {
|
) {
|
||||||
this.logger.setContext(MediaService.name);
|
this.logger.setContext(MediaService.name);
|
||||||
this.mediaBackendType = this.chooseBackendType();
|
this.mediaBackendType = this.chooseBackendType();
|
||||||
|
@ -120,7 +120,7 @@ export class MediaService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private chooseBackendType(): BackendType {
|
private chooseBackendType(): BackendType {
|
||||||
switch (this.appConfig.media.backend.use) {
|
switch (this.mediaConfig.backend.use) {
|
||||||
case 'filesystem':
|
case 'filesystem':
|
||||||
return BackendType.FILESYSTEM;
|
return BackendType.FILESYSTEM;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { promises as fs } from 'fs';
|
||||||
import * as request from 'supertest';
|
import * as request from 'supertest';
|
||||||
import { PublicApiModule } from '../../src/api/public/public-api.module';
|
import { PublicApiModule } from '../../src/api/public/public-api.module';
|
||||||
import appConfigMock from '../../src/config/app.config.mock';
|
import appConfigMock from '../../src/config/app.config.mock';
|
||||||
|
import mediaConfigMock from '../../src/config/media.config.mock';
|
||||||
import { GroupsModule } from '../../src/groups/groups.module';
|
import { GroupsModule } from '../../src/groups/groups.module';
|
||||||
import { LoggerModule } from '../../src/logger/logger.module';
|
import { LoggerModule } from '../../src/logger/logger.module';
|
||||||
import { NestConsoleLoggerService } from '../../src/logger/nest-console-logger.service';
|
import { NestConsoleLoggerService } from '../../src/logger/nest-console-logger.service';
|
||||||
|
@ -31,7 +32,7 @@ describe('Notes', () => {
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
load: [appConfigMock],
|
load: [appConfigMock, mediaConfigMock],
|
||||||
}),
|
}),
|
||||||
PublicApiModule,
|
PublicApiModule,
|
||||||
MediaModule,
|
MediaModule,
|
||||||
|
|
|
@ -5,12 +5,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { INestApplication } from '@nestjs/common';
|
import { INestApplication } from '@nestjs/common';
|
||||||
import { ConfigModule, registerAs } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
import { Test } from '@nestjs/testing';
|
import { Test } from '@nestjs/testing';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import * as request from 'supertest';
|
import * as request from 'supertest';
|
||||||
import { PublicApiModule } from '../../src/api/public/public-api.module';
|
import { PublicApiModule } from '../../src/api/public/public-api.module';
|
||||||
import appConfigMock from '../../src/config/app.config.mock';
|
import appConfigMock from '../../src/config/app.config.mock';
|
||||||
|
import mediaConfigMock from '../../src/config/media.config.mock';
|
||||||
import { NotInDBError } from '../../src/errors/errors';
|
import { NotInDBError } from '../../src/errors/errors';
|
||||||
import { GroupsModule } from '../../src/groups/groups.module';
|
import { GroupsModule } from '../../src/groups/groups.module';
|
||||||
import { LoggerModule } from '../../src/logger/logger.module';
|
import { LoggerModule } from '../../src/logger/logger.module';
|
||||||
|
@ -27,7 +28,7 @@ describe('Notes', () => {
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
load: [appConfigMock],
|
load: [appConfigMock, mediaConfigMock],
|
||||||
}),
|
}),
|
||||||
PublicApiModule,
|
PublicApiModule,
|
||||||
NotesModule,
|
NotesModule,
|
||||||
|
|
Loading…
Reference in a new issue