Extend config with various options from 1.x

Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
Philip Molares 2020-12-31 22:37:37 +01:00 committed by David Mehren
parent 18c6694bcb
commit 286575315e
No known key found for this signature in database
GPG key ID: 185982BA4C42B7C3
13 changed files with 686 additions and 32 deletions

View file

@ -6,47 +6,112 @@
import { registerAs } from '@nestjs/config'; import { registerAs } from '@nestjs/config';
import * as Joi from 'joi'; 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 { export interface AppConfig {
domain: string;
port: number; port: number;
media: { loglevel: Loglevel;
backend: { /*linkifyHeaderStyle: LinkifyHeaderStyle;
use: string; sourceURL: string;
filesystem: { urlPath: string;
uploadPath: 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({ const schema = Joi.object({
port: Joi.number(), domain: Joi.string(),
media: { port: Joi.number().default(3000).optional(),
backend: { loglevel: Joi.string()
use: Joi.string().valid('filesystem'), .valid(...Object.values(Loglevel))
filesystem: { .default(Loglevel.WARN)
uploadPath: Joi.when('...use', { .optional(),
is: Joi.valid('filesystem'), /*linkifyHeaderStyle: Joi.string().valid(...Object.values(LinkifyHeaderStyle)).default(LinkifyHeaderStyle.GFM).optional(),
then: Joi.string(), sourceURL: Joi.string(),
otherwise: Joi.optional(), 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 () => { export default registerAs('appConfig', async () => {
const appConfig = schema.validate( const appConfig = schema.validate(
{ {
domain: process.env.HD_DOMAIN,
port: parseInt(process.env.PORT) || undefined, port: parseInt(process.env.PORT) || undefined,
media: { loglevel: process.env.HD_LOGLEVEL, //|| Loglevel.WARN,
backend: { /*linkifyHeaderStyle: process.env.HD_LINKIFY_HEADER_STYLE,
use: process.env.HD_MEDIA_BACKEND, sourceURL: process.env.HD_SOURCE_URL,
filesystem: { urlPath: process.env.HD_URL_PATH,
uploadPath: process.env.HD_MEDIA_BACKEND_FILESYSTEM_UPLOAD_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,
}, },
{ {
abortEarly: false, abortEarly: false,

331
src/config/auth-config.ts Normal file
View file

@ -0,0 +1,331 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import * as Joi from 'joi';
import { GitlabScope, GitlabVersion } from './gitlab.enum';
import { toArrayConfig } from './utils';
export interface AuthConfig {
email: {
enableLogin: boolean;
enableRegister: boolean;
};
facebook: {
clientID: string;
clientSecret: string;
};
twitter: {
consumerKey: string;
consumerSecret: string;
};
github: {
clientID: string;
clientSecret: string;
};
dropbox: {
clientID: string;
clientSecret: string;
appKey: string;
};
google: {
clientID: string;
clientSecret: string;
apiKey: string;
};
gitlab: [
{
providerName: string;
baseURL: string;
clientID: string;
clientSecret: string;
scope: GitlabScope;
version: GitlabVersion;
},
];
// ToDo: tlsOptions exist in config.json.example. See https://nodejs.org/api/tls.html#tls_tls_connect_options_callback
ldap: [
{
providerName: string;
url: string;
bindDn: string;
bindCredentials: string;
searchBase: string;
searchFilter: string;
searchAttributes: string[];
usernameField: string;
useridField: string;
tlsCa: string[];
},
];
saml: [
{
providerName: string;
idpSsoUrl: string;
idpCert: string;
clientCert: string;
issuer: string;
identifierFormat: string;
disableRequestedAuthnContext: string;
groupAttribute: string;
requiredGroups: string[];
externalGroups: string;
attribute: {
id: string;
username: string;
email: string;
};
},
];
oauth2: [
{
providerName: string;
baseURL: string;
userProfileURL: string;
userProfileIdAttr: string;
userProfileUsernameAttr: string;
userProfileDisplayNameAttr: string;
userProfileEmailAttr: string;
tokenURL: string;
authorizationURL: string;
clientID: string;
clientSecret: string;
scope: string;
rolesClaim: string;
accessRole: string;
},
];
}
export const authSchema = Joi.object({
email: {
enableLogin: Joi.boolean().default(false).optional(),
enableRegister: Joi.boolean().default(false).optional(),
},
facebook: {
clientID: Joi.string().optional(),
clientSecret: Joi.string().optional(),
},
twitter: {
consumerKey: Joi.string().optional(),
consumerSecret: Joi.string().optional(),
},
github: {
clientID: Joi.string().optional(),
clientSecret: Joi.string().optional(),
},
dropbox: {
clientID: Joi.string().optional(),
clientSecret: Joi.string().optional(),
appKey: Joi.string().optional(),
},
google: {
clientID: Joi.string().optional(),
clientSecret: Joi.string().optional(),
apiKey: Joi.string().optional(),
},
gitlab: Joi.array()
.items(
Joi.object({
providerName: Joi.string().default('Gitlab').optional(),
baseURL: Joi.string().optional(),
clientID: Joi.string().optional(),
clientSecret: Joi.string().optional(),
scope: Joi.string()
.valid(...Object.values(GitlabScope))
.default(GitlabScope.READ_USER)
.optional(),
version: Joi.string()
.valid(...Object.values(GitlabVersion))
.default(GitlabVersion.V4)
.optional(),
}),
)
.optional(),
// ToDo: should searchfilter have a default?
ldap: Joi.array()
.items(
Joi.object({
providerName: Joi.string().default('LDAP').optional(),
url: Joi.string().optional(),
bindDn: Joi.string().optional(),
bindCredentials: Joi.string().optional(),
searchBase: Joi.string().optional(),
searchFilter: Joi.string().default('(uid={{username}})').optional(),
searchAttributes: Joi.array().items(Joi.string()),
usernameField: Joi.string().default('userid').optional(),
useridField: Joi.string().optional(),
tlsCa: Joi.array().items(Joi.string()),
}),
)
.optional(),
saml: Joi.array()
.items(
Joi.object({
providerName: Joi.string().default('SAML').optional(),
idpSsoUrl: Joi.string().optional(),
idpCert: Joi.string().optional(),
clientCert: Joi.string().optional(),
// ToDo: (default: config.serverURL) will be build on-the-fly in the config/index.js from domain, urlAddPort and urlPath.
issuer: Joi.string().optional(), //.default().optional(),
identifierFormat: Joi.string()
.default('urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress')
.optional(),
disableRequestedAuthnContext: Joi.boolean().default(false).optional(),
groupAttribute: Joi.string().optional(),
requiredGroups: Joi.array().items(Joi.string()),
externalGroups: Joi.array().items(Joi.string()),
attribute: {
id: Joi.string().default('NameId').optional(),
username: Joi.string().default('NameId').optional(),
email: Joi.string().default('NameId').optional(),
},
}),
)
.optional(),
oauth2: Joi.array()
.items(
Joi.object({
providerName: Joi.string().default('OAuth2').optional(),
baseURL: Joi.string().optional(),
userProfileURL: Joi.string().optional(),
userProfileIdAttr: Joi.string().optional(),
userProfileUsernameAttr: Joi.string().optional(),
userProfileDisplayNameAttr: Joi.string().optional(),
userProfileEmailAttr: Joi.string().optional(),
tokenURL: Joi.string().optional(),
authorizationURL: Joi.string().optional(),
clientID: Joi.string().optional(),
clientSecret: Joi.string().optional(),
scope: Joi.string().optional(),
rolesClaim: Joi.string().optional(),
accessRole: Joi.string().optional(),
}),
)
.optional(),
});
// ToDo: Validate these with Joi to prevent duplicate entries?
const gitlabNames = toArrayConfig(process.env.HD_AUTH_GITLABS, ',');
const ldapNames = toArrayConfig(process.env.HD_AUTH_LDAPS, ',');
const samlNames = toArrayConfig(process.env.HD_AUTH_SAMLS, ',');
const oauth2Names = toArrayConfig(process.env.HD_AUTH_OAUTH2S, ',');
const gitlabs = gitlabNames.map((gitlabName) => {
return {
providerName: process.env[`HD_AUTH_GITLAB_${gitlabName}_PROVIDER_NAME`],
baseURL: process.env[`HD_AUTH_GITLAB_${gitlabName}_BASE_URL`],
clientID: process.env[`HD_AUTH_GITLAB_${gitlabName}_CLIENT_ID`],
clientSecret: process.env[`HD_AUTH_GITLAB_${gitlabName}_CLIENT_SECRET`],
scope: process.env[`HD_AUTH_GITLAB_${gitlabName}_GITLAB_SCOPE`],
version: process.env[`HD_AUTH_GITLAB_${gitlabName}_GITLAB_VERSION`],
};
});
const ldaps = ldapNames.map((ldapName) => {
return {
providerName: process.env[`HD_AUTH_LDAP_${ldapName}_PROVIDER_NAME`],
url: process.env[`HD_AUTH_LDAP_${ldapName}_URL`],
bindDn: process.env[`HD_AUTH_LDAP_${ldapName}_BIND_DN`],
bindCredentials: process.env[`HD_AUTH_LDAP_${ldapName}_BIND_CREDENTIALS`],
searchBase: process.env[`HD_AUTH_LDAP_${ldapName}_SEARCH_BASE`],
searchFilter: process.env[`HD_AUTH_LDAP_${ldapName}_SEARCH_FILTER`],
searchAttributes: toArrayConfig(
process.env[`HD_AUTH_LDAP_${ldapName}_SEARCH_ATTRIBUTES`],
',',
),
usernameField: process.env[`HD_AUTH_LDAP_${ldapName}_USERNAME_FIELD`],
useridField: process.env[`HD_AUTH_LDAP_${ldapName}_USERID_FIELD`],
tlsCa: toArrayConfig(process.env[`HD_AUTH_LDAP_${ldapName}_TLS_CA`], ','),
};
});
const samls = samlNames.map((samlName) => {
return {
providerName: process.env[`HD_AUTH_SAML_${samlName}_PROVIDER_NAME`],
idpSsoUrl: process.env[`HD_AUTH_SAML_${samlName}_IDPSSOURL`],
idpCert: process.env[`HD_AUTH_SAML_${samlName}_IDPCERT`],
clientCert: process.env[`HD_AUTH_SAML_${samlName}_CLIENTCERT`],
issuer: process.env[`HD_AUTH_SAML_${samlName}_ISSUER`],
identifierFormat: process.env[`HD_AUTH_SAML_${samlName}_IDENTIFIERFORMAT`],
disableRequestedAuthnContext:
process.env[`HD_AUTH_SAML_${samlName}_DISABLEREQUESTEDAUTHNCONTEXT`],
groupAttribute: process.env[`HD_AUTH_SAML_${samlName}_GROUPATTRIBUTE`],
requiredGroups: toArrayConfig(
process.env[`HD_AUTH_SAML_${samlName}_REQUIREDGROUPS`],
'|',
),
externalGroups: toArrayConfig(
process.env[`HD_AUTH_SAML_${samlName}_EXTERNALGROUPS`],
'|',
),
attribute: {
id: process.env[`HD_AUTH_SAML_${samlName}_ATTRIBUTE_ID`],
username: process.env[`HD_AUTH_SAML_${samlName}_ATTRIBUTE_USERNAME`],
email: process.env[`HD_AUTH_SAML_${samlName}_ATTRIBUTE_USERNAME`],
},
};
});
const oauth2s = oauth2Names.map((oauth2Name) => {
return {
providerName: process.env[`HD_AUTH_OAUTH2_${oauth2Name}_PROVIDER_NAME`],
baseURL: process.env[`HD_AUTH_OAUTH2_${oauth2Name}_BASEURL`],
userProfileURL:
process.env[`HD_AUTH_OAUTH2_${oauth2Name}_USER_PROFILE_URL`],
userProfileIdAttr:
process.env[`HD_AUTH_OAUTH2_${oauth2Name}_USER_PROFILE_ID_ATTR`],
userProfileUsernameAttr:
process.env[`HD_AUTH_OAUTH2_${oauth2Name}_USER_PROFILE_USERNAME_ATTR`],
userProfileDisplayNameAttr:
process.env[
`HD_AUTH_OAUTH2_${oauth2Name}_USER_PROFILE_DISPLAY_NAME_ATTR`
],
userProfileEmailAttr:
process.env[`HD_AUTH_OAUTH2_${oauth2Name}_USER_PROFILE_EMAIL_ATTR`],
tokenURL: process.env[`HD_AUTH_OAUTH2_${oauth2Name}_TOKEN_URL`],
authorizationURL:
process.env[`HD_AUTH_OAUTH2_${oauth2Name}_AUTHORIZATION_URL`],
clientID: process.env[`HD_AUTH_OAUTH2_${oauth2Name}_CLIENT_ID`],
clientSecret: process.env[`HD_AUTH_OAUTH2_${oauth2Name}_CLIENT_SECRET`],
scope: process.env[`HD_AUTH_OAUTH2_${oauth2Name}_SCOPE`],
rolesClaim: process.env[`HD_AUTH_OAUTH2_${oauth2Name}_ROLES_CLAIM`],
accessRole: process.env[`HD_AUTH_OAUTH2_${oauth2Name}_ACCESS_ROLE`],
};
});
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,
};

24
src/config/csp-config.ts Normal file
View file

@ -0,0 +1,24 @@
/*
* 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,
};

View file

@ -0,0 +1,42 @@
/*
* 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,
};

View file

@ -0,0 +1,12 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
export enum DatabaseDialect {
POSTGRES = 'postgres',
MYSQL = 'mysql',
MARIADB = 'mariadb',
SQLITE = 'sqlite',
}

16
src/config/gitlab.enum.ts Normal file
View file

@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
export enum GitlabScope {
READ_USER = 'read_user',
API = 'api',
}
// ToDo: Evaluate if V3 is really necessary anymore (it's deprecated since 2017)
export enum GitlabVersion {
V3 = 'v3',
V4 = 'v4',
}

30
src/config/hsts-config.ts Normal file
View file

@ -0,0 +1,30 @@
/*
* 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,
};

View file

@ -0,0 +1,11 @@
/*
* 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',
}

View file

@ -0,0 +1,13 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
export enum Loglevel {
TRACE = 'trace',
DEBUG = 'debug',
INFO = 'info',
WARN = 'warn',
ERROR = 'error',
}

View file

@ -0,0 +1,93 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import * as Joi from 'joi';
import { BackendType } from '../media/backends/backend-type.enum';
export interface MediaConfig {
backend: {
use: BackendType;
filesystem: {
uploadPath: string;
};
s3: {
accessKeyId: string;
secretAccessKey: string;
region: string;
bucket: string;
endPoint: string;
};
azure: {
connectionString: string;
container: string;
};
imgur: {
clientID: string;
};
};
}
export const mediaSchema = Joi.object({
backend: {
use: Joi.string().valid(...Object.values(BackendType)),
filesystem: {
uploadPath: Joi.when('...use', {
is: Joi.valid(BackendType.FILESYSTEM),
then: Joi.string(),
otherwise: Joi.optional(),
}),
},
s3: Joi.when('...use', {
is: Joi.valid(BackendType.S3),
then: Joi.object({
accessKey: Joi.string(),
secretKey: Joi.string(),
endPoint: Joi.string(),
secure: Joi.boolean(),
port: Joi.number(),
}),
otherwise: Joi.optional(),
}),
azure: Joi.when('...use', {
is: Joi.valid(BackendType.AZURE),
then: Joi.object({
connectionString: Joi.string(),
container: Joi.string(),
}),
otherwise: Joi.optional(),
}),
imgur: Joi.when('...use', {
is: Joi.valid(BackendType.IMGUR),
then: Joi.object({
clientID: Joi.string(),
}),
otherwise: Joi.optional(),
}),
},
});
export const appConfigMedia = {
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,
},
},
};

17
src/config/utils.ts Normal file
View file

@ -0,0 +1,17 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
export const toArrayConfig = (configValue: string, separator = ',') => {
if (!configValue) {
return [];
}
if (!configValue.includes(separator)) {
return [configValue.trim()];
}
return configValue.split(separator).map((arrayItem) => arrayItem.trim());
};

View file

@ -5,7 +5,7 @@
*/ */
export enum BackendType { export enum BackendType {
FILEYSTEM = 'filesystem', FILESYSTEM = 'filesystem',
S3 = 's3', S3 = 's3',
IMGUR = 'imgur', IMGUR = 'imgur',
AZURE = 'azure', AZURE = 'azure',

View file

@ -122,13 +122,13 @@ export class MediaService {
private chooseBackendType(): BackendType { private chooseBackendType(): BackendType {
switch (this.appConfig.media.backend.use) { switch (this.appConfig.media.backend.use) {
case 'filesystem': case 'filesystem':
return BackendType.FILEYSTEM; return BackendType.FILESYSTEM;
} }
} }
private getBackendFromType(type: BackendType): MediaBackend { private getBackendFromType(type: BackendType): MediaBackend {
switch (type) { switch (type) {
case BackendType.FILEYSTEM: case BackendType.FILESYSTEM:
return this.moduleRef.get(FilesystemBackend); return this.moduleRef.get(FilesystemBackend);
} }
} }