config-loader.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. const debug = require('debug')('growi:service:ConfigLoader');
  2. const TYPES = {
  3. NUMBER: { parse: (v) => parseInt(v) },
  4. STRING: { parse: (v) => v },
  5. BOOLEAN: { parse: (v) => /^(true|1)$/i.test(v) }
  6. };
  7. /**
  8. * The following env vars are excluded because these are currently used before the configuration setup.
  9. * - MONGO_URI
  10. * - NODE_ENV
  11. * - PORT
  12. * - REDIS_URI
  13. * - SESSION_NAME
  14. * - PASSWORD_SEED
  15. * - SECRET_TOKEN
  16. *
  17. * The commented out item has not yet entered the migration work.
  18. * So, parameters of these are under consideration.
  19. */
  20. const ENV_VAR_NAME_TO_CONFIG_INFO = {
  21. // ELASTICSEARCH_URI: {
  22. // ns: ,
  23. // key: ,
  24. // type: ,
  25. // default:
  26. // },
  27. // FILE_UPLOAD: {
  28. // ns: ,
  29. // key: ,
  30. // type: ,
  31. // default:
  32. // },
  33. // HACKMD_URI: {
  34. // ns: ,
  35. // key: ,
  36. // type: ,
  37. // default:
  38. // },
  39. // HACKMD_URI_FOR_SERVER: {
  40. // ns: ,
  41. // key: ,
  42. // type: ,
  43. // default:
  44. // },
  45. // PLANTUML_URI: {
  46. // ns: ,
  47. // key: ,
  48. // type: ,
  49. // default:
  50. // },
  51. // BLOCKDIAG_URI: {
  52. // ns: ,
  53. // key: ,
  54. // type: ,
  55. // default:
  56. // },
  57. // OAUTH_GOOGLE_CLIENT_ID: {
  58. // ns: 'crowi',
  59. // key: 'security:passport-google:clientId',
  60. // type: ,
  61. // default:
  62. // },
  63. // OAUTH_GOOGLE_CLIENT_SECRET: {
  64. // ns: 'crowi',
  65. // key: 'security:passport-google:clientSecret',
  66. // type: ,
  67. // default:
  68. // },
  69. // OAUTH_GOOGLE_CALLBACK_URI: {
  70. // ns: 'crowi',
  71. // key: 'security:passport-google:callbackUrl',
  72. // type: ,
  73. // default:
  74. // },
  75. // OAUTH_GITHUB_CLIENT_ID: {
  76. // ns: 'crowi',
  77. // key: 'security:passport-github:clientId',
  78. // type: ,
  79. // default:
  80. // },
  81. // OAUTH_GITHUB_CLIENT_SECRET: {
  82. // ns: 'crowi',
  83. // key: 'security:passport-github:clientSecret',
  84. // type: ,
  85. // default:
  86. // },
  87. // OAUTH_GITHUB_CALLBACK_URI: {
  88. // ns: 'crowi',
  89. // key: 'security:passport-github:callbackUrl',
  90. // type: ,
  91. // default:
  92. // },
  93. // OAUTH_TWITTER_CONSUMER_KEY: {
  94. // ns: 'crowi',
  95. // key: 'security:passport-twitter:consumerKey',
  96. // type: ,
  97. // default:
  98. // },
  99. // OAUTH_TWITTER_CONSUMER_SECRET: {
  100. // ns: 'crowi',
  101. // key: 'security:passport-twitter:consumerSecret',
  102. // type: ,
  103. // default:
  104. // },
  105. // OAUTH_TWITTER_CALLBACK_URI: {
  106. // ns: 'crowi',
  107. // key: 'security:passport-twitter:callbackUrl',
  108. // type: ,
  109. // default:
  110. // },
  111. SAML_USES_ONLY_ENV_VARS: {
  112. ns: 'crowi',
  113. key: 'security:passport-saml:useOnlyEnvVars',
  114. type: TYPES.BOOLEAN,
  115. default: null
  116. },
  117. SAML_ENTRY_POINT: {
  118. ns: 'crowi',
  119. key: 'security:passport-saml:entryPoint',
  120. type: TYPES.STRING,
  121. default: null
  122. },
  123. SAML_CALLBACK_URI: {
  124. ns: 'crowi',
  125. key: 'security:passport-saml:callbackUrl',
  126. type: TYPES.STRING,
  127. default: null
  128. },
  129. SAML_ISSUER: {
  130. ns: 'crowi',
  131. key: 'security:passport-saml:issuer',
  132. type: TYPES.STRING,
  133. default: null
  134. },
  135. SAML_CERT: {
  136. ns: 'crowi',
  137. key: 'security:passport-saml:cert',
  138. type: TYPES.STRING,
  139. default: null
  140. }
  141. };
  142. class ConfigLoader {
  143. constructor(configModel) {
  144. this.configModel = configModel;
  145. }
  146. /**
  147. * return a config object
  148. */
  149. async load() {
  150. const configFromDB = await this.loadFromDB();
  151. const configFromEnvVars = this.loadFromEnvVars();
  152. // merge defaults
  153. let mergedConfigFromDB = Object.assign({'crowi': this.configModel.getDefaultCrowiConfigsObject()}, configFromDB);
  154. mergedConfigFromDB = Object.assign({'markdown': this.configModel.getDefaultMarkdownConfigsObject()}, mergedConfigFromDB);
  155. return {
  156. fromDB: mergedConfigFromDB,
  157. fromEnvVars: configFromEnvVars
  158. };
  159. }
  160. async loadFromDB() {
  161. const config = {};
  162. const docs = await this.configModel.find().exec();
  163. for (const doc of docs) {
  164. if (!config[doc.ns]) {
  165. config[doc.ns] = {};
  166. }
  167. config[doc.ns][doc.key] = JSON.parse(doc.value);
  168. }
  169. debug('ConfigLoader#loadFromDB', config);
  170. return config;
  171. }
  172. loadFromEnvVars() {
  173. const config = {};
  174. for (const ENV_VAR_NAME of Object.keys(ENV_VAR_NAME_TO_CONFIG_INFO)) {
  175. const configInfo = ENV_VAR_NAME_TO_CONFIG_INFO[ENV_VAR_NAME];
  176. if (config[configInfo.ns] === undefined) {
  177. config[configInfo.ns] = {};
  178. }
  179. if (process.env[ENV_VAR_NAME] === undefined) {
  180. config[configInfo.ns][configInfo.key] = configInfo.default;
  181. }
  182. else {
  183. config[configInfo.ns][configInfo.key] = configInfo.type.parse(process.env[ENV_VAR_NAME]);
  184. }
  185. }
  186. debug('ConfigLoader#loadFromEnvVars', config);
  187. return config;
  188. }
  189. }
  190. module.exports = ConfigLoader;