2017-10-25 13:49:37 +00:00
2017-04-12 17:57:55 +00:00
'use strict'
2018-03-25 22:30:17 +00:00
const crypto = require ( 'crypto' )
2017-04-12 17:57:55 +00:00
const fs = require ( 'fs' )
const path = require ( 'path' )
2019-04-12 09:58:24 +00:00
const { merge } = require ( 'lodash' )
2017-04-12 17:57:55 +00:00
const deepFreeze = require ( 'deep-freeze' )
2019-04-12 09:58:24 +00:00
const { Environment , Permission } = require ( './enum' )
2018-03-18 01:14:50 +00:00
const logger = require ( '../logger' )
2019-04-12 09:58:24 +00:00
const { getGitCommit , getGitHubURL } = require ( './utils' )
2017-04-12 17:57:55 +00:00
2018-09-10 20:35:38 +00:00
const appRootPath = path . resolve ( _ _dirname , '../../' )
2017-04-12 17:57:55 +00:00
const env = process . env . NODE _ENV || Environment . development
const debugConfig = {
debug : ( env === Environment . development )
}
2018-01-26 13:00:48 +00:00
// Get version string from package.json
2019-04-12 09:58:24 +00:00
const { version , repository } = require ( path . join ( appRootPath , 'package.json' ) )
2018-10-05 17:33:40 +00:00
const commitID = getGitCommit ( appRootPath )
const sourceURL = getGitHubURL ( repository . url , commitID || version )
const fullversion = commitID ? ` ${ version } - ${ commitID } ` : version
2018-01-19 12:23:30 +00:00
2017-04-12 17:57:55 +00:00
const packageConfig = {
2018-01-19 12:23:30 +00:00
version : version ,
2018-10-05 17:33:40 +00:00
minimumCompatibleVersion : '0.5.0' ,
fullversion : fullversion ,
sourceURL : sourceURL
2017-04-12 17:57:55 +00:00
}
2018-09-05 17:50:46 +00:00
const configFilePath = path . resolve ( appRootPath , process . env . CMD _CONFIG _FILE ||
'config.json' )
2017-04-12 17:57:55 +00:00
const fileConfig = fs . existsSync ( configFilePath ) ? require ( configFilePath ) [ env ] : undefined
let config = require ( './default' )
merge ( config , require ( './defaultSSL' ) )
2018-03-07 14:17:35 +00:00
merge ( config , require ( './oldDefault' ) )
2017-04-12 17:57:55 +00:00
merge ( config , debugConfig )
merge ( config , packageConfig )
merge ( config , fileConfig )
merge ( config , require ( './oldEnvironment' ) )
2018-06-24 11:22:51 +00:00
merge ( config , require ( './hackmdEnvironment' ) )
2017-04-12 17:57:55 +00:00
merge ( config , require ( './environment' ) )
merge ( config , require ( './dockerSecret' ) )
2018-11-13 22:29:33 +00:00
if ( [ 'debug' , 'verbose' , 'info' , 'warn' , 'error' ] . includes ( config . loglevel ) ) {
logger . level = config . loglevel
} else {
logger . error ( 'Selected loglevel %s doesn\'t exist, using default level \'debug\'. Available options: debug, verbose, info, warn, error' , config . loglevel )
}
2017-04-12 17:57:55 +00:00
// load LDAP CA
if ( config . ldap . tlsca ) {
2019-08-01 16:57:39 +00:00
const certificateAuthorities = config . ldap . tlsca . split ( ',' )
const caContent = [ ]
for ( const ca of certificateAuthorities ) {
if ( fs . existsSync ( ca ) ) {
caContent . push ( fs . readFileSync ( ca , 'utf8' ) )
2017-04-12 17:57:55 +00:00
}
}
2019-08-01 16:57:39 +00:00
const tlsOptions = {
2017-04-12 17:57:55 +00:00
ca : caContent
}
config . ldap . tlsOptions = config . ldap . tlsOptions ? Object . assign ( config . ldap . tlsOptions , tlsOptions ) : tlsOptions
}
// Permission
config . permission = Permission
2019-02-23 04:33:37 +00:00
let defaultPermission = config . permission . editable
if ( ! config . allowAnonymous && ! config . allowAnonymousViews ) {
delete config . permission . freely
delete config . permission . editable
delete config . permission . locked
defaultPermission = config . permission . limited
} else if ( ! config . allowAnonymous && ! config . allowAnonymousEdits ) {
2017-04-12 17:57:55 +00:00
delete config . permission . freely
}
2018-03-07 14:17:35 +00:00
if ( ! ( config . defaultPermission in config . permission ) ) {
2019-02-23 04:33:37 +00:00
config . defaultPermission = defaultPermission
2017-04-12 17:57:55 +00:00
}
// cache result, cannot change config in runtime!!!
config . isStandardHTTPsPort = ( function isStandardHTTPsPort ( ) {
2018-03-07 14:17:35 +00:00
return config . useSSL && config . port === 443
2017-04-12 17:57:55 +00:00
} ) ( )
config . isStandardHTTPPort = ( function isStandardHTTPPort ( ) {
2018-03-07 14:17:35 +00:00
return ! config . useSSL && config . port === 80
2017-04-12 17:57:55 +00:00
} ) ( )
// cache serverURL
2018-03-07 14:17:35 +00:00
config . serverURL = ( function getserverurl ( ) {
2017-04-12 17:57:55 +00:00
var url = ''
if ( config . domain ) {
2018-03-07 14:17:35 +00:00
var protocol = config . protocolUseSSL ? 'https://' : 'http://'
2017-04-12 17:57:55 +00:00
url = protocol + config . domain
2018-03-07 14:17:35 +00:00
if ( config . urlAddPort ) {
2017-04-12 17:57:55 +00:00
if ( ! config . isStandardHTTPPort || ! config . isStandardHTTPsPort ) {
url += ':' + config . port
}
}
}
2018-03-07 14:17:35 +00:00
if ( config . urlPath ) {
url += '/' + config . urlPath
2017-04-12 17:57:55 +00:00
}
return url
} ) ( )
2018-11-28 13:38:42 +00:00
if ( config . serverURL === '' ) {
logger . warn ( 'Neither \'domain\' nor \'CMD_DOMAIN\' is configured. This can cause issues with various components.\nHint: Make sure \'protocolUseSSL\' and \'urlAddPort\' or \'CMD_PROTOCOL_USESSL\' and \'CMD_URL_ADDPORT\' are configured properly.' )
}
2017-04-12 17:57:55 +00:00
config . Environment = Environment
// auth method
config . isFacebookEnable = config . facebook . clientID && config . facebook . clientSecret
config . isGoogleEnable = config . google . clientID && config . google . clientSecret
config . isDropboxEnable = config . dropbox . clientID && config . dropbox . clientSecret
config . isTwitterEnable = config . twitter . consumerKey && config . twitter . consumerSecret
config . isEmailEnable = config . email
2017-08-31 21:33:55 +00:00
config . isOpenIDEnable = config . openID
2017-04-12 17:57:55 +00:00
config . isGitHubEnable = config . github . clientID && config . github . clientSecret
2019-12-28 13:20:18 +00:00
config . isBitbucketEnable = config . bitbucket . clientID && config . bitbucket . clientSecret
2017-04-12 17:57:55 +00:00
config . isGitLabEnable = config . gitlab . clientID && config . gitlab . clientSecret
2017-10-29 10:16:40 +00:00
config . isMattermostEnable = config . mattermost . clientID && config . mattermost . clientSecret
2017-04-12 17:57:55 +00:00
config . isLDAPEnable = config . ldap . url
2017-11-28 03:46:58 +00:00
config . isSAMLEnable = config . saml . idpSsoUrl
2017-06-27 17:08:05 +00:00
config . isOAuth2Enable = config . oauth2 . clientID && config . oauth2 . clientSecret
2018-03-07 14:17:35 +00:00
config . isPDFExportEnable = config . allowPDFExport
2017-04-12 17:57:55 +00:00
2018-07-30 13:47:09 +00:00
// Check gitlab api version
2018-09-24 22:26:30 +00:00
if ( config . gitlab && config . gitlab . version !== 'v4' && config . gitlab . version !== 'v3' ) {
2018-08-23 12:06:26 +00:00
logger . warn ( 'config.js contains wrong version (' + config . gitlab . version + ') for gitlab api; it should be \'v3\' or \'v4\'. Defaulting to v4' )
2018-07-30 13:47:09 +00:00
config . gitlab . version = 'v4'
}
2018-11-07 12:12:50 +00:00
// If gitlab scope is api, enable snippets Export/import
2019-01-25 18:48:31 +00:00
config . isGitlabSnippetsEnable = ( ! config . gitlab . scope || config . gitlab . scope === 'api' ) && config . isGitLabEnable
2018-07-30 13:47:09 +00:00
2018-06-04 23:29:27 +00:00
// Only update i18n files in development setups
config . updateI18nFiles = ( env === Environment . development )
2018-01-26 13:00:48 +00:00
// merge legacy values
2019-08-01 16:57:39 +00:00
const keys = Object . keys ( config )
2018-03-07 14:17:35 +00:00
const uppercase = /[A-Z]/
for ( let i = keys . length ; i -- ; ) {
2019-08-01 16:57:39 +00:00
const lowercaseKey = keys [ i ] . toLowerCase ( )
2018-03-07 14:17:35 +00:00
// if the config contains uppercase letters
// and a lowercase version of this setting exists
// and the config with uppercase is not set
// we set the new config using the old key.
if ( uppercase . test ( keys [ i ] ) &&
2018-03-26 18:49:24 +00:00
config [ lowercaseKey ] !== undefined &&
fileConfig [ keys [ i ] ] === undefined ) {
2018-03-07 14:17:35 +00:00
logger . warn ( 'config.js contains deprecated lowercase setting for ' + keys [ i ] + '. Please change your config.js file to replace ' + lowercaseKey + ' with ' + keys [ i ] )
config [ keys [ i ] ] = config [ lowercaseKey ]
}
2018-01-26 13:00:48 +00:00
}
2018-06-24 11:22:51 +00:00
// Notify users about the prefix change and inform them they use legacy prefix for environment variables
if ( Object . keys ( process . env ) . toString ( ) . indexOf ( 'HMD_' ) !== - 1 ) {
logger . warn ( 'Using legacy HMD prefix for environment variables. Please change your variables in future. For details see: https://github.com/hackmdio/codimd#environment-variables-will-overwrite-other-server-configs' )
}
2018-03-25 22:30:17 +00:00
// Generate session secret if it stays on default values
if ( config . sessionSecret === 'secret' ) {
logger . warn ( 'Session secret not set. Using random generated one. Please set `sessionSecret` in your config.js file. All users will be logged out.' )
config . sessionSecret = crypto . randomBytes ( Math . ceil ( config . sessionSecretLen / 2 ) ) // generate crypto graphic random number
2019-04-12 09:58:24 +00:00
. toString ( 'hex' ) // convert to hexadecimal format
. slice ( 0 , config . sessionSecretLen ) // return required number of characters
2018-03-25 22:30:17 +00:00
}
2018-03-18 01:14:50 +00:00
// Validate upload upload providers
2019-02-01 11:36:58 +00:00
if ( [ 'filesystem' , 's3' , 'minio' , 'imgur' , 'azure' , 'lutim' ] . indexOf ( config . imageUploadType ) === - 1 ) {
logger . error ( '"imageuploadtype" is not correctly set. Please use "filesystem", "s3", "minio", "azure", "lutim" or "imgur". Defaulting to "filesystem"' )
2018-07-09 18:27:15 +00:00
config . imageUploadType = 'filesystem'
2018-03-18 01:14:50 +00:00
}
2018-01-20 14:08:31 +00:00
// figure out mime types for image uploads
2018-03-07 14:17:35 +00:00
switch ( config . imageUploadType ) {
2018-01-20 14:08:31 +00:00
case 'imgur' :
config . allowedUploadMimeTypes = [
'image/jpeg' ,
'image/png' ,
'image/jpg' ,
'image/gif'
]
break
default :
config . allowedUploadMimeTypes = [
'image/jpeg' ,
'image/png' ,
'image/jpg' ,
'image/gif' ,
'image/svg+xml'
]
}
2017-04-12 17:57:55 +00:00
// generate correct path
2018-03-07 14:17:35 +00:00
config . sslCAPath . forEach ( function ( capath , i , array ) {
2017-12-22 11:25:13 +00:00
array [ i ] = path . resolve ( appRootPath , capath )
2017-12-22 11:19:19 +00:00
} )
2017-11-28 13:23:50 +00:00
2019-10-21 04:37:59 +00:00
config . appRootPath = appRootPath
2018-09-05 17:56:41 +00:00
config . sslCertPath = path . resolve ( appRootPath , config . sslCertPath )
config . sslKeyPath = path . resolve ( appRootPath , config . sslKeyPath )
config . dhParamPath = path . resolve ( appRootPath , config . dhParamPath )
2018-09-10 20:35:38 +00:00
config . viewPath = path . resolve ( appRootPath , config . viewPath )
2018-09-05 17:56:41 +00:00
config . tmpPath = path . resolve ( appRootPath , config . tmpPath )
config . defaultNotePath = path . resolve ( appRootPath , config . defaultNotePath )
config . docsPath = path . resolve ( appRootPath , config . docsPath )
config . uploadsPath = path . resolve ( appRootPath , config . uploadsPath )
2017-04-12 17:57:55 +00:00
2017-10-25 13:49:37 +00:00
// make config readonly
2017-04-12 17:57:55 +00:00
config = deepFreeze ( config )
module . exports = config