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.
- package/.dockerignore +10 -0
- package/.grype.yaml +16 -0
- package/.ncurc.yaml +9 -0
- package/.nvmrc +1 -0
- package/.versionrc.js +16 -0
- package/CHANGELOG.md +504 -0
- package/CODEOWNERS +30 -0
- package/Dockerfile +42 -0
- package/Dockerfile-newman +13 -0
- package/LICENSE.md +9 -0
- package/README.md +119 -0
- package/assets/diagrams/architectural/architectural-diagram.svg +3 -0
- package/assets/diagrams/flow/flow-diagram.svg +3 -0
- package/assets/images/Sample-Response-Failure.png +0 -0
- package/assets/images/Screenshot 2020-04-16 at 22.58.04.png +0 -0
- package/assets/images/TLS-Enabled-on-Environment.png +0 -0
- package/assets/images/adapter-mutual-tls-enabled.png +0 -0
- package/assets/images/add-additional-input-values.png +0 -0
- package/assets/images/add-condition-button.png +0 -0
- package/assets/images/add-new-assertion.png +0 -0
- package/assets/images/add-new-input-value.png +0 -0
- package/assets/images/add-new-input-variable.png +0 -0
- package/assets/images/additional-transfers.png +0 -0
- package/assets/images/api-provisioning-add-new-api-confirmation.png +0 -0
- package/assets/images/api-provisioning-file-input-window.png +0 -0
- package/assets/images/api-provisioning-list-apis-view.png +0 -0
- package/assets/images/api-provisioning-menu-item.png +0 -0
- package/assets/images/apply_and_restart.jpg +0 -0
- package/assets/images/assess-request-or-response.png +0 -0
- package/assets/images/assess-response-equation-save.png +0 -0
- package/assets/images/assess-response-equation.png +0 -0
- package/assets/images/assess-response-status.png +0 -0
- package/assets/images/building-new-rules-file.png +0 -0
- package/assets/images/callback-rules-screen.png +0 -0
- package/assets/images/configurable-parameter-assertion.png +0 -0
- package/assets/images/configurable-parameter-currency.png +0 -0
- package/assets/images/configurable-parameter.png +0 -0
- package/assets/images/connection-manager-ui-opening.png +0 -0
- package/assets/images/create-inbound-user-simulator.png +0 -0
- package/assets/images/creating-new-rule-file.png +0 -0
- package/assets/images/dfsp-client-cacert.png +0 -0
- package/assets/images/dfsp-client-submit.png +0 -0
- package/assets/images/dfsp-client.png +0 -0
- package/assets/images/dfsp-p2p-happy-path.png +0 -0
- package/assets/images/dfsp-server-cacert.png +0 -0
- package/assets/images/dfsp-server-cert.png +0 -0
- package/assets/images/download-report.png +0 -0
- package/assets/images/drive_have_not_been_shared.jpg +0 -0
- package/assets/images/event-response-options.png +0 -0
- package/assets/images/expand-monitoring-messages.png +0 -0
- package/assets/images/fixed-response-sample.png +0 -0
- package/assets/images/header-selection.png +0 -0
- package/assets/images/heap_error_windows.jpg +0 -0
- package/assets/images/hosted-mode-docker-compose-intro.png +0 -0
- package/assets/images/hub-client-cert.png +0 -0
- package/assets/images/import-template.png +0 -0
- package/assets/images/inbound-requests-environment.png +0 -0
- package/assets/images/inbound-requests-scripts.png +0 -0
- package/assets/images/jws-certificate-submit.png +0 -0
- package/assets/images/jws-certificate.png +0 -0
- package/assets/images/jws-certs-keys.png +0 -0
- package/assets/images/jws-hub-certs-keys.png +0 -0
- package/assets/images/local-enable-jws-publickey.png +0 -0
- package/assets/images/local-mutual-tls-enabled.png +0 -0
- package/assets/images/local_drives_to_be_available.jpg +0 -0
- package/assets/images/mcm-environment-opening.png +0 -0
- package/assets/images/menu-items.png +0 -0
- package/assets/images/mock-response-sample.png +0 -0
- package/assets/images/monitoring-initial-state.png +0 -0
- package/assets/images/monitoring-messages.png +0 -0
- package/assets/images/new-empty-assertion.png +0 -0
- package/assets/images/opened-imported-template.png +0 -0
- package/assets/images/opening-default-settings.png +0 -0
- package/assets/images/opening-sync-response-rules.png +0 -0
- package/assets/images/opening-view.png +0 -0
- package/assets/images/outbound-display-opening-hub.png +0 -0
- package/assets/images/outbound-display-opening.png +0 -0
- package/assets/images/override-with-environment-variable.png +0 -0
- package/assets/images/populate-with-sample-body.png +0 -0
- package/assets/images/resource-selection.png +0 -0
- package/assets/images/rule-builder-select-api.png +0 -0
- package/assets/images/sample-condition-add-configurable-params.png +0 -0
- package/assets/images/sample-condition.png +0 -0
- package/assets/images/sample-editor.png +0 -0
- package/assets/images/sample-request.png +0 -0
- package/assets/images/sample-test-assertion.png +0 -0
- package/assets/images/send-transfer.png +0 -0
- package/assets/images/sending-single-test-case-1.png +0 -0
- package/assets/images/sending-single-test-case-2.png +0 -0
- package/assets/images/sending-test-cases.png +0 -0
- package/assets/images/server-certificates-submitted.png +0 -0
- package/assets/images/simulator-response.png +0 -0
- package/assets/images/simulator-scheme-adapter-endpoint.png +0 -0
- package/assets/images/summarized-view-of-rule.png +0 -0
- package/assets/images/template-window.png +0 -0
- package/assets/images/test-case-editor-console-log.png +0 -0
- package/assets/images/test-case-editor-environment-state.png +0 -0
- package/assets/images/test-case-editor-scripts.png +0 -0
- package/assets/images/test-case-editor.png +0 -0
- package/assets/images/testcase-definition-download.png +0 -0
- package/assets/images/testcase-definition-edit-meta-info.png +0 -0
- package/assets/images/testing-toolkit-mojaloop-testing-toolkit-endpoint.png +0 -0
- package/assets/images/tls-hub-certs-keys.png +0 -0
- package/assets/images/tls-jws-enabled-on-environment.png +0 -0
- package/assets/images/updated-sample-body-data.png +0 -0
- package/assets/images/using-configurable-parameter.png +0 -0
- package/assets/images/validation-rules-screen.png +0 -0
- package/assets/images/view-response.png +0 -0
- package/audit-ci.jsonc +7 -0
- package/connection-manager/docker-compose.yml +55 -0
- package/database/docker-compose.yml +16 -0
- package/docker/hosted-mode/docker-compose.yaml +107 -0
- package/docker/hosted-mode/keycloak/keycloak-realm.json +2298 -0
- package/docker/hosted-mode/mongo-init.sh +1 -0
- package/docker/hosted-mode-tls/docker-compose.yaml +171 -0
- package/docker/hosted-mode-tls/keycloak/keycloak-realm.json +2298 -0
- package/docker/hosted-mode-tls/mongo-init.sh +1 -0
- package/docker-compose.yml +62 -0
- package/documents/Mojaloop-Testing-Toolkit.md +296 -0
- package/documents/RULES_ENGINE.md +403 -0
- package/documents/User-Guide-API-Provisioning.md +121 -0
- package/documents/User-Guide-CLI.md +218 -0
- package/documents/User-Guide-Connection-Manager.md +282 -0
- package/documents/User-Guide-Frequently-Asked-Questions.md +39 -0
- package/documents/User-Guide-Hosted-Mode-Docker-Compose.md +110 -0
- package/documents/User-Guide-Installation.md +163 -0
- package/documents/User-Guide-Mojaloop-Testing-Toolkit.md +642 -0
- package/documents/User-Guide-OAuth-Server-Deployment.md +283 -0
- package/documents/User-Guide-Onboarding-DFSP.md +197 -0
- package/documents/User-Guide-Onboarding-HUB.md +191 -0
- package/documents/User-Guide.md +53 -0
- package/examples/collections/dfsp/p2p_failed_tests.json +7161 -0
- package/examples/collections/dfsp/p2p_fx_happy_path.json +502 -0
- package/examples/collections/dfsp/p2p_happy_path.json +350 -0
- package/examples/collections/dfsp/p2p_happy_path_extended.json +6106 -0
- package/examples/collections/dfsp/p2p_happy_path_jws.json +511 -0
- package/examples/collections/dfsp/p2p_payee_assertions_websocket.json +441 -0
- package/examples/collections/dfsp/sample.json +5029 -0
- package/examples/collections/dfsp/transaction_request_service.json +240 -0
- package/examples/collections/fxp/FXP.json +264 -0
- package/examples/collections/fxp/SDK_backend.json +98 -0
- package/examples/collections/fxp/SDK_outbound.json +163 -0
- package/examples/collections/hub/hub_01_p2p_happy_path/hub_p2p_receive_quote.json +400 -0
- package/examples/collections/hub/hub_01_p2p_happy_path/hub_p2p_send_quote.json +395 -0
- package/examples/collections/hub/hub_02_block_transfer/hub_block_transfer.json +393 -0
- package/examples/collections/hub/hub_03_funds_in_out/hub_funds_in.json +224 -0
- package/examples/collections/hub/hub_03_funds_in_out/hub_funds_out.json +780 -0
- package/examples/collections/hub/hub_04_settlements/hub_settlements.json +3138 -0
- package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_payee_abort.json +475 -0
- package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_payee_invalid_fulfillment.json +370 -0
- package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_transfer_timeout.json +262 -0
- package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_authorizations.json +117 -0
- package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_error_framework.json +591 -0
- package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_received_state.json +379 -0
- package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_reject_state.json +361 -0
- package/examples/collections/hub/hub_07_quoting_service.json +525 -0
- package/examples/collections/hub/hub_08_participant_inactive_stop_transfers.json +706 -0
- package/examples/collections/hub/hub_09_duplicate_handling_transfers.json +1377 -0
- package/examples/collections/hub/hub_10_on_us_transfers.json +245 -0
- package/examples/collections/hub/hub_11_accented_and_spl_chars.json +629 -0
- package/examples/collections/hub/hub_12_fspiop_version_1.1.json +646 -0
- package/examples/collections/hub/hub_13_bulk_transfers.json +1857 -0
- package/examples/collections/iso20022/self_referencing_iso20022.json +926 -0
- package/examples/collections/provisioning/testingtoolkitdfsp.json +904 -0
- package/examples/environments/dfsp_local_environment.json +46 -0
- package/examples/environments/hub_local_environment.json +57 -0
- package/jest.config.js +17 -0
- package/package.json +199 -0
- package/sbom-v18.12.4.csv +1553 -0
- package/secrets/keygen.sh +5 -0
- package/secrets/privatekey.pem +27 -0
- package/secrets/publickey.cer +21 -0
- package/secrets/tls/01.pem +132 -0
- package/secrets/tls/createSecrets.sh +20 -0
- package/secrets/tls/hub_client.csr +32 -0
- package/secrets/tls/hub_client_cacert.pem +35 -0
- package/secrets/tls/hub_client_cakey.pem +52 -0
- package/secrets/tls/hub_client_key.key +52 -0
- package/secrets/tls/hub_server.csr +31 -0
- package/secrets/tls/hub_server_cacert.pem +35 -0
- package/secrets/tls/hub_server_cakey.pem +52 -0
- package/secrets/tls/hub_server_cert.pem +132 -0
- package/secrets/tls/hub_server_key.key +52 -0
- package/secrets/tls/index.txt +1 -0
- package/secrets/tls/index.txt.attr +1 -0
- package/secrets/tls/openssl-client.cnf +36 -0
- package/secrets/tls/openssl-clientca.cnf +71 -0
- package/secrets/tls/openssl-server.cnf +39 -0
- package/secrets/tls/openssl-serverca.cnf +71 -0
- package/secrets/tls/serial.txt +1 -0
- package/spec_files/api_definitions/als_admin_1.1/api_spec.yaml +804 -0
- package/spec_files/api_definitions/central_admin_1.0/api_spec.yaml +1850 -0
- package/spec_files/api_definitions/central_admin_1.0/response_map.json +96 -0
- package/spec_files/api_definitions/central_admin_old_9.3/api_spec.yaml +2467 -0
- package/spec_files/api_definitions/central_admin_old_9.3/response_map.json +96 -0
- package/spec_files/api_definitions/fspiop_1.0/api_spec.yaml +4187 -0
- package/spec_files/api_definitions/fspiop_1.0/callback_map.json +568 -0
- package/spec_files/api_definitions/fspiop_1.0/mockRef.json +79 -0
- package/spec_files/api_definitions/fspiop_1.0/trigger_templates/transaction_request_followup.json +126 -0
- package/spec_files/api_definitions/fspiop_1.0/trigger_templates/transaction_request_followup_quotes_only.json +97 -0
- package/spec_files/api_definitions/fspiop_1.1/api_spec.yaml +3778 -0
- package/spec_files/api_definitions/fspiop_1.1/callback_map.json +568 -0
- package/spec_files/api_definitions/fspiop_1.1/mockRef.json +79 -0
- package/spec_files/api_definitions/fspiop_1.1/trigger_templates/transaction_request_followup.json +125 -0
- package/spec_files/api_definitions/fspiop_2.0/api_spec.yaml +4839 -0
- package/spec_files/api_definitions/fspiop_2.0/callback_map.json +716 -0
- package/spec_files/api_definitions/fspiop_2.0/mockRef.json +79 -0
- package/spec_files/api_definitions/fspiop_2.0/trigger_templates/transaction_request_followup.json +125 -0
- package/spec_files/api_definitions/fspiop_2.0_iso20022/api_spec.yaml +8331 -0
- package/spec_files/api_definitions/fspiop_2.0_iso20022/callback_map.json +508 -0
- package/spec_files/api_definitions/fspiop_2.0_iso20022/mockRef.json +66 -0
- package/spec_files/api_definitions/fx-api_2.0/api_spec.yaml +1768 -0
- package/spec_files/api_definitions/fx-api_2.0/callback_map.json +188 -0
- package/spec_files/api_definitions/fx-api_2.0/mockRef.json +83 -0
- package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/api_spec.yaml +2612 -0
- package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/mockRef.json +22 -0
- package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/response_map.json +35 -0
- package/spec_files/api_definitions/mojaloop_simulator_0.1/api_spec.yaml +225 -0
- package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/api_spec.yaml +1087 -0
- package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/mockRef.json +75 -0
- package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/response_map.json +55 -0
- package/spec_files/api_definitions/payment_manager_1.4/api_spec.yaml +1389 -0
- package/spec_files/api_definitions/sdk-scheme-adapter-backend-v2_1_0-openapi3-snippets_2.1/api_spec.yaml +2834 -0
- package/spec_files/api_definitions/sdk-scheme-adapter-outbound-v2_1_0-openapi3-snippets_2.1/api_spec.yaml +3449 -0
- package/spec_files/api_definitions/settlements_1.0/api_spec.yaml +983 -0
- package/spec_files/api_definitions/settlements_1.0/mockRef.json +38 -0
- package/spec_files/api_definitions/settlements_1.0/response_map.json +34 -0
- package/spec_files/api_definitions/settlements_2.0/api_spec.yaml +1001 -0
- package/spec_files/api_definitions/settlements_2.0/mockRef.json +38 -0
- package/spec_files/api_definitions/settlements_2.0/response_map.json +34 -0
- package/spec_files/api_definitions/thirdparty_sdk_outbound_0.1/api_spec.yaml +2139 -0
- package/spec_files/reports/templates/newman/html_template.html +1202 -0
- package/spec_files/reports/templates/newman/pdf_template.html +790 -0
- package/spec_files/reports/templates/testcase_definition/table_view.html +1602 -0
- package/spec_files/rules_callback/config.json +3 -0
- package/spec_files/rules_callback/default.json +2698 -0
- package/spec_files/rules_callback/p2p-limit.json +129 -0
- package/spec_files/rules_forward/config.json +3 -0
- package/spec_files/rules_forward/default.json +482 -0
- package/spec_files/rules_response/config.json +3 -0
- package/spec_files/rules_response/default.json +295 -0
- package/spec_files/rules_validation/config.json +3 -0
- package/spec_files/rules_validation/default.json +1 -0
- package/spec_files/rules_validation/p2p-limit.json +55 -0
- package/spec_files/system_config.json +175 -0
- package/spec_files/user_config.json +109 -0
- package/src/index.js +67 -0
- package/src/lib/MyEventEmitter.js +54 -0
- package/src/lib/api-management.js +143 -0
- package/src/lib/api-routes/config.js +83 -0
- package/src/lib/api-routes/history.js +139 -0
- package/src/lib/api-routes/keycloak.js +54 -0
- package/src/lib/api-routes/longpolling.js +70 -0
- package/src/lib/api-routes/oauth2.js +149 -0
- package/src/lib/api-routes/objectstore.js +53 -0
- package/src/lib/api-routes/openapi.js +224 -0
- package/src/lib/api-routes/outbound.js +134 -0
- package/src/lib/api-routes/reports.js +72 -0
- package/src/lib/api-routes/rules.js +356 -0
- package/src/lib/api-routes/samples.js +92 -0
- package/src/lib/api-routes/server-logs.js +44 -0
- package/src/lib/api-routes/settings.js +71 -0
- package/src/lib/api-server.js +135 -0
- package/src/lib/arrayStore.js +101 -0
- package/src/lib/callbackHandler.js +201 -0
- package/src/lib/config.js +177 -0
- package/src/lib/configuration-providers/mb-connection-manager.js +625 -0
- package/src/lib/db/adapters/dbAdapter.js +184 -0
- package/src/lib/db/dfspMockUsers.js +64 -0
- package/src/lib/db/models/mongoDBWrapper.js +78 -0
- package/src/lib/eventListenerClient/inboundEventListener.js +176 -0
- package/src/lib/fileAdapter.js +57 -0
- package/src/lib/httpAgentStore.js +135 -0
- package/src/lib/importExport.js +186 -0
- package/src/lib/jws/JwsSigning.js +141 -0
- package/src/lib/loadSamples.js +128 -0
- package/src/lib/logger.js +20 -0
- package/src/lib/longpollingEmitter.js +56 -0
- package/src/lib/metrics.js +51 -0
- package/src/lib/mocking/custom-functions/generic.js +57 -0
- package/src/lib/mocking/middleware-functions/ilpModel.js +238 -0
- package/src/lib/mocking/middleware-functions/quotesAssociation.js +75 -0
- package/src/lib/mocking/middleware-functions/transactionRequestsService.js +78 -0
- package/src/lib/mocking/openApiDefinitionsModel.js +64 -0
- package/src/lib/mocking/openApiMockHandler.js +466 -0
- package/src/lib/mocking/openApiRulesEngine.js +492 -0
- package/src/lib/mocking/openApiVersionTools.js +136 -0
- package/src/lib/mocking/transformers/fspiopToISO20022.js +230 -0
- package/src/lib/mocking/transformers/index.js +41 -0
- package/src/lib/notificationEmitter.js +64 -0
- package/src/lib/oauth/KeycloakHelper.js +220 -0
- package/src/lib/oauth/LoginService.js +133 -0
- package/src/lib/oauth/OAuthHelper.js +181 -0
- package/src/lib/oauth/OAuthValidator.js +118 -0
- package/src/lib/oauth/Wso2Client.js +64 -0
- package/src/lib/objectStore/inMemoryImpl.js +50 -0
- package/src/lib/objectStore/objectStoreInterface.js +51 -0
- package/src/lib/objectStore.js +122 -0
- package/src/lib/report-generator/generator.js +126 -0
- package/src/lib/report-generator/helpers.js +154 -0
- package/src/lib/requestLogger.js +190 -0
- package/src/lib/resources/wso2carbon-publickey.cert +20 -0
- package/src/lib/rulesEngine.js +95 -0
- package/src/lib/rulesEngineModel.js +463 -0
- package/src/lib/scripting-engines/postman-sandbox.js +142 -0
- package/src/lib/scripting-engines/vm-javascript-sandbox.js +294 -0
- package/src/lib/server-logs/adapters/elastic-search.js +102 -0
- package/src/lib/server-logs/adapters/grafana.js +0 -0
- package/src/lib/server-logs/index.js +75 -0
- package/src/lib/socket-server.js +55 -0
- package/src/lib/storageAdapter.js +109 -0
- package/src/lib/test-outbound/TestCaseRunner.js +173 -0
- package/src/lib/test-outbound/getTracing.js +19 -0
- package/src/lib/test-outbound/outbound-initiator.js +1107 -0
- package/src/lib/uniqueIdGenerator.js +35 -0
- package/src/lib/utils.js +89 -0
- package/src/lib/utilsInternal.js +56 -0
- package/src/lib/webSocketClient/WebSocketClientManager.js +197 -0
- 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
|
+
}
|