account-lookup-service 15.6.0-iso.2 → 15.6.0-iso.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +1 -1
- package/.ncurc.yaml +1 -2
- package/audit-ci.jsonc +3 -1
- package/jest.config.js +2 -0
- package/package.json +14 -16
- package/src/constants.js +2 -1
- package/src/domain/participants/participants.js +173 -130
- package/src/domain/parties/getPartiesByTypeAndID.js +15 -14
- package/src/domain/parties/parties.js +13 -12
- package/src/domain/parties/utils.js +13 -6
- package/src/domain/timeout/dto.js +4 -10
- package/src/handlers/index.js +4 -4
- package/src/handlers/monitoring/index.js +1 -1
- package/src/interface/api-swagger-iso20022-parties.yaml +7 -6
- package/src/interface/api-swagger.yaml +7 -6
- package/src/interface/fspiop-rest-v2.0-ISO20022_parties.yaml +2043 -1583
- package/src/lib/config.js +1 -1
- package/src/lib/index.js +1 -2
- package/src/models/participantEndpoint/facade.js +21 -19
- package/src/plugins.js +20 -9
- package/src/server.js +3 -19
- package/test/fixtures/index.js +30 -6
- package/test/fixtures/iso.js +1 -1
- package/test/unit/api/health.test.js +3 -0
- package/test/unit/api/participants/participants.test.js +5 -7
- package/test/unit/api/participants/{Type}/{ID}/{SubId}.test.js +0 -3
- package/test/unit/api/participants/{Type}/{ID}.test.js +0 -3
- package/test/unit/api/participants.test.js +36 -3
- package/test/unit/domain/participants/participants.test.js +76 -48
- package/test/unit/domain/parties/parties.test.js +3 -3
- package/test/unit/domain/parties/utils.test.js +60 -0
- package/test/unit/domain/timeout/dto.test.js +1 -2
- package/test/unit/lib/TransformFacades.test.js +2 -1
- package/test/unit/lib/config.test.js +7 -0
- package/test/unit/models/participantEndpoint/facade.test.js +25 -8
- package/test/unit/plugins.test.js +4 -2
- package/test/util/apiClients/BasicApiClient.js +2 -2
- package/src/handlers/monitoring/plugins/metrics.js +0 -48
- package/src/lib/requestLogger.js +0 -54
- package/src/metrics/handler.js +0 -33
- package/src/metrics/plugin.js +0 -52
- package/src/metrics/routes.js +0 -43
- package/test/unit/lib/requestLogger.test.js +0 -115
package/.circleci/config.yml
CHANGED
package/.ncurc.yaml
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
## Add a TODO comment indicating the reason for each rejected dependency upgrade added to this list, and what should be done to resolve it (i.e. handle it through a story, etc).
|
2
2
|
reject: [
|
3
3
|
# TODO: v6+ (ref: https://github.com/sindresorhus/get-port/releases/tag/v6.0.0) is an ESM library and thus not compatible with CommonJS. Future story needed to resolve.
|
4
|
-
"get-port"
|
5
|
-
"@mojaloop/central-services-shared" ## need to remove before merging proxyCache functionality to main
|
4
|
+
"get-port"
|
6
5
|
]
|
package/audit-ci.jsonc
CHANGED
@@ -27,6 +27,8 @@
|
|
27
27
|
"GHSA-7fh5-64p2-3v2j",
|
28
28
|
"GHSA-rm97-x556-q36h", // https://github.com/advisories/GHSA-rm97-x556-q36h
|
29
29
|
"GHSA-rv95-896h-c2vc", // https://github.com/advisories/GHSA-rv95-896h-c2vc
|
30
|
-
"GHSA-952p-6rrq-rcjv" // https://github.com/advisories/GHSA-952p-6rrq-rcjv
|
30
|
+
"GHSA-952p-6rrq-rcjv", // https://github.com/advisories/GHSA-952p-6rrq-rcjv
|
31
|
+
"GHSA-3xgq-45jj-v275", // https://github.com/advisories/GHSA-3xgq-45jj-v275
|
32
|
+
"GHSA-rhx6-c78j-4q9w" // https://github.com/advisories/GHSA-rhx6-c78j-4q9w
|
31
33
|
]
|
32
34
|
}
|
package/jest.config.js
CHANGED
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "account-lookup-service",
|
3
3
|
"description": "Account Lookup Service is used to validate Party and Participant lookups.",
|
4
|
-
"version": "15.6.0-iso.
|
4
|
+
"version": "15.6.0-iso.20",
|
5
5
|
"license": "Apache-2.0",
|
6
6
|
"author": "ModusBox",
|
7
7
|
"contributors": [
|
@@ -54,7 +54,7 @@
|
|
54
54
|
"test:coverage-check": "npm test -- --coverage",
|
55
55
|
"test:junit": "npm test -- --reporters=default --reporters=jest-junit",
|
56
56
|
"test:xunit": "npm run test:junit",
|
57
|
-
"test:functional": "
|
57
|
+
"test:functional": "bash ./scripts/test-functional.sh",
|
58
58
|
"test:int": "npm run migrate && npm run onboarding && jest --config=./jest-int.config.js --runInBand",
|
59
59
|
"test:integration": "npm run dc:up && npm run wait-4-docker && npm run test:int | tee ./test/results/test-int.log",
|
60
60
|
"test:integration-runner": "TEST_MODE=rm ./test/integration-runner.sh",
|
@@ -87,27 +87,26 @@
|
|
87
87
|
"@hapi/boom": "10.0.1",
|
88
88
|
"@hapi/catbox-memory": "6.0.2",
|
89
89
|
"@hapi/good": "9.0.1",
|
90
|
-
"@hapi/hapi": "21.3.
|
90
|
+
"@hapi/hapi": "21.3.12",
|
91
91
|
"@hapi/inert": "7.1.0",
|
92
|
-
"@hapi/joi": "17.1.1",
|
93
92
|
"@hapi/vision": "7.0.3",
|
94
|
-
"@mojaloop/central-services-error-handling": "13.0.
|
93
|
+
"@mojaloop/central-services-error-handling": "13.0.2",
|
95
94
|
"@mojaloop/central-services-health": "15.0.0",
|
96
95
|
"@mojaloop/central-services-logger": "11.5.1",
|
97
|
-
"@mojaloop/central-services-metrics": "12.
|
98
|
-
"@mojaloop/central-services-shared": "18.
|
96
|
+
"@mojaloop/central-services-metrics": "12.4.1",
|
97
|
+
"@mojaloop/central-services-shared": "18.13.0",
|
99
98
|
"@mojaloop/central-services-stream": "11.3.1",
|
100
99
|
"@mojaloop/database-lib": "11.0.6",
|
101
100
|
"@mojaloop/event-sdk": "14.1.1",
|
102
101
|
"@mojaloop/inter-scheme-proxy-cache-lib": "2.3.0",
|
103
|
-
"@mojaloop/ml-schema-transformer-lib": "
|
104
|
-
"@mojaloop/sdk-standard-components": "19.
|
102
|
+
"@mojaloop/ml-schema-transformer-lib": "2.4.1",
|
103
|
+
"@mojaloop/sdk-standard-components": "19.6.2",
|
105
104
|
"@now-ims/hapi-now-auth": "2.1.0",
|
106
105
|
"ajv": "8.17.1",
|
107
106
|
"ajv-keywords": "5.1.0",
|
108
107
|
"blipp": "4.0.2",
|
109
108
|
"commander": "12.1.0",
|
110
|
-
"cron": "3.
|
109
|
+
"cron": "3.3.0",
|
111
110
|
"fast-safe-stringify": "^2.1.1",
|
112
111
|
"hapi-auth-bearer-token": "8.0.0",
|
113
112
|
"joi": "17.13.3",
|
@@ -147,22 +146,21 @@
|
|
147
146
|
"jsonpointer": "5.0.0"
|
148
147
|
},
|
149
148
|
"devDependencies": {
|
150
|
-
"@types/jest": "29.5.
|
149
|
+
"@types/jest": "29.5.14",
|
151
150
|
"audit-ci": "^7.1.0",
|
152
|
-
"axios": "1.7.
|
151
|
+
"axios": "1.7.9",
|
153
152
|
"axios-retry": "^4.5.0",
|
154
153
|
"docdash": "2.0.2",
|
155
|
-
"dotenv": "^16.4.
|
154
|
+
"dotenv": "^16.4.7",
|
156
155
|
"get-port": "5.1.1",
|
157
156
|
"ioredis-mock": "^8.9.0",
|
158
157
|
"jest": "29.7.0",
|
159
158
|
"jest-junit": "16.0.0",
|
160
|
-
"jsdoc": "4.0.
|
159
|
+
"jsdoc": "4.0.4",
|
161
160
|
"nodemon": "3.1.7",
|
162
|
-
"npm-check-updates": "17.1.
|
161
|
+
"npm-check-updates": "17.1.11",
|
163
162
|
"nyc": "17.1.0",
|
164
163
|
"pre-commit": "1.2.2",
|
165
|
-
"proxyquire": "2.1.3",
|
166
164
|
"replace": "^1.2.2",
|
167
165
|
"sinon": "19.0.2",
|
168
166
|
"standard": "17.1.2",
|
package/src/constants.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
const ERROR_MESSAGES = Object.freeze({
|
2
|
-
|
2
|
+
sourceFspNotFound: 'Requester FSP not found',
|
3
|
+
partySourceFspNotFound: 'Requester FSP not found', // todo: use sourceFspNotFound
|
3
4
|
partyDestinationFspNotFound: 'Destination FSP not found',
|
4
5
|
partyProxyNotFound: 'Proxy not found',
|
5
6
|
proxyConnectionError: 'Proxy connection error',
|
@@ -28,7 +28,6 @@
|
|
28
28
|
|
29
29
|
const Enums = require('@mojaloop/central-services-shared').Enum
|
30
30
|
const { decodePayload } = require('@mojaloop/central-services-shared').Util.StreamingProtocol
|
31
|
-
const Logger = require('@mojaloop/central-services-logger')
|
32
31
|
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
33
32
|
const EventSdk = require('@mojaloop/event-sdk')
|
34
33
|
const Metrics = require('@mojaloop/central-services-metrics')
|
@@ -36,6 +35,10 @@ const Metrics = require('@mojaloop/central-services-metrics')
|
|
36
35
|
const oracle = require('../../models/oracle/facade')
|
37
36
|
const participant = require('../../models/participantEndpoint/facade')
|
38
37
|
const Config = require('../../lib/config')
|
38
|
+
const { logger } = require('../../lib')
|
39
|
+
const { ERROR_MESSAGES } = require('../../constants')
|
40
|
+
|
41
|
+
const { FSPIOPErrorCodes } = ErrorHandler.Enums
|
39
42
|
|
40
43
|
/**
|
41
44
|
* @function getParticipantsByTypeAndID
|
@@ -55,57 +58,85 @@ const getParticipantsByTypeAndID = async (headers, params, method, query, span,
|
|
55
58
|
'Get participants by ID',
|
56
59
|
['success']
|
57
60
|
).startTimer()
|
61
|
+
const log = logger.child('getParticipantsByTypeAndID')
|
58
62
|
const type = params.Type
|
59
|
-
const partySubIdOrType = params.SubId
|
60
|
-
const
|
61
|
-
const callbackEndpointType = partySubIdOrType
|
62
|
-
|
63
|
+
const partySubIdOrType = params.SubId
|
64
|
+
const source = headers[Enums.Http.Headers.FSPIOP.SOURCE]
|
65
|
+
const callbackEndpointType = partySubIdOrType
|
66
|
+
? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT
|
67
|
+
: Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
|
68
|
+
const errorCallbackEndpointType = params.SubId
|
69
|
+
? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
|
70
|
+
: Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
71
|
+
|
63
72
|
let fspiopError
|
73
|
+
|
64
74
|
try {
|
65
|
-
|
66
|
-
const requesterParticipantModel = await participant.validateParticipant(
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
await participant.sendRequest(clonedHeaders, requesterName, callbackEndpointType, Enums.Http.RestMethods.PUT, payload, options, childSpan)
|
84
|
-
} else {
|
85
|
-
await participant.sendErrorToParticipant(requesterName, errorCallbackEndpointType,
|
86
|
-
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND).toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
|
75
|
+
log.info('processing started...', { source, params })
|
76
|
+
const requesterParticipantModel = await participant.validateParticipant(source)
|
77
|
+
|
78
|
+
if (!requesterParticipantModel) {
|
79
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
80
|
+
logger.warn(errMessage, { requesterName: source })
|
81
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
82
|
+
}
|
83
|
+
|
84
|
+
const response = await oracle.oracleRequest(headers, method, params, query, undefined, cache)
|
85
|
+
if (response?.data && Array.isArray(response.data.partyList) && response.data.partyList.length > 0) {
|
86
|
+
const options = {
|
87
|
+
partyIdType: type,
|
88
|
+
partyIdentifier: params.ID,
|
89
|
+
...(partySubIdOrType && { partySubIdOrType })
|
90
|
+
}
|
91
|
+
const payload = {
|
92
|
+
fspId: response.data.partyList[0].fspId
|
87
93
|
}
|
88
|
-
|
94
|
+
const clonedHeaders = { ...headers }
|
95
|
+
if (!clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] || clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] === '') {
|
96
|
+
clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE]
|
97
|
+
}
|
98
|
+
clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
|
99
|
+
await participant.sendRequest(
|
100
|
+
clonedHeaders,
|
101
|
+
source,
|
102
|
+
callbackEndpointType,
|
103
|
+
Enums.Http.RestMethods.PUT,
|
104
|
+
payload,
|
105
|
+
options,
|
106
|
+
childSpan
|
107
|
+
)
|
89
108
|
} else {
|
90
|
-
|
91
|
-
|
109
|
+
await participant.sendErrorToParticipant(
|
110
|
+
source,
|
111
|
+
errorCallbackEndpointType,
|
112
|
+
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND).toApiErrorObject(Config.ERROR_HANDLING),
|
113
|
+
headers,
|
114
|
+
params,
|
115
|
+
childSpan
|
116
|
+
)
|
92
117
|
}
|
118
|
+
log.info('processing finished', { source, params })
|
119
|
+
|
93
120
|
if (childSpan && !childSpan.isFinished) {
|
94
121
|
await childSpan.finish()
|
95
122
|
}
|
96
123
|
} catch (err) {
|
97
|
-
|
124
|
+
log.warn('error in getParticipantsByTypeAndID', err)
|
98
125
|
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
99
126
|
try {
|
100
|
-
const errorCallbackEndpointType = params.SubId ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
101
127
|
await participant.sendErrorToParticipant(
|
102
|
-
headers[Enums.Http.Headers.FSPIOP.SOURCE],
|
103
|
-
|
128
|
+
headers[Enums.Http.Headers.FSPIOP.SOURCE],
|
129
|
+
errorCallbackEndpointType,
|
130
|
+
fspiopError.toApiErrorObject(Config.ERROR_HANDLING),
|
131
|
+
headers,
|
132
|
+
params,
|
133
|
+
childSpan
|
134
|
+
)
|
104
135
|
} catch (exc) {
|
105
136
|
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(exc)
|
106
137
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
107
138
|
// we've already sent a sync response- we cannot throw.
|
108
|
-
|
139
|
+
log.error('error in final participant.sendErrorToParticipant', exc)
|
109
140
|
}
|
110
141
|
} finally {
|
111
142
|
if (childSpan && !childSpan.isFinished && fspiopError) {
|
@@ -138,7 +169,7 @@ const putParticipantsByTypeAndID = async (headers, params, method, payload, cach
|
|
138
169
|
['success']
|
139
170
|
).startTimer()
|
140
171
|
try {
|
141
|
-
|
172
|
+
logger.info('putParticipantsByTypeAndID::begin')
|
142
173
|
const type = params.Type
|
143
174
|
const partySubIdOrType = params.SubId || undefined
|
144
175
|
const callbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
|
@@ -177,17 +208,17 @@ const putParticipantsByTypeAndID = async (headers, params, method, payload, cach
|
|
177
208
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
178
209
|
}
|
179
210
|
} else {
|
180
|
-
|
181
|
-
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND,
|
211
|
+
logger.warn(ERROR_MESSAGES.sourceFspNotFound)
|
212
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, ERROR_MESSAGES.sourceFspNotFound)
|
182
213
|
}
|
183
214
|
} else {
|
184
215
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
185
216
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
186
217
|
}
|
187
|
-
|
218
|
+
logger.info('putParticipantsByTypeAndID::end')
|
188
219
|
histTimerEnd({ success: true })
|
189
220
|
} catch (err) {
|
190
|
-
|
221
|
+
logger.error('error in putParticipantsByTypeAndID:', err)
|
191
222
|
try {
|
192
223
|
const errorCallbackEndpointType = params.SubId ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
193
224
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
@@ -195,7 +226,7 @@ const putParticipantsByTypeAndID = async (headers, params, method, payload, cach
|
|
195
226
|
} catch (exc) {
|
196
227
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
197
228
|
// we've already sent a sync response- we cannot throw.
|
198
|
-
|
229
|
+
logger.error('error in participant.sendErrorToParticipant:', exc)
|
199
230
|
}
|
200
231
|
histTimerEnd({ success: false })
|
201
232
|
}
|
@@ -222,7 +253,9 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
|
|
222
253
|
).startTimer()
|
223
254
|
try {
|
224
255
|
const partySubIdOrType = params.SubId || undefined
|
225
|
-
const callbackEndpointType = partySubIdOrType
|
256
|
+
const callbackEndpointType = partySubIdOrType
|
257
|
+
? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
|
258
|
+
: Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
226
259
|
const destinationParticipant = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.DESTINATION])
|
227
260
|
if (destinationParticipant) {
|
228
261
|
const decodedPayload = decodePayload(dataUri, { asParsed: false })
|
@@ -231,7 +264,8 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
|
|
231
264
|
callbackEndpointType,
|
232
265
|
decodedPayload.body.toString(),
|
233
266
|
headers,
|
234
|
-
params
|
267
|
+
params
|
268
|
+
)
|
235
269
|
} else {
|
236
270
|
await participant.sendErrorToParticipant(
|
237
271
|
headers[Enums.Http.Headers.FSPIOP.SOURCE],
|
@@ -239,19 +273,27 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
|
|
239
273
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_FSP_ERROR).toApiErrorObject(),
|
240
274
|
headers,
|
241
275
|
params,
|
242
|
-
payload
|
276
|
+
payload
|
277
|
+
)
|
243
278
|
}
|
244
279
|
histTimerEnd({ success: true })
|
245
280
|
} catch (err) {
|
246
|
-
|
281
|
+
logger.error('error in putParticipantsErrorByTypeAndID:', err)
|
247
282
|
try {
|
248
|
-
const callbackEndpointType = params.SubId
|
249
|
-
|
250
|
-
|
283
|
+
const callbackEndpointType = params.SubId
|
284
|
+
? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
|
285
|
+
: Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
286
|
+
await participant.sendErrorToParticipant(
|
287
|
+
headers[Enums.Http.Headers.FSPIOP.SOURCE],
|
288
|
+
callbackEndpointType,
|
289
|
+
ErrorHandler.Factory.reformatFSPIOPError(err).toApiErrorObject(),
|
290
|
+
headers,
|
291
|
+
params
|
292
|
+
)
|
251
293
|
} catch (exc) {
|
252
294
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
253
295
|
// we've already sent a sync response- we cannot throw.
|
254
|
-
|
296
|
+
logger.error('error in participant.sendErrorToParticipant:', exc)
|
255
297
|
}
|
256
298
|
histTimerEnd({ success: false })
|
257
299
|
}
|
@@ -277,7 +319,7 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
277
319
|
const childSpan = span ? span.getChild('postParticipants') : undefined
|
278
320
|
let fspiopError
|
279
321
|
try {
|
280
|
-
|
322
|
+
logger.info('postParticipants::begin')
|
281
323
|
const type = params.Type
|
282
324
|
const partySubIdOrType = params.SubId
|
283
325
|
const callbackEndpointType = partySubIdOrType
|
@@ -325,8 +367,9 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
325
367
|
fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
|
326
368
|
}
|
327
369
|
} else {
|
328
|
-
|
329
|
-
|
370
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
371
|
+
logger.error(errMessage)
|
372
|
+
fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
330
373
|
throw fspiopError
|
331
374
|
}
|
332
375
|
} else {
|
@@ -334,10 +377,10 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
334
377
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
335
378
|
fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
|
336
379
|
}
|
337
|
-
|
380
|
+
logger.info('postParticipants::end')
|
338
381
|
histTimerEnd({ success: true })
|
339
382
|
} catch (err) {
|
340
|
-
|
383
|
+
logger.error('error in postParticipants:', err)
|
341
384
|
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
342
385
|
try {
|
343
386
|
const errorCallbackEndpointType = params.SubId
|
@@ -348,7 +391,7 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
348
391
|
} catch (exc) {
|
349
392
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
350
393
|
// we've already sent a sync response- we cannot throw.
|
351
|
-
|
394
|
+
logger.error('failed to handle exception in postParticipants:', exc)
|
352
395
|
}
|
353
396
|
histTimerEnd({ success: false })
|
354
397
|
} finally {
|
@@ -376,92 +419,90 @@ const postParticipantsBatch = async (headers, method, requestPayload, span) => {
|
|
376
419
|
'Post participants batch',
|
377
420
|
['success']
|
378
421
|
).startTimer()
|
422
|
+
const requestId = requestPayload.requestId
|
423
|
+
const log = logger.child({ context: 'postParticipantsBatch', requestId })
|
379
424
|
const childSpan = span ? span.getChild('postParticipantsBatch') : undefined
|
380
425
|
let fspiopError
|
426
|
+
|
381
427
|
try {
|
382
|
-
|
428
|
+
log.info('postParticipantsBatch::begin', { headers, requestPayload })
|
383
429
|
const typeMap = new Map()
|
384
430
|
const overallReturnList = []
|
385
|
-
const
|
431
|
+
const pushPartyError = (party, errCode) => {
|
432
|
+
log.debug('party error details:', { party, errCode })
|
433
|
+
overallReturnList.push({
|
434
|
+
partyId: party,
|
435
|
+
...ErrorHandler.Factory.createFSPIOPError(errCode, undefined, undefined, undefined, [{
|
436
|
+
key: party.partyIdType,
|
437
|
+
value: party.partyIdentifier
|
438
|
+
}]).toApiErrorObject(Config.ERROR_HANDLING)
|
439
|
+
})
|
440
|
+
}
|
441
|
+
|
386
442
|
const requesterParticipantModel = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], childSpan)
|
387
|
-
if (requesterParticipantModel) {
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
const partyList = typeMap.get(party.partyIdType)
|
394
|
-
partyList.push(party)
|
395
|
-
typeMap.set(party.partyIdType, partyList)
|
396
|
-
} else {
|
397
|
-
typeMap.set(party.partyIdType, [party])
|
398
|
-
}
|
399
|
-
} else {
|
400
|
-
overallReturnList.push(ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND, undefined, undefined, undefined, [{
|
401
|
-
key: party.partyIdType,
|
402
|
-
value: party.partyIdentifier
|
403
|
-
}]).toApiErrorObject(Config.ERROR_HANDLING))
|
404
|
-
}
|
405
|
-
} else {
|
406
|
-
overallReturnList.push(ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, undefined, undefined, undefined, [{
|
407
|
-
key: party.partyIdType,
|
408
|
-
value: party.partyIdentifier
|
409
|
-
}]).toApiErrorObject(Config.ERROR_HANDLING))
|
410
|
-
}
|
411
|
-
}
|
443
|
+
if (!requesterParticipantModel) {
|
444
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
445
|
+
log.error(errMessage)
|
446
|
+
fspiopError = ErrorHandler.Factory.createFSPIOPError(FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
447
|
+
throw fspiopError
|
448
|
+
}
|
412
449
|
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
if (Array.isArray(response.data.partyList) && response.data.partyList.length > 0) {
|
422
|
-
for (const party of response.data.partyList) {
|
423
|
-
party.partyId.currency = undefined
|
424
|
-
overallReturnList.push(party)
|
425
|
-
}
|
450
|
+
for (const party of requestPayload.partyList) {
|
451
|
+
if (Object.values(Enums.Accounts.PartyAccountTypes).includes(party.partyIdType)) {
|
452
|
+
party.currency = requestPayload.currency
|
453
|
+
if (party.fspId === headers[Enums.Http.Headers.FSPIOP.SOURCE]) {
|
454
|
+
if (typeMap.get(party.partyIdType)) {
|
455
|
+
const partyList = typeMap.get(party.partyIdType)
|
456
|
+
partyList.push(party)
|
457
|
+
typeMap.set(party.partyIdType, partyList)
|
426
458
|
} else {
|
427
|
-
|
428
|
-
overallReturnList.push(ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, undefined, undefined, undefined, [{
|
429
|
-
key: party.partyIdType,
|
430
|
-
value: party.partyIdentifier
|
431
|
-
}]).toApiErrorObject(Config.ERROR_HANDLING))
|
432
|
-
}
|
459
|
+
typeMap.set(party.partyIdType, [party])
|
433
460
|
}
|
434
461
|
} else {
|
435
|
-
|
436
|
-
overallReturnList.push(ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, undefined, undefined, undefined, [{
|
437
|
-
key: party.partyIdType,
|
438
|
-
value: party.partyIdentifier
|
439
|
-
}]).toApiErrorObject(Config.ERROR_HANDLING))
|
440
|
-
}
|
462
|
+
pushPartyError(party, FSPIOPErrorCodes.PARTY_NOT_FOUND)
|
441
463
|
}
|
464
|
+
} else {
|
465
|
+
pushPartyError(party, FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
442
466
|
}
|
467
|
+
}
|
468
|
+
|
469
|
+
for (const [key, value] of typeMap) {
|
443
470
|
const payload = {
|
444
|
-
|
445
|
-
|
446
|
-
}
|
447
|
-
const clonedHeaders = { ...headers }
|
448
|
-
if (!clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] || clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] === '') {
|
449
|
-
clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = payload.partyList[0].partyId.fspId
|
450
|
-
clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
|
471
|
+
requestId,
|
472
|
+
partyList: value
|
451
473
|
}
|
452
|
-
|
453
|
-
|
454
|
-
|
474
|
+
log.info(`postParticipantsBatch::oracleBatchRequest::type=${key}`, { payload })
|
475
|
+
const response = await oracle.oracleBatchRequest(headers, method, requestPayload, key, payload)
|
476
|
+
if (Array.isArray(response?.data?.partyList) && response.data.partyList.length > 0) {
|
477
|
+
for (const party of response.data.partyList) {
|
478
|
+
party.partyId.currency = undefined
|
479
|
+
overallReturnList.push(party)
|
480
|
+
}
|
481
|
+
} else {
|
482
|
+
for (const party of value) {
|
483
|
+
pushPartyError(party, FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
484
|
+
}
|
455
485
|
}
|
456
|
-
Logger.isInfoEnabled && Logger.info('postParticipantsBatch::end')
|
457
|
-
} else {
|
458
|
-
Logger.isErrorEnabled && Logger.error('Requester FSP not found')
|
459
|
-
fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, 'Requester FSP not found')
|
460
|
-
throw fspiopError
|
461
486
|
}
|
487
|
+
|
488
|
+
const payload = {
|
489
|
+
partyList: overallReturnList,
|
490
|
+
currency: requestPayload.currency
|
491
|
+
}
|
492
|
+
const clonedHeaders = { ...headers }
|
493
|
+
if (!clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] || clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] === '') {
|
494
|
+
clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = headers[Enums.Http.Headers.FSPIOP.SOURCE]
|
495
|
+
clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
|
496
|
+
}
|
497
|
+
await participant.sendRequest(clonedHeaders, clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION], Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT, Enums.Http.RestMethods.PUT, payload, { requestId }, childSpan)
|
498
|
+
if (childSpan && !childSpan.isFinished) {
|
499
|
+
await childSpan.finish()
|
500
|
+
}
|
501
|
+
log.info('postParticipantsBatch::end')
|
502
|
+
|
462
503
|
histTimerEnd({ success: true })
|
463
504
|
} catch (err) {
|
464
|
-
|
505
|
+
log.error('error in postParticipantsBatch', err)
|
465
506
|
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
|
466
507
|
try {
|
467
508
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR,
|
@@ -469,7 +510,7 @@ const postParticipantsBatch = async (headers, method, requestPayload, span) => {
|
|
469
510
|
} catch (exc) {
|
470
511
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
471
512
|
// we've already sent a sync response- we cannot throw.
|
472
|
-
|
513
|
+
log.error('error in participant.sendErrorToParticipant', exc)
|
473
514
|
}
|
474
515
|
histTimerEnd({ success: false })
|
475
516
|
} finally {
|
@@ -498,8 +539,9 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
|
|
498
539
|
'Delete participants',
|
499
540
|
['success']
|
500
541
|
).startTimer()
|
542
|
+
const log = logger.child('deleteParticipants')
|
501
543
|
try {
|
502
|
-
|
544
|
+
log.debug('deleteParticipants::begin', { headers, params })
|
503
545
|
const type = params.Type
|
504
546
|
const partySubIdOrType = params.SubId || undefined
|
505
547
|
const callbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
|
@@ -526,17 +568,18 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
|
|
526
568
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
527
569
|
}
|
528
570
|
} else {
|
529
|
-
|
530
|
-
|
571
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
572
|
+
log.error(errMessage)
|
573
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
531
574
|
}
|
532
575
|
} else {
|
533
576
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
534
577
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
535
578
|
}
|
536
|
-
|
579
|
+
log.info('deleteParticipants::end')
|
537
580
|
histTimerEnd({ success: true })
|
538
581
|
} catch (err) {
|
539
|
-
|
582
|
+
log.error('error in deleteParticipants', err)
|
540
583
|
try {
|
541
584
|
const errorCallbackEndpointType = params.SubId ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
542
585
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
@@ -544,7 +587,7 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
|
|
544
587
|
} catch (exc) {
|
545
588
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
546
589
|
// we've already sent a sync response- we cannot throw.
|
547
|
-
|
590
|
+
log.error('error in participant.sendErrorToParticipant', exc)
|
548
591
|
}
|
549
592
|
histTimerEnd({ success: false })
|
550
593
|
}
|