account-lookup-service 15.5.0-iso.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (209) hide show
  1. package/.circleci/config.yml +11 -0
  2. package/.ncurc.yaml +6 -0
  3. package/.nvmrc +1 -0
  4. package/.nycrc.yml +20 -0
  5. package/.versionrc +15 -0
  6. package/CHANGELOG.md +330 -0
  7. package/CODEOWNERS +38 -0
  8. package/Dockerfile +45 -0
  9. package/LICENSE.md +10 -0
  10. package/README.md +252 -0
  11. package/audit-ci.jsonc +32 -0
  12. package/audit-resolve.json +161 -0
  13. package/config/default.json +109 -0
  14. package/config/knexfile.js +21 -0
  15. package/docker/account-lookup-service/default.json +106 -0
  16. package/docker/account-lookup-service/make-default-json.sh +5 -0
  17. package/docker/account-lookup-service/override.json +15 -0
  18. package/docker/central-ledger/default.json +458 -0
  19. package/docker/config-modifier/account-lookup-service.js +31 -0
  20. package/docker/kafka/consumer.properties +26 -0
  21. package/docker/kafka/producer.properties +45 -0
  22. package/docker/kafka/server.properties +143 -0
  23. package/docker/kafka/tools-log4j.properties +21 -0
  24. package/docker/mock-proxy/Dockerfile +15 -0
  25. package/docker/mock-proxy/package-lock.json +4986 -0
  26. package/docker/mock-proxy/package.json +24 -0
  27. package/docker/mock-proxy/src/config.ts +14 -0
  28. package/docker/mock-proxy/src/server.ts +94 -0
  29. package/docker/mock-proxy/src/utils.ts +29 -0
  30. package/docker/mock-proxy/tsconfig.json +24 -0
  31. package/docker/sql-init/01_permissions.sql +2 -0
  32. package/docker/sql-init-central-ledger/01_permissions.sql +2 -0
  33. package/docker/wait-for/wait-for-account-lookup-service.sh +10 -0
  34. package/docker/wait-for/wait-for-central-ledger.sh +11 -0
  35. package/docker/wait-for/wait-for-kafka.sh +7 -0
  36. package/docker/wait-for/wait-for-ml-api-adapter.sh +9 -0
  37. package/docker/wait-for/wait-for-mockserver.sh +20 -0
  38. package/docker/wait-for/wait-for-mysql-als.sh +14 -0
  39. package/docker/wait-for/wait-for-mysql-central-ledger.sh +11 -0
  40. package/docker/wait-for/wait-for-mysql.sh +11 -0
  41. package/docker/wait-for/wait-for-objstore.sh +12 -0
  42. package/docker/wait-for/wait-for.env +18 -0
  43. package/docker/wait-for/wait-for.sh +81 -0
  44. package/docker-compose.integration.yml +29 -0
  45. package/docker-compose.yml +243 -0
  46. package/jest-int.config.js +8 -0
  47. package/jest.config.js +16 -0
  48. package/jsdoc.json +38 -0
  49. package/migrations/01_currency.js +42 -0
  50. package/migrations/02_endpointType.js +43 -0
  51. package/migrations/03_endpointType-indexes.js +37 -0
  52. package/migrations/04_partyIdType.js +43 -0
  53. package/migrations/05_partyIdType-indexes.js +38 -0
  54. package/migrations/08_oracleEndpoint.js +51 -0
  55. package/migrations/09_oracleEndpoint-indexes.js +41 -0
  56. package/migrations/10_oracleEndpoint-remove-constraints.js +38 -0
  57. package/package.json +180 -0
  58. package/scripts/_wait4_all.js +143 -0
  59. package/scripts/test-functional.sh +76 -0
  60. package/secrets/jwsSigningKey.key +27 -0
  61. package/seeds/currency.js +765 -0
  62. package/seeds/endpointType.js +65 -0
  63. package/seeds/partyIdType.js +79 -0
  64. package/src/api/endpointcache.js +67 -0
  65. package/src/api/health.js +66 -0
  66. package/src/api/index.js +85 -0
  67. package/src/api/oracles/{ID}.js +100 -0
  68. package/src/api/oracles.js +96 -0
  69. package/src/api/participants/{ID}/error.js +44 -0
  70. package/src/api/participants/{ID}.js +44 -0
  71. package/src/api/participants/{Type}/{ID}/error.js +74 -0
  72. package/src/api/participants/{Type}/{ID}/{SubId}/error.js +68 -0
  73. package/src/api/participants/{Type}/{ID}/{SubId}.js +113 -0
  74. package/src/api/participants/{Type}/{ID}.js +133 -0
  75. package/src/api/participants.js +63 -0
  76. package/src/api/parties/{Type}/{ID}/error.js +66 -0
  77. package/src/api/parties/{Type}/{ID}/{SubId}/error.js +56 -0
  78. package/src/api/parties/{Type}/{ID}/{SubId}.js +77 -0
  79. package/src/api/parties/{Type}/{ID}.js +98 -0
  80. package/src/api/routes.js +294 -0
  81. package/src/constants.js +16 -0
  82. package/src/domain/oracle/index.js +33 -0
  83. package/src/domain/oracle/oracle.js +234 -0
  84. package/src/domain/participants/index.js +35 -0
  85. package/src/domain/participants/participants.js +560 -0
  86. package/src/domain/parties/getPartiesByTypeAndID.js +239 -0
  87. package/src/domain/parties/index.js +32 -0
  88. package/src/domain/parties/parties.js +215 -0
  89. package/src/domain/parties/utils.js +84 -0
  90. package/src/domain/timeout/dto.js +48 -0
  91. package/src/domain/timeout/index.js +104 -0
  92. package/src/handlers/TimeoutHandler.js +94 -0
  93. package/src/handlers/index.js +70 -0
  94. package/src/handlers/monitoring/index.js +51 -0
  95. package/src/handlers/monitoring/plugins/health.js +61 -0
  96. package/src/handlers/monitoring/plugins/metrics.js +48 -0
  97. package/src/handlers/register.js +102 -0
  98. package/src/index.js +66 -0
  99. package/src/interface/admin-swagger.yaml +804 -0
  100. package/src/interface/admin_swagger.json +959 -0
  101. package/src/interface/api-swagger-iso20022-parties.yaml +1734 -0
  102. package/src/interface/api-swagger.yaml +1733 -0
  103. package/src/interface/api_swagger.json +3046 -0
  104. package/src/interface/fspiop-rest-v2.0-ISO20022_parties.yaml +2256 -0
  105. package/src/interface/thirdparty/admin-swagger.yaml +808 -0
  106. package/src/interface/thirdparty/admin_swagger.json +961 -0
  107. package/src/interface/thirdparty/api-swagger.yaml +1739 -0
  108. package/src/interface/thirdparty/api_swagger.json +3142 -0
  109. package/src/lib/argv.js +39 -0
  110. package/src/lib/cache.js +126 -0
  111. package/src/lib/config.js +183 -0
  112. package/src/lib/db.js +26 -0
  113. package/src/lib/headers.js +53 -0
  114. package/src/lib/healthCheck/subServiceHealth.js +84 -0
  115. package/src/lib/index.js +11 -0
  116. package/src/lib/migrator.js +17 -0
  117. package/src/lib/requestLogger.js +54 -0
  118. package/src/lib/util.js +66 -0
  119. package/src/metrics/handler.js +33 -0
  120. package/src/metrics/plugin.js +52 -0
  121. package/src/metrics/routes.js +43 -0
  122. package/src/models/currency/currency.js +48 -0
  123. package/src/models/currency/index.js +32 -0
  124. package/src/models/endpointType/endpointType.js +48 -0
  125. package/src/models/endpointType/index.js +32 -0
  126. package/src/models/misc/migrationLock.js +49 -0
  127. package/src/models/oracle/facade.js +341 -0
  128. package/src/models/oracle/index.js +41 -0
  129. package/src/models/oracle/oracleEndpoint.js +192 -0
  130. package/src/models/oracle/oracleEndpointCached.js +108 -0
  131. package/src/models/participantEndpoint/facade.js +238 -0
  132. package/src/models/partyIdType/index.js +32 -0
  133. package/src/models/partyIdType/partyIdType.js +41 -0
  134. package/src/plugins.js +139 -0
  135. package/src/server.js +199 -0
  136. package/test/fixtures/index.js +131 -0
  137. package/test/fixtures/iso.js +110 -0
  138. package/test/integration/.env +8 -0
  139. package/test/integration/api/parties.test.js +137 -0
  140. package/test/integration/constants.js +20 -0
  141. package/test/integration/domain/oracle/index.test.js +324 -0
  142. package/test/integration/domain/timeout/index.test.js +75 -0
  143. package/test/integration/env.sh +15 -0
  144. package/test/integration/example.test.js +12 -0
  145. package/test/integration/models/currency/currency.test.js +68 -0
  146. package/test/integration/plugins.test.js +62 -0
  147. package/test/integration/prepareTestParticipants.js +30 -0
  148. package/test/integration/setup.js +5 -0
  149. package/test/integration-config.json +81 -0
  150. package/test/integration-runner.sh +108 -0
  151. package/test/unit/api/health.test.js +142 -0
  152. package/test/unit/api/oracles/{ID}.test.js +264 -0
  153. package/test/unit/api/oracles.test.js +173 -0
  154. package/test/unit/api/participants/participants.test.js +117 -0
  155. package/test/unit/api/participants/{Type}/{ID}/error.test.js +155 -0
  156. package/test/unit/api/participants/{Type}/{ID}/{SubId}/error.test.js +131 -0
  157. package/test/unit/api/participants/{Type}/{ID}/{SubId}.test.js +377 -0
  158. package/test/unit/api/participants/{Type}/{ID}.test.js +383 -0
  159. package/test/unit/api/participants.test.js +108 -0
  160. package/test/unit/api/parties/endpointcache.test.js +83 -0
  161. package/test/unit/api/parties/parties.test.js +102 -0
  162. package/test/unit/api/parties/{Type}/{ID}/error.test.js +145 -0
  163. package/test/unit/api/parties/{Type}/{ID}/{SubId}/error.test.js +141 -0
  164. package/test/unit/api/parties/{Type}/{ID}/{SubId}.test.js +241 -0
  165. package/test/unit/api/parties/{Type}/{ID}.test.js +240 -0
  166. package/test/unit/domain/oracle/oracle.test.js +505 -0
  167. package/test/unit/domain/participants/participants.test.js +1724 -0
  168. package/test/unit/domain/parties/parties.test.js +940 -0
  169. package/test/unit/domain/timeout/dto.test.js +28 -0
  170. package/test/unit/domain/timeout/index.test.js +81 -0
  171. package/test/unit/handlers/TimeoutHandler.test.js +125 -0
  172. package/test/unit/handlers/index.test.js +56 -0
  173. package/test/unit/handlers/register.test.js +90 -0
  174. package/test/unit/index.test.js +139 -0
  175. package/test/unit/iso20022/partiesValidation.test.js +129 -0
  176. package/test/unit/lib/TransformFacades.test.js +18 -0
  177. package/test/unit/lib/argv.test.js +40 -0
  178. package/test/unit/lib/cache.test.js +172 -0
  179. package/test/unit/lib/config.test.js +108 -0
  180. package/test/unit/lib/healthCheck/subServiceHealth.test.js +89 -0
  181. package/test/unit/lib/migrator.test.js +52 -0
  182. package/test/unit/lib/requestLogger.test.js +115 -0
  183. package/test/unit/lib/util.test.js +68 -0
  184. package/test/unit/mocks.js +66 -0
  185. package/test/unit/models/currency/currency.test.js +91 -0
  186. package/test/unit/models/endpointType/endpointType.test.js +69 -0
  187. package/test/unit/models/misc/migrationLock.test.js +96 -0
  188. package/test/unit/models/oracle/facade.test.js +546 -0
  189. package/test/unit/models/oracle/oracleEndpoint.test.js +409 -0
  190. package/test/unit/models/oracle/oracleEndpointCached.test.js +153 -0
  191. package/test/unit/models/participantEndpoint/facade.test.js +295 -0
  192. package/test/unit/models/partyIdType/partyIdType.test.js +88 -0
  193. package/test/unit/plugins.test.js +89 -0
  194. package/test/unit/setup.js +7 -0
  195. package/test/util/apiClients/AlsApiClient.js +44 -0
  196. package/test/util/apiClients/BasicApiClient.js +34 -0
  197. package/test/util/apiClients/ProxyApiClient.js +25 -0
  198. package/test/util/apiClients/index.js +7 -0
  199. package/test/util/helper.js +332 -0
  200. package/test/util/index.js +11 -0
  201. package/test/util/mockgen.js +43 -0
  202. package/test/util/onboarding.js +132 -0
  203. package/test/util/scripts/addAlsDb.sh +33 -0
  204. package/test/util/scripts/configureMockServer.sh +35 -0
  205. package/test/util/scripts/env.sh +19 -0
  206. package/test/util/scripts/populateTestData.sh +62 -0
  207. package/test/util/scripts/startMockCentralServer.sh +45 -0
  208. package/test/util/scripts/startMockOracleServer.sh +45 -0
  209. package/test/util/testConfig.js +44 -0
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ###
4
+ # integration-runner.sh
5
+ #
6
+ # A basic integration test runner using docker-compose
7
+ ###
8
+
9
+ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
10
+
11
+ ##
12
+ # TEST_MODE
13
+ # Options:
14
+ # - default runs the tests as usual
15
+ # - wait sets up the docker-compose environment, but don't do anything (this allows for repeat tests)
16
+ # - rm same as default, but stops and removes docker-compose containers afterwards
17
+ ###
18
+ TEST_MODE="${TEST_MODE:-"default"}"
19
+
20
+
21
+ # Controls where Jest places test outputs inside of `als_account-lookup-service-int` container
22
+ JEST_JUNIT_OUTPUT_DIR="${JEST_JUNIT_OUTPUT_DIR:-"/tmp"}"
23
+ JEST_JUNIT_OUTPUT_NAME="${JEST_JUNIT_OUTPUT_NAME:-"junit.xml"}"
24
+
25
+ # Test output on host machine
26
+ RESULTS_DIR="${RESULTS_DIR:-"/tmp"}"
27
+
28
+ function startDocker() {
29
+ docker-compose \
30
+ -f ${DIR}/../docker-compose.yml \
31
+ -f ${DIR}/../docker-compose.integration.yml \
32
+ up -d
33
+ }
34
+
35
+ function waitForDocker() {
36
+ echo 'Waiting for docker services to be healthy'
37
+ HEALTHY_COUNT=$(docker ps | grep "healthy" | wc -l)
38
+ EXPECTED_HEALTHY_COUNT=5
39
+ EXPECTED_SERVICE_COUNT=6
40
+ while [ $(docker ps | grep "healthy" | wc -l) -lt $EXPECTED_HEALTHY_COUNT ]; do
41
+ TOTAL_SERVICES=$(docker ps | grep "als_*" | wc -l)
42
+ # exit early if we don't have the required services
43
+ if [ ${TOTAL_SERVICES} -lt ${EXPECTED_SERVICE_COUNT} ]; then
44
+ echo 'Not all docker-compose services are running. Check the logs and try again.'
45
+ exit 1
46
+ fi
47
+
48
+ echo "."
49
+ sleep 5
50
+ done
51
+ }
52
+
53
+ function runMigration() {
54
+ docker exec -it als_account-lookup-service sh -c "npm run migrate"
55
+ }
56
+
57
+ function runTests() {
58
+ docker exec -it als_account-lookup-service-int sh -c "JEST_JUNIT_OUTPUT_DIR=${JEST_JUNIT_OUTPUT_DIR} JEST_JUNIT_OUTPUT_NAME=${JEST_JUNIT_OUTPUT_NAME} npm run test:int"
59
+ }
60
+
61
+ function copyResults() {
62
+ echo "Copying results from: ${JEST_JUNIT_OUTPUT_DIR}/${JEST_JUNIT_OUTPUT_NAME} to: ${RESULTS_DIR}"
63
+ docker cp als_account-lookup-service-int:${JEST_JUNIT_OUTPUT_DIR}/${JEST_JUNIT_OUTPUT_NAME} ${RESULTS_DIR}
64
+ }
65
+
66
+ function tearDown() {
67
+ docker-compose \
68
+ -f ${DIR}/../docker-compose.yml \
69
+ -f ${DIR}/../docker-compose.integration.yml \
70
+ stop
71
+ docker-compose \
72
+ -f ${DIR}/../docker-compose.yml \
73
+ -f ${DIR}/../docker-compose.integration.yml \
74
+ down -v
75
+ docker-compose \
76
+ -f ${DIR}/../docker-compose.yml \
77
+ -f ${DIR}/../docker-compose.integration.yml \
78
+ rm -f
79
+ }
80
+
81
+ startDocker
82
+ waitForDocker
83
+ runMigration
84
+
85
+ case ${TEST_MODE} in
86
+ default)
87
+ runTests
88
+ EXIT_RESULT=$?
89
+ copyResults
90
+ exit ${EXIT_RESULT}
91
+ ;;
92
+
93
+ wait)
94
+ echo 'Running tests in `wait` mode'
95
+ ;;
96
+
97
+ rm)
98
+ runTests
99
+ EXIT_RESULT=$?
100
+ copyResults
101
+ tearDown
102
+ exit ${EXIT_RESULT}
103
+ ;;
104
+
105
+ *)
106
+ echo "Unsupported TEST_MODE: ${TEST_MODE}"
107
+ exit 1
108
+ esac
@@ -0,0 +1,142 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2017 Bill & Melinda Gates Foundation
5
+ The Mojaloop files are made available by the Bill & Melinda Gates 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
+ http://www.apache.org/licenses/LICENSE-2.0
7
+ 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.
8
+ Contributors
9
+ --------------
10
+ This is the official list of the Mojaloop project contributors for this file.
11
+ Names of the original copyright holders (individuals or organizations)
12
+ should be listed with a '*' in the first column. People who have
13
+ contributed from an organization can be listed under the organization
14
+ that actually holds the copyright for their contributions (see the
15
+ Gates Foundation organization for an example). Those individuals should have
16
+ their names indented and be marked with a '-'. Email address can be added
17
+ optionally within square brackets <email>.
18
+ * Gates Foundation
19
+ - Name Surname <name.surname@gatesfoundation.com>
20
+
21
+ * ModusBox
22
+ - Rajiv Mothilal <rajiv.mothilal@modusbox.com>
23
+ - Steven Oderayi <steven.oderayi@modusbox.com>
24
+
25
+ * Crosslake
26
+ - Lewis Daly <lewisd@crosslaketech.com>
27
+
28
+ --------------
29
+ ******/
30
+
31
+ 'use strict'
32
+
33
+ const Helper = require('../../util/helper')
34
+ const Db = require('../../../src/lib/db')
35
+ const initServer = require('../../../src/server').initializeApi
36
+ const getPort = require('get-port')
37
+ const Sinon = require('sinon')
38
+ const MigrationLockModel = require('../../../src/models/misc/migrationLock')
39
+ const Logger = require('@mojaloop/central-services-logger')
40
+ const Config = require('../../../src/lib/config')
41
+
42
+ Logger.isDebugEnabled = jest.fn(() => true)
43
+ Logger.isErrorEnabled = jest.fn(() => true)
44
+ Logger.isInfoEnabled = jest.fn(() => true)
45
+ let sandbox
46
+ let server
47
+
48
+ describe('/health', () => {
49
+ beforeEach(async () => {
50
+ Config.PROXY_CACHE_CONFIG.enabled = false
51
+ sandbox = Sinon.createSandbox()
52
+ sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
53
+ Config.API_PORT = await getPort()
54
+ server = await initServer(Config)
55
+ })
56
+
57
+ afterEach(async () => {
58
+ await server.stop()
59
+ sandbox.restore()
60
+ })
61
+
62
+ /**
63
+ * summary: Get Health
64
+ * description: The HTTP request GET /health is used to get the status of the server
65
+ * parameters: type, currency, accept, content-type, date
66
+ * produces: application/json
67
+ * responses: 200, 400, 401, 403, 404, 405, 406, 501, 503
68
+ */
69
+ it('GET /health', async () => {
70
+ // Arrange
71
+ sandbox.stub(MigrationLockModel, 'getIsMigrationLocked').returns(false)
72
+ const mock = await Helper.generateMockRequest('/health', 'get')
73
+
74
+ const options = {
75
+ method: 'get',
76
+ url: mock.request.path,
77
+ headers: Helper.defaultAdminHeaders()
78
+ }
79
+
80
+ // Act
81
+ const response = await server.inject(options)
82
+
83
+ // Assert
84
+ expect(response.statusCode).toBe(200)
85
+ const payload = JSON.parse(response.payload)
86
+ expect(payload.status).toBe('OK')
87
+ expect(payload.services.length).toBe(1)
88
+ expect(payload.services[0].name).toBe('datastore')
89
+ })
90
+
91
+ it('GET /health service unavailable', async () => {
92
+ // Arrange
93
+ sandbox.stub(MigrationLockModel, 'getIsMigrationLocked').returns(true)
94
+ const mock = await Helper.generateMockRequest('/health', 'get')
95
+
96
+ const options = {
97
+ method: 'get',
98
+ url: mock.request.path,
99
+ headers: Helper.defaultAdminHeaders()
100
+ }
101
+
102
+ // Act
103
+ const response = await server.inject(options)
104
+
105
+ // Assert
106
+ expect(response.statusCode).toBe(503)
107
+ const payload = JSON.parse(response.payload)
108
+ expect(payload.status).toBe('DOWN')
109
+ expect(payload.services.length).toBe(1)
110
+ expect(payload.services[0].name).toBe('datastore')
111
+ })
112
+
113
+ it('GET /health should include proxy health', async () => {
114
+ // Arrange
115
+ Config.PROXY_CACHE_CONFIG.enabled = true
116
+ Config.API_PORT = await getPort()
117
+ Config.proxyMap = { proxied: 'proxy' }
118
+ let serverWithProxy
119
+ try {
120
+ serverWithProxy = await initServer(Config)
121
+ sandbox.stub(MigrationLockModel, 'getIsMigrationLocked').resolves(false)
122
+ const mock = await Helper.generateMockRequest('/health', 'get')
123
+
124
+ const options = {
125
+ method: 'get',
126
+ url: mock.request.path,
127
+ headers: Helper.defaultAdminHeaders()
128
+ }
129
+
130
+ // Act
131
+ const response = await serverWithProxy.inject(options)
132
+
133
+ // Assert
134
+ const payload = JSON.parse(response.payload)
135
+ expect(response.statusCode).toBe(200)
136
+ expect(payload.services.length).toBe(2)
137
+ expect(payload.services[1].name).toBe('proxyCache')
138
+ } finally {
139
+ serverWithProxy && await serverWithProxy.stop()
140
+ }
141
+ })
142
+ })
@@ -0,0 +1,264 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2017 Bill & Melinda Gates Foundation
5
+ The Mojaloop files are made available by the Bill & Melinda Gates 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
+ http://www.apache.org/licenses/LICENSE-2.0
7
+ 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.
8
+ Contributors
9
+ --------------
10
+ This is the official list of the Mojaloop project contributors for this file.
11
+ Names of the original copyright holders (individuals or organizations)
12
+ should be listed with a '*' in the first column. People who have
13
+ contributed from an organization can be listed under the organization
14
+ that actually holds the copyright for their contributions (see the
15
+ Gates Foundation organization for an example). Those individuals should have
16
+ their names indented and be marked with a '-'. Email address can be added
17
+ optionally within square brackets <email>.
18
+ * Gates Foundation
19
+ - Name Surname <name.surname@gatesfoundation.com>
20
+
21
+ * ModusBox
22
+ - Rajiv Mothilal <rajiv.mothilal@modusbox.com>
23
+
24
+ * Crosslake
25
+ - Lewis Daly <lewisd@crosslaketech.com>
26
+
27
+ --------------
28
+ ******/
29
+
30
+ 'use strict'
31
+
32
+ const Mockgen = require('../../../util/mockgen.js')
33
+ const helper = require('../../../util/helper.js')
34
+ const Sinon = require('sinon')
35
+ const oracle = require('../../../../src/domain/oracle/index.js')
36
+ const initServer = require('../../../../src/server.js').initializeAdmin
37
+ const getPort = require('get-port')
38
+ const Db = require('../../../../src/lib/db.js')
39
+ const Migrator = require('../../../../src/lib/migrator.js')
40
+ const Logger = require('@mojaloop/central-services-logger')
41
+ const Config = require('../../../../src/lib/config.js')
42
+
43
+ Logger.isDebugEnabled = jest.fn(() => true)
44
+ Logger.isErrorEnabled = jest.fn(() => true)
45
+ Logger.isInfoEnabled = jest.fn(() => true)
46
+ let sandbox
47
+ let server
48
+
49
+ describe('/oracles/{ID} handler', () => {
50
+ beforeAll(async () => {
51
+ sandbox = Sinon.createSandbox()
52
+ sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
53
+ sandbox.stub(Migrator, 'migrate').returns(Promise.resolve({}))
54
+ Config.ADMIN_PORT = await getPort()
55
+ server = await initServer(Config)
56
+ })
57
+
58
+ afterAll(async () => {
59
+ await server.stop()
60
+ sandbox.restore()
61
+ })
62
+
63
+ /**
64
+ * summary: Update Oracle
65
+ * description: The HTTP request PUT /oracles/{ID} is used to update information in the server regarding the provided oracle. This request should be used for individual update of Oracle information.
66
+ * parameters: body, ID, content-length, content-type, date
67
+ * produces: application/json
68
+ * responses: 204, 400, 401, 403, 404, 405, 406, 501, 503
69
+ */
70
+ it('PUT /oracles/{ID}', async () => {
71
+ expect.hasAssertions()
72
+ // Arrange
73
+ const requests = new Promise((resolve, reject) => {
74
+ Mockgen(false).requests({
75
+ path: '/oracles/{ID}',
76
+ operation: 'put'
77
+ }, function (error, mock) {
78
+ return error ? reject(error) : resolve(mock)
79
+ })
80
+ })
81
+
82
+ const mock = await requests
83
+
84
+ /*
85
+ Get the resolved path from mock request
86
+ Mock request Path templates({}) are resolved using path parameters
87
+ */
88
+ const options = {
89
+ method: 'put',
90
+ url: mock.request.path,
91
+ headers: helper.defaultAdminHeaders()
92
+ }
93
+ if (mock.request.body) {
94
+ // Send the request body
95
+ options.payload = mock.request.body
96
+ } else if (mock.request.formData) {
97
+ // Send the request form data
98
+ options.payload = mock.request.formData
99
+ // Set the Content-Type as application/x-www-form-urlencoded
100
+ options.headers = options.headers || {}
101
+ options.headers = helper.defaultAdminHeaders()
102
+ }
103
+ // If headers are present, set the headers.
104
+ if (mock.request.headers && mock.request.headers.length > 0) {
105
+ options.headers = mock.request.headers
106
+ }
107
+ sandbox.stub(oracle, 'updateOracle').returns(Promise.resolve({}))
108
+
109
+ // Act
110
+ const response = await server.inject(options)
111
+
112
+ // Assert
113
+ expect(response.statusCode).toBe(204)
114
+ oracle.updateOracle.restore()
115
+ })
116
+
117
+ it('PUT /oracles/{ID} error', async () => {
118
+ expect.hasAssertions()
119
+ // Arrange
120
+ const requests = new Promise((resolve, reject) => {
121
+ Mockgen(false).requests({
122
+ path: '/oracles/{ID}',
123
+ operation: 'put'
124
+ }, function (error, mock) {
125
+ return error ? reject(error) : resolve(mock)
126
+ })
127
+ })
128
+
129
+ const mock = await requests
130
+
131
+ /*
132
+ Get the resolved path from mock request
133
+ Mock request Path templates({}) are resolved using path parameters
134
+ */
135
+ const options = {
136
+ method: 'put',
137
+ url: mock.request.path,
138
+ headers: helper.defaultAdminHeaders()
139
+ }
140
+ if (mock.request.body) {
141
+ // Send the request body
142
+ options.payload = mock.request.body
143
+ } else if (mock.request.formData) {
144
+ // Send the request form data
145
+ options.payload = mock.request.formData
146
+ // Set the Content-Type as application/x-www-form-urlencoded
147
+ options.headers = options.headers || {}
148
+ options.headers = helper.defaultAdminHeaders()
149
+ }
150
+ // If headers are present, set the headers.
151
+ if (mock.request.headers && mock.request.headers.length > 0) {
152
+ options.headers = mock.request.headers
153
+ }
154
+ sandbox.stub(oracle, 'updateOracle').throws()
155
+
156
+ // Act
157
+ const response = await server.inject(options)
158
+
159
+ // Assert
160
+ expect(response.statusCode).toBe(500)
161
+ oracle.updateOracle.restore()
162
+ })
163
+
164
+ /**
165
+ * summary: Delete Oracle
166
+ * description: The HTTP request DELETE /oracles/{ID} is used to delete information in the server regarding the provided oracle.
167
+ * parameters: accept, ID, content-type, date
168
+ * produces: application/json
169
+ * responses: 204, 400, 401, 403, 404, 405, 406, 501, 503
170
+ */
171
+ it('delete /oracles/{ID}', async () => {
172
+ expect.hasAssertions()
173
+ // Arrange
174
+ const requests = new Promise((resolve, reject) => {
175
+ Mockgen(false).requests({
176
+ path: '/oracles/{ID}',
177
+ operation: 'delete'
178
+ }, function (error, mock) {
179
+ return error ? reject(error) : resolve(mock)
180
+ })
181
+ })
182
+
183
+ const mock = await requests
184
+
185
+ /*
186
+ Get the resolved path from mock request
187
+ Mock request Path templates({}) are resolved using path parameters
188
+ */
189
+ const options = {
190
+ method: 'delete',
191
+ url: '' + mock.request.path,
192
+ headers: helper.defaultAdminHeaders()
193
+ }
194
+ if (mock.request.body) {
195
+ // Send the request body
196
+ options.payload = mock.request.body
197
+ } else if (mock.request.formData) {
198
+ // Send the request form data
199
+ options.payload = mock.request.formData
200
+ // Set the Content-Type as application/x-www-form-urlencoded
201
+ options.headers = options.headers || {}
202
+ options.headers = helper.defaultAdminHeaders()
203
+ }
204
+ // If headers are present, set the headers.
205
+ if (mock.request.headers && mock.request.headers.length > 0) {
206
+ options.headers = mock.request.headers
207
+ }
208
+ sandbox.stub(oracle, 'deleteOracle').returns(Promise.resolve({}))
209
+
210
+ // Act
211
+ const response = await server.inject(options)
212
+
213
+ // Assert
214
+ expect(response.statusCode).toBe(204)
215
+ oracle.deleteOracle.restore()
216
+ })
217
+
218
+ it('delete /oracles/{ID} error', async () => {
219
+ expect.hasAssertions()
220
+ // Arrange
221
+ const requests = new Promise((resolve, reject) => {
222
+ Mockgen(false).requests({
223
+ path: '/oracles/{ID}',
224
+ operation: 'delete'
225
+ }, function (error, mock) {
226
+ return error ? reject(error) : resolve(mock)
227
+ })
228
+ })
229
+
230
+ const mock = await requests
231
+
232
+ /*
233
+ Get the resolved path from mock request
234
+ Mock request Path templates({}) are resolved using path parameters
235
+ */
236
+ const options = {
237
+ method: 'delete',
238
+ url: '' + mock.request.path,
239
+ headers: helper.defaultAdminHeaders()
240
+ }
241
+ if (mock.request.body) {
242
+ // Send the request body
243
+ options.payload = mock.request.body
244
+ } else if (mock.request.formData) {
245
+ // Send the request form data
246
+ options.payload = mock.request.formData
247
+ // Set the Content-Type as application/x-www-form-urlencoded
248
+ options.headers = options.headers || {}
249
+ options.headers = helper.defaultAdminHeaders()
250
+ }
251
+ // If headers are present, set the headers.
252
+ if (mock.request.headers && mock.request.headers.length > 0) {
253
+ options.headers = mock.request.headers
254
+ }
255
+ sandbox.stub(oracle, 'deleteOracle').throws()
256
+
257
+ // Act
258
+ const response = await server.inject(options)
259
+
260
+ // Assert
261
+ expect(response.statusCode).toBe(500)
262
+ oracle.deleteOracle.restore()
263
+ })
264
+ })
@@ -0,0 +1,173 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2017 Bill & Melinda Gates Foundation
5
+ The Mojaloop files are made available by the Bill & Melinda Gates 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
+ http://www.apache.org/licenses/LICENSE-2.0
7
+ 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.
8
+ Contributors
9
+ --------------
10
+ This is the official list of the Mojaloop project contributors for this file.
11
+ Names of the original copyright holders (individuals or organizations)
12
+ should be listed with a '*' in the first column. People who have
13
+ contributed from an organization can be listed under the organization
14
+ that actually holds the copyright for their contributions (see the
15
+ Gates Foundation organization for an example). Those individuals should have
16
+ their names indented and be marked with a '-'. Email address can be added
17
+ optionally within square brackets <email>.
18
+ * Gates Foundation
19
+ - Name Surname <name.surname@gatesfoundation.com>
20
+
21
+ * ModusBox
22
+ - Rajiv Mothilal <rajiv.mothilal@modusbox.com>
23
+
24
+ * Crosslake
25
+ - Lewis Daly <lewisd@crosslaketech.com>
26
+
27
+ --------------
28
+ ******/
29
+
30
+ 'use strict'
31
+
32
+ const Sinon = require('sinon')
33
+ const getPort = require('get-port')
34
+ const Logger = require('@mojaloop/central-services-logger')
35
+ const oracle = require('../../../src/domain/oracle')
36
+ const Helper = require('../../util/helper')
37
+ const initServer = require('../../../src/server').initializeAdmin
38
+ const Db = require('../../../src/lib/db')
39
+ const Migrator = require('../../../src/lib/migrator')
40
+ const Config = require('../../../src/lib/config')
41
+
42
+ Logger.isDebugEnabled = jest.fn(() => true)
43
+ Logger.isErrorEnabled = jest.fn(() => true)
44
+ Logger.isInfoEnabled = jest.fn(() => true)
45
+
46
+ const getResponse = [{
47
+ oracleId: '1',
48
+ oracleIdType: 'MSISDN',
49
+ endpoint: {
50
+ value: 'http://localhost:8444',
51
+ endpointType: 'URL'
52
+ },
53
+ isDefault: true
54
+ }]
55
+
56
+ let sandbox
57
+ let server
58
+
59
+ describe('/oracles', () => {
60
+ beforeAll(async () => {
61
+ sandbox = Sinon.createSandbox()
62
+ sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
63
+ sandbox.stub(Migrator, 'migrate').returns(Promise.resolve({}))
64
+ Config.ADMIN_PORT = await getPort()
65
+ server = await initServer(Config)
66
+ })
67
+
68
+ afterAll(async () => {
69
+ await server.stop()
70
+ sandbox.restore()
71
+ })
72
+
73
+ /**
74
+ * summary: Get Oracles
75
+ * description: The HTTP request GET /oracles is used to return the list of all oracle endpoints. There are optional fields for type and currency i.e. /admin/oracles?type=MSISDN&amp;currency=USD which can be used to get more filtered results or a specific entry
76
+ * parameters: type, currency, accept, content-type, date
77
+ * produces: application/json
78
+ * responses: 200, 400, 401, 403, 404, 405, 406, 501, 503
79
+ */
80
+ it('GET /oracle', async () => {
81
+ // Arrange
82
+ const mock = await Helper.generateMockRequest('/oracles', 'get', false)
83
+
84
+ // Get the resolved path from mock request
85
+ // Mock request Path templates({}) are resolved using path parameters
86
+ const options = {
87
+ method: 'get',
88
+ url: mock.request.path,
89
+ headers: Helper.defaultAdminHeaders()
90
+ }
91
+ sandbox.stub(oracle, 'getOracle').returns(Promise.resolve(getResponse))
92
+
93
+ // Act
94
+ const response = await server.inject(options)
95
+
96
+ // Assert
97
+ expect(response.statusCode).toBe(200)
98
+ oracle.getOracle.restore()
99
+ })
100
+
101
+ it('GET /oracle throws on error', async () => {
102
+ // Arrange
103
+ const mock = await Helper.generateMockRequest('/oracles', 'get', false)
104
+
105
+ // Get the resolved path from mock request
106
+ // Mock request Path templates({}) are resolved using path parameters
107
+ const options = {
108
+ method: 'get',
109
+ url: mock.request.path,
110
+ headers: Helper.defaultAdminHeaders()
111
+ }
112
+ sandbox.stub(oracle, 'getOracle').throws(new Error('Error Thrown'))
113
+
114
+ // Act
115
+ const response = await server.inject(options)
116
+
117
+ // Assert
118
+ expect(response.statusCode).toBe(500)
119
+ oracle.getOracle.restore()
120
+ })
121
+
122
+ /**
123
+ * summary: Create Oracles
124
+ * description: The HTTP request POST /oracles is used to create information in the server regarding the provided oracles. This request should be used for creation of Oracle information.
125
+ * parameters: body, accept, content-length, content-type, date
126
+ * produces: application/json
127
+ * responses: 201, 400, 401, 403, 404, 405, 406, 501, 503
128
+ */
129
+ it('POST /oracle', async () => {
130
+ // Arrange
131
+ const mock = await Helper.generateMockRequest('/oracles', 'post', false)
132
+
133
+ // Get the resolved path from mock request
134
+ // Mock request Path templates({}) are resolved using path parameters
135
+ const options = {
136
+ method: 'post',
137
+ url: mock.request.path,
138
+ headers: Helper.defaultAdminHeaders(),
139
+ payload: mock.request.body
140
+ }
141
+
142
+ sandbox.stub(oracle, 'createOracle').returns(Promise.resolve({}))
143
+
144
+ // Act
145
+ const response = await server.inject(options)
146
+
147
+ // Assert
148
+ expect(response.statusCode).toBe(201)
149
+ oracle.createOracle.restore()
150
+ })
151
+
152
+ it('POST /oracle throws error', async () => {
153
+ // Arrange
154
+ const mock = await Helper.generateMockRequest('/oracles', 'post', false)
155
+
156
+ // Get the resolved path from mock request
157
+ // Mock request Path templates({}) are resolved using path parameters
158
+ const options = {
159
+ method: 'post',
160
+ url: mock.request.path,
161
+ headers: Helper.defaultAdminHeaders(),
162
+ payload: mock.request.body
163
+ }
164
+ sandbox.stub(oracle, 'createOracle').throws(new Error('Error Thrown'))
165
+
166
+ // Act
167
+ const response = await server.inject(options)
168
+
169
+ // Assert
170
+ expect(response.statusCode).toBe(500)
171
+ oracle.createOracle.restore()
172
+ })
173
+ })