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,295 @@
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
+ - Shashikant Hirugade <shashikant.hirugade@modusbox.com>
21
+
22
+ * Crosslake
23
+ - Lewis Daly <lewisd@crosslaketech.com>
24
+
25
+ --------------
26
+ ******/
27
+
28
+ 'use strict'
29
+
30
+ const mockHubName = require('../../../util/testConfig').HUB_NAME
31
+
32
+ const mockGetEndpoint = jest.fn()
33
+ const mockGetParticipant = jest.fn()
34
+ const mockSendRequest = jest.fn()
35
+ const mockEnums = {
36
+ Http: {
37
+ Headers: { FSPIOP: { DESTINATION: 'fsp1', SOURCE: 'fsp2', SWITCH: { value: mockHubName } } },
38
+ RestMethods: { PUT: 'PUT' },
39
+ ResponseTypes: { JSON: 'json' },
40
+ HeaderResources: { PARTICIPANTS: 'value' }
41
+ },
42
+ EndPoints: { FspEndpointTemplates: { PARTICIPANTS_GET: '/{{fsp}}/' } }
43
+ }
44
+
45
+ const src = '../../../../src'
46
+
47
+ jest.mock('@mojaloop/central-services-shared', () => ({
48
+ Util: {
49
+ Endpoints: { getEndpoint: mockGetEndpoint },
50
+ Participants: { getParticipant: mockGetParticipant },
51
+ Request: { sendRequest: mockSendRequest },
52
+ Http: { SwitchDefaultHeaders: jest.fn() },
53
+ HeaderValidation: { getHubNameRegex: jest.fn().mockReturnValue(new RegExp(mockHubName)) }
54
+ },
55
+ Enum: mockEnums
56
+ }))
57
+
58
+ const Logger = require('@mojaloop/central-services-logger')
59
+ const fixtures = require('../../../fixtures')
60
+
61
+ Logger.isDebugEnabled = jest.fn(() => true)
62
+ Logger.isErrorEnabled = jest.fn(() => true)
63
+ Logger.isInfoEnabled = jest.fn(() => true)
64
+
65
+ describe('participantEndpoint Facade', () => {
66
+ afterEach(() => {
67
+ jest.resetModules()
68
+ jest.clearAllMocks()
69
+ jest.unmock('@mojaloop/sdk-standard-components')
70
+ })
71
+
72
+ describe('sendRequest', () => {
73
+ it('sends the most basic request', async () => {
74
+ // Arrange
75
+ const mockedConfig = {
76
+ JWS_SIGN: false,
77
+ FSPIOP_SOURCE_TO_SIGN: mockHubName,
78
+ PROTOCOL_VERSIONS: fixtures.protocolVersionsDto()
79
+ }
80
+
81
+ jest.mock('../../../../src/lib/config', () => (mockedConfig))
82
+
83
+ mockGetEndpoint.mockImplementation(() => 'https://example.com/12345')
84
+ mockSendRequest.mockImplementation(() => Promise.resolve(true))
85
+ const ParticipantFacade = require(`${src}/models/participantEndpoint/facade`)
86
+
87
+ const headers = {}
88
+ const requestedParticipant = {}
89
+ const endpointType = 'URL'
90
+
91
+ // Act
92
+ const result = await ParticipantFacade.sendRequest(headers, requestedParticipant, endpointType)
93
+
94
+ // Assert
95
+ expect(result).toBe(true)
96
+ expect(mockSendRequest.mock.calls[0][0].protocolVersions).toMatchObject({
97
+ accept: mockedConfig.PROTOCOL_VERSIONS.ACCEPT.DEFAULT,
98
+ content: mockedConfig.PROTOCOL_VERSIONS.CONTENT.DEFAULT
99
+ })
100
+ })
101
+
102
+ it('fails to send the request', async () => {
103
+ // Arrange
104
+ const mockedConfig = {
105
+ JWS_SIGN: false,
106
+ FSPIOP_SOURCE_TO_SIGN: mockHubName,
107
+ PROTOCOL_VERSIONS: {
108
+ CONTENT: {
109
+ DEFAULT: '2.1',
110
+ VALIDATELIST: [
111
+ '2.1'
112
+ ]
113
+ },
114
+ ACCEPT: {
115
+ DEFAULT: '2',
116
+ VALIDATELIST: [
117
+ '2',
118
+ '2.1'
119
+ ]
120
+ }
121
+ }
122
+ }
123
+
124
+ jest.mock('../../../../src/lib/config', () => (mockedConfig))
125
+
126
+ mockGetEndpoint.mockImplementation(() => 'https://example.com/12345')
127
+ mockSendRequest.mockImplementation(() => { throw new Error('Request failed') })
128
+ const ParticipantFacade = require(`${src}/models/participantEndpoint/facade`)
129
+
130
+ const headers = {}
131
+ const requestedParticipant = {}
132
+ const endpointType = 'URL'
133
+
134
+ // Act
135
+ const action = async () => ParticipantFacade.sendRequest(headers, requestedParticipant, endpointType)
136
+
137
+ // Assert
138
+ await expect(action()).rejects.toThrow('Request failed')
139
+ expect(mockSendRequest.mock.calls[0][0].protocolVersions).toMatchObject({
140
+ accept: mockedConfig.PROTOCOL_VERSIONS.ACCEPT.DEFAULT,
141
+ content: mockedConfig.PROTOCOL_VERSIONS.CONTENT.DEFAULT
142
+ })
143
+ })
144
+
145
+ it('should define jwsSigner and add fspiop-signature header', async () => {
146
+ jest.mock('../../../../src/lib/config', () => ({
147
+ JWS_SIGN: true,
148
+ FSPIOP_SOURCE_TO_SIGN: mockHubName,
149
+ JWS_SIGNING_KEY_PATH: 'secrets/jwsSigningKey.key',
150
+ JWS_SIGNING_KEY: 'somekey',
151
+ PROTOCOL_VERSIONS: {
152
+ CONTENT: { DEFAULT: '2' },
153
+ ACCEPT: { DEFAULT: '2' }
154
+ }
155
+ }))
156
+ jest.mock('@mojaloop/sdk-standard-components') // to mock JwsSigner.getSignature()
157
+
158
+ mockSendRequest.mockImplementation(async (args) =>/* Util.Request.sendRequest */(args))
159
+ mockGetEndpoint.mockImplementation(() => 'https://example.com/parties/MSISDN12345')
160
+ const participantFacade = require(`${src}/models/participantEndpoint/facade`)
161
+
162
+ const participantName = 'fsp1'
163
+ const headers = {
164
+ [mockEnums.Http.Headers.FSPIOP.DESTINATION]: participantName,
165
+ [mockEnums.Http.Headers.FSPIOP.SOURCE]: mockHubName,
166
+ 'fspiop-source': mockHubName
167
+ }
168
+ const endpointType = 'URL'
169
+ const method = 'PUT'
170
+ const payload = {}
171
+ await participantFacade.sendRequest(headers, participantName, endpointType, method, payload)
172
+
173
+ expect(mockSendRequest.mock.lastCall[0].jwsSigner).toBeTruthy()
174
+ })
175
+ })
176
+
177
+ describe('validateParticipant', () => {
178
+ it('fails to validate the participant', async () => {
179
+ // Arrange
180
+ mockGetParticipant.mockImplementation(() => { throw new Error('Validate Request failed') })
181
+ const fspId = 'fsp1'
182
+ const ParticipantFacade = require(`${src}/models/participantEndpoint/facade`)
183
+
184
+ // Act
185
+ const action = async () => ParticipantFacade.validateParticipant(fspId)
186
+
187
+ // Assert
188
+ await expect(action()).rejects.toThrow('Validate Request failed')
189
+ })
190
+ })
191
+
192
+ describe('sendErrorToParticipant', () => {
193
+ const mockConfigDto = ({ jwsSign = false } = {}) => ({
194
+ JWS_SIGN: jwsSign,
195
+ FSPIOP_SOURCE_TO_SIGN: mockHubName,
196
+ JWS_SIGNING_KEY_PATH: 'secrets/jwsSigningKey.key',
197
+ JWS_SIGNING_KEY: 'somekey',
198
+ PROTOCOL_VERSIONS: fixtures.protocolVersionsDto()
199
+ })
200
+
201
+ it('throws an error when the request fails', async () => {
202
+ // Arrange
203
+ jest.mock('../../../../src/lib/config', () => mockConfigDto())
204
+
205
+ mockGetEndpoint.mockImplementation(() => 'https://example.com/12345')
206
+ mockSendRequest.mockImplementation(() => { throw new Error('Request failed') })
207
+
208
+ const ParticipantFacade = require(`${src}/models/participantEndpoint/facade`)
209
+
210
+ const participantName = 'fsp1'
211
+ const endpointType = 'URL'
212
+ const errorInformation = {
213
+ message: 'Test error message'
214
+ }
215
+ const headers = {}
216
+ const params = {}
217
+ const payload = { requestId: '1234-5678' }
218
+
219
+ // Act
220
+ const action = async () => ParticipantFacade.sendErrorToParticipant(participantName, endpointType, errorInformation, headers, params, payload)
221
+ // Assert
222
+ await expect(action()).rejects.toThrow('Request failed')
223
+ })
224
+
225
+ it('Success without JWS', async () => {
226
+ // Arrange
227
+ const mockedConfig = mockConfigDto()
228
+ jest.mock('../../../../src/lib/config', () => mockedConfig)
229
+
230
+ mockGetEndpoint.mockImplementation(() => 'https://example.com/12345')
231
+ mockSendRequest.mockImplementation(() => Promise.resolve(true))
232
+
233
+ const ParticipantFacade = require(`${src}/models/participantEndpoint/facade`)
234
+ const spy = jest.spyOn(ParticipantFacade, 'sendErrorToParticipant')
235
+
236
+ const participantName = 'fsp1'
237
+ const endpointType = 'URL'
238
+ const errorInformation = {
239
+ message: 'Test error message'
240
+ }
241
+ const headers = {}
242
+ const params = {}
243
+ const payload = { requestId: '1234-5678' }
244
+
245
+ // Act
246
+ const action = async () => ParticipantFacade.sendErrorToParticipant(participantName, endpointType, errorInformation, headers, params, payload)
247
+ await action()
248
+
249
+ // Assert
250
+ expect(spy).toHaveBeenCalled()
251
+ const { jwsSigner, protocolVersions } = mockSendRequest.mock.calls[0][0]
252
+ expect(jwsSigner).toBe(null)
253
+ expect(protocolVersions).toMatchObject({
254
+ accept: mockedConfig.PROTOCOL_VERSIONS.ACCEPT.DEFAULT,
255
+ content: mockedConfig.PROTOCOL_VERSIONS.CONTENT.DEFAULT
256
+ })
257
+ spy.mockRestore()
258
+ })
259
+
260
+ it('adds jws signature when enabled', async () => {
261
+ // Arrange
262
+ const mockedConfig = mockConfigDto({ jwsSign: true })
263
+ jest.mock('../../../../src/lib/config', () => mockedConfig)
264
+
265
+ mockGetEndpoint.mockImplementation(() => 'https://example.com/parties/MSISDN12345')
266
+ mockSendRequest.mockImplementation(() => Promise.resolve(true))
267
+
268
+ const ParticipantFacade = require(`${src}/models/participantEndpoint/facade`)
269
+ const spy = jest.spyOn(ParticipantFacade, 'sendErrorToParticipant')
270
+
271
+ const participantName = 'fsp1'
272
+ const endpointType = 'URL'
273
+ const errorInformation = {
274
+ message: 'Test error message'
275
+ }
276
+ const headers = {}
277
+ headers[mockEnums.Http.Headers.FSPIOP.DESTINATION] = 'fsp1'
278
+ headers[mockEnums.Http.Headers.FSPIOP.SOURCE] = mockHubName
279
+
280
+ // Act
281
+ const action = async () => ParticipantFacade.sendErrorToParticipant(participantName, endpointType, errorInformation, headers)
282
+ await action()
283
+
284
+ // Assert
285
+ expect(spy).toHaveBeenCalled()
286
+ const { jwsSigner, protocolVersions } = mockSendRequest.mock.calls[0][0]
287
+ expect(jwsSigner).toBeTruthy()
288
+ expect(protocolVersions).toMatchObject({
289
+ accept: mockedConfig.PROTOCOL_VERSIONS.ACCEPT.DEFAULT,
290
+ content: mockedConfig.PROTOCOL_VERSIONS.CONTENT.DEFAULT
291
+ })
292
+ spy.mockRestore()
293
+ })
294
+ })
295
+ })
@@ -0,0 +1,88 @@
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
+
34
+ const { getPartyIdTypeByName } = require('../../../../src/models/partyIdType/partyIdType')
35
+ const Db = require('../../../../src/lib/db')
36
+ const Logger = require('@mojaloop/central-services-logger')
37
+
38
+ Logger.isDebugEnabled = jest.fn(() => true)
39
+ Logger.isErrorEnabled = jest.fn(() => true)
40
+ Logger.isInfoEnabled = jest.fn(() => true)
41
+
42
+ describe('partyIdType Model', () => {
43
+ let sandbox
44
+
45
+ beforeEach(() => {
46
+ sandbox = Sinon.createSandbox()
47
+ Db.from = (table) => {
48
+ return Db[table]
49
+ }
50
+ })
51
+
52
+ afterEach(() => {
53
+ sandbox.restore()
54
+ })
55
+
56
+ it('Gets the partyIdType by name', async () => {
57
+ // Arrange
58
+ const partyIdType = {
59
+ partyIdTypeId: 1,
60
+ name: 'MSISDN',
61
+ description: 'A MSISDN (Mobile Station International Subscriber Directory Number, that is, the phone number)',
62
+ isActive: true,
63
+ createdDate: '2019-05-24 08:52:19'
64
+ }
65
+ Db.partyIdType = {
66
+ findOne: sandbox.stub().resolves(partyIdType)
67
+ }
68
+
69
+ // Act
70
+ const response = await getPartyIdTypeByName('MSISDN')
71
+
72
+ // Assert
73
+ expect(response).toEqual(partyIdType)
74
+ })
75
+
76
+ it('throws an error if Db call fails', async () => {
77
+ // Arrange
78
+ Db.partyIdType = {
79
+ findOne: sandbox.stub().throws(new Error('Error finding partyIdType'))
80
+ }
81
+
82
+ // Act
83
+ const action = async () => getPartyIdTypeByName('MSISDN')
84
+
85
+ // Assert
86
+ await expect(action()).rejects.toThrowError(/Error finding partyIdType/)
87
+ })
88
+ })
@@ -0,0 +1,89 @@
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
+ const Path = require('path')
31
+ const Sinon = require('sinon')
32
+ const OpenapiBackend = require('@mojaloop/central-services-shared').Util.OpenapiBackend
33
+
34
+ const { registerPlugins } = require('../../src/plugins')
35
+ const Config = require('../../src/lib/config')
36
+ const Handlers = require('../../src/api')
37
+
38
+ let sandbox
39
+
40
+ describe('Plugin Tests', () => {
41
+ beforeEach(() => {
42
+ sandbox = Sinon.createSandbox()
43
+ })
44
+
45
+ afterEach(() => {
46
+ sandbox.restore()
47
+ })
48
+
49
+ it('should change the title based on the API_PORT', async () => {
50
+ // Arrange
51
+ const server = {
52
+ register: sandbox.spy(),
53
+ info: {
54
+ port: '8000'
55
+ }
56
+ }
57
+ const api = await OpenapiBackend.initialise(Path.resolve(__dirname, '../../src/interface/api-swagger.yaml'), Handlers.ApiHandlers)
58
+
59
+ sandbox.mock(Config)
60
+ Config.API_PORT = '8000'
61
+
62
+ // Act
63
+ await registerPlugins(server, api)
64
+
65
+ // Assert
66
+ expect(server.register.callCount).toBe(10)
67
+ const firstCallArgs = server.register.getCall(1).args
68
+ expect(firstCallArgs[0].options.document.info.title.includes('Open API for FSP Interoperability (FSPIOP) (Implementation Friendly Version)')).toBe(true)
69
+ })
70
+
71
+ it('should not register Blipp if DISPLAY_ROUTES is false', async () => {
72
+ // Arrange
73
+ const server = {
74
+ register: sandbox.spy(),
75
+ info: {
76
+ port: '8000'
77
+ }
78
+ }
79
+ const api = await OpenapiBackend.initialise(Path.resolve(__dirname, '../../src/interface/api-swagger.yaml'), Handlers.ApiHandlers)
80
+ sandbox.mock(Config)
81
+ Config.DISPLAY_ROUTES = false
82
+
83
+ // Act
84
+ await registerPlugins(server, api)
85
+
86
+ // Assert
87
+ expect(server.register.callCount).toBe(9)
88
+ })
89
+ })
@@ -0,0 +1,7 @@
1
+ const { MockIoRedis } = require('./mocks')
2
+ jest.mock('ioredis', () => MockIoRedis)
3
+
4
+ Object.assign(process.env, {
5
+ LOG_LEVEL: 'debug'
6
+ // override any other env vars needed for unit-tests
7
+ })
@@ -0,0 +1,44 @@
1
+ const config = require('../../../src/lib/config')
2
+ const BasicApiClient = require('./BasicApiClient')
3
+
4
+ const baseURL = `http://localhost:${config.API_PORT}`
5
+
6
+ class AlsProxyApiClient extends BasicApiClient {
7
+ constructor (deps) {
8
+ super({ ...deps, baseURL })
9
+ }
10
+
11
+ async getPartyByIdAndType ({ partyId, partyIdType, source, destination, proxy = '' }) {
12
+ return this.sendPartyRequest({
13
+ partyId, partyIdType, source, destination, proxy
14
+ })
15
+ }
16
+
17
+ async putPartiesSuccess ({ partyId, partyIdType, source, destination, proxy = '', body = {} }) {
18
+ return this.sendPartyRequest({
19
+ partyId, partyIdType, source, destination, proxy, body
20
+ })
21
+ }
22
+
23
+ async putPartiesError ({ partyId, partyIdType, source, destination, proxy = '', body = {} }) {
24
+ const isError = true
25
+ return this.sendPartyRequest({
26
+ partyId, partyIdType, source, destination, proxy, body, isError
27
+ })
28
+ }
29
+
30
+ async sendPartyRequest ({ partyId, partyIdType, source, destination, proxy = '', body = null, isError = false }) {
31
+ const method = body ? 'PUT' : 'GET'
32
+ const url = `/parties/${partyIdType}/${partyId}${isError ? '/error' : ''}`
33
+ const headers = this.fixtures.partiesCallHeadersDto({ source, destination, proxy })
34
+
35
+ return this.sendRequest({
36
+ method,
37
+ url,
38
+ headers,
39
+ body
40
+ })
41
+ }
42
+ }
43
+
44
+ module.exports = AlsProxyApiClient
@@ -0,0 +1,34 @@
1
+ const axiosLib = require('axios')
2
+ const { loggerFactory } = require('../../../src/lib')
3
+ const fixtures = require('../../fixtures')
4
+
5
+ class BasicApiClient {
6
+ constructor ({
7
+ baseURL,
8
+ axios = axiosLib.create({ baseURL }),
9
+ logger = loggerFactory(this.constructor.name)
10
+ } = {}) {
11
+ this.baseURL = baseURL
12
+ this.axios = axios
13
+ this.logger = logger
14
+ this.fixtures = fixtures
15
+ }
16
+
17
+ async sendRequest ({ url, method = 'GET', headers = {}, body = null }) {
18
+ try {
19
+ const { data, status } = await this.axios.request({
20
+ method,
21
+ url,
22
+ headers,
23
+ data: body
24
+ })
25
+ this.logger.info('sendRequest is done:', { method, url, body, headers, response: { status, data } })
26
+ return { data, status }
27
+ } catch (err) {
28
+ this.logger.error('error in sendRequest: ', err)
29
+ throw err
30
+ }
31
+ }
32
+ }
33
+
34
+ module.exports = BasicApiClient
@@ -0,0 +1,25 @@
1
+ const { PROXY_PORT } = require('../../integration/constants')
2
+ const BasicApiClient = require('./BasicApiClient')
3
+
4
+ const baseURL = `http://localhost:${PROXY_PORT}`
5
+
6
+ class ProxyApiClient extends BasicApiClient {
7
+ constructor (deps) {
8
+ super({ ...deps, baseURL })
9
+ }
10
+
11
+ async getHistory () {
12
+ const { data } = await this.sendRequest({ url: '/history' })
13
+ return data.history
14
+ }
15
+
16
+ async deleteHistory () {
17
+ const { data } = await this.sendRequest({
18
+ url: '/history',
19
+ method: 'DELETE'
20
+ })
21
+ return data.history
22
+ }
23
+ }
24
+
25
+ module.exports = ProxyApiClient
@@ -0,0 +1,7 @@
1
+ const AlsApiClient = require('./AlsApiClient')
2
+ const ProxyApiClient = require('./ProxyApiClient')
3
+
4
+ module.exports = {
5
+ AlsApiClient,
6
+ ProxyApiClient
7
+ }