account-lookup-service 15.6.0-iso.2 → 15.6.0-iso.21
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 +15 -17
- package/src/constants.js +2 -1
- package/src/domain/oracle/oracle.js +63 -4
- package/src/domain/participants/participants.js +259 -133
- package/src/domain/parties/getPartiesByTypeAndID.js +36 -15
- package/src/domain/parties/parties.js +44 -14
- package/src/domain/parties/utils.js +13 -6
- package/src/domain/timeout/dto.js +4 -10
- package/src/domain/timeout/index.js +12 -1
- 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/currency/currency.js +10 -1
- package/src/models/endpointType/endpointType.js +10 -1
- package/src/models/oracle/facade.js +24 -3
- package/src/models/oracle/oracleEndpoint.js +64 -10
- package/src/models/oracle/oracleEndpointCached.js +22 -3
- package/src/models/participantEndpoint/facade.js +61 -23
- package/src/models/partyIdType/partyIdType.js +10 -1
- package/src/plugins.js +20 -9
- package/src/server.js +11 -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/oracle/oracle.test.js +8 -0
- package/test/unit/domain/participants/participants.test.js +83 -48
- package/test/unit/domain/parties/parties.test.js +11 -3
- package/test/unit/domain/parties/utils.test.js +60 -0
- package/test/unit/domain/timeout/dto.test.js +1 -2
- package/test/unit/domain/timeout/index.test.js +8 -0
- 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
@@ -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,97 @@ const getParticipantsByTypeAndID = async (headers, params, method, query, span,
|
|
55
58
|
'Get participants by ID',
|
56
59
|
['success']
|
57
60
|
).startTimer()
|
61
|
+
const errorCounter = Metrics.getCounter('errorCount')
|
62
|
+
const log = logger.child('getParticipantsByTypeAndID')
|
58
63
|
const type = params.Type
|
59
|
-
const partySubIdOrType = params.SubId
|
60
|
-
const
|
61
|
-
const callbackEndpointType = partySubIdOrType
|
62
|
-
|
64
|
+
const partySubIdOrType = params.SubId
|
65
|
+
const source = headers[Enums.Http.Headers.FSPIOP.SOURCE]
|
66
|
+
const callbackEndpointType = partySubIdOrType
|
67
|
+
? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT
|
68
|
+
: Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
|
69
|
+
const errorCallbackEndpointType = params.SubId
|
70
|
+
? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
|
71
|
+
: Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
72
|
+
|
63
73
|
let fspiopError
|
74
|
+
let step
|
75
|
+
|
64
76
|
try {
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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)
|
77
|
+
log.info('processing started...', { source, params })
|
78
|
+
step = 'validateParticipant-1'
|
79
|
+
const requesterParticipantModel = await participant.validateParticipant(source)
|
80
|
+
|
81
|
+
if (!requesterParticipantModel) {
|
82
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
83
|
+
logger.warn(errMessage, { requesterName: source })
|
84
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
85
|
+
}
|
86
|
+
step = 'oracleRequest-2'
|
87
|
+
const response = await oracle.oracleRequest(headers, method, params, query, undefined, cache)
|
88
|
+
if (response?.data && Array.isArray(response.data.partyList) && response.data.partyList.length > 0) {
|
89
|
+
const options = {
|
90
|
+
partyIdType: type,
|
91
|
+
partyIdentifier: params.ID,
|
92
|
+
...(partySubIdOrType && { partySubIdOrType })
|
93
|
+
}
|
94
|
+
const payload = {
|
95
|
+
fspId: response.data.partyList[0].fspId
|
87
96
|
}
|
88
|
-
|
97
|
+
const clonedHeaders = { ...headers }
|
98
|
+
if (!clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] || clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] === '') {
|
99
|
+
clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE]
|
100
|
+
}
|
101
|
+
clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
|
102
|
+
step = 'sendRequest-3'
|
103
|
+
await participant.sendRequest(
|
104
|
+
clonedHeaders,
|
105
|
+
source,
|
106
|
+
callbackEndpointType,
|
107
|
+
Enums.Http.RestMethods.PUT,
|
108
|
+
payload,
|
109
|
+
options,
|
110
|
+
childSpan
|
111
|
+
)
|
89
112
|
} else {
|
90
|
-
|
91
|
-
|
113
|
+
step = 'sendErrorToParticipant-4'
|
114
|
+
await participant.sendErrorToParticipant(
|
115
|
+
source,
|
116
|
+
errorCallbackEndpointType,
|
117
|
+
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND).toApiErrorObject(Config.ERROR_HANDLING),
|
118
|
+
headers,
|
119
|
+
params,
|
120
|
+
childSpan
|
121
|
+
)
|
92
122
|
}
|
123
|
+
log.info('processing finished', { source, params })
|
124
|
+
|
93
125
|
if (childSpan && !childSpan.isFinished) {
|
94
126
|
await childSpan.finish()
|
95
127
|
}
|
96
128
|
} catch (err) {
|
97
|
-
|
129
|
+
log.warn('error in getParticipantsByTypeAndID', err)
|
98
130
|
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
131
|
+
const extensions = err.extensions || []
|
132
|
+
const system = extensions.find((element) => element.key === 'system')?.value || ''
|
133
|
+
errorCounter.inc({
|
134
|
+
code: fspiopError?.apiErrorCode,
|
135
|
+
system,
|
136
|
+
operation: 'getParticipantsByTypeAndID',
|
137
|
+
step
|
138
|
+
})
|
99
139
|
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
140
|
await participant.sendErrorToParticipant(
|
102
|
-
headers[Enums.Http.Headers.FSPIOP.SOURCE],
|
103
|
-
|
141
|
+
headers[Enums.Http.Headers.FSPIOP.SOURCE],
|
142
|
+
errorCallbackEndpointType,
|
143
|
+
fspiopError.toApiErrorObject(Config.ERROR_HANDLING),
|
144
|
+
headers,
|
145
|
+
params,
|
146
|
+
childSpan
|
147
|
+
)
|
104
148
|
} catch (exc) {
|
105
|
-
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(exc)
|
106
149
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
107
150
|
// we've already sent a sync response- we cannot throw.
|
108
|
-
|
151
|
+
log.error('error in final participant.sendErrorToParticipant', exc)
|
109
152
|
}
|
110
153
|
} finally {
|
111
154
|
if (childSpan && !childSpan.isFinished && fspiopError) {
|
@@ -137,15 +180,19 @@ const putParticipantsByTypeAndID = async (headers, params, method, payload, cach
|
|
137
180
|
'Put participants by type and ID',
|
138
181
|
['success']
|
139
182
|
).startTimer()
|
183
|
+
const errorCounter = Metrics.getCounter('errorCount')
|
184
|
+
let step
|
140
185
|
try {
|
141
|
-
|
186
|
+
logger.info('putParticipantsByTypeAndID::begin')
|
142
187
|
const type = params.Type
|
143
188
|
const partySubIdOrType = params.SubId || undefined
|
144
189
|
const callbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
|
145
190
|
const errorCallbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
146
191
|
if (Object.values(Enums.Accounts.PartyAccountTypes).includes(type)) {
|
192
|
+
step = 'validateParticipant-1'
|
147
193
|
const requesterParticipantModel = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE])
|
148
194
|
if (requesterParticipantModel) {
|
195
|
+
step = 'oracleRequest-2'
|
149
196
|
const response = await oracle.oracleRequest(headers, method, params, undefined, payload, cache)
|
150
197
|
if (response && response.data) {
|
151
198
|
const responsePayload = {
|
@@ -171,32 +218,45 @@ const putParticipantsByTypeAndID = async (headers, params, method, payload, cach
|
|
171
218
|
clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = payload.fspId
|
172
219
|
clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
|
173
220
|
}
|
221
|
+
step = 'sendRequest-3'
|
174
222
|
await participant.sendRequest(clonedHeaders, clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION], callbackEndpointType, Enums.Http.RestMethods.PUT, responsePayload, options)
|
175
223
|
} else {
|
224
|
+
step = 'sendErrorToParticipant-4'
|
176
225
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
177
226
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
178
227
|
}
|
179
228
|
} else {
|
180
|
-
|
181
|
-
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND,
|
229
|
+
logger.warn(ERROR_MESSAGES.sourceFspNotFound)
|
230
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, ERROR_MESSAGES.sourceFspNotFound)
|
182
231
|
}
|
183
232
|
} else {
|
233
|
+
step = 'sendErrorToParticipant-5'
|
184
234
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
185
235
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
186
236
|
}
|
187
|
-
|
237
|
+
logger.info('putParticipantsByTypeAndID::end')
|
188
238
|
histTimerEnd({ success: true })
|
189
239
|
} catch (err) {
|
190
|
-
|
240
|
+
logger.error('error in putParticipantsByTypeAndID:', err)
|
241
|
+
let fspiopError
|
191
242
|
try {
|
192
243
|
const errorCallbackEndpointType = params.SubId ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
244
|
+
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
193
245
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
194
|
-
|
246
|
+
fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
195
247
|
} catch (exc) {
|
196
248
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
197
249
|
// we've already sent a sync response- we cannot throw.
|
198
|
-
|
250
|
+
logger.error('error in participant.sendErrorToParticipant:', exc)
|
199
251
|
}
|
252
|
+
const extensions = err.extensions || []
|
253
|
+
const system = extensions.find((element) => element.key === 'system')?.value || ''
|
254
|
+
errorCounter.inc({
|
255
|
+
code: fspiopError?.apiErrorCode,
|
256
|
+
system,
|
257
|
+
operation: 'putParticipantsByTypeAndID',
|
258
|
+
step
|
259
|
+
})
|
200
260
|
histTimerEnd({ success: false })
|
201
261
|
}
|
202
262
|
}
|
@@ -220,38 +280,63 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
|
|
220
280
|
'Put participants error by type and ID',
|
221
281
|
['success']
|
222
282
|
).startTimer()
|
283
|
+
const errorCounter = Metrics.getCounter('errorCount')
|
284
|
+
let step
|
223
285
|
try {
|
224
286
|
const partySubIdOrType = params.SubId || undefined
|
225
|
-
const callbackEndpointType = partySubIdOrType
|
287
|
+
const callbackEndpointType = partySubIdOrType
|
288
|
+
? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
|
289
|
+
: Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
290
|
+
step = 'validateParticipant-1'
|
226
291
|
const destinationParticipant = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.DESTINATION])
|
227
292
|
if (destinationParticipant) {
|
228
293
|
const decodedPayload = decodePayload(dataUri, { asParsed: false })
|
294
|
+
step = 'sendErrorToParticipant-2'
|
229
295
|
await participant.sendErrorToParticipant(
|
230
296
|
headers[Enums.Http.Headers.FSPIOP.DESTINATION],
|
231
297
|
callbackEndpointType,
|
232
298
|
decodedPayload.body.toString(),
|
233
299
|
headers,
|
234
|
-
params
|
300
|
+
params
|
301
|
+
)
|
235
302
|
} else {
|
303
|
+
step = 'sendErrorToParticipant-3'
|
236
304
|
await participant.sendErrorToParticipant(
|
237
305
|
headers[Enums.Http.Headers.FSPIOP.SOURCE],
|
238
306
|
callbackEndpointType,
|
239
307
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_FSP_ERROR).toApiErrorObject(),
|
240
308
|
headers,
|
241
309
|
params,
|
242
|
-
payload
|
310
|
+
payload
|
311
|
+
)
|
243
312
|
}
|
244
313
|
histTimerEnd({ success: true })
|
245
314
|
} catch (err) {
|
246
|
-
|
315
|
+
logger.error('error in putParticipantsErrorByTypeAndID:', err)
|
247
316
|
try {
|
248
|
-
const
|
249
|
-
|
250
|
-
|
317
|
+
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
|
318
|
+
const callbackEndpointType = params.SubId
|
319
|
+
? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
|
320
|
+
: Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
321
|
+
await participant.sendErrorToParticipant(
|
322
|
+
headers[Enums.Http.Headers.FSPIOP.SOURCE],
|
323
|
+
callbackEndpointType,
|
324
|
+
fspiopError.toApiErrorObject(),
|
325
|
+
headers,
|
326
|
+
params
|
327
|
+
)
|
328
|
+
const extensions = err.extensions || []
|
329
|
+
const system = extensions.find((element) => element.key === 'system')?.value || ''
|
330
|
+
errorCounter.inc({
|
331
|
+
code: fspiopError?.apiErrorCode,
|
332
|
+
system,
|
333
|
+
operation: 'putParticipantsErrorByTypeAndID',
|
334
|
+
step
|
335
|
+
})
|
251
336
|
} catch (exc) {
|
252
337
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
253
338
|
// we've already sent a sync response- we cannot throw.
|
254
|
-
|
339
|
+
logger.error('error in participant.sendErrorToParticipant:', exc)
|
255
340
|
}
|
256
341
|
histTimerEnd({ success: false })
|
257
342
|
}
|
@@ -274,10 +359,12 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
274
359
|
'Post participants',
|
275
360
|
['success']
|
276
361
|
).startTimer()
|
362
|
+
const errorCounter = Metrics.getCounter('errorCount')
|
277
363
|
const childSpan = span ? span.getChild('postParticipants') : undefined
|
278
364
|
let fspiopError
|
365
|
+
let step
|
279
366
|
try {
|
280
|
-
|
367
|
+
logger.info('postParticipants::begin')
|
281
368
|
const type = params.Type
|
282
369
|
const partySubIdOrType = params.SubId
|
283
370
|
const callbackEndpointType = partySubIdOrType
|
@@ -288,8 +375,10 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
288
375
|
: Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
289
376
|
|
290
377
|
if (Object.values(Enums.Accounts.PartyAccountTypes).includes(type)) {
|
378
|
+
step = 'validateParticipant-1'
|
291
379
|
const requesterParticipantModel = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], childSpan)
|
292
380
|
if (requesterParticipantModel) {
|
381
|
+
step = 'oracleRequest-2'
|
293
382
|
const response = await oracle.oracleRequest(headers, method, params, undefined, payload, cache)
|
294
383
|
if (response && response.status === Enums.Http.ReturnCodes.CREATED.CODE) {
|
295
384
|
const responsePayload = {
|
@@ -315,18 +404,21 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
315
404
|
clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = payload.fspId
|
316
405
|
clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
|
317
406
|
}
|
407
|
+
step = 'sendRequest-3'
|
318
408
|
await participant.sendRequest(clonedHeaders, clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION], callbackEndpointType, Enums.Http.RestMethods.PUT, responsePayload, options, childSpan)
|
319
409
|
if (childSpan && !childSpan.isFinished) {
|
320
410
|
await childSpan.finish()
|
321
411
|
}
|
322
412
|
} else {
|
323
413
|
fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
414
|
+
step = 'sendErrorToParticipant-4'
|
324
415
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
325
416
|
fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
|
326
417
|
}
|
327
418
|
} else {
|
328
|
-
|
329
|
-
|
419
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
420
|
+
logger.error(errMessage)
|
421
|
+
fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
330
422
|
throw fspiopError
|
331
423
|
}
|
332
424
|
} else {
|
@@ -334,11 +426,19 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
334
426
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
335
427
|
fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
|
336
428
|
}
|
337
|
-
|
429
|
+
logger.info('postParticipants::end')
|
338
430
|
histTimerEnd({ success: true })
|
339
431
|
} catch (err) {
|
340
|
-
|
432
|
+
logger.error('error in postParticipants:', err)
|
341
433
|
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
434
|
+
const extensions = err.extensions || []
|
435
|
+
const system = extensions.find((element) => element.key === 'system')?.value || ''
|
436
|
+
errorCounter.inc({
|
437
|
+
code: fspiopError?.apiErrorCode,
|
438
|
+
system,
|
439
|
+
operation: 'postParticipants',
|
440
|
+
step
|
441
|
+
})
|
342
442
|
try {
|
343
443
|
const errorCallbackEndpointType = params.SubId
|
344
444
|
? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
|
@@ -348,7 +448,7 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
348
448
|
} catch (exc) {
|
349
449
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
350
450
|
// we've already sent a sync response- we cannot throw.
|
351
|
-
|
451
|
+
logger.error('failed to handle exception in postParticipants:', exc)
|
352
452
|
}
|
353
453
|
histTimerEnd({ success: false })
|
354
454
|
} finally {
|
@@ -376,100 +476,108 @@ const postParticipantsBatch = async (headers, method, requestPayload, span) => {
|
|
376
476
|
'Post participants batch',
|
377
477
|
['success']
|
378
478
|
).startTimer()
|
479
|
+
const errorCounter = Metrics.getCounter('errorCount')
|
480
|
+
const requestId = requestPayload.requestId
|
481
|
+
const log = logger.child({ context: 'postParticipantsBatch', requestId })
|
379
482
|
const childSpan = span ? span.getChild('postParticipantsBatch') : undefined
|
380
483
|
let fspiopError
|
484
|
+
let step
|
381
485
|
try {
|
382
|
-
|
486
|
+
log.info('postParticipantsBatch::begin', { headers, requestPayload })
|
383
487
|
const typeMap = new Map()
|
384
488
|
const overallReturnList = []
|
385
|
-
const
|
489
|
+
const pushPartyError = (party, errCode) => {
|
490
|
+
log.debug('party error details:', { party, errCode })
|
491
|
+
overallReturnList.push({
|
492
|
+
partyId: party,
|
493
|
+
...ErrorHandler.Factory.createFSPIOPError(errCode, undefined, undefined, undefined, [{
|
494
|
+
key: party.partyIdType,
|
495
|
+
value: party.partyIdentifier
|
496
|
+
}]).toApiErrorObject(Config.ERROR_HANDLING)
|
497
|
+
})
|
498
|
+
}
|
499
|
+
step = 'validateParticipant-1'
|
386
500
|
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
|
-
}
|
501
|
+
if (!requesterParticipantModel) {
|
502
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
503
|
+
log.error(errMessage)
|
504
|
+
fspiopError = ErrorHandler.Factory.createFSPIOPError(FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
505
|
+
throw fspiopError
|
506
|
+
}
|
412
507
|
|
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
|
-
}
|
508
|
+
for (const party of requestPayload.partyList) {
|
509
|
+
if (Object.values(Enums.Accounts.PartyAccountTypes).includes(party.partyIdType)) {
|
510
|
+
party.currency = requestPayload.currency
|
511
|
+
if (party.fspId === headers[Enums.Http.Headers.FSPIOP.SOURCE]) {
|
512
|
+
if (typeMap.get(party.partyIdType)) {
|
513
|
+
const partyList = typeMap.get(party.partyIdType)
|
514
|
+
partyList.push(party)
|
515
|
+
typeMap.set(party.partyIdType, partyList)
|
426
516
|
} 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
|
-
}
|
517
|
+
typeMap.set(party.partyIdType, [party])
|
433
518
|
}
|
434
519
|
} 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
|
-
}
|
520
|
+
pushPartyError(party, FSPIOPErrorCodes.PARTY_NOT_FOUND)
|
441
521
|
}
|
522
|
+
} else {
|
523
|
+
pushPartyError(party, FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
442
524
|
}
|
525
|
+
}
|
526
|
+
|
527
|
+
for (const [key, value] of typeMap) {
|
443
528
|
const payload = {
|
444
|
-
|
445
|
-
|
529
|
+
requestId,
|
530
|
+
partyList: value
|
446
531
|
}
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
532
|
+
log.info(`postParticipantsBatch::oracleBatchRequest::type=${key}`, { payload })
|
533
|
+
step = 'oracleBatchRequest-2'
|
534
|
+
const response = await oracle.oracleBatchRequest(headers, method, requestPayload, key, payload)
|
535
|
+
if (Array.isArray(response?.data?.partyList) && response.data.partyList.length > 0) {
|
536
|
+
for (const party of response.data.partyList) {
|
537
|
+
party.partyId.currency = undefined
|
538
|
+
overallReturnList.push(party)
|
539
|
+
}
|
540
|
+
} else {
|
541
|
+
for (const party of value) {
|
542
|
+
pushPartyError(party, FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
543
|
+
}
|
455
544
|
}
|
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
545
|
}
|
546
|
+
|
547
|
+
const payload = {
|
548
|
+
partyList: overallReturnList,
|
549
|
+
currency: requestPayload.currency
|
550
|
+
}
|
551
|
+
const clonedHeaders = { ...headers }
|
552
|
+
if (!clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] || clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] === '') {
|
553
|
+
clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = headers[Enums.Http.Headers.FSPIOP.SOURCE]
|
554
|
+
clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
|
555
|
+
}
|
556
|
+
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)
|
557
|
+
if (childSpan && !childSpan.isFinished) {
|
558
|
+
await childSpan.finish()
|
559
|
+
}
|
560
|
+
log.info('postParticipantsBatch::end')
|
561
|
+
|
462
562
|
histTimerEnd({ success: true })
|
463
563
|
} catch (err) {
|
464
|
-
|
564
|
+
log.error('error in postParticipantsBatch', err)
|
465
565
|
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
|
566
|
+
const extensions = err.extensions || []
|
567
|
+
const system = extensions.find((element) => element.key === 'system')?.value || ''
|
568
|
+
errorCounter.inc({
|
569
|
+
code: fspiopError?.apiErrorCode,
|
570
|
+
system,
|
571
|
+
operation: 'postParticipantsBatch',
|
572
|
+
step
|
573
|
+
})
|
466
574
|
try {
|
467
575
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR,
|
468
576
|
fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, undefined, requestPayload)
|
469
577
|
} catch (exc) {
|
470
578
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
471
579
|
// we've already sent a sync response- we cannot throw.
|
472
|
-
|
580
|
+
log.error('error in participant.sendErrorToParticipant', exc)
|
473
581
|
}
|
474
582
|
histTimerEnd({ success: false })
|
475
583
|
} finally {
|
@@ -498,15 +606,20 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
|
|
498
606
|
'Delete participants',
|
499
607
|
['success']
|
500
608
|
).startTimer()
|
609
|
+
const errorCounter = Metrics.getCounter('errorCount')
|
610
|
+
const log = logger.child('deleteParticipants')
|
611
|
+
let step
|
501
612
|
try {
|
502
|
-
|
613
|
+
log.debug('deleteParticipants::begin', { headers, params })
|
503
614
|
const type = params.Type
|
504
615
|
const partySubIdOrType = params.SubId || undefined
|
505
616
|
const callbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
|
506
617
|
const errorCallbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
507
618
|
if (Object.values(Enums.Accounts.PartyAccountTypes).includes(type)) {
|
619
|
+
step = 'validateParticipant-1'
|
508
620
|
const requesterParticipantModel = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE])
|
509
621
|
if (requesterParticipantModel) {
|
622
|
+
step = 'oracleRequest-2'
|
510
623
|
const response = await oracle.oracleRequest(headers, method, params, query, undefined, cache)
|
511
624
|
if (response) {
|
512
625
|
const responsePayload = {
|
@@ -520,31 +633,44 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
|
|
520
633
|
const clonedHeaders = { ...headers }
|
521
634
|
clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = headers[Enums.Http.Headers.FSPIOP.SOURCE]
|
522
635
|
clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
|
636
|
+
step = 'sendRequest-3'
|
523
637
|
await participant.sendRequest(clonedHeaders, clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION], callbackEndpointType, Enums.Http.RestMethods.PUT, responsePayload, options)
|
524
638
|
} else {
|
639
|
+
step = 'sendErrorToParticipant-4'
|
525
640
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
526
641
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
527
642
|
}
|
528
643
|
} else {
|
529
|
-
|
530
|
-
|
644
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
645
|
+
log.error(errMessage)
|
646
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
531
647
|
}
|
532
648
|
} else {
|
649
|
+
step = 'sendErrorToParticipant-5'
|
533
650
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
534
651
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
535
652
|
}
|
536
|
-
|
653
|
+
log.info('deleteParticipants::end')
|
537
654
|
histTimerEnd({ success: true })
|
538
655
|
} catch (err) {
|
539
|
-
|
656
|
+
log.error('error in deleteParticipants', err)
|
540
657
|
try {
|
658
|
+
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR)
|
541
659
|
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
660
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
543
|
-
|
661
|
+
fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
662
|
+
const extensions = err.extensions || []
|
663
|
+
const system = extensions.find((element) => element.key === 'system')?.value || ''
|
664
|
+
errorCounter.inc({
|
665
|
+
code: fspiopError?.apiErrorCode,
|
666
|
+
system,
|
667
|
+
operation: 'deleteParticipants',
|
668
|
+
step
|
669
|
+
})
|
544
670
|
} catch (exc) {
|
545
671
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
546
672
|
// we've already sent a sync response- we cannot throw.
|
547
|
-
|
673
|
+
log.error('error in participant.sendErrorToParticipant', exc)
|
548
674
|
}
|
549
675
|
histTimerEnd({ success: false })
|
550
676
|
}
|