config-loader.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. import { envUtils } from '@growi/core';
  2. import loggerFactory from '~/utils/logger';
  3. import ConfigModel, {
  4. Config, defaultCrowiConfigs, defaultMarkdownConfigs, defaultNotificationConfigs,
  5. } from '../models/config';
  6. const logger = loggerFactory('growi:service:ConfigLoader');
  7. enum ValueType { NUMBER, STRING, BOOLEAN }
  8. interface ValueParser<T> {
  9. parse(value: string): T;
  10. }
  11. interface EnvConfig {
  12. ns: string,
  13. key: string,
  14. type: ValueType,
  15. default?: number | string | boolean | null,
  16. }
  17. type EnumDictionary<T extends string | symbol | number, U> = {
  18. [K in T]: U;
  19. };
  20. const parserDictionary: EnumDictionary<ValueType, ValueParser<number | string | boolean>> = {
  21. [ValueType.NUMBER]: { parse: (v: string) => { return parseInt(v, 10) } },
  22. [ValueType.STRING]: { parse: (v: string) => { return v } },
  23. [ValueType.BOOLEAN]: { parse: (v: string) => { return envUtils.toBoolean(v) } },
  24. };
  25. /**
  26. * The following env vars are excluded because these are currently used before the configuration setup.
  27. * - MONGO_URI
  28. * - NODE_ENV
  29. * - PORT
  30. * - REDIS_URI
  31. * - SESSION_NAME
  32. * - PASSWORD_SEED
  33. * - SECRET_TOKEN
  34. *
  35. * The commented out item has not yet entered the migration work.
  36. * So, parameters of these are under consideration.
  37. */
  38. const ENV_VAR_NAME_TO_CONFIG_INFO = {
  39. FILE_UPLOAD: {
  40. ns: 'crowi',
  41. key: 'app:fileUploadType',
  42. type: ValueType.STRING,
  43. default: 'aws',
  44. },
  45. FILE_UPLOAD_USES_ONLY_ENV_VAR_FOR_FILE_UPLOAD_TYPE: {
  46. ns: 'crowi',
  47. key: 'app:useOnlyEnvVarForFileUploadType',
  48. type: ValueType.BOOLEAN,
  49. default: false,
  50. },
  51. HACKMD_URI: {
  52. ns: 'crowi',
  53. key: 'app:hackmdUri',
  54. type: ValueType.STRING,
  55. default: null,
  56. },
  57. HACKMD_URI_FOR_SERVER: {
  58. ns: 'crowi',
  59. key: 'app:hackmdUriForServer',
  60. type: ValueType.STRING,
  61. default: null,
  62. },
  63. MATHJAX: {
  64. ns: 'crowi',
  65. key: 'app:mathJax',
  66. type: ValueType.STRING,
  67. default: null,
  68. },
  69. NO_CDN: {
  70. ns: 'crowi',
  71. key: 'app:noCdn',
  72. type: ValueType.STRING,
  73. default: null,
  74. },
  75. // PLANTUML_URI: {
  76. // ns: ,
  77. // key: ,
  78. // type: ,
  79. // default:
  80. // },
  81. // BLOCKDIAG_URI: {
  82. // ns: ,
  83. // key: ,
  84. // type: ,
  85. // default:
  86. // },
  87. // OAUTH_GOOGLE_CLIENT_ID: {
  88. // ns: 'crowi',
  89. // key: 'security:passport-google:clientId',
  90. // type: ,
  91. // default:
  92. // },
  93. // OAUTH_GOOGLE_CLIENT_SECRET: {
  94. // ns: 'crowi',
  95. // key: 'security:passport-google:clientSecret',
  96. // type: ,
  97. // default:
  98. // },
  99. // OAUTH_GOOGLE_CALLBACK_URI: {
  100. // ns: 'crowi',
  101. // key: 'security:passport-google:callbackUrl',
  102. // type: ,
  103. // default:
  104. // },
  105. // OAUTH_GITHUB_CLIENT_ID: {
  106. // ns: 'crowi',
  107. // key: 'security:passport-github:clientId',
  108. // type: ,
  109. // default:
  110. // },
  111. // OAUTH_GITHUB_CLIENT_SECRET: {
  112. // ns: 'crowi',
  113. // key: 'security:passport-github:clientSecret',
  114. // type: ,
  115. // default:
  116. // },
  117. // OAUTH_GITHUB_CALLBACK_URI: {
  118. // ns: 'crowi',
  119. // key: 'security:passport-github:callbackUrl',
  120. // type: ,
  121. // default:
  122. // },
  123. // OAUTH_TWITTER_CONSUMER_KEY: {
  124. // ns: 'crowi',
  125. // key: 'security:passport-twitter:consumerKey',
  126. // type: ,
  127. // default:
  128. // },
  129. // OAUTH_TWITTER_CONSUMER_SECRET: {
  130. // ns: 'crowi',
  131. // key: 'security:passport-twitter:consumerSecret',
  132. // type: ,
  133. // default:
  134. // },
  135. // OAUTH_TWITTER_CALLBACK_URI: {
  136. // ns: 'crowi',
  137. // key: 'security:passport-twitter:callbackUrl',
  138. // type: ,
  139. // default:
  140. // },
  141. DRAWIO_URI: {
  142. ns: 'crowi',
  143. key: 'app:drawioUri',
  144. type: ValueType.STRING,
  145. default: 'https://embed.diagrams.net/',
  146. },
  147. NCHAN_URI: {
  148. ns: 'crowi',
  149. key: 'app:nchanUri',
  150. type: ValueType.STRING,
  151. default: null,
  152. },
  153. APP_SITE_URL: {
  154. ns: 'crowi',
  155. key: 'app:siteUrl',
  156. type: ValueType.STRING,
  157. default: null,
  158. },
  159. PUBLISH_OPEN_API: {
  160. ns: 'crowi',
  161. key: 'app:publishOpenAPI',
  162. type: ValueType.BOOLEAN,
  163. default: false,
  164. },
  165. IS_V5_COMPATIBLE: {
  166. ns: 'crowi',
  167. key: 'app:isV5Compatible',
  168. type: ValueType.BOOLEAN,
  169. default: undefined,
  170. },
  171. S2SMSG_PUBSUB_SERVER_TYPE: {
  172. ns: 'crowi',
  173. key: 's2sMessagingPubsub:serverType',
  174. type: ValueType.STRING,
  175. default: null,
  176. },
  177. S2SMSG_PUBSUB_NCHAN_PUBLISH_PATH: {
  178. ns: 'crowi',
  179. key: 's2sMessagingPubsub:nchan:publishPath',
  180. type: ValueType.STRING,
  181. default: '/pubsub',
  182. },
  183. S2SMSG_PUBSUB_NCHAN_SUBSCRIBE_PATH: {
  184. ns: 'crowi',
  185. key: 's2sMessagingPubsub:nchan:subscribePath',
  186. type: ValueType.STRING,
  187. default: '/pubsub',
  188. },
  189. S2SMSG_PUBSUB_NCHAN_CHANNEL_ID: {
  190. ns: 'crowi',
  191. key: 's2sMessagingPubsub:nchan:channelId',
  192. type: ValueType.STRING,
  193. default: null,
  194. },
  195. S2CMSG_PUBSUB_CONNECTIONS_LIMIT: {
  196. ns: 'crowi',
  197. key: 's2cMessagingPubsub:connectionsLimit',
  198. type: ValueType.NUMBER,
  199. default: 5000,
  200. },
  201. S2CMSG_PUBSUB_CONNECTIONS_LIMIT_FOR_ADMIN: {
  202. ns: 'crowi',
  203. key: 's2cMessagingPubsub:connectionsLimitForAdmin',
  204. type: ValueType.NUMBER,
  205. default: 100,
  206. },
  207. S2CMSG_PUBSUB_CONNECTIONS_LIMIT_FOR_GUEST: {
  208. ns: 'crowi',
  209. key: 's2cMessagingPubsub:connectionsLimitForGuest',
  210. type: ValueType.NUMBER,
  211. default: 2000,
  212. },
  213. MAX_FILE_SIZE: {
  214. ns: 'crowi',
  215. key: 'app:maxFileSize',
  216. type: ValueType.NUMBER,
  217. default: Infinity,
  218. },
  219. FILE_UPLOAD_TOTAL_LIMIT: {
  220. ns: 'crowi',
  221. key: 'app:fileUploadTotalLimit',
  222. type: ValueType.NUMBER,
  223. default: Infinity,
  224. },
  225. FILE_UPLOAD_DISABLED: {
  226. ns: 'crowi',
  227. key: 'app:fileUploadDisabled',
  228. type: ValueType.BOOLEAN,
  229. default: false,
  230. },
  231. FILE_UPLOAD_LOCAL_USE_INTERNAL_REDIRECT: {
  232. ns: 'crowi',
  233. key: 'fileUpload:local:useInternalRedirect',
  234. type: ValueType.BOOLEAN,
  235. default: false,
  236. },
  237. FILE_UPLOAD_LOCAL_INTERNAL_REDIRECT_PATH: {
  238. ns: 'crowi',
  239. key: 'fileUpload:local:internalRedirectPath',
  240. type: ValueType.STRING,
  241. default: '/growi-internal/',
  242. },
  243. ELASTICSEARCH_URI: {
  244. ns: 'crowi',
  245. key: 'app:elasticsearchUri',
  246. type: ValueType.STRING,
  247. default: null,
  248. },
  249. ELASTICSEARCH_REQUEST_TIMEOUT: {
  250. ns: 'crowi',
  251. key: 'app:elasticsearchRequestTimeout',
  252. type: ValueType.NUMBER,
  253. default: 8000, // msec
  254. },
  255. MONGO_GRIDFS_TOTAL_LIMIT: {
  256. ns: 'crowi',
  257. key: 'gridfs:totalLimit',
  258. type: ValueType.NUMBER,
  259. default: null, // set null in default for backward compatibility
  260. // cz: Newer system respects FILE_UPLOAD_TOTAL_LIMIT.
  261. // If the default value of MONGO_GRIDFS_TOTAL_LIMIT is Infinity,
  262. // the system can't distinguish between "not specified" and "Infinity is specified".
  263. },
  264. FORCE_WIKI_MODE: {
  265. ns: 'crowi',
  266. key: 'security:wikiMode',
  267. type: ValueType.STRING,
  268. default: undefined,
  269. },
  270. SESSION_MAX_AGE: {
  271. ns: 'crowi',
  272. key: 'security:sessionMaxAge',
  273. type: ValueType.NUMBER,
  274. default: undefined,
  275. },
  276. USER_UPPER_LIMIT: {
  277. ns: 'crowi',
  278. key: 'security:userUpperLimit',
  279. type: ValueType.NUMBER,
  280. default: Infinity,
  281. },
  282. DISABLE_LINK_SHARING: {
  283. ns: 'crowi',
  284. key: 'security:disableSharing',
  285. type: ValueType.BOOLEAN,
  286. default: false,
  287. },
  288. LOCAL_STRATEGY_ENABLED: {
  289. ns: 'crowi',
  290. key: 'security:passport-local:isEnabled',
  291. type: ValueType.BOOLEAN,
  292. default: true,
  293. },
  294. LOCAL_STRATEGY_USES_ONLY_ENV_VARS_FOR_SOME_OPTIONS: {
  295. ns: 'crowi',
  296. key: 'security:passport-local:useOnlyEnvVarsForSomeOptions',
  297. type: ValueType.BOOLEAN,
  298. default: false,
  299. },
  300. LOCAL_STRATEGY_PASSWORD_RESET_ENABLED: {
  301. ns: 'crowi',
  302. key: 'security:passport-local:isPasswordResetEnabled',
  303. type: ValueType.BOOLEAN,
  304. default: true,
  305. },
  306. LOCAL_STRATEGY_EMAIL_AUTHENTICATION_ENABLED: {
  307. ns: 'crowi',
  308. key: 'security:passport-local:isEmailAuthenticationEnabled',
  309. type: ValueType.BOOLEAN,
  310. default: false,
  311. },
  312. SAML_USES_ONLY_ENV_VARS_FOR_SOME_OPTIONS: {
  313. ns: 'crowi',
  314. key: 'security:passport-saml:useOnlyEnvVarsForSomeOptions',
  315. type: ValueType.BOOLEAN,
  316. default: false,
  317. },
  318. SAML_ENABLED: {
  319. ns: 'crowi',
  320. key: 'security:passport-saml:isEnabled',
  321. type: ValueType.BOOLEAN,
  322. default: null,
  323. },
  324. SAML_ENTRY_POINT: {
  325. ns: 'crowi',
  326. key: 'security:passport-saml:entryPoint',
  327. type: ValueType.STRING,
  328. default: null,
  329. },
  330. SAML_CALLBACK_URI: {
  331. ns: 'crowi',
  332. key: 'security:passport-saml:callbackUrl',
  333. type: ValueType.STRING,
  334. default: null,
  335. },
  336. SAML_ISSUER: {
  337. ns: 'crowi',
  338. key: 'security:passport-saml:issuer',
  339. type: ValueType.STRING,
  340. default: null,
  341. },
  342. SAML_ATTR_MAPPING_ID: {
  343. ns: 'crowi',
  344. key: 'security:passport-saml:attrMapId',
  345. type: ValueType.STRING,
  346. default: null,
  347. },
  348. SAML_ATTR_MAPPING_USERNAME: {
  349. ns: 'crowi',
  350. key: 'security:passport-saml:attrMapUsername',
  351. type: ValueType.STRING,
  352. default: null,
  353. },
  354. SAML_ATTR_MAPPING_MAIL: {
  355. ns: 'crowi',
  356. key: 'security:passport-saml:attrMapMail',
  357. type: ValueType.STRING,
  358. default: null,
  359. },
  360. SAML_ATTR_MAPPING_FIRST_NAME: {
  361. ns: 'crowi',
  362. key: 'security:passport-saml:attrMapFirstName',
  363. type: ValueType.STRING,
  364. default: null,
  365. },
  366. SAML_ATTR_MAPPING_LAST_NAME: {
  367. ns: 'crowi',
  368. key: 'security:passport-saml:attrMapLastName',
  369. type: ValueType.STRING,
  370. default: null,
  371. },
  372. SAML_CERT: {
  373. ns: 'crowi',
  374. key: 'security:passport-saml:cert',
  375. type: ValueType.STRING,
  376. default: null,
  377. },
  378. SAML_ABLC_RULE: {
  379. ns: 'crowi',
  380. key: 'security:passport-saml:ABLCRule',
  381. type: ValueType.STRING,
  382. default: null,
  383. },
  384. OIDC_TIMEOUT_MULTIPLIER: {
  385. ns: 'crowi',
  386. key: 'security:passport-oidc:timeoutMultiplier',
  387. type: ValueType.NUMBER,
  388. default: 1.5,
  389. },
  390. OIDC_DISCOVERY_RETRIES: {
  391. ns: 'crowi',
  392. key: 'security:passport-oidc:discoveryRetries',
  393. type: ValueType.NUMBER,
  394. default: 3,
  395. },
  396. OIDC_CLIENT_CLOCK_TOLERANCE: {
  397. ns: 'crowi',
  398. key: 'security:passport-oidc:oidcClientClockTolerance',
  399. type: ValueType.NUMBER,
  400. default: 10,
  401. },
  402. S3_REFERENCE_FILE_WITH_RELAY_MODE: {
  403. ns: 'crowi',
  404. key: 'aws:referenceFileWithRelayMode',
  405. type: ValueType.BOOLEAN,
  406. default: false,
  407. },
  408. S3_LIFETIME_SEC_FOR_TEMPORARY_URL: {
  409. ns: 'crowi',
  410. key: 'aws:lifetimeSecForTemporaryUrl',
  411. type: ValueType.NUMBER,
  412. default: 120,
  413. },
  414. GCS_API_KEY_JSON_PATH: {
  415. ns: 'crowi',
  416. key: 'gcs:apiKeyJsonPath',
  417. type: ValueType.STRING,
  418. default: null,
  419. },
  420. GCS_BUCKET: {
  421. ns: 'crowi',
  422. key: 'gcs:bucket',
  423. type: ValueType.STRING,
  424. default: null,
  425. },
  426. GCS_UPLOAD_NAMESPACE: {
  427. ns: 'crowi',
  428. key: 'gcs:uploadNamespace',
  429. type: ValueType.STRING,
  430. default: null,
  431. },
  432. GCS_REFERENCE_FILE_WITH_RELAY_MODE: {
  433. ns: 'crowi',
  434. key: 'gcs:referenceFileWithRelayMode',
  435. type: ValueType.BOOLEAN,
  436. default: false,
  437. },
  438. GCS_USES_ONLY_ENV_VARS_FOR_SOME_OPTIONS: {
  439. ns: 'crowi',
  440. key: 'gcs:useOnlyEnvVarsForSomeOptions',
  441. type: ValueType.BOOLEAN,
  442. default: false,
  443. },
  444. GCS_LIFETIME_SEC_FOR_TEMPORARY_URL: {
  445. ns: 'crowi',
  446. key: 'gcs:lifetimeSecForTemporaryUrl',
  447. type: ValueType.NUMBER,
  448. default: 120,
  449. },
  450. PROMSTER_ENABLED: {
  451. ns: 'crowi',
  452. key: 'promster:isEnabled',
  453. type: ValueType.BOOLEAN,
  454. default: false,
  455. },
  456. PROMSTER_PORT: {
  457. ns: 'crowi',
  458. key: 'promster:port',
  459. type: ValueType.NUMBER,
  460. default: 7788,
  461. },
  462. GROWI_CLOUD_URI: {
  463. ns: 'crowi',
  464. key: 'app:growiCloudUri',
  465. type: ValueType.STRING,
  466. default: null,
  467. },
  468. GROWI_APP_ID_FOR_GROWI_CLOUD: {
  469. ns: 'crowi',
  470. key: 'app:growiAppIdForCloud',
  471. type: ValueType.STRING,
  472. default: null,
  473. },
  474. DEFAULT_EMAIL_PUBLISHED: {
  475. ns: 'crowi',
  476. key: 'customize:isEmailPublishedForNewUser',
  477. type: ValueType.BOOLEAN,
  478. default: true,
  479. },
  480. SLACKBOT_TYPE: {
  481. ns: 'crowi',
  482. key: 'slackbot:currentBotType', // enum SlackbotType
  483. type: ValueType.STRING,
  484. default: null,
  485. },
  486. SLACKBOT_INTEGRATION_PROXY_URI: {
  487. ns: 'crowi',
  488. key: 'slackbot:proxyUri',
  489. type: ValueType.STRING,
  490. default: null,
  491. },
  492. SLACKBOT_WITHOUT_PROXY_SIGNING_SECRET: {
  493. ns: 'crowi',
  494. key: 'slackbot:withoutProxy:signingSecret',
  495. type: ValueType.STRING,
  496. default: null,
  497. },
  498. SLACKBOT_WITHOUT_PROXY_BOT_TOKEN: {
  499. ns: 'crowi',
  500. key: 'slackbot:withoutProxy:botToken',
  501. type: ValueType.STRING,
  502. default: null,
  503. },
  504. SLACKBOT_WITHOUT_PROXY_COMMAND_PERMISSION: {
  505. ns: 'crowi',
  506. key: 'slackbot:withoutProxy:commandPermission',
  507. type: ValueType.STRING,
  508. default: null,
  509. },
  510. SLACKBOT_WITHOUT_PROXY_EVENT_ACTIONS_PERMISSION: {
  511. ns: 'crowi',
  512. key: 'slackbot:withoutProxy:eventActionsPermission',
  513. type: ValueType.STRING,
  514. default: null,
  515. },
  516. SLACKBOT_WITH_PROXY_SALT_FOR_GTOP: {
  517. ns: 'crowi',
  518. key: 'slackbot:withProxy:saltForGtoP',
  519. type: ValueType.STRING,
  520. default: 'gtop',
  521. },
  522. SLACKBOT_WITH_PROXY_SALT_FOR_PTOG: {
  523. ns: 'crowi',
  524. key: 'slackbot:withProxy:saltForPtoG',
  525. type: ValueType.STRING,
  526. default: 'ptog',
  527. },
  528. };
  529. /**
  530. * return whether env belongs to Security settings
  531. * @param key ex. 'security:passport-saml:isEnabled' is true
  532. * @returns
  533. */
  534. const isSecurityEnv = (key) => {
  535. const array = key.split(':');
  536. return (array[0] === 'security');
  537. };
  538. export interface ConfigObject extends Record<string, any> {
  539. fromDB: any,
  540. fromEnvVars: any,
  541. }
  542. export default class ConfigLoader {
  543. /**
  544. * return a config object
  545. */
  546. async load(): Promise<ConfigObject> {
  547. const configFromDB: any = await this.loadFromDB();
  548. const configFromEnvVars: any = this.loadFromEnvVars();
  549. // merge defaults per ns
  550. const mergedConfigFromDB = {
  551. crowi: Object.assign(defaultCrowiConfigs, configFromDB.crowi),
  552. markdown: Object.assign(defaultMarkdownConfigs, configFromDB.markdown),
  553. notification: Object.assign(defaultNotificationConfigs, configFromDB.notification),
  554. };
  555. // In getConfig API, only null is used as a value to indicate that a config is not set.
  556. // So, if a value loaded from the database is empty,
  557. // it is converted to null because an empty string is used as the same meaning in the config model.
  558. // By this processing, whether a value is loaded from the database or from the environment variable,
  559. // only null indicates a config is not set.
  560. for (const namespace of Object.keys(mergedConfigFromDB)) {
  561. for (const key of Object.keys(mergedConfigFromDB[namespace])) {
  562. if (mergedConfigFromDB[namespace][key] === '') {
  563. mergedConfigFromDB[namespace][key] = null;
  564. }
  565. }
  566. }
  567. return {
  568. fromDB: mergedConfigFromDB,
  569. fromEnvVars: configFromEnvVars,
  570. };
  571. }
  572. async loadFromDB(): Promise<any> {
  573. const config = {};
  574. const docs: Config[] = await ConfigModel.find().exec();
  575. for (const doc of docs) {
  576. if (!config[doc.ns]) {
  577. config[doc.ns] = {};
  578. }
  579. config[doc.ns][doc.key] = doc.value ? JSON.parse(doc.value) : null;
  580. }
  581. logger.debug('ConfigLoader#loadFromDB', config);
  582. return config;
  583. }
  584. loadFromEnvVars(): any {
  585. const config = {};
  586. for (const ENV_VAR_NAME of Object.keys(ENV_VAR_NAME_TO_CONFIG_INFO)) {
  587. const configInfo = ENV_VAR_NAME_TO_CONFIG_INFO[ENV_VAR_NAME];
  588. if (config[configInfo.ns] === undefined) {
  589. config[configInfo.ns] = {};
  590. }
  591. if (process.env[ENV_VAR_NAME] === undefined) {
  592. config[configInfo.ns][configInfo.key] = configInfo.default;
  593. }
  594. else {
  595. const parser: ValueParser<number | string | boolean> = parserDictionary[configInfo.type];
  596. config[configInfo.ns][configInfo.key] = parser.parse(process.env[ENV_VAR_NAME] as string);
  597. }
  598. }
  599. logger.debug('ConfigLoader#loadFromEnvVars', config);
  600. return config;
  601. }
  602. /**
  603. * get config from the environment variables for display admin page
  604. *
  605. * **use this only admin home page.**
  606. */
  607. static getEnvVarsForDisplay(avoidSecurity = false): any {
  608. const config = {};
  609. for (const ENV_VAR_NAME of Object.keys(ENV_VAR_NAME_TO_CONFIG_INFO)) {
  610. const configInfo = ENV_VAR_NAME_TO_CONFIG_INFO[ENV_VAR_NAME];
  611. if (process.env[ENV_VAR_NAME] === undefined) {
  612. continue;
  613. }
  614. if (isSecurityEnv(configInfo.key) && avoidSecurity) {
  615. continue;
  616. }
  617. const parser: ValueParser<number | string | boolean> = parserDictionary[configInfo.type];
  618. config[ENV_VAR_NAME] = parser.parse(process.env[ENV_VAR_NAME] as string);
  619. }
  620. logger.debug('ConfigLoader#getEnvVarsForDisplay', config);
  621. return config;
  622. }
  623. }