config.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. const fs = require('fs');
  2. const NodeRSA = require('node-rsa');
  3. const logger = require('../logger').global;
  4. const keysFile = '/data/keys.json';
  5. const mysqlEngine = 'mysql2';
  6. const postgresEngine = 'pg';
  7. const sqliteClientName = 'sqlite3';
  8. let instance = null;
  9. // 1. Load from config file first (not recommended anymore)
  10. // 2. Use config env variables next
  11. const configure = () => {
  12. const filename = (process.env.NODE_CONFIG_DIR || './config') + '/' + (process.env.NODE_ENV || 'default') + '.json';
  13. if (fs.existsSync(filename)) {
  14. let configData;
  15. try {
  16. configData = require(filename);
  17. } catch (_) {
  18. // do nothing
  19. }
  20. if (configData && configData.database) {
  21. logger.info(`Using configuration from file: ${filename}`);
  22. instance = configData;
  23. instance.keys = getKeys();
  24. return;
  25. }
  26. }
  27. const envMysqlHost = process.env.DB_MYSQL_HOST || null;
  28. const envMysqlUser = process.env.DB_MYSQL_USER || null;
  29. const envMysqlName = process.env.DB_MYSQL_NAME || null;
  30. if (envMysqlHost && envMysqlUser && envMysqlName) {
  31. // we have enough mysql creds to go with mysql
  32. logger.info('Using MySQL configuration');
  33. instance = {
  34. database: {
  35. engine: mysqlEngine,
  36. host: envMysqlHost,
  37. port: process.env.DB_MYSQL_PORT || 3306,
  38. user: envMysqlUser,
  39. password: process.env.DB_MYSQL_PASSWORD,
  40. name: envMysqlName,
  41. },
  42. keys: getKeys(),
  43. };
  44. return;
  45. }
  46. const envPostgresHost = process.env.DB_POSTGRES_HOST || null;
  47. const envPostgresUser = process.env.DB_POSTGRES_USER || null;
  48. const envPostgresName = process.env.DB_POSTGRES_NAME || null;
  49. if (envPostgresHost && envPostgresUser && envPostgresName) {
  50. // we have enough postgres creds to go with postgres
  51. logger.info('Using Postgres configuration');
  52. instance = {
  53. database: {
  54. engine: postgresEngine,
  55. host: envPostgresHost,
  56. port: process.env.DB_POSTGRES_PORT || 5432,
  57. user: envPostgresUser,
  58. password: process.env.DB_POSTGRES_PASSWORD,
  59. name: envPostgresName,
  60. },
  61. keys: getKeys(),
  62. };
  63. return;
  64. }
  65. const envSqliteFile = process.env.DB_SQLITE_FILE || '/data/database.sqlite';
  66. logger.info(`Using Sqlite: ${envSqliteFile}`);
  67. instance = {
  68. database: {
  69. engine: 'knex-native',
  70. knex: {
  71. client: sqliteClientName,
  72. connection: {
  73. filename: envSqliteFile
  74. },
  75. useNullAsDefault: true
  76. }
  77. },
  78. keys: getKeys(),
  79. };
  80. };
  81. const getKeys = () => {
  82. // Get keys from file
  83. if (!fs.existsSync(keysFile)) {
  84. generateKeys();
  85. } else if (process.env.DEBUG) {
  86. logger.info('Keys file exists OK');
  87. }
  88. try {
  89. return require(keysFile);
  90. } catch (err) {
  91. logger.error('Could not read JWT key pair from config file: ' + keysFile, err);
  92. process.exit(1);
  93. }
  94. };
  95. const generateKeys = () => {
  96. logger.info('Creating a new JWT key pair...');
  97. // Now create the keys and save them in the config.
  98. const key = new NodeRSA({ b: 2048 });
  99. key.generateKeyPair();
  100. const keys = {
  101. key: key.exportKey('private').toString(),
  102. pub: key.exportKey('public').toString(),
  103. };
  104. // Write keys config
  105. try {
  106. fs.writeFileSync(keysFile, JSON.stringify(keys, null, 2));
  107. } catch (err) {
  108. logger.error('Could not write JWT key pair to config file: ' + keysFile + ': ' + err.message);
  109. process.exit(1);
  110. }
  111. logger.info('Wrote JWT key pair to config file: ' + keysFile);
  112. };
  113. module.exports = {
  114. /**
  115. *
  116. * @param {string} key ie: 'database' or 'database.engine'
  117. * @returns {boolean}
  118. */
  119. has: function(key) {
  120. instance === null && configure();
  121. const keys = key.split('.');
  122. let level = instance;
  123. let has = true;
  124. keys.forEach((keyItem) =>{
  125. if (typeof level[keyItem] === 'undefined') {
  126. has = false;
  127. } else {
  128. level = level[keyItem];
  129. }
  130. });
  131. return has;
  132. },
  133. /**
  134. * Gets a specific key from the top level
  135. *
  136. * @param {string} key
  137. * @returns {*}
  138. */
  139. get: function (key) {
  140. instance === null && configure();
  141. if (key && typeof instance[key] !== 'undefined') {
  142. return instance[key];
  143. }
  144. return instance;
  145. },
  146. /**
  147. * Is this a sqlite configuration?
  148. *
  149. * @returns {boolean}
  150. */
  151. isSqlite: function () {
  152. instance === null && configure();
  153. return instance.database.knex && instance.database.knex.client === sqliteClientName;
  154. },
  155. /**
  156. * Is this a mysql configuration?
  157. *
  158. * @returns {boolean}
  159. */
  160. isMysql: function () {
  161. instance === null && configure();
  162. return instance.database.engine === mysqlEngine;
  163. },
  164. /**
  165. * Is this a postgres configuration?
  166. *
  167. * @returns {boolean}
  168. */
  169. isPostgres: function () {
  170. instance === null && configure();
  171. return instance.database.engine === postgresEngine;
  172. },
  173. /**
  174. * Are we running in debug mdoe?
  175. *
  176. * @returns {boolean}
  177. */
  178. debug: function () {
  179. return !!process.env.DEBUG;
  180. },
  181. /**
  182. * Returns a public key
  183. *
  184. * @returns {string}
  185. */
  186. getPublicKey: function () {
  187. instance === null && configure();
  188. return instance.keys.pub;
  189. },
  190. /**
  191. * Returns a private key
  192. *
  193. * @returns {string}
  194. */
  195. getPrivateKey: function () {
  196. instance === null && configure();
  197. return instance.keys.key;
  198. },
  199. /**
  200. * @returns {boolean}
  201. */
  202. useLetsencryptStaging: function () {
  203. return !!process.env.LE_STAGING;
  204. },
  205. /**
  206. * @returns {string|null}
  207. */
  208. useLetsencryptServer: function () {
  209. if (process.env.LE_SERVER) {
  210. return process.env.LE_SERVER;
  211. }
  212. return null;
  213. }
  214. };