ml-testing-toolkit 18.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/.dockerignore +10 -0
  2. package/.grype.yaml +16 -0
  3. package/.ncurc.yaml +9 -0
  4. package/.nvmrc +1 -0
  5. package/.versionrc.js +16 -0
  6. package/CHANGELOG.md +504 -0
  7. package/CODEOWNERS +30 -0
  8. package/Dockerfile +42 -0
  9. package/Dockerfile-newman +13 -0
  10. package/LICENSE.md +9 -0
  11. package/README.md +119 -0
  12. package/assets/diagrams/architectural/architectural-diagram.svg +3 -0
  13. package/assets/diagrams/flow/flow-diagram.svg +3 -0
  14. package/assets/images/Sample-Response-Failure.png +0 -0
  15. package/assets/images/Screenshot 2020-04-16 at 22.58.04.png +0 -0
  16. package/assets/images/TLS-Enabled-on-Environment.png +0 -0
  17. package/assets/images/adapter-mutual-tls-enabled.png +0 -0
  18. package/assets/images/add-additional-input-values.png +0 -0
  19. package/assets/images/add-condition-button.png +0 -0
  20. package/assets/images/add-new-assertion.png +0 -0
  21. package/assets/images/add-new-input-value.png +0 -0
  22. package/assets/images/add-new-input-variable.png +0 -0
  23. package/assets/images/additional-transfers.png +0 -0
  24. package/assets/images/api-provisioning-add-new-api-confirmation.png +0 -0
  25. package/assets/images/api-provisioning-file-input-window.png +0 -0
  26. package/assets/images/api-provisioning-list-apis-view.png +0 -0
  27. package/assets/images/api-provisioning-menu-item.png +0 -0
  28. package/assets/images/apply_and_restart.jpg +0 -0
  29. package/assets/images/assess-request-or-response.png +0 -0
  30. package/assets/images/assess-response-equation-save.png +0 -0
  31. package/assets/images/assess-response-equation.png +0 -0
  32. package/assets/images/assess-response-status.png +0 -0
  33. package/assets/images/building-new-rules-file.png +0 -0
  34. package/assets/images/callback-rules-screen.png +0 -0
  35. package/assets/images/configurable-parameter-assertion.png +0 -0
  36. package/assets/images/configurable-parameter-currency.png +0 -0
  37. package/assets/images/configurable-parameter.png +0 -0
  38. package/assets/images/connection-manager-ui-opening.png +0 -0
  39. package/assets/images/create-inbound-user-simulator.png +0 -0
  40. package/assets/images/creating-new-rule-file.png +0 -0
  41. package/assets/images/dfsp-client-cacert.png +0 -0
  42. package/assets/images/dfsp-client-submit.png +0 -0
  43. package/assets/images/dfsp-client.png +0 -0
  44. package/assets/images/dfsp-p2p-happy-path.png +0 -0
  45. package/assets/images/dfsp-server-cacert.png +0 -0
  46. package/assets/images/dfsp-server-cert.png +0 -0
  47. package/assets/images/download-report.png +0 -0
  48. package/assets/images/drive_have_not_been_shared.jpg +0 -0
  49. package/assets/images/event-response-options.png +0 -0
  50. package/assets/images/expand-monitoring-messages.png +0 -0
  51. package/assets/images/fixed-response-sample.png +0 -0
  52. package/assets/images/header-selection.png +0 -0
  53. package/assets/images/heap_error_windows.jpg +0 -0
  54. package/assets/images/hosted-mode-docker-compose-intro.png +0 -0
  55. package/assets/images/hub-client-cert.png +0 -0
  56. package/assets/images/import-template.png +0 -0
  57. package/assets/images/inbound-requests-environment.png +0 -0
  58. package/assets/images/inbound-requests-scripts.png +0 -0
  59. package/assets/images/jws-certificate-submit.png +0 -0
  60. package/assets/images/jws-certificate.png +0 -0
  61. package/assets/images/jws-certs-keys.png +0 -0
  62. package/assets/images/jws-hub-certs-keys.png +0 -0
  63. package/assets/images/local-enable-jws-publickey.png +0 -0
  64. package/assets/images/local-mutual-tls-enabled.png +0 -0
  65. package/assets/images/local_drives_to_be_available.jpg +0 -0
  66. package/assets/images/mcm-environment-opening.png +0 -0
  67. package/assets/images/menu-items.png +0 -0
  68. package/assets/images/mock-response-sample.png +0 -0
  69. package/assets/images/monitoring-initial-state.png +0 -0
  70. package/assets/images/monitoring-messages.png +0 -0
  71. package/assets/images/new-empty-assertion.png +0 -0
  72. package/assets/images/opened-imported-template.png +0 -0
  73. package/assets/images/opening-default-settings.png +0 -0
  74. package/assets/images/opening-sync-response-rules.png +0 -0
  75. package/assets/images/opening-view.png +0 -0
  76. package/assets/images/outbound-display-opening-hub.png +0 -0
  77. package/assets/images/outbound-display-opening.png +0 -0
  78. package/assets/images/override-with-environment-variable.png +0 -0
  79. package/assets/images/populate-with-sample-body.png +0 -0
  80. package/assets/images/resource-selection.png +0 -0
  81. package/assets/images/rule-builder-select-api.png +0 -0
  82. package/assets/images/sample-condition-add-configurable-params.png +0 -0
  83. package/assets/images/sample-condition.png +0 -0
  84. package/assets/images/sample-editor.png +0 -0
  85. package/assets/images/sample-request.png +0 -0
  86. package/assets/images/sample-test-assertion.png +0 -0
  87. package/assets/images/send-transfer.png +0 -0
  88. package/assets/images/sending-single-test-case-1.png +0 -0
  89. package/assets/images/sending-single-test-case-2.png +0 -0
  90. package/assets/images/sending-test-cases.png +0 -0
  91. package/assets/images/server-certificates-submitted.png +0 -0
  92. package/assets/images/simulator-response.png +0 -0
  93. package/assets/images/simulator-scheme-adapter-endpoint.png +0 -0
  94. package/assets/images/summarized-view-of-rule.png +0 -0
  95. package/assets/images/template-window.png +0 -0
  96. package/assets/images/test-case-editor-console-log.png +0 -0
  97. package/assets/images/test-case-editor-environment-state.png +0 -0
  98. package/assets/images/test-case-editor-scripts.png +0 -0
  99. package/assets/images/test-case-editor.png +0 -0
  100. package/assets/images/testcase-definition-download.png +0 -0
  101. package/assets/images/testcase-definition-edit-meta-info.png +0 -0
  102. package/assets/images/testing-toolkit-mojaloop-testing-toolkit-endpoint.png +0 -0
  103. package/assets/images/tls-hub-certs-keys.png +0 -0
  104. package/assets/images/tls-jws-enabled-on-environment.png +0 -0
  105. package/assets/images/updated-sample-body-data.png +0 -0
  106. package/assets/images/using-configurable-parameter.png +0 -0
  107. package/assets/images/validation-rules-screen.png +0 -0
  108. package/assets/images/view-response.png +0 -0
  109. package/audit-ci.jsonc +7 -0
  110. package/connection-manager/docker-compose.yml +55 -0
  111. package/database/docker-compose.yml +16 -0
  112. package/docker/hosted-mode/docker-compose.yaml +107 -0
  113. package/docker/hosted-mode/keycloak/keycloak-realm.json +2298 -0
  114. package/docker/hosted-mode/mongo-init.sh +1 -0
  115. package/docker/hosted-mode-tls/docker-compose.yaml +171 -0
  116. package/docker/hosted-mode-tls/keycloak/keycloak-realm.json +2298 -0
  117. package/docker/hosted-mode-tls/mongo-init.sh +1 -0
  118. package/docker-compose.yml +62 -0
  119. package/documents/Mojaloop-Testing-Toolkit.md +296 -0
  120. package/documents/RULES_ENGINE.md +403 -0
  121. package/documents/User-Guide-API-Provisioning.md +121 -0
  122. package/documents/User-Guide-CLI.md +218 -0
  123. package/documents/User-Guide-Connection-Manager.md +282 -0
  124. package/documents/User-Guide-Frequently-Asked-Questions.md +39 -0
  125. package/documents/User-Guide-Hosted-Mode-Docker-Compose.md +110 -0
  126. package/documents/User-Guide-Installation.md +163 -0
  127. package/documents/User-Guide-Mojaloop-Testing-Toolkit.md +642 -0
  128. package/documents/User-Guide-OAuth-Server-Deployment.md +283 -0
  129. package/documents/User-Guide-Onboarding-DFSP.md +197 -0
  130. package/documents/User-Guide-Onboarding-HUB.md +191 -0
  131. package/documents/User-Guide.md +53 -0
  132. package/examples/collections/dfsp/p2p_failed_tests.json +7161 -0
  133. package/examples/collections/dfsp/p2p_fx_happy_path.json +502 -0
  134. package/examples/collections/dfsp/p2p_happy_path.json +350 -0
  135. package/examples/collections/dfsp/p2p_happy_path_extended.json +6106 -0
  136. package/examples/collections/dfsp/p2p_happy_path_jws.json +511 -0
  137. package/examples/collections/dfsp/p2p_payee_assertions_websocket.json +441 -0
  138. package/examples/collections/dfsp/sample.json +5029 -0
  139. package/examples/collections/dfsp/transaction_request_service.json +240 -0
  140. package/examples/collections/fxp/FXP.json +264 -0
  141. package/examples/collections/fxp/SDK_backend.json +98 -0
  142. package/examples/collections/fxp/SDK_outbound.json +163 -0
  143. package/examples/collections/hub/hub_01_p2p_happy_path/hub_p2p_receive_quote.json +400 -0
  144. package/examples/collections/hub/hub_01_p2p_happy_path/hub_p2p_send_quote.json +395 -0
  145. package/examples/collections/hub/hub_02_block_transfer/hub_block_transfer.json +393 -0
  146. package/examples/collections/hub/hub_03_funds_in_out/hub_funds_in.json +224 -0
  147. package/examples/collections/hub/hub_03_funds_in_out/hub_funds_out.json +780 -0
  148. package/examples/collections/hub/hub_04_settlements/hub_settlements.json +3138 -0
  149. package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_payee_abort.json +475 -0
  150. package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_payee_invalid_fulfillment.json +370 -0
  151. package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_transfer_timeout.json +262 -0
  152. package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_authorizations.json +117 -0
  153. package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_error_framework.json +591 -0
  154. package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_received_state.json +379 -0
  155. package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_reject_state.json +361 -0
  156. package/examples/collections/hub/hub_07_quoting_service.json +525 -0
  157. package/examples/collections/hub/hub_08_participant_inactive_stop_transfers.json +706 -0
  158. package/examples/collections/hub/hub_09_duplicate_handling_transfers.json +1377 -0
  159. package/examples/collections/hub/hub_10_on_us_transfers.json +245 -0
  160. package/examples/collections/hub/hub_11_accented_and_spl_chars.json +629 -0
  161. package/examples/collections/hub/hub_12_fspiop_version_1.1.json +646 -0
  162. package/examples/collections/hub/hub_13_bulk_transfers.json +1857 -0
  163. package/examples/collections/iso20022/self_referencing_iso20022.json +926 -0
  164. package/examples/collections/provisioning/testingtoolkitdfsp.json +904 -0
  165. package/examples/environments/dfsp_local_environment.json +46 -0
  166. package/examples/environments/hub_local_environment.json +57 -0
  167. package/jest.config.js +17 -0
  168. package/package.json +199 -0
  169. package/sbom-v18.12.4.csv +1553 -0
  170. package/secrets/keygen.sh +5 -0
  171. package/secrets/privatekey.pem +27 -0
  172. package/secrets/publickey.cer +21 -0
  173. package/secrets/tls/01.pem +132 -0
  174. package/secrets/tls/createSecrets.sh +20 -0
  175. package/secrets/tls/hub_client.csr +32 -0
  176. package/secrets/tls/hub_client_cacert.pem +35 -0
  177. package/secrets/tls/hub_client_cakey.pem +52 -0
  178. package/secrets/tls/hub_client_key.key +52 -0
  179. package/secrets/tls/hub_server.csr +31 -0
  180. package/secrets/tls/hub_server_cacert.pem +35 -0
  181. package/secrets/tls/hub_server_cakey.pem +52 -0
  182. package/secrets/tls/hub_server_cert.pem +132 -0
  183. package/secrets/tls/hub_server_key.key +52 -0
  184. package/secrets/tls/index.txt +1 -0
  185. package/secrets/tls/index.txt.attr +1 -0
  186. package/secrets/tls/openssl-client.cnf +36 -0
  187. package/secrets/tls/openssl-clientca.cnf +71 -0
  188. package/secrets/tls/openssl-server.cnf +39 -0
  189. package/secrets/tls/openssl-serverca.cnf +71 -0
  190. package/secrets/tls/serial.txt +1 -0
  191. package/spec_files/api_definitions/als_admin_1.1/api_spec.yaml +804 -0
  192. package/spec_files/api_definitions/central_admin_1.0/api_spec.yaml +1850 -0
  193. package/spec_files/api_definitions/central_admin_1.0/response_map.json +96 -0
  194. package/spec_files/api_definitions/central_admin_old_9.3/api_spec.yaml +2467 -0
  195. package/spec_files/api_definitions/central_admin_old_9.3/response_map.json +96 -0
  196. package/spec_files/api_definitions/fspiop_1.0/api_spec.yaml +4187 -0
  197. package/spec_files/api_definitions/fspiop_1.0/callback_map.json +568 -0
  198. package/spec_files/api_definitions/fspiop_1.0/mockRef.json +79 -0
  199. package/spec_files/api_definitions/fspiop_1.0/trigger_templates/transaction_request_followup.json +126 -0
  200. package/spec_files/api_definitions/fspiop_1.0/trigger_templates/transaction_request_followup_quotes_only.json +97 -0
  201. package/spec_files/api_definitions/fspiop_1.1/api_spec.yaml +3778 -0
  202. package/spec_files/api_definitions/fspiop_1.1/callback_map.json +568 -0
  203. package/spec_files/api_definitions/fspiop_1.1/mockRef.json +79 -0
  204. package/spec_files/api_definitions/fspiop_1.1/trigger_templates/transaction_request_followup.json +125 -0
  205. package/spec_files/api_definitions/fspiop_2.0/api_spec.yaml +4839 -0
  206. package/spec_files/api_definitions/fspiop_2.0/callback_map.json +716 -0
  207. package/spec_files/api_definitions/fspiop_2.0/mockRef.json +79 -0
  208. package/spec_files/api_definitions/fspiop_2.0/trigger_templates/transaction_request_followup.json +125 -0
  209. package/spec_files/api_definitions/fspiop_2.0_iso20022/api_spec.yaml +8331 -0
  210. package/spec_files/api_definitions/fspiop_2.0_iso20022/callback_map.json +508 -0
  211. package/spec_files/api_definitions/fspiop_2.0_iso20022/mockRef.json +66 -0
  212. package/spec_files/api_definitions/fx-api_2.0/api_spec.yaml +1768 -0
  213. package/spec_files/api_definitions/fx-api_2.0/callback_map.json +188 -0
  214. package/spec_files/api_definitions/fx-api_2.0/mockRef.json +83 -0
  215. package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/api_spec.yaml +2612 -0
  216. package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/mockRef.json +22 -0
  217. package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/response_map.json +35 -0
  218. package/spec_files/api_definitions/mojaloop_simulator_0.1/api_spec.yaml +225 -0
  219. package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/api_spec.yaml +1087 -0
  220. package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/mockRef.json +75 -0
  221. package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/response_map.json +55 -0
  222. package/spec_files/api_definitions/payment_manager_1.4/api_spec.yaml +1389 -0
  223. package/spec_files/api_definitions/sdk-scheme-adapter-backend-v2_1_0-openapi3-snippets_2.1/api_spec.yaml +2834 -0
  224. package/spec_files/api_definitions/sdk-scheme-adapter-outbound-v2_1_0-openapi3-snippets_2.1/api_spec.yaml +3449 -0
  225. package/spec_files/api_definitions/settlements_1.0/api_spec.yaml +983 -0
  226. package/spec_files/api_definitions/settlements_1.0/mockRef.json +38 -0
  227. package/spec_files/api_definitions/settlements_1.0/response_map.json +34 -0
  228. package/spec_files/api_definitions/settlements_2.0/api_spec.yaml +1001 -0
  229. package/spec_files/api_definitions/settlements_2.0/mockRef.json +38 -0
  230. package/spec_files/api_definitions/settlements_2.0/response_map.json +34 -0
  231. package/spec_files/api_definitions/thirdparty_sdk_outbound_0.1/api_spec.yaml +2139 -0
  232. package/spec_files/reports/templates/newman/html_template.html +1202 -0
  233. package/spec_files/reports/templates/newman/pdf_template.html +790 -0
  234. package/spec_files/reports/templates/testcase_definition/table_view.html +1602 -0
  235. package/spec_files/rules_callback/config.json +3 -0
  236. package/spec_files/rules_callback/default.json +2698 -0
  237. package/spec_files/rules_callback/p2p-limit.json +129 -0
  238. package/spec_files/rules_forward/config.json +3 -0
  239. package/spec_files/rules_forward/default.json +482 -0
  240. package/spec_files/rules_response/config.json +3 -0
  241. package/spec_files/rules_response/default.json +295 -0
  242. package/spec_files/rules_validation/config.json +3 -0
  243. package/spec_files/rules_validation/default.json +1 -0
  244. package/spec_files/rules_validation/p2p-limit.json +55 -0
  245. package/spec_files/system_config.json +175 -0
  246. package/spec_files/user_config.json +109 -0
  247. package/src/index.js +67 -0
  248. package/src/lib/MyEventEmitter.js +54 -0
  249. package/src/lib/api-management.js +143 -0
  250. package/src/lib/api-routes/config.js +83 -0
  251. package/src/lib/api-routes/history.js +139 -0
  252. package/src/lib/api-routes/keycloak.js +54 -0
  253. package/src/lib/api-routes/longpolling.js +70 -0
  254. package/src/lib/api-routes/oauth2.js +149 -0
  255. package/src/lib/api-routes/objectstore.js +53 -0
  256. package/src/lib/api-routes/openapi.js +224 -0
  257. package/src/lib/api-routes/outbound.js +134 -0
  258. package/src/lib/api-routes/reports.js +72 -0
  259. package/src/lib/api-routes/rules.js +356 -0
  260. package/src/lib/api-routes/samples.js +92 -0
  261. package/src/lib/api-routes/server-logs.js +44 -0
  262. package/src/lib/api-routes/settings.js +71 -0
  263. package/src/lib/api-server.js +135 -0
  264. package/src/lib/arrayStore.js +101 -0
  265. package/src/lib/callbackHandler.js +201 -0
  266. package/src/lib/config.js +177 -0
  267. package/src/lib/configuration-providers/mb-connection-manager.js +625 -0
  268. package/src/lib/db/adapters/dbAdapter.js +184 -0
  269. package/src/lib/db/dfspMockUsers.js +64 -0
  270. package/src/lib/db/models/mongoDBWrapper.js +78 -0
  271. package/src/lib/eventListenerClient/inboundEventListener.js +176 -0
  272. package/src/lib/fileAdapter.js +57 -0
  273. package/src/lib/httpAgentStore.js +135 -0
  274. package/src/lib/importExport.js +186 -0
  275. package/src/lib/jws/JwsSigning.js +141 -0
  276. package/src/lib/loadSamples.js +128 -0
  277. package/src/lib/logger.js +20 -0
  278. package/src/lib/longpollingEmitter.js +56 -0
  279. package/src/lib/metrics.js +51 -0
  280. package/src/lib/mocking/custom-functions/generic.js +57 -0
  281. package/src/lib/mocking/middleware-functions/ilpModel.js +238 -0
  282. package/src/lib/mocking/middleware-functions/quotesAssociation.js +75 -0
  283. package/src/lib/mocking/middleware-functions/transactionRequestsService.js +78 -0
  284. package/src/lib/mocking/openApiDefinitionsModel.js +64 -0
  285. package/src/lib/mocking/openApiMockHandler.js +466 -0
  286. package/src/lib/mocking/openApiRulesEngine.js +492 -0
  287. package/src/lib/mocking/openApiVersionTools.js +136 -0
  288. package/src/lib/mocking/transformers/fspiopToISO20022.js +230 -0
  289. package/src/lib/mocking/transformers/index.js +41 -0
  290. package/src/lib/notificationEmitter.js +64 -0
  291. package/src/lib/oauth/KeycloakHelper.js +220 -0
  292. package/src/lib/oauth/LoginService.js +133 -0
  293. package/src/lib/oauth/OAuthHelper.js +181 -0
  294. package/src/lib/oauth/OAuthValidator.js +118 -0
  295. package/src/lib/oauth/Wso2Client.js +64 -0
  296. package/src/lib/objectStore/inMemoryImpl.js +50 -0
  297. package/src/lib/objectStore/objectStoreInterface.js +51 -0
  298. package/src/lib/objectStore.js +122 -0
  299. package/src/lib/report-generator/generator.js +126 -0
  300. package/src/lib/report-generator/helpers.js +154 -0
  301. package/src/lib/requestLogger.js +190 -0
  302. package/src/lib/resources/wso2carbon-publickey.cert +20 -0
  303. package/src/lib/rulesEngine.js +95 -0
  304. package/src/lib/rulesEngineModel.js +463 -0
  305. package/src/lib/scripting-engines/postman-sandbox.js +142 -0
  306. package/src/lib/scripting-engines/vm-javascript-sandbox.js +294 -0
  307. package/src/lib/server-logs/adapters/elastic-search.js +102 -0
  308. package/src/lib/server-logs/adapters/grafana.js +0 -0
  309. package/src/lib/server-logs/index.js +75 -0
  310. package/src/lib/socket-server.js +55 -0
  311. package/src/lib/storageAdapter.js +109 -0
  312. package/src/lib/test-outbound/TestCaseRunner.js +173 -0
  313. package/src/lib/test-outbound/getTracing.js +19 -0
  314. package/src/lib/test-outbound/outbound-initiator.js +1107 -0
  315. package/src/lib/uniqueIdGenerator.js +35 -0
  316. package/src/lib/utils.js +89 -0
  317. package/src/lib/utilsInternal.js +56 -0
  318. package/src/lib/webSocketClient/WebSocketClientManager.js +197 -0
  319. package/src/server.js +218 -0
@@ -0,0 +1,135 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 Mojaloop Foundation
5
+ The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
10
+
11
+ Contributors
12
+ --------------
13
+ This is the official list of the Mojaloop project contributors for this file.
14
+ Names of the original copyright holders (individuals or organizations)
15
+ should be listed with a '*' in the first column. People who have
16
+ contributed from an organization can be listed under the organization
17
+ that actually holds the copyright for their contributions (see the
18
+ Mojaloop Foundation for an example). Those individuals should have
19
+ their names indented and be marked with a '-'. Email address can be added
20
+ optionally within square brackets <email>.
21
+
22
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Georgi Logodazhki <georgi.logodazhki@modusbox.com>
27
+ * Vijaya Kumar Guthi <vijaya.guthi@modusbox.com> (Original Author)
28
+ --------------
29
+ ******/
30
+ const express = require('express')
31
+ const app = express()
32
+ const http = require('http').Server(app)
33
+ const customLogger = require('./requestLogger')
34
+ const Config = require('./config')
35
+ const passport = require('passport')
36
+ const cookieParser = require('cookie-parser')
37
+ const util = require('util')
38
+ const path = require('path')
39
+ const fs = require('fs')
40
+ const cors = require('cors')
41
+ const OAuthHelper = require('./oauth/OAuthHelper')
42
+
43
+ const initServer = () => {
44
+ // For CORS policy
45
+ app.use(cors({
46
+ allowedHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization'],
47
+ exposedHeaders: ['Content-Disposition'],
48
+ methods: ['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'],
49
+ origin: true,
50
+ credentials: true
51
+ }))
52
+
53
+ // For parsing incoming JSON requests
54
+ app.use(express.json({ limit: '50mb' }))
55
+ app.use(express.urlencoded({ extended: true }))
56
+
57
+ // For oauth
58
+ app.use(cookieParser())
59
+ OAuthHelper.handleMiddleware()
60
+
61
+ // Metrics
62
+ app.use(require('./metrics')(Config.getSystemConfig().METRICS))
63
+
64
+ const verifyUserMiddleware = verifyUser()
65
+ // For admin API
66
+ app.use('/api/rules', verifyUserMiddleware, require('./api-routes/rules'))
67
+ app.use('/api/openapi', verifyUserMiddleware, require('./api-routes/openapi'))
68
+ app.use('/api/outbound', verifyUserMiddleware, require('./api-routes/outbound'))
69
+ app.use('/api/config', verifyUserMiddleware, require('./api-routes/config'))
70
+ app.use('/longpolling', verifyUserMiddleware, require('./api-routes/longpolling'))
71
+ app.use('/api/oauth2', require('./api-routes/oauth2'))
72
+ app.use('/api/keycloak', verifyUserMiddleware, require('./api-routes/keycloak'))
73
+ app.use('/api/reports', verifyUserMiddleware, require('./api-routes/reports'))
74
+ app.use('/api/settings', verifyUserMiddleware, require('./api-routes/settings'))
75
+ app.use('/api/samples', verifyUserMiddleware, require('./api-routes/samples'))
76
+ app.use('/api/objectstore', verifyUserMiddleware, require('./api-routes/objectstore'))
77
+ app.use('/api/history', verifyUserMiddleware, require('./api-routes/history'))
78
+ app.use('/api/serverlogs', verifyUserMiddleware, require('./api-routes/server-logs'))
79
+
80
+ // For front-end UI
81
+ if (fs.existsSync(path.join('public_html'))) {
82
+ customLogger.logMessage('info', 'Folder public_html found: Serving Static Web UI', { notification: false })
83
+ // app.use('*.(jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|css|js)', express.static(path.join('public_html')))
84
+ app.use(express.static(path.join('public_html')))
85
+ app.get('*', (req, res) => {
86
+ res.sendFile(process.cwd() + '/public_html/index.html')
87
+ })
88
+ } else {
89
+ customLogger.logMessage('warn', 'Folder public_html not found', { notification: false })
90
+ }
91
+ }
92
+
93
+ const startServer = port => {
94
+ initServer()
95
+ http.listen(port)
96
+ customLogger.logMessage('info', 'API Server started on port ' + port, { notification: false })
97
+ }
98
+
99
+ const stopServer = port => {
100
+ http.close()
101
+ customLogger.logMessage('info', 'API Server stopped', { notification: false })
102
+ }
103
+
104
+ const getApp = () => {
105
+ if (!Object.prototype.hasOwnProperty.call(app, '_router')) { // To check whether app is initialized or not
106
+ initServer()
107
+ }
108
+ return app
109
+ }
110
+ const getHttp = () => {
111
+ return http
112
+ }
113
+
114
+ const verifyUser = () => {
115
+ if (Config.getSystemConfig().OAUTH.AUTH_ENABLED) {
116
+ return (req, res, next) => {
117
+ req.session = {}
118
+ passport.authenticate('jwt', { session: false, failureMessage: true })(req, res, next)
119
+ // failWithError: true returns awful html error. , failureMessage: True to store failure message in req.session.messages, or a string to use as override message for failure.
120
+ if (res.statusCode === 401) {
121
+ customLogger.logMessage('error', `Unable to authenticate with passport.authenticate - ${util.inspect(req.session.messages)}`, { additionalData: req.session.messages, notification: false })
122
+ }
123
+ }
124
+ // return passport.authenticate('jwt', { session: false, failWithError: true })
125
+ }
126
+ return (req, res, next) => { next() }
127
+ }
128
+
129
+ module.exports = {
130
+ startServer,
131
+ stopServer,
132
+ getHttp,
133
+ getApp,
134
+ verifyUser
135
+ }
@@ -0,0 +1,101 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 Mojaloop Foundation
5
+ The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
10
+
11
+ Contributors
12
+ --------------
13
+ This is the official list of the Mojaloop project contributors for this file.
14
+ Names of the original copyright holders (individuals or organizations)
15
+ should be listed with a '*' in the first column. People who have
16
+ contributed from an organization can be listed under the organization
17
+ that actually holds the copyright for their contributions (see the
18
+ Mojaloop Foundation for an example). Those individuals should have
19
+ their names indented and be marked with a '-'. Email address can be added
20
+ optionally within square brackets <email>.
21
+
22
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Vijaya Kumar Guthi <vijaya.guthi@modusbox.com> (Original Author)
27
+ --------------
28
+ ******/
29
+
30
+ const storedObject = {
31
+ data: {
32
+ requestsHistory: [],
33
+ callbacksHistory: []
34
+ }
35
+ }
36
+
37
+ const init = (key, user) => {
38
+ const context = user ? user.dfspId : 'data'
39
+ if (!storedObject[context]) {
40
+ storedObject[context] = {}
41
+ }
42
+ if (!storedObject[context][key]) {
43
+ storedObject[context][key] = []
44
+ }
45
+ return context
46
+ }
47
+
48
+ const reset = (key, user) => {
49
+ const context = init(key, user)
50
+ storedObject[context][key] = []
51
+ }
52
+
53
+ const get = (key, user) => {
54
+ const context = init(key, user)
55
+ return [...storedObject[context][key]]
56
+ }
57
+
58
+ const push = (key, value, user) => {
59
+ const context = init(key, user)
60
+ storedObject[context][key].push({
61
+ insertedDate: Date.now(),
62
+ data: JSON.parse(JSON.stringify(value))
63
+ })
64
+ }
65
+
66
+ const clear = (arrName, interval) => {
67
+ for (const context in storedObject) {
68
+ if (storedObject[context][arrName]) {
69
+ let delEndIndex = -1
70
+ for (let i = 0; i < storedObject[context][arrName].length; i++) {
71
+ const timeDiff = Date.now() - storedObject[context][arrName][i].insertedDate
72
+ if (timeDiff > interval) {
73
+ delEndIndex = i
74
+ } else {
75
+ break
76
+ }
77
+ }
78
+ if (delEndIndex >= 0) {
79
+ storedObject[context][arrName].splice(0, delEndIndex + 1)
80
+ }
81
+ }
82
+ }
83
+ }
84
+
85
+ const clearOldObjects = () => {
86
+ const interval = 10 * 60 * 1000
87
+ clear('requestsHistory', interval)
88
+ clear('callbacksHistory', interval)
89
+ }
90
+
91
+ const initArrayStore = () => {
92
+ setInterval(clearOldObjects, 1000)
93
+ }
94
+
95
+ module.exports = {
96
+ get,
97
+ reset,
98
+ initArrayStore,
99
+ push,
100
+ clear
101
+ }
@@ -0,0 +1,201 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 Mojaloop Foundation
5
+ The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
10
+
11
+ Contributors
12
+ --------------
13
+ This is the official list of the Mojaloop project contributors for this file.
14
+ Names of the original copyright holders (individuals or organizations)
15
+ should be listed with a '*' in the first column. People who have
16
+ contributed from an organization can be listed under the organization
17
+ that actually holds the copyright for their contributions (see the
18
+ Mojaloop Foundation for an example). Those individuals should have
19
+ their names indented and be marked with a '-'. Email address can be added
20
+ optionally within square brackets <email>.
21
+
22
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Vijaya Kumar Guthi <vijaya.guthi@modusbox.com> (Original Author)
27
+ --------------
28
+ ******/
29
+
30
+ const customLogger = require('./requestLogger')
31
+ const Config = require('./config')
32
+ const axios = require('axios').default
33
+ const https = require('https')
34
+ const objectStore = require('./objectStore')
35
+ const arrayStore = require('./arrayStore')
36
+ const MyEventEmitter = require('./MyEventEmitter')
37
+ const JwsSigning = require('./jws/JwsSigning')
38
+ const ConnectionProvider = require('./configuration-providers/mb-connection-manager')
39
+ const { TraceHeaderUtils } = require('@mojaloop/ml-testing-toolkit-shared-lib')
40
+ const UniqueIdGenerator = require('./uniqueIdGenerator')
41
+ const httpAgentStore = require('./httpAgentStore')
42
+
43
+ const handleCallback = async (callbackObject, context, req) => {
44
+ if (callbackObject.delay) {
45
+ await new Promise(resolve => setTimeout(resolve, callbackObject.delay))
46
+ }
47
+ const userConfig = await Config.getUserConfig(req.customInfo.user)
48
+ const uniqueId = UniqueIdGenerator.generateUniqueId(req)
49
+ let callbackEndpoint = userConfig.CALLBACK_ENDPOINT
50
+
51
+ const endpointsDfspWise = userConfig.ENDPOINTS_DFSP_WISE
52
+ if (userConfig.HUB_ONLY_MODE && callbackObject.callbackInfo && callbackObject.callbackInfo.fspid && endpointsDfspWise.dfsps[callbackObject.callbackInfo.fspid]) {
53
+ const dfspEndpoints = endpointsDfspWise.dfsps[callbackObject.callbackInfo.fspid]
54
+ const dfspEndpoint = dfspEndpoints.endpoints.find(endpoint => endpoint.method === callbackObject.method && endpoint.path && callbackObject.path && endpoint.endpoint)
55
+ if (dfspEndpoint) {
56
+ callbackEndpoint = dfspEndpoint.endpoint
57
+ } else {
58
+ callbackEndpoint = dfspEndpoints.defaultEndpoint
59
+ }
60
+ } else if (userConfig.CALLBACK_RESOURCE_ENDPOINTS && userConfig.CALLBACK_RESOURCE_ENDPOINTS.enabled) {
61
+ const callbackEndpoints = userConfig.CALLBACK_RESOURCE_ENDPOINTS
62
+ const matchedObject = callbackEndpoints.endpoints.find(item => {
63
+ if (item.method === callbackObject.method) {
64
+ const path = new RegExp(item.path.replace(/{.*}/, '.*'))
65
+ return path.test(callbackObject.path)
66
+ }
67
+ return false
68
+ })
69
+ if (matchedObject && matchedObject.endpoint) {
70
+ callbackEndpoint = matchedObject.endpoint
71
+ }
72
+ }
73
+
74
+ // Handle the host header for hub-only requests
75
+ if (userConfig.HUB_ONLY_MODE && callbackObject.headers && callbackObject.headers.host) {
76
+ delete callbackObject.headers.host
77
+ }
78
+
79
+ const httpAgentProps = {}
80
+ let urlGenerated = callbackEndpoint + callbackObject.path
81
+ if (Config.getSystemConfig().OUTBOUND_MUTUAL_TLS_ENABLED) {
82
+ const tlsConfig = await ConnectionProvider.getTlsConfig()
83
+ if (!tlsConfig.dfsps[callbackObject.callbackInfo.fspid]) {
84
+ const errorMsg = 'Outbound TLS is enabled, but there is no TLS config found for DFSP ID: ' + callbackObject.callbackInfo.fspid
85
+ customLogger.logMessage('error', errorMsg, { request: req, notification: false })
86
+ throw errorMsg
87
+ }
88
+ const httpsAgent = new https.Agent({
89
+ cert: tlsConfig.dfsps[callbackObject.callbackInfo.fspid].hubClientCert,
90
+ key: tlsConfig.hubClientKey,
91
+ ca: [tlsConfig.dfsps[callbackObject.callbackInfo.fspid].dfspServerCaRootCert],
92
+ rejectUnauthorized: true
93
+ })
94
+ httpsAgent.toJSON = () => ({})
95
+ httpAgentProps.httpsAgent = httpsAgent
96
+ urlGenerated = urlGenerated.replace('http:', 'https:')
97
+ } else if (userConfig.CLIENT_MUTUAL_TLS_ENABLED) {
98
+ const urlObject = new URL(urlGenerated)
99
+ const cred = userConfig.CLIENT_TLS_CREDS.filter(item => item.HOST === urlObject.host)
100
+ if (Array.isArray(cred) && cred.length === 1) {
101
+ customLogger.logMessage('info', `Found the Client certificate for ${urlObject.host}`, { request: req, notification: false })
102
+ httpAgentProps.httpsAgent = httpAgentStore.getHttpsAgent(urlObject.host, {
103
+ cert: cred[0].CERT,
104
+ key: cred[0].KEY,
105
+ rejectUnauthorized: false
106
+ })
107
+ urlGenerated = urlGenerated.replace('http:', 'https:')
108
+ } else {
109
+ const errorMsg = `client mutual TLS is enabled, but there is no TLS config found for ${urlObject.host}`
110
+ customLogger.logMessage('error', errorMsg, { request: req, notification: false })
111
+ }
112
+ } else {
113
+ if (urlGenerated.startsWith('https:')) {
114
+ httpAgentProps.httpsAgent = httpAgentStore.getHttpsAgent('generic', {
115
+ rejectUnauthorized: false
116
+ })
117
+ } else {
118
+ httpAgentProps.httpAgent = httpAgentStore.getHttpAgent('generic')
119
+ }
120
+ }
121
+
122
+ if (!callbackObject.headers) {
123
+ callbackObject.headers = {}
124
+ }
125
+ // Pass on the traceparent header if exists
126
+ if (req.headers && req.headers.traceparent) {
127
+ callbackObject.headers.traceparent = req.headers.traceparent
128
+ } else {
129
+ if (req.customInfo && req.customInfo.traceID) {
130
+ callbackObject.headers.traceparent = TraceHeaderUtils.getTraceParentHeader(req.customInfo.traceID)
131
+ }
132
+ }
133
+
134
+ const reqOpts = {
135
+ method: callbackObject.method,
136
+ url: urlGenerated,
137
+ path: callbackObject.path,
138
+ headers: {
139
+ ...callbackObject.headers
140
+ },
141
+ data: callbackObject.body,
142
+ customInfo: req.customInfo,
143
+ timeout: userConfig.DEFAULT_REQUEST_TIMEOUT || 3000,
144
+ ...httpAgentProps
145
+ }
146
+
147
+ // Remove content-length header
148
+ if (reqOpts.headers['Content-Length']) {
149
+ delete reqOpts.headers['Content-Length']
150
+ }
151
+ if (reqOpts.headers['content-length']) {
152
+ delete reqOpts.headers['content-length']
153
+ }
154
+
155
+ // JwsSigning
156
+ if (!userConfig.HUB_ONLY_MODE) {
157
+ try {
158
+ await JwsSigning.sign(reqOpts)
159
+ } catch (err) {
160
+ customLogger.logMessage('error', 'JWS signing failed', { additionalData: err })
161
+ }
162
+ }
163
+ // Validate callback against openapi
164
+ if (callbackObject.method !== 'put') {
165
+ const validationResult = await context.api.validateRequest(callbackObject)
166
+ if (validationResult.valid) {
167
+ customLogger.logMessage('info', 'Callback schema is valid ' + callbackObject.method + ' ' + callbackObject.path, { request: req })
168
+ } else {
169
+ customLogger.logMessage('error', 'Callback schema is invalid ' + callbackObject.method + ' ' + callbackObject.path, { additionalData: validationResult.errors, request: req })
170
+ }
171
+ }
172
+ // Store callbacks for assertion
173
+ let assertionPath = callbackObject.path
174
+ const assertionData = { headers: callbackObject.headers, body: callbackObject.body }
175
+ if (assertionPath.endsWith('/error')) {
176
+ assertionPath = assertionPath.replace('/error', '')
177
+ assertionData.error = true
178
+ }
179
+ objectStore.push('callbacks', assertionPath, assertionData)
180
+ MyEventEmitter.getEmitter('assertionCallback', req.customInfo.user).emit(assertionPath, assertionData)
181
+
182
+ // Store all the callbacks in callbacksHistory
183
+ arrayStore.push('callbacksHistory', { timestamp: Date.now(), url: urlGenerated, method: callbackObject.method, path: callbackObject.path, headers: callbackObject.headers, body: callbackObject.body })
184
+
185
+ // Send callback
186
+ if (userConfig.SEND_CALLBACK_ENABLE) {
187
+ customLogger.logOutboundRequest('info', 'Request: ' + reqOpts.method + ' ' + reqOpts.path, { additionalData: { request: reqOpts }, request: reqOpts, uniqueId })
188
+ customLogger.logMessage('info', 'Sending callback ' + callbackObject.method + ' ' + reqOpts.url, { additionalData: callbackObject, request: req })
189
+ axios(reqOpts).then((result) => {
190
+ customLogger.logOutboundRequest('info', 'Response: ' + reqOpts.method + ' ' + reqOpts.path, { additionalData: { response: result }, request: reqOpts, uniqueId })
191
+ customLogger.logMessage('info', 'Received callback response ' + result.status + ' ' + result.statusText, { request: req })
192
+ }, (err) => {
193
+ customLogger.logOutboundRequest('error', 'Response: ' + reqOpts.method + ' ' + reqOpts.path, { additionalData: err.response, request: reqOpts, uniqueId })
194
+ customLogger.logMessage('error', 'Failed to send callback ' + callbackObject.method + ' ' + reqOpts.url, { additionalData: { message: err.message, responseData: (err.response && err.response.data) ? err.response.data : {} }, request: req })
195
+ })
196
+ } else {
197
+ customLogger.logMessage('info', 'Log callback ' + callbackObject.method + ' ' + callbackObject.path, { additionalData: callbackObject, request: req })
198
+ }
199
+ }
200
+
201
+ module.exports.handleCallback = handleCallback
@@ -0,0 +1,177 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 Mojaloop Foundation
5
+ The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
10
+
11
+ Contributors
12
+ --------------
13
+ This is the official list of the Mojaloop project contributors for this file.
14
+ Names of the original copyright holders (individuals or organizations)
15
+ should be listed with a '*' in the first column. People who have
16
+ contributed from an organization can be listed under the organization
17
+ that actually holds the copyright for their contributions (see the
18
+ Mojaloop Foundation for an example). Those individuals should have
19
+ their names indented and be marked with a '-'. Email address can be added
20
+ optionally within square brackets <email>.
21
+
22
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Georgi Logodazhki <georgi.logodazhki@modusbox.com>
27
+ * Vijaya Kumar Guthi <vijaya.guthi@modusbox.com> (Original Author)
28
+ --------------
29
+ ******/
30
+
31
+ const storageAdapter = require('./storageAdapter')
32
+ const SYSTEM_CONFIG_FILE = 'spec_files/system_config.json'
33
+ const USER_CONFIG_FILE = 'spec_files/user_config.json'
34
+ const _ = require('lodash')
35
+
36
+ let SYSTEM_CONFIG = {}
37
+
38
+ const USER_CONFIG = {
39
+ data: undefined
40
+ }
41
+
42
+ const getSystemConfig = () => {
43
+ return SYSTEM_CONFIG
44
+ }
45
+
46
+ const getUserConfig = async (user) => {
47
+ const item = user ? user.dfspId : 'data'
48
+ if (!USER_CONFIG[item]) {
49
+ await loadUserConfig(user)
50
+ }
51
+ return USER_CONFIG[item]
52
+ }
53
+
54
+ const getStoredUserConfig = async (user) => {
55
+ try {
56
+ const storedConfig = await loadUserConfigDFSPWise(user)
57
+ return storedConfig
58
+ } catch (err) {
59
+ console.log(`Can not read the file ${USER_CONFIG_FILE}`, err)
60
+ return {}
61
+ }
62
+ }
63
+
64
+ const setStoredUserConfig = async (newConfig, user) => {
65
+ try {
66
+ await storageAdapter.upsert(USER_CONFIG_FILE, { ...getUserConfig(), ...newConfig }, user)
67
+ return true
68
+ } catch (err) {
69
+ return false
70
+ }
71
+ }
72
+
73
+ const loadUserConfig = async (user, filename = USER_CONFIG_FILE) => {
74
+ try {
75
+ USER_CONFIG[user ? user.dfspId : 'data'] = await loadUserConfigDFSPWise(user, filename)
76
+ } catch (err) {
77
+ console.log(`Can not read the file ${USER_CONFIG_FILE}`, err)
78
+ }
79
+ return true
80
+ }
81
+
82
+ const loadUserConfigDFSPWise = async (user, filename = USER_CONFIG_FILE) => {
83
+ const userConfig = await storageAdapter.read(filename, user)
84
+ return userConfig.data
85
+ }
86
+
87
+ const loadSystemConfig = async (filename = SYSTEM_CONFIG_FILE) => {
88
+ try {
89
+ SYSTEM_CONFIG = (await storageAdapter.read(filename)).data
90
+ const systemConfigFromEnvironment = _getSystemConfigFromEnvironment()
91
+ _.merge(SYSTEM_CONFIG, systemConfigFromEnvironment)
92
+ const secretsFromEnvironment = _getSecretsFromEnvironment()
93
+ console.log(secretsFromEnvironment)
94
+ _.merge(SYSTEM_CONFIG, secretsFromEnvironment)
95
+ } catch (err) {
96
+ console.log(`Can not read the file ${filename}`, err)
97
+ }
98
+ return true
99
+ }
100
+
101
+ const _getSecretsFromEnvironment = () => {
102
+ const secretsFromEnvironment = {}
103
+ if (process.env.REPORTING_DB_CONNECTION_PASSWORD || process.env.REPORTING_DB_CONNECTION_STRING) {
104
+ try {
105
+ const reportingDbConnectionPassword = process.env.REPORTING_DB_CONNECTION_PASSWORD
106
+ const reportingDbConnectionString = process.env.REPORTING_DB_CONNECTION_STRING
107
+ console.log(`Retrieved reporting database password in environment '${process.env.REPORTING_DB_CONNECTION_PASSWORD}'`)
108
+ console.log(`Retrieved reporting database connection string in environment '${process.env.REPORTING_DB_CONNECTION_STRING}'`)
109
+ secretsFromEnvironment.DB = {
110
+ PASSWORD: reportingDbConnectionPassword,
111
+ CONNECTION_STRING: reportingDbConnectionString
112
+ }
113
+ console.log(`Secrets retrieved from environment to be merged into system config ${secretsFromEnvironment}`)
114
+ } catch (err) {
115
+ console.log(err)
116
+ console.log('Failed to retrieve reporting database password or connection string in environment')
117
+ }
118
+ }
119
+ return secretsFromEnvironment
120
+ }
121
+
122
+ const _getSystemConfigFromEnvironment = () => {
123
+ let systemConfigFromEnvironment = {}
124
+ if (process.env.TTK_SYSTEM_CONFIG) {
125
+ try {
126
+ systemConfigFromEnvironment = JSON.parse(process.env.TTK_SYSTEM_CONFIG)
127
+ } catch (err) {
128
+ console.log(`Failed to parse system config passed in environment ${process.env.TTK_SYSTEM_CONFIG}`)
129
+ }
130
+ }
131
+ return systemConfigFromEnvironment
132
+ }
133
+
134
+ const setSystemConfig = async (newConfig) => {
135
+ try {
136
+ await storageAdapter.upsert(SYSTEM_CONFIG_FILE, { ...getSystemConfig(), ...newConfig })
137
+ await loadSystemConfig()
138
+ return true
139
+ } catch (err) {
140
+ return false
141
+ }
142
+ }
143
+
144
+ // const _getObjectStoreInitConfigFromEnvironment = () => {
145
+ // let objectStoreInitConfigFromEnvironment = {}
146
+ // if (process.env.TTK_OBJECT_STORE_INIT_CONFIG) {
147
+ // try {
148
+ // objectStoreInitConfigFromEnvironment = JSON.parse(process.env.TTK_OBJECT_STORE_INIT_CONFIG)
149
+ // } catch (err) {
150
+ // console.log(`Failed to parse objectStore init config passed in environment ${process.env.TTK_OBJECT_STORE_INIT_CONFIG}`)
151
+ // }
152
+ // }
153
+ // return objectStoreInitConfigFromEnvironment
154
+ // }
155
+
156
+ const _getObjectStoreInitConfigFromSystemConfig = () => {
157
+ let objectStoreInitConfigFromSystemConfig = {}
158
+ if (SYSTEM_CONFIG.INIT_CONFIG && SYSTEM_CONFIG.INIT_CONFIG.objectStore) {
159
+ objectStoreInitConfigFromSystemConfig = SYSTEM_CONFIG.INIT_CONFIG.objectStore
160
+ }
161
+ return objectStoreInitConfigFromSystemConfig
162
+ }
163
+
164
+ const getObjectStoreInitConfig = async () => {
165
+ return _getObjectStoreInitConfigFromSystemConfig()
166
+ }
167
+
168
+ module.exports = {
169
+ getUserConfig,
170
+ getStoredUserConfig,
171
+ setStoredUserConfig,
172
+ loadUserConfig,
173
+ getSystemConfig,
174
+ loadSystemConfig,
175
+ setSystemConfig,
176
+ getObjectStoreInitConfig
177
+ }