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,145 @@
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
+ * Crosslake
22
+ - Lewis Daly <lewisd@crosslaketech.com>
23
+
24
+ --------------
25
+ ******/
26
+
27
+ 'use strict'
28
+
29
+ const Sinon = require('sinon')
30
+ const getPort = require('get-port')
31
+
32
+ const src = '../../../../../../src'
33
+
34
+ const initServer = require(`${src}/server`).initializeApi
35
+ const Db = require(`${src}/lib/db`)
36
+ const parties = require(`${src}/domain/parties`)
37
+ const ErrHandler = require(`${src}/api/parties/{Type}/{ID}/error`)
38
+ const Helper = require('../../../../../util/helper')
39
+ const LibUtil = require(`${src}/lib/util`)
40
+ const Logger = require('@mojaloop/central-services-logger')
41
+ const Config = require(`${src}/lib/config`)
42
+
43
+ Logger.isDebugEnabled = jest.fn(() => true)
44
+ Logger.isErrorEnabled = jest.fn(() => true)
45
+ Logger.isInfoEnabled = jest.fn(() => true)
46
+ let server
47
+ let sandbox
48
+ const mockContext = jest.fn()
49
+
50
+ describe('/parties/{Type}/{ID}/error', () => {
51
+ beforeAll(async () => {
52
+ sandbox = Sinon.createSandbox()
53
+ sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
54
+ Config.API_PORT = await getPort()
55
+ server = await initServer(Config)
56
+ sandbox.stub(LibUtil, 'getSpanTags').returns({})
57
+ })
58
+
59
+ afterAll(async () => {
60
+ await server.stop()
61
+ sandbox.restore()
62
+ })
63
+
64
+ it('handles PUT /error', async () => {
65
+ // Arrange
66
+ const codeStub = sandbox.stub()
67
+ const handler = {
68
+ response: sandbox.stub().returns({
69
+ code: codeStub
70
+ })
71
+ }
72
+
73
+ const mock = await Helper.generateMockRequest('/parties/{Type}/{ID}/error', 'put')
74
+ const setTagsStub = sandbox.stub().returns({})
75
+
76
+ mock.request = {
77
+ log: sandbox.stub(),
78
+ server: {
79
+ log: sandbox.stub(),
80
+ app: {}
81
+ },
82
+ span: {
83
+ setTags: setTagsStub,
84
+ audit: sandbox.stub().returns(Promise.resolve({}))
85
+ }
86
+ }
87
+
88
+ sandbox.stub(parties, 'putPartiesErrorByTypeAndID').resolves({})
89
+
90
+ // Act
91
+ await ErrHandler.put(mockContext, mock.request, handler)
92
+
93
+ // Assert
94
+ expect(codeStub.calledWith(200)).toBe(true)
95
+ expect(setTagsStub.calledWith({})).toBe(true)
96
+ expect(setTagsStub.calledOnce).toBe(true)
97
+ expect(parties.putPartiesErrorByTypeAndID.callCount).toBe(1)
98
+ expect(parties.putPartiesErrorByTypeAndID.getCall(0).returnValue).resolves.toStrictEqual({})
99
+ expect(mock.request.server.log.callCount).toEqual(0)
100
+
101
+ // Cleanup
102
+ parties.putPartiesErrorByTypeAndID.restore()
103
+ })
104
+
105
+ it('handles error when putPartiesErrorByTypeAndID fails', async () => {
106
+ // Arrange
107
+ const codeStub = sandbox.stub()
108
+ const handler = {
109
+ response: sandbox.stub().returns({
110
+ code: codeStub
111
+ })
112
+ }
113
+
114
+ const mock = await Helper.generateMockRequest('/parties/{Type}/{ID}/error', 'put')
115
+ const setTagsStub = sandbox.stub().returns({})
116
+
117
+ mock.request = {
118
+ log: sandbox.stub(),
119
+ server: {
120
+ log: sandbox.stub(),
121
+ app: {}
122
+ },
123
+ span: {
124
+ setTags: setTagsStub,
125
+ audit: sandbox.stub().returns(Promise.resolve({}))
126
+ }
127
+ }
128
+
129
+ const throwError = new Error('Unknown error')
130
+ sandbox.stub(parties, 'putPartiesErrorByTypeAndID').rejects(throwError)
131
+
132
+ // Act
133
+ await ErrHandler.put(mockContext, mock.request, handler)
134
+
135
+ // Assert
136
+ expect(parties.putPartiesErrorByTypeAndID.callCount).toBe(1)
137
+ expect(parties.putPartiesErrorByTypeAndID.getCall(0).returnValue).rejects.toStrictEqual(throwError)
138
+ expect(mock.request.server.log.callCount).toEqual(1)
139
+ const logCatchCallArgs = mock.request.server.log.getCall(0).args
140
+ expect(logCatchCallArgs[0]).toEqual(['error'])
141
+
142
+ // Cleanup
143
+ parties.putPartiesErrorByTypeAndID.restore()
144
+ })
145
+ })
@@ -0,0 +1,141 @@
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
+ * Crosslake
22
+ - Lewis Daly <lewisd@crosslaketech.com>
23
+
24
+ --------------
25
+ ******/
26
+
27
+ 'use strict'
28
+
29
+ const Sinon = require('sinon')
30
+ const getPort = require('get-port')
31
+
32
+ const src = '../../../../../../../src'
33
+ const initServer = require(`${src}/server`).initializeApi
34
+ const Db = require(`${src}/lib/db`)
35
+ const parties = require(`${src}/domain/parties`)
36
+ const ErrHandler = require(`${src}/api/parties/{Type}/{ID}/{SubId}/error`)
37
+ const Helper = require('../../../../../../util/helper')
38
+ const Config = require(`${src}/lib/config`)
39
+
40
+ let server
41
+ let sandbox
42
+ const mockContext = jest.fn()
43
+
44
+ describe('/parties/{Type}/{ID}/{SubId}/error', () => {
45
+ beforeAll(async () => {
46
+ sandbox = Sinon.createSandbox()
47
+ sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
48
+ Config.API_PORT = await getPort()
49
+ server = await initServer(Config)
50
+ })
51
+
52
+ afterAll(async () => {
53
+ await server.stop()
54
+ sandbox.restore()
55
+ })
56
+
57
+ it('handles PUT /error with resolve', async () => {
58
+ // Arrange
59
+ const response = sandbox.stub().returns({
60
+ code: sandbox.stub()
61
+ })
62
+ const handler = {
63
+ response
64
+ }
65
+
66
+ const mock = await Helper.generateMockRequest('/parties/{Type}/{ID}/{SubId}/error', 'put')
67
+ mock.request.server = {
68
+ log: sandbox.stub(),
69
+ app: {}
70
+ }
71
+ const stub = sandbox.stub(parties, 'putPartiesErrorByTypeAndID').resolves({})
72
+
73
+ // Act
74
+ await ErrHandler.put(mockContext, mock.request, handler)
75
+
76
+ // Assert
77
+ expect(handler.response.calledOnce).toBe(true)
78
+ expect(parties.putPartiesErrorByTypeAndID.callCount).toBe(1)
79
+ expect(parties.putPartiesErrorByTypeAndID.getCall(0).returnValue).resolves.toStrictEqual({})
80
+ expect(mock.request.server.log.callCount).toEqual(0)
81
+
82
+ // Cleanup
83
+ stub.restore()
84
+ })
85
+
86
+ it('handles PUT /error with reject', async () => {
87
+ // Arrange
88
+ const response = sandbox.stub().returns({
89
+ code: sandbox.stub()
90
+ })
91
+ const handler = {
92
+ response
93
+ }
94
+ const mock = await Helper.generateMockRequest('/parties/{Type}/{ID}/{SubId}/error', 'put')
95
+ mock.request.server = {
96
+ log: sandbox.stub(),
97
+ app: {}
98
+ }
99
+ const throwError = new Error('Unknown error')
100
+ const stub = sandbox.stub(parties, 'putPartiesErrorByTypeAndID').rejects(throwError)
101
+
102
+ // Act
103
+ await ErrHandler.put(mockContext, mock.request, handler)
104
+
105
+ // Assert
106
+ expect(handler.response.calledOnce).toBe(true)
107
+ expect(parties.putPartiesErrorByTypeAndID.callCount).toBe(1)
108
+ expect(parties.putPartiesErrorByTypeAndID.getCall(0).returnValue).rejects.toStrictEqual(throwError)
109
+
110
+ expect(mock.request.server.log.callCount).toEqual(1)
111
+ const logCatchCallArgs = mock.request.server.log.getCall(0).args
112
+ expect(logCatchCallArgs[0]).toEqual(['error'])
113
+
114
+ // Cleanup
115
+ stub.restore()
116
+ })
117
+
118
+ it('putPartiesSubIdErrorByTypeAndID endpoint', async () => {
119
+ // Arrange
120
+ const mock = await Helper.generateMockRequest('/parties/{Type}/{ID}/{SubId}/error', 'put')
121
+ const options = {
122
+ method: 'put',
123
+ url: mock.request.path,
124
+ headers: Helper.defaultStandardHeaders('parties'),
125
+ payload: mock.request.body
126
+ }
127
+
128
+ const stub = sandbox.stub(parties, 'putPartiesErrorByTypeAndID').resolves({})
129
+
130
+ // Act
131
+ const response = await server.inject(options)
132
+
133
+ // Assert
134
+ expect(response.statusCode).toBe(200)
135
+ expect(parties.putPartiesErrorByTypeAndID.callCount).toBe(1)
136
+ expect(parties.putPartiesErrorByTypeAndID.getCall(0).returnValue).resolves.toStrictEqual({})
137
+
138
+ // Cleanup
139
+ stub.restore()
140
+ })
141
+ })
@@ -0,0 +1,241 @@
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
+ - Steven Oderayi <steven.oderayi@modusbox.com>
23
+
24
+ --------------
25
+ ******/
26
+
27
+ 'use strict'
28
+
29
+ const Sinon = require('sinon')
30
+ const getPort = require('get-port')
31
+ const ErrorHandler = require('@mojaloop/central-services-error-handling')
32
+ const Logger = require('@mojaloop/central-services-logger')
33
+ const requestUtil = require('@mojaloop/central-services-shared').Util.Request
34
+ const Enums = require('@mojaloop/central-services-shared').Enum
35
+ const initServer = require('../../../../../../src/server').initializeApi
36
+ const Db = require('../../../../../../src/lib/db')
37
+ const parties = require('../../../../../../src/domain/parties')
38
+ const participant = require('../../../../../../src/models/participantEndpoint/facade')
39
+ const Helper = require('../../../../../util/helper')
40
+ const oracleEndpointCached = require('../../../../../../src/models/oracle/oracleEndpointCached')
41
+ const Config = require('../../../../../../src/lib/config')
42
+
43
+ Logger.isDebugEnabled = jest.fn(() => true)
44
+ Logger.isErrorEnabled = jest.fn(() => true)
45
+ Logger.isInfoEnabled = jest.fn(() => true)
46
+ let server
47
+ let sandbox
48
+
49
+ describe('/parties/{Type}/{ID}/{SubId}', () => {
50
+ beforeAll(async () => {
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
+ afterAll(async () => {
58
+ await server.stop()
59
+ sandbox.restore()
60
+ })
61
+
62
+ it('getPartiesByTypeAndID (with SubId) failure', async () => {
63
+ // Arrange
64
+ const mock = await Helper.generateMockRequest('/parties/{Type}/{ID}/{SubId}', 'get')
65
+ const options = {
66
+ method: 'get',
67
+ url: mock.request.path,
68
+ headers: Helper.defaultStandardHeaders('parties')
69
+ }
70
+ const throwError = new Error('Unknown error')
71
+ sandbox.stub(parties, 'getPartiesByTypeAndID').rejects(throwError)
72
+
73
+ // Act
74
+ const response = await server.inject(options)
75
+
76
+ // Assert
77
+ expect(response.statusCode).toBe(202)
78
+ expect(parties.getPartiesByTypeAndID.callCount).toBe(1)
79
+ expect(parties.getPartiesByTypeAndID.getCall(0).returnValue).rejects.toStrictEqual(throwError)
80
+
81
+ // Cleanup
82
+ parties.getPartiesByTypeAndID.restore()
83
+ })
84
+
85
+ it('getPartiesByTypeAndID (with SubId) success', async () => {
86
+ // Arrange
87
+ const mock = await Helper.generateMockRequest('/parties/{Type}/{ID}/{SubId}', 'get')
88
+ const options = {
89
+ method: 'get',
90
+ url: mock.request.path,
91
+ headers: Helper.defaultStandardHeaders('parties')
92
+ }
93
+ sandbox.stub(parties, 'getPartiesByTypeAndID').resolves({})
94
+
95
+ // Act
96
+ const response = await server.inject(options)
97
+
98
+ // Assert
99
+ expect(response.statusCode).toBe(202)
100
+ expect(parties.getPartiesByTypeAndID.callCount).toBe(1)
101
+ expect(parties.getPartiesByTypeAndID.getCall(0).returnValue).resolves.toStrictEqual({})
102
+
103
+ // Cleanup
104
+ parties.getPartiesByTypeAndID.restore()
105
+ })
106
+
107
+ it('getPartiesByTypeAndID endpoint sends async 3204 to /error for invalid party ID on response with status 400', async () => {
108
+ // Arrange
109
+ const mock = await Helper.generateMockRequest('/parties/{Type}/{ID}/{SubId}', 'get')
110
+
111
+ const headers = Helper.defaultStandardHeaders('parties')
112
+ delete headers['fspiop-destination']
113
+
114
+ const options = {
115
+ method: 'get',
116
+ url: mock.request.path,
117
+ headers
118
+ }
119
+
120
+ const badRequestError = ErrorHandler.Factory.createFSPIOPError(
121
+ ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_COMMUNICATION_ERROR,
122
+ 'Failed to send HTTP request to host',
123
+ {},
124
+ {},
125
+ [{ key: 'status', value: 400 }]
126
+ )
127
+ const stubs = [
128
+ sandbox.stub(participant, 'sendErrorToParticipant').resolves({}),
129
+ sandbox.stub(participant, 'validateParticipant').resolves(true),
130
+ sandbox.stub(oracleEndpointCached, 'getOracleEndpointByType').resolves(['whatever']),
131
+ sandbox.stub(requestUtil, 'sendRequest').rejects(badRequestError)
132
+ ]
133
+
134
+ // Act
135
+ const response = await server.inject(options)
136
+
137
+ // Assert
138
+ const errorCallStub = stubs[0]
139
+ expect(errorCallStub.args[0][2].errorInformation.errorCode).toBe('3204')
140
+ expect(errorCallStub.args[0][1]).toBe(Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_PUT_ERROR)
141
+ expect(response.statusCode).toBe(202)
142
+
143
+ // Cleanup
144
+ stubs.forEach(s => s.restore())
145
+ })
146
+
147
+ // Added error 404 to cover a special case of the Mowali implementation
148
+ // which uses mojaloop/als-oracle-pathfinder and currently returns 404.
149
+ it('getPartiesByTypeAndID endpoint sends async 3201 to /error for invalid party ID with status 404', async () => {
150
+ // Arrange
151
+ const mock = await Helper.generateMockRequest('/parties/{Type}/{ID}/{SubId}', 'get')
152
+
153
+ const headers = Helper.defaultStandardHeaders('parties')
154
+ delete headers['fspiop-destination']
155
+
156
+ const options = {
157
+ method: 'get',
158
+ url: mock.request.path,
159
+ headers
160
+ }
161
+
162
+ const badRequestError = ErrorHandler.Factory.createFSPIOPError(
163
+ ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_COMMUNICATION_ERROR,
164
+ 'Failed to send HTTP request to host',
165
+ {},
166
+ {},
167
+ [{ key: 'status', value: 404 }]
168
+ )
169
+ const stubs = [
170
+ sandbox.stub(participant, 'sendErrorToParticipant').resolves({}),
171
+ sandbox.stub(participant, 'validateParticipant').resolves(true),
172
+ sandbox.stub(oracleEndpointCached, 'getOracleEndpointByType').resolves(['whatever']),
173
+ sandbox.stub(requestUtil, 'sendRequest').rejects(badRequestError)
174
+ ]
175
+
176
+ // Act
177
+ const response = await server.inject(options)
178
+
179
+ // Assert
180
+ const errorCallStub = stubs[0]
181
+ expect(errorCallStub.args[0][2].errorInformation.errorCode).toBe('3201')
182
+ expect(errorCallStub.args[0][1]).toBe(Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_PUT_ERROR)
183
+ expect(response.statusCode).toBe(202)
184
+
185
+ // Cleanup
186
+ stubs.forEach(s => s.restore())
187
+ })
188
+
189
+ it('putPartiesByTypeAndID endpoint success', async () => {
190
+ // Arrange
191
+ const mock = await Helper.generateMockRequest('/parties/{Type}/{ID}/{SubId}', 'put')
192
+ const options = {
193
+ method: 'put',
194
+ url: mock.request.path,
195
+ headers: Helper.defaultStandardHeaders('parties'),
196
+ payload: mock.request.body
197
+ }
198
+ options.payload.party.personalInfo.complexName.firstName = 'Justin'
199
+ options.payload.party.personalInfo.complexName.middleName = 'middle'
200
+ options.payload.party.personalInfo.complexName.lastName = 'résumé'
201
+ sandbox.stub(parties, 'putPartiesByTypeAndID').resolves({})
202
+
203
+ // Act
204
+ const response = await server.inject(options)
205
+
206
+ // Assert
207
+ expect(response.statusCode).toBe(200)
208
+ expect(parties.putPartiesByTypeAndID.callCount).toBe(1)
209
+ expect(parties.putPartiesByTypeAndID.getCall(0).returnValue).resolves.toStrictEqual({})
210
+
211
+ // Cleanup
212
+ parties.putPartiesByTypeAndID.restore()
213
+ })
214
+
215
+ it('putPartiesByTypeAndID endpoint failure', async () => {
216
+ // Arrange
217
+ const mock = await Helper.generateMockRequest('/parties/{Type}/{ID}/{SubId}', 'put')
218
+ const options = {
219
+ method: 'put',
220
+ url: mock.request.path,
221
+ headers: Helper.defaultStandardHeaders('parties'),
222
+ payload: mock.request.body
223
+ }
224
+ options.payload.party.personalInfo.complexName.firstName = 'Justin'
225
+ options.payload.party.personalInfo.complexName.middleName = 'middle'
226
+ options.payload.party.personalInfo.complexName.lastName = 'résumé'
227
+ const throwError = new Error('Unknown error')
228
+ sandbox.stub(parties, 'putPartiesByTypeAndID').rejects(throwError)
229
+
230
+ // Act
231
+ const response = await server.inject(options)
232
+
233
+ // Assert
234
+ expect(response.statusCode).toBe(200)
235
+ expect(parties.putPartiesByTypeAndID.callCount).toBe(1)
236
+ expect(parties.putPartiesByTypeAndID.getCall(0).returnValue).rejects.toStrictEqual(throwError)
237
+
238
+ // Cleanup
239
+ parties.putPartiesByTypeAndID.restore()
240
+ })
241
+ })