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,383 @@
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 Sinon = require('sinon')
34
+ const getPort = require('get-port')
35
+ const ErrorHandler = require('@mojaloop/central-services-error-handling')
36
+ const Logger = require('@mojaloop/central-services-logger')
37
+ const requestUtil = require('@mojaloop/central-services-shared').Util.Request
38
+ const Enums = require('@mojaloop/central-services-shared').Enum
39
+ const Db = require('../../../../../src/lib/db')
40
+ const oracleEndpointCached = require('../../../../../src/models/oracle/oracleEndpointCached')
41
+ const participant = require('../../../../../src/models/participantEndpoint/facade')
42
+ const participants = require('../../../../../src/domain/participants')
43
+ const requestLogger = require('../../../../../src/lib/requestLogger')
44
+ const Helper = require('../../../../util/helper')
45
+ const initServer = require('../../../../../src/server').initializeApi
46
+ const Config = require('../../../../../src/lib/config')
47
+
48
+ Logger.isDebugEnabled = jest.fn(() => true)
49
+ Logger.isErrorEnabled = jest.fn(() => true)
50
+ Logger.isInfoEnabled = jest.fn(() => true)
51
+ let server
52
+ let sandbox
53
+
54
+ describe('/participants/{Type}/{ID}', () => {
55
+ beforeAll(async () => {
56
+ sandbox = Sinon.createSandbox()
57
+ sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
58
+ sandbox.stub(requestLogger, 'logRequest').returns({})
59
+ sandbox.stub(requestLogger, 'logResponse').returns({})
60
+ Config.API_PORT = await getPort()
61
+ server = await initServer(Config)
62
+ sandbox.stub(Logger)
63
+ Logger.error = sandbox.stub()
64
+ })
65
+
66
+ afterAll(async () => {
67
+ await server.stop()
68
+ sandbox.restore()
69
+ })
70
+
71
+ describe('GET /participants', () => {
72
+ it('returns 202 when getParticipantsByTypeAndID resolves', async () => {
73
+ // Arrange
74
+ const mock = await Helper.generateMockRequest('/participants/{Type}/{ID}', 'get')
75
+ const options = {
76
+ method: 'get',
77
+ url: mock.request.path,
78
+ headers: Helper.defaultSwitchHeaders
79
+ }
80
+ sandbox.stub(participants, 'getParticipantsByTypeAndID').resolves({})
81
+
82
+ // Act
83
+ const response = await server.inject(options)
84
+
85
+ // Assert
86
+ expect(response.statusCode).toBe(202)
87
+ expect(participants.getParticipantsByTypeAndID.callCount).toBe(1)
88
+ expect(participants.getParticipantsByTypeAndID.getCall(0).returnValue).resolves.toStrictEqual({})
89
+
90
+ // Cleanup
91
+ participants.getParticipantsByTypeAndID.restore()
92
+ })
93
+
94
+ it('getParticipantsByTypeAndID sends an async 3204 for invalid party id on response with status 400', async () => {
95
+ // Arrange
96
+ const mock = await Helper.generateMockRequest('/participants/{Type}/{ID}', 'get')
97
+ const options = {
98
+ method: 'get',
99
+ url: mock.request.path,
100
+ headers: Helper.defaultSwitchHeaders
101
+ }
102
+
103
+ const badRequestError = ErrorHandler.Factory.createFSPIOPError(
104
+ ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_COMMUNICATION_ERROR,
105
+ 'Failed to send HTTP request to host',
106
+ {},
107
+ {},
108
+ [{ key: 'status', value: 400 }]
109
+ )
110
+ const stubs = [
111
+ sandbox.stub(participant, 'sendErrorToParticipant').resolves({}),
112
+ sandbox.stub(participant, 'validateParticipant').resolves(true),
113
+ sandbox.stub(oracleEndpointCached, 'getOracleEndpointByType').resolves(['whatever']),
114
+ sandbox.stub(requestUtil, 'sendRequest').rejects(badRequestError)
115
+ ]
116
+ const response = await server.inject(options)
117
+ const errorCallStub = stubs[0]
118
+
119
+ // Assert
120
+ expect(errorCallStub.args[0][2].errorInformation.errorCode).toBe('3204')
121
+ expect(errorCallStub.args[0][1]).toBe(Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR)
122
+ expect(response.statusCode).toBe(202)
123
+
124
+ // Cleanup
125
+ stubs.forEach(s => s.restore())
126
+ })
127
+
128
+ // Added error 404 to cover a special case of the Mowali implementation
129
+ // which uses mojaloop/als-oracle-pathfinder and currently returns 404.
130
+ it('getParticipantsByTypeAndID sends an async 3201 for invalid party id on response with status 404', async () => {
131
+ // Arrange
132
+ const mock = await Helper.generateMockRequest('/participants/{Type}/{ID}', 'get')
133
+ const options = {
134
+ method: 'get',
135
+ url: mock.request.path,
136
+ headers: Helper.defaultSwitchHeaders
137
+ }
138
+
139
+ const badRequestError = ErrorHandler.Factory.createFSPIOPError(
140
+ ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_COMMUNICATION_ERROR,
141
+ 'Failed to send HTTP request to host',
142
+ {},
143
+ {},
144
+ [{ key: 'status', value: 404 }]
145
+ )
146
+ const stubs = [
147
+ sandbox.stub(participant, 'sendErrorToParticipant').resolves({}),
148
+ sandbox.stub(participant, 'validateParticipant').resolves(true),
149
+ sandbox.stub(oracleEndpointCached, 'getOracleEndpointByType').resolves(['whatever']),
150
+ sandbox.stub(requestUtil, 'sendRequest').rejects(badRequestError)
151
+ ]
152
+ const response = await server.inject(options)
153
+ const errorCallStub = stubs[0]
154
+
155
+ // Assert
156
+ expect(errorCallStub.args[0][2].errorInformation.errorCode).toBe('3201')
157
+ expect(errorCallStub.args[0][1]).toBe(Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR)
158
+ expect(response.statusCode).toBe(202)
159
+
160
+ // Cleanup
161
+ stubs.forEach(s => s.restore())
162
+ })
163
+
164
+ it('returns 202 when getParticipantsByTypeAndID rejects with an unknown error', async () => {
165
+ // Arrange
166
+ const mock = await Helper.generateMockRequest('/participants/{Type}/{ID}', 'get')
167
+ const options = {
168
+ method: 'get',
169
+ url: mock.request.path,
170
+ headers: Helper.defaultSwitchHeaders
171
+ }
172
+ const throwError = new Error('Unknown error')
173
+ sandbox.stub(participants, 'getParticipantsByTypeAndID').rejects(throwError)
174
+
175
+ // Act
176
+ const response = await server.inject(options)
177
+
178
+ // Assert
179
+ expect(response.statusCode).toBe(202)
180
+ expect(participants.getParticipantsByTypeAndID.callCount).toBe(1)
181
+ expect(participants.getParticipantsByTypeAndID.getCall(0).returnValue).rejects.toStrictEqual(throwError)
182
+
183
+ // Cleanup
184
+ participants.getParticipantsByTypeAndID.restore()
185
+ })
186
+ })
187
+
188
+ describe('POST /participants', () => {
189
+ it('returns 202 when postParticipants resolves', async () => {
190
+ // Arrange
191
+ const mock = await Helper.generateMockRequest('/participants/{Type}/{ID}', 'post')
192
+ const options = {
193
+ method: 'post',
194
+ url: mock.request.path,
195
+ headers: Helper.defaultSwitchHeaders,
196
+ payload: mock.request.body
197
+ }
198
+ sandbox.stub(participants, 'postParticipants').resolves({})
199
+
200
+ // Act
201
+ const response = await server.inject(options)
202
+
203
+ // Assert
204
+ expect(response.statusCode).toBe(202)
205
+ expect(participants.postParticipants.callCount).toBe(1)
206
+ expect(participants.postParticipants.getCall(0).returnValue).resolves.toStrictEqual({})
207
+
208
+ // Cleanup
209
+ participants.postParticipants.restore()
210
+ })
211
+
212
+ it('returns 202 when postParticipants rejects with an unknown error', async () => {
213
+ // Arrange
214
+ const mock = await Helper.generateMockRequest('/participants/{Type}/{ID}', 'post')
215
+ const options = {
216
+ method: 'post',
217
+ url: mock.request.path,
218
+ headers: Helper.defaultSwitchHeaders,
219
+ payload: mock.request.body
220
+ }
221
+ const throwError = new Error('Unknown error')
222
+ sandbox.stub(participants, 'postParticipants').rejects(throwError)
223
+
224
+ // Act
225
+ const response = await server.inject(options)
226
+
227
+ // Assert
228
+ expect(response.statusCode).toBe(202)
229
+ expect(participants.postParticipants.callCount).toBe(1)
230
+ expect(participants.postParticipants.getCall(0).returnValue).rejects.toStrictEqual(throwError)
231
+
232
+ // Cleanup
233
+ participants.postParticipants.restore()
234
+ })
235
+ })
236
+
237
+ describe('PUT /participants', () => {
238
+ it('returns 200 when putParticipantsByTypeAndID resolves', async () => {
239
+ // Arrange
240
+ const mock = await Helper.generateMockRequest('/participants/{Type}/{ID}', 'put')
241
+ const options = {
242
+ method: 'put',
243
+ url: mock.request.path,
244
+ headers: Helper.defaultSwitchHeaders,
245
+ payload: mock.request.body
246
+ }
247
+ sandbox.stub(participants, 'putParticipantsByTypeAndID').resolves({})
248
+
249
+ // Act
250
+ const response = await server.inject(options)
251
+
252
+ // Assert
253
+ expect(response.statusCode).toBe(200)
254
+ expect(participants.putParticipantsByTypeAndID.callCount).toBe(1)
255
+ expect(participants.putParticipantsByTypeAndID.getCall(0).returnValue).resolves.toStrictEqual({})
256
+
257
+ // Cleanup
258
+ participants.putParticipantsByTypeAndID.restore()
259
+ })
260
+
261
+ it('returns 200 when putParticipantsByTypeAndID rejects with an unknown error', async () => {
262
+ // Arrange
263
+ const mock = await Helper.generateMockRequest('/participants/{Type}/{ID}', 'put')
264
+ const options = {
265
+ method: 'put',
266
+ url: mock.request.path,
267
+ headers: Helper.defaultSwitchHeaders,
268
+ payload: mock.request.body
269
+ }
270
+ const throwError = new Error('Unknown error')
271
+ sandbox.stub(participants, 'putParticipantsByTypeAndID').rejects(throwError)
272
+
273
+ // Act
274
+ const response = await server.inject(options)
275
+
276
+ // Assert
277
+ expect(response.statusCode).toBe(200)
278
+ expect(participants.putParticipantsByTypeAndID.callCount).toBe(1)
279
+ expect(participants.putParticipantsByTypeAndID.getCall(0).returnValue).rejects.toStrictEqual(throwError)
280
+
281
+ // Cleanup
282
+ participants.putParticipantsByTypeAndID.restore()
283
+ })
284
+ })
285
+
286
+ describe('DELETE /participants', () => {
287
+ it('returns 202 when deleteParticipants resolves', async () => {
288
+ // Arrange
289
+ const mock = await Helper.generateMockRequest('/participants/{Type}/{ID}', 'delete')
290
+ const options = {
291
+ method: 'delete',
292
+ url: mock.request.path,
293
+ headers: Helper.defaultSwitchHeaders,
294
+ payload: mock.request.body
295
+ }
296
+ sandbox.stub(participants, 'deleteParticipants').resolves({})
297
+
298
+ // Act
299
+ const response = await server.inject(options)
300
+
301
+ // Assert
302
+ expect(response.statusCode).toBe(202)
303
+ expect(participants.deleteParticipants.callCount).toBe(1)
304
+ expect(participants.deleteParticipants.getCall(0).returnValue).resolves.toStrictEqual({})
305
+
306
+ // Cleanup
307
+ participants.deleteParticipants.restore()
308
+ })
309
+
310
+ it('returns 202 when deleteParticipants rejects with an unknown error', async () => {
311
+ // Arrange
312
+ const mock = await Helper.generateMockRequest('/participants/{Type}/{ID}', 'delete')
313
+ const options = {
314
+ method: 'delete',
315
+ url: mock.request.path,
316
+ headers: Helper.defaultSwitchHeaders,
317
+ payload: mock.request.body
318
+ }
319
+ const throwError = new Error('Unknown error')
320
+ sandbox.stub(participants, 'deleteParticipants').rejects(throwError)
321
+
322
+ // Act
323
+ const response = await server.inject(options)
324
+
325
+ // Assert
326
+ expect(response.statusCode).toBe(202)
327
+ expect(participants.deleteParticipants.callCount).toBe(1)
328
+ expect(participants.deleteParticipants.getCall(0).returnValue).rejects.toStrictEqual(throwError)
329
+
330
+ // Cleanup
331
+ participants.deleteParticipants.restore()
332
+ })
333
+ })
334
+
335
+ describe('PUT /error', () => {
336
+ it('returns 200 when putParticipantsErrorByTypeAndID resolves', async () => {
337
+ // Arrange
338
+ const mock = await Helper.generateMockRequest('/participants/{Type}/{ID}/error', 'put')
339
+ const options = {
340
+ method: 'put',
341
+ url: mock.request.path,
342
+ headers: Helper.defaultSwitchHeaders,
343
+ payload: mock.request.body
344
+ }
345
+ sandbox.stub(participants, 'putParticipantsErrorByTypeAndID').resolves({})
346
+
347
+ // Act
348
+ const response = await server.inject(options)
349
+
350
+ // Assert
351
+ expect(response.statusCode).toBe(200)
352
+ expect(participants.putParticipantsErrorByTypeAndID.callCount).toBe(1)
353
+ expect(participants.putParticipantsErrorByTypeAndID.getCall(0).returnValue).resolves.toStrictEqual({})
354
+
355
+ // Cleanup
356
+ participants.putParticipantsErrorByTypeAndID.restore()
357
+ })
358
+
359
+ it('returns 200 when putParticipantsErrorByTypeAndID rejects with an unknown error', async () => {
360
+ // Arrange
361
+ const mock = await Helper.generateMockRequest('/participants/{Type}/{ID}/error', 'put')
362
+ const options = {
363
+ method: 'put',
364
+ url: mock.request.path,
365
+ headers: Helper.defaultSwitchHeaders,
366
+ payload: mock.request.body
367
+ }
368
+ const throwError = new Error('Unknown error')
369
+ sandbox.stub(participants, 'putParticipantsErrorByTypeAndID').rejects(throwError)
370
+
371
+ // Act
372
+ const response = await server.inject(options)
373
+
374
+ // Assert
375
+ expect(response.statusCode).toBe(200)
376
+ expect(participants.putParticipantsErrorByTypeAndID.callCount).toBe(1)
377
+ expect(participants.putParticipantsErrorByTypeAndID.getCall(0).returnValue).rejects.toStrictEqual(throwError)
378
+
379
+ // Cleanup
380
+ participants.putParticipantsErrorByTypeAndID.restore()
381
+ })
382
+ })
383
+ })
@@ -0,0 +1,108 @@
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 initServer = require('../../../src/server').initializeApi
36
+ const Helper = require('../../util/helper')
37
+ const Db = require('../../../src/lib/db')
38
+ const Config = require('../../../src/lib/config')
39
+
40
+ Logger.isDebugEnabled = jest.fn(() => true)
41
+ Logger.isErrorEnabled = jest.fn(() => true)
42
+ Logger.isInfoEnabled = jest.fn(() => true)
43
+ let sandbox
44
+ let server
45
+
46
+ describe('/participants', () => {
47
+ beforeEach(async () => {
48
+ sandbox = Sinon.createSandbox()
49
+ sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
50
+ Config.API_PORT = await getPort()
51
+ server = await initServer(Config)
52
+ })
53
+
54
+ afterEach(async () => {
55
+ await server.stop()
56
+ sandbox.restore()
57
+ })
58
+
59
+ /**
60
+ * summary: Participants
61
+ * description: The HTTP request POST /participants is used to create information in the server regarding the provided list of identities. This request should be used for bulk creation of FSP information for more than one Party. The optional currency parameter should indicate that each provided Party supports the currency
62
+ * parameters: body, Accept, Content-Length, Content-Type, Date, X-Forwarded-For, FSPIOP-Source, FSPIOP-Destination, FSPIOP-Encryption, FSPIOP-Signature, FSPIOP-URI, FSPIOP-HTTP-Method
63
+ * produces: application/json
64
+ * responses: 202, 400, 401, 403, 404, 405, 406, 501, 503
65
+ */
66
+
67
+ it('POST /participants', async () => {
68
+ // Arrange
69
+ const mock = {
70
+ requestId: 'HNNnJ',
71
+ partyList: [{
72
+ partyIdType: 'LnlWooyQk',
73
+ partyIdentifier: 'MIYCVaNdsLD',
74
+ partySubIdOrType: 'GNYKQO',
75
+ fspId: 'ohidNUSaZRGCUViMhXOwyiPKq'
76
+ },
77
+ {
78
+ partyIdType: 'QGijB',
79
+ partyIdentifier: 'eEmRAczAyz',
80
+ partySubIdOrType: 'ki',
81
+ fspId: 'sYhkSmfUW'
82
+ },
83
+ {
84
+ partyIdType: 'nxRgD',
85
+ partyIdentifier: 'SNLwBJVZ',
86
+ partySubIdOrType: 'fBcEvS',
87
+ fspId: 'lgfJVXYOpsNfY'
88
+ }
89
+ ],
90
+ currency: 'EUR'
91
+ }
92
+ // Get the resolved path from mock request
93
+ // Mock request Path templates({}) are resolved using path parameters
94
+ const options = {
95
+ method: 'post',
96
+ url: '/participants',
97
+ headers: Helper.defaultAdminHeaders(),
98
+ payload: mock
99
+ }
100
+
101
+ // Act
102
+ const response = await server.inject(options)
103
+
104
+ // Assert
105
+ expect(response.statusCode).toBe(400)
106
+ await server.stop()
107
+ })
108
+ })
@@ -0,0 +1,83 @@
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
+ - Juan Correa <juan.correa@modusbox.com>
24
+
25
+ --------------
26
+ ******/
27
+
28
+ 'use strict'
29
+
30
+ const Sinon = require('sinon')
31
+ const getPort = require('get-port')
32
+ const Logger = require('@mojaloop/central-services-logger')
33
+
34
+ const { initializeApi } = require('../../../../src/server')
35
+ const Db = require('../../../../src/lib/db')
36
+ const MigrationLockModel = require('../../../../src/models/misc/migrationLock')
37
+ const Helper = require('../../../util/helper')
38
+ const Config = require('../../../../src/lib/config')
39
+
40
+ Logger.isDebugEnabled = jest.fn(() => true)
41
+ Logger.isErrorEnabled = jest.fn(() => true)
42
+ Logger.isInfoEnabled = jest.fn(() => true)
43
+ let sandbox
44
+ let server
45
+
46
+ describe('/endpointcache', () => {
47
+ beforeEach(async () => {
48
+ sandbox = Sinon.createSandbox()
49
+ sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
50
+ Config.API_PORT = await getPort()
51
+ server = await initializeApi(Config)
52
+ })
53
+
54
+ afterEach(async () => {
55
+ await server.stop()
56
+ sandbox.restore()
57
+ })
58
+
59
+ /**
60
+ * summary: DELETE endpointcache
61
+ * description: The HTTP request DELETE /endpointcache is used to reset the endpoint cache by performing an stopCache and initializeCache the Admin API.",
62
+ * parameters: date
63
+ * produces: application/json
64
+ * responses: 202, 400, 401, 403, 404, 405, 406, 501, 503
65
+ */
66
+ it('DELETE /endpointcache', async () => {
67
+ // Arrange
68
+ sandbox.stub(MigrationLockModel, 'getIsMigrationLocked').returns(false)
69
+ const mock = await Helper.generateMockRequest('/endpointcache', 'delete')
70
+
71
+ const options = {
72
+ method: 'delete',
73
+ url: mock.request.path,
74
+ headers: Helper.defaultAdminHeaders()
75
+ }
76
+
77
+ // Act
78
+ const response = await server.inject(options)
79
+
80
+ // Assert
81
+ expect(response.statusCode).toBe(202)
82
+ })
83
+ })
@@ -0,0 +1,102 @@
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 Db = require('../../../../src/lib/db')
34
+ const Helper = require('../../../util/helper')
35
+ const participants = require('../../../../src/domain/participants')
36
+ const initServer = require('../../../../src/server').initializeApi
37
+ const getPort = require('get-port')
38
+ const Logger = require('@mojaloop/central-services-logger')
39
+ const Config = require('../../../../src/lib/config')
40
+
41
+ Logger.isDebugEnabled = jest.fn(() => true)
42
+ Logger.isErrorEnabled = jest.fn(() => true)
43
+ Logger.isInfoEnabled = jest.fn(() => true)
44
+ let server
45
+ let sandbox
46
+
47
+ describe('/parties', () => {
48
+ beforeAll(async () => {
49
+ sandbox = Sinon.createSandbox()
50
+ sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
51
+ Config.API_PORT = await getPort()
52
+ server = await initServer(Config)
53
+ })
54
+
55
+ afterAll(async () => {
56
+ await server.stop()
57
+ sandbox.restore()
58
+ })
59
+
60
+ it('postParticipantsBatch returns 200', async () => {
61
+ // Arrange
62
+ const mock = {
63
+ requestId: 'f3c6a35e-dd36-4186-9363-ec5accf3338a',
64
+ partyList: [{
65
+ partyIdType: 'MSISDN',
66
+ partyIdentifier: 'MIYCVaNdsLD',
67
+ partySubIdOrType: 'GNYKQO',
68
+ fspId: 'ohidNUSaZRGCUViMhXOwyiPKq'
69
+ },
70
+ {
71
+ partyIdType: 'MSISDN',
72
+ partyIdentifier: 'eEmRAczAyz',
73
+ partySubIdOrType: 'ki',
74
+ fspId: 'sYhkSmfUW'
75
+ },
76
+ {
77
+ partyIdType: 'MSISDN',
78
+ partyIdentifier: 'SNLwBJVZ',
79
+ partySubIdOrType: 'fBcEvS',
80
+ fspId: 'lgfJVXYOpsNfY'
81
+ }
82
+ ],
83
+ currency: 'EUR'
84
+ }
85
+
86
+ const options = {
87
+ method: 'post',
88
+ url: '/participants',
89
+ headers: Helper.defaultSwitchHeaders,
90
+ payload: mock
91
+ }
92
+
93
+ sandbox.stub(participants, 'postParticipantsBatch').returns({})
94
+
95
+ // Act
96
+ const response = await server.inject(options)
97
+
98
+ // Assert
99
+ expect(response.statusCode).toBe(200)
100
+ participants.postParticipantsBatch.restore()
101
+ })
102
+ })