account-lookup-service 15.6.0-iso.13 → 15.6.0-iso.14
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/package.json
CHANGED
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
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
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
|
93
|
+
}
|
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]
|
87
97
|
}
|
88
|
-
|
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
|
}
|
@@ -247,9 +278,11 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
|
|
247
278
|
}
|
248
279
|
histTimerEnd({ success: true })
|
249
280
|
} catch (err) {
|
250
|
-
|
281
|
+
logger.error('error in putParticipantsErrorByTypeAndID:', err)
|
251
282
|
try {
|
252
|
-
const callbackEndpointType = params.SubId
|
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
|
253
286
|
await participant.sendErrorToParticipant(
|
254
287
|
headers[Enums.Http.Headers.FSPIOP.SOURCE],
|
255
288
|
callbackEndpointType,
|
@@ -260,7 +293,7 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
|
|
260
293
|
} catch (exc) {
|
261
294
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
262
295
|
// we've already sent a sync response- we cannot throw.
|
263
|
-
|
296
|
+
logger.error('error in participant.sendErrorToParticipant:', exc)
|
264
297
|
}
|
265
298
|
histTimerEnd({ success: false })
|
266
299
|
}
|
@@ -286,7 +319,7 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
286
319
|
const childSpan = span ? span.getChild('postParticipants') : undefined
|
287
320
|
let fspiopError
|
288
321
|
try {
|
289
|
-
|
322
|
+
logger.info('postParticipants::begin')
|
290
323
|
const type = params.Type
|
291
324
|
const partySubIdOrType = params.SubId
|
292
325
|
const callbackEndpointType = partySubIdOrType
|
@@ -334,8 +367,9 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
334
367
|
fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
|
335
368
|
}
|
336
369
|
} else {
|
337
|
-
|
338
|
-
|
370
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
371
|
+
logger.error(errMessage)
|
372
|
+
fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
339
373
|
throw fspiopError
|
340
374
|
}
|
341
375
|
} else {
|
@@ -343,10 +377,10 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
343
377
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
344
378
|
fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
|
345
379
|
}
|
346
|
-
|
380
|
+
logger.info('postParticipants::end')
|
347
381
|
histTimerEnd({ success: true })
|
348
382
|
} catch (err) {
|
349
|
-
|
383
|
+
logger.error('error in postParticipants:', err)
|
350
384
|
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
351
385
|
try {
|
352
386
|
const errorCallbackEndpointType = params.SubId
|
@@ -357,7 +391,7 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
357
391
|
} catch (exc) {
|
358
392
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
359
393
|
// we've already sent a sync response- we cannot throw.
|
360
|
-
|
394
|
+
logger.error('failed to handle exception in postParticipants:', exc)
|
361
395
|
}
|
362
396
|
histTimerEnd({ success: false })
|
363
397
|
} finally {
|
@@ -385,92 +419,90 @@ const postParticipantsBatch = async (headers, method, requestPayload, span) => {
|
|
385
419
|
'Post participants batch',
|
386
420
|
['success']
|
387
421
|
).startTimer()
|
422
|
+
const requestId = requestPayload.requestId
|
423
|
+
const log = logger.child({ context: 'postParticipantsBatch', requestId })
|
388
424
|
const childSpan = span ? span.getChild('postParticipantsBatch') : undefined
|
389
425
|
let fspiopError
|
426
|
+
|
390
427
|
try {
|
391
|
-
|
428
|
+
log.info('postParticipantsBatch::begin', { headers, requestPayload })
|
392
429
|
const typeMap = new Map()
|
393
430
|
const overallReturnList = []
|
394
|
-
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
|
+
|
395
442
|
const requesterParticipantModel = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], childSpan)
|
396
|
-
if (requesterParticipantModel) {
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
const partyList = typeMap.get(party.partyIdType)
|
403
|
-
partyList.push(party)
|
404
|
-
typeMap.set(party.partyIdType, partyList)
|
405
|
-
} else {
|
406
|
-
typeMap.set(party.partyIdType, [party])
|
407
|
-
}
|
408
|
-
} else {
|
409
|
-
overallReturnList.push(ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND, undefined, undefined, undefined, [{
|
410
|
-
key: party.partyIdType,
|
411
|
-
value: party.partyIdentifier
|
412
|
-
}]).toApiErrorObject(Config.ERROR_HANDLING))
|
413
|
-
}
|
414
|
-
} else {
|
415
|
-
overallReturnList.push(ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, undefined, undefined, undefined, [{
|
416
|
-
key: party.partyIdType,
|
417
|
-
value: party.partyIdentifier
|
418
|
-
}]).toApiErrorObject(Config.ERROR_HANDLING))
|
419
|
-
}
|
420
|
-
}
|
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
|
+
}
|
421
449
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
if (Array.isArray(response.data.partyList) && response.data.partyList.length > 0) {
|
431
|
-
for (const party of response.data.partyList) {
|
432
|
-
party.partyId.currency = undefined
|
433
|
-
overallReturnList.push(party)
|
434
|
-
}
|
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)
|
435
458
|
} else {
|
436
|
-
|
437
|
-
overallReturnList.push(ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, undefined, undefined, undefined, [{
|
438
|
-
key: party.partyIdType,
|
439
|
-
value: party.partyIdentifier
|
440
|
-
}]).toApiErrorObject(Config.ERROR_HANDLING))
|
441
|
-
}
|
459
|
+
typeMap.set(party.partyIdType, [party])
|
442
460
|
}
|
443
461
|
} else {
|
444
|
-
|
445
|
-
overallReturnList.push(ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, undefined, undefined, undefined, [{
|
446
|
-
key: party.partyIdType,
|
447
|
-
value: party.partyIdentifier
|
448
|
-
}]).toApiErrorObject(Config.ERROR_HANDLING))
|
449
|
-
}
|
462
|
+
pushPartyError(party, FSPIOPErrorCodes.PARTY_NOT_FOUND)
|
450
463
|
}
|
464
|
+
} else {
|
465
|
+
pushPartyError(party, FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
451
466
|
}
|
467
|
+
}
|
468
|
+
|
469
|
+
for (const [key, value] of typeMap) {
|
452
470
|
const payload = {
|
453
|
-
|
454
|
-
|
471
|
+
requestId,
|
472
|
+
partyList: value
|
455
473
|
}
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
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
|
+
}
|
464
485
|
}
|
465
|
-
Logger.isInfoEnabled && Logger.info('postParticipantsBatch::end')
|
466
|
-
} else {
|
467
|
-
Logger.isErrorEnabled && Logger.error('Requester FSP not found')
|
468
|
-
fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, 'Requester FSP not found')
|
469
|
-
throw fspiopError
|
470
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
|
+
|
471
503
|
histTimerEnd({ success: true })
|
472
504
|
} catch (err) {
|
473
|
-
|
505
|
+
log.error('error in postParticipantsBatch', err)
|
474
506
|
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
|
475
507
|
try {
|
476
508
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR,
|
@@ -478,7 +510,7 @@ const postParticipantsBatch = async (headers, method, requestPayload, span) => {
|
|
478
510
|
} catch (exc) {
|
479
511
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
480
512
|
// we've already sent a sync response- we cannot throw.
|
481
|
-
|
513
|
+
log.error('error in participant.sendErrorToParticipant', exc)
|
482
514
|
}
|
483
515
|
histTimerEnd({ success: false })
|
484
516
|
} finally {
|
@@ -507,8 +539,9 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
|
|
507
539
|
'Delete participants',
|
508
540
|
['success']
|
509
541
|
).startTimer()
|
542
|
+
const log = logger.child('deleteParticipants')
|
510
543
|
try {
|
511
|
-
|
544
|
+
log.debug('deleteParticipants::begin', { headers, params })
|
512
545
|
const type = params.Type
|
513
546
|
const partySubIdOrType = params.SubId || undefined
|
514
547
|
const callbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
|
@@ -535,17 +568,18 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
|
|
535
568
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
536
569
|
}
|
537
570
|
} else {
|
538
|
-
|
539
|
-
|
571
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
572
|
+
log.error(errMessage)
|
573
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
540
574
|
}
|
541
575
|
} else {
|
542
576
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
543
577
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
544
578
|
}
|
545
|
-
|
579
|
+
log.info('deleteParticipants::end')
|
546
580
|
histTimerEnd({ success: true })
|
547
581
|
} catch (err) {
|
548
|
-
|
582
|
+
log.error('error in deleteParticipants', err)
|
549
583
|
try {
|
550
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
|
551
585
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
@@ -553,7 +587,7 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
|
|
553
587
|
} catch (exc) {
|
554
588
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
555
589
|
// we've already sent a sync response- we cannot throw.
|
556
|
-
|
590
|
+
log.error('error in participant.sendErrorToParticipant', exc)
|
557
591
|
}
|
558
592
|
histTimerEnd({ success: false })
|
559
593
|
}
|
@@ -35,16 +35,12 @@ const Helper = require('../../../util/helper')
|
|
35
35
|
const participants = require('../../../../src/domain/participants')
|
36
36
|
const initServer = require('../../../../src/server').initializeApi
|
37
37
|
const getPort = require('get-port')
|
38
|
-
const Logger = require('@mojaloop/central-services-logger')
|
39
38
|
const Config = require('../../../../src/lib/config')
|
40
39
|
|
41
|
-
Logger.isDebugEnabled = jest.fn(() => true)
|
42
|
-
Logger.isErrorEnabled = jest.fn(() => true)
|
43
|
-
Logger.isInfoEnabled = jest.fn(() => true)
|
44
|
-
let server
|
45
|
-
let sandbox
|
46
|
-
|
47
40
|
describe('/participants', () => {
|
41
|
+
let server
|
42
|
+
let sandbox
|
43
|
+
|
48
44
|
beforeAll(async () => {
|
49
45
|
sandbox = Sinon.createSandbox()
|
50
46
|
sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
|
@@ -56,6 +52,7 @@ describe('/participants', () => {
|
|
56
52
|
await server.stop()
|
57
53
|
sandbox.restore()
|
58
54
|
})
|
55
|
+
|
59
56
|
const mock = {
|
60
57
|
requestId: '3ede3c17-36aa-42f4-b6db-b0df2e42f31e',
|
61
58
|
partyList: [{
|
@@ -79,6 +76,7 @@ describe('/participants', () => {
|
|
79
76
|
],
|
80
77
|
currency: 'EUR'
|
81
78
|
}
|
79
|
+
|
82
80
|
it('postParticipantsBatch success', async () => {
|
83
81
|
// Arrange
|
84
82
|
const options = {
|
@@ -38,12 +38,13 @@ const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
38
38
|
const participantsDomain = require('../../../../src/domain/participants/participants')
|
39
39
|
const participant = require('../../../../src/models/participantEndpoint/facade')
|
40
40
|
const oracle = require('../../../../src/models/oracle/facade')
|
41
|
-
const Helper = require('../../../util/helper')
|
42
41
|
const Config = require('../../../../src/lib/config')
|
42
|
+
const { logger } = require('../../../../src/lib')
|
43
|
+
const { ERROR_MESSAGES } = require('../../../../src/constants')
|
44
|
+
const Helper = require('../../../util/helper')
|
45
|
+
const fixtures = require('../../../fixtures')
|
43
46
|
|
44
|
-
|
45
|
-
Logger.isErrorEnabled = jest.fn(() => true)
|
46
|
-
Logger.isInfoEnabled = jest.fn(() => true)
|
47
|
+
const { Headers } = Enums.Http
|
47
48
|
|
48
49
|
describe('participant Tests', () => {
|
49
50
|
describe('getParticipantsByTypeAndID', () => {
|
@@ -185,7 +186,7 @@ describe('participant Tests', () => {
|
|
185
186
|
expect.hasAssertions()
|
186
187
|
// Arrange
|
187
188
|
participant.validateParticipant = sandbox.stub().resolves(null)
|
188
|
-
const
|
189
|
+
const logStub = sandbox.stub(logger.constructor.prototype, 'warn')
|
189
190
|
|
190
191
|
participant.sendRequest = sandbox.stub()
|
191
192
|
const args = [
|
@@ -199,8 +200,8 @@ describe('participant Tests', () => {
|
|
199
200
|
await participantsDomain.getParticipantsByTypeAndID(...args)
|
200
201
|
|
201
202
|
// Assert
|
202
|
-
const firstCallArgs =
|
203
|
-
expect(firstCallArgs[0]).toBe(
|
203
|
+
const firstCallArgs = logStub.getCall(0).args
|
204
|
+
expect(firstCallArgs[0]).toBe(ERROR_MESSAGES.sourceFspNotFound)
|
204
205
|
})
|
205
206
|
|
206
207
|
it('fails when `oracleRequest` response is empty', async () => {
|
@@ -485,9 +486,8 @@ describe('participant Tests', () => {
|
|
485
486
|
it('handles the case where `validateParticipant` returns null', async () => {
|
486
487
|
expect.hasAssertions()
|
487
488
|
// Arrange
|
489
|
+
const logStub = sandbox.stub(logger.constructor.prototype, 'error')
|
488
490
|
participant.validateParticipant = sandbox.stub().resolves(null)
|
489
|
-
sandbox.stub(Logger)
|
490
|
-
Logger.error = sandbox.stub()
|
491
491
|
participant.sendErrorToParticipant = sandbox.stub()
|
492
492
|
const headers = {
|
493
493
|
accept: 'application/vnd.interoperability.participants+json;version=1',
|
@@ -510,8 +510,7 @@ describe('participant Tests', () => {
|
|
510
510
|
await participantsDomain.putParticipantsByTypeAndID(headers, params, method, payload)
|
511
511
|
|
512
512
|
// Assert
|
513
|
-
|
514
|
-
expect(loggerFirstCallArgs[0]).toBe('Requester FSP not found')
|
513
|
+
expect(logStub.getCall(0).args[1].message).toBe(ERROR_MESSAGES.sourceFspNotFound)
|
515
514
|
})
|
516
515
|
|
517
516
|
it('handles case where type is not in `PartyAccountTypes`', async () => {
|
@@ -739,9 +738,6 @@ describe('participant Tests', () => {
|
|
739
738
|
it('handles PUT /error when SubId supplied but validateParticipant throws error', async () => {
|
740
739
|
expect.hasAssertions()
|
741
740
|
// Arrange
|
742
|
-
sandbox.stub(Logger)
|
743
|
-
Logger.info = sandbox.stub()
|
744
|
-
Logger.error = sandbox.stub()
|
745
741
|
participant.validateParticipant = sandbox.stub().throws(new Error('Validation failed'))
|
746
742
|
oracle.oracleRequest = sandbox.stub().resolves(null)
|
747
743
|
participant.sendErrorToParticipant = sandbox.stub()
|
@@ -771,15 +767,11 @@ describe('participant Tests', () => {
|
|
771
767
|
expect(participant.sendErrorToParticipant.callCount).toBe(1)
|
772
768
|
const firstCallArgs = participant.sendErrorToParticipant.getCall(0).args
|
773
769
|
expect(firstCallArgs[1]).toBe(expectedCallbackEndpointType)
|
774
|
-
expect(Logger.error.callCount).toBe(1)
|
775
770
|
})
|
776
771
|
|
777
772
|
it('handles PUT /error when `sendErrorToParticipant` throws error', async () => {
|
778
773
|
expect.hasAssertions()
|
779
774
|
// Arrange
|
780
|
-
sandbox.stub(Logger)
|
781
|
-
Logger.info = sandbox.stub()
|
782
|
-
Logger.error = sandbox.stub()
|
783
775
|
participant.validateParticipant = sandbox.stub().resolves({})
|
784
776
|
participant.sendErrorToParticipant = sandbox.stub().throws(new Error('sendErrorToParticipant failed'))
|
785
777
|
const expectedCallbackEndpointType = Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
@@ -809,15 +801,11 @@ describe('participant Tests', () => {
|
|
809
801
|
const secondCallArgs = participant.sendErrorToParticipant.getCall(1).args
|
810
802
|
expect(firstCallArgs[1]).toBe(expectedCallbackEndpointType)
|
811
803
|
expect(secondCallArgs[0]).toBe(Config.HUB_NAME)
|
812
|
-
expect(Logger.error.callCount).toBe(2)
|
813
804
|
})
|
814
805
|
|
815
806
|
it('handles PUT /error when SubId is supplied and `sendErrorToParticipant` throws error', async () => {
|
816
807
|
expect.hasAssertions()
|
817
808
|
// Arrange
|
818
|
-
sandbox.stub(Logger)
|
819
|
-
Logger.info = sandbox.stub()
|
820
|
-
Logger.error = sandbox.stub()
|
821
809
|
participant.validateParticipant = sandbox.stub().resolves({})
|
822
810
|
participant.sendErrorToParticipant = sandbox.stub().throws(new Error('sendErrorToParticipant failed'))
|
823
811
|
const expectedCallbackEndpointType = Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
|
@@ -848,7 +836,6 @@ describe('participant Tests', () => {
|
|
848
836
|
const secondCallArgs = participant.sendErrorToParticipant.getCall(1).args
|
849
837
|
expect(firstCallArgs[1]).toBe(expectedCallbackEndpointType)
|
850
838
|
expect(secondCallArgs[0]).toBe(Config.HUB_NAME)
|
851
|
-
expect(Logger.error.callCount).toBe(2)
|
852
839
|
})
|
853
840
|
})
|
854
841
|
|
@@ -1048,9 +1035,8 @@ describe('participant Tests', () => {
|
|
1048
1035
|
it('handles the case where `validateParticipant` returns null', async () => {
|
1049
1036
|
expect.hasAssertions()
|
1050
1037
|
// Arrange
|
1038
|
+
const logStub = sandbox.stub(logger.constructor.prototype, 'error')
|
1051
1039
|
participant.validateParticipant = sandbox.stub().resolves(null)
|
1052
|
-
sandbox.stub(Logger)
|
1053
|
-
Logger.error = sandbox.stub()
|
1054
1040
|
participant.sendErrorToParticipant = sandbox.stub()
|
1055
1041
|
const headers = {
|
1056
1042
|
accept: 'application/vnd.interoperability.participants+json;version=1',
|
@@ -1072,8 +1058,7 @@ describe('participant Tests', () => {
|
|
1072
1058
|
await participantsDomain.postParticipants(headers, 'get', params, payload)
|
1073
1059
|
|
1074
1060
|
// Assert
|
1075
|
-
|
1076
|
-
expect(loggerFirstCallArgs[0]).toBe('Requester FSP not found')
|
1061
|
+
expect(logStub.getCall(0).args[0]).toBe(ERROR_MESSAGES.sourceFspNotFound)
|
1077
1062
|
})
|
1078
1063
|
|
1079
1064
|
it('handles case where type is not in `PartyAccountTypes`', async () => {
|
@@ -1202,7 +1187,7 @@ describe('participant Tests', () => {
|
|
1202
1187
|
|
1203
1188
|
const headers = {
|
1204
1189
|
accept: 'application/vnd.interoperability.participants+json;version=1',
|
1205
|
-
'fspiop-destination': Config.HUB_NAME,
|
1190
|
+
// 'fspiop-destination': Config.HUB_NAME,
|
1206
1191
|
'content-type': 'application/vnd.interoperability.participants+json;version=1.1',
|
1207
1192
|
date: '2019-05-24 08:52:19',
|
1208
1193
|
'fspiop-source': 'fsp1'
|
@@ -1318,15 +1303,23 @@ describe('participant Tests', () => {
|
|
1318
1303
|
const expected = {
|
1319
1304
|
currency: 'USD',
|
1320
1305
|
partyList: [
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1306
|
+
{
|
1307
|
+
...ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND, undefined, undefined, undefined, [{
|
1308
|
+
key: Enums.Accounts.PartyAccountTypes.MSISDN,
|
1309
|
+
value: undefined
|
1310
|
+
}]).toApiErrorObject(Config.ERROR_HANDLING),
|
1311
|
+
partyId: payload.partyList[1]
|
1312
|
+
},
|
1313
|
+
{
|
1314
|
+
...ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, undefined, undefined, undefined, [{
|
1315
|
+
key: 'NOT_A_VALID_PARTY_ID',
|
1316
|
+
value: undefined
|
1317
|
+
}]).toApiErrorObject(Config.ERROR_HANDLING),
|
1318
|
+
partyId: payload.partyList[2]
|
1319
|
+
},
|
1320
|
+
{
|
1321
|
+
partyId: { currency: undefined }
|
1322
|
+
}
|
1330
1323
|
]
|
1331
1324
|
}
|
1332
1325
|
|
@@ -1342,10 +1335,10 @@ describe('participant Tests', () => {
|
|
1342
1335
|
it('handles error when `validateParticipant` fails and `sendErrorToParticipant` throws', async () => {
|
1343
1336
|
expect.hasAssertions()
|
1344
1337
|
// Arrange
|
1345
|
-
sandbox.stub(
|
1346
|
-
Logger.error = sandbox.stub()
|
1338
|
+
const logStub = sandbox.stub(logger.constructor.prototype, 'error')
|
1347
1339
|
participant.validateParticipant = sandbox.stub().resolves(null)
|
1348
|
-
|
1340
|
+
const cbError = new Error('unknown error')
|
1341
|
+
participant.sendErrorToParticipant = sandbox.stub().throws(cbError)
|
1349
1342
|
|
1350
1343
|
const headers = {
|
1351
1344
|
accept: 'application/vnd.interoperability.participants+json;version=1',
|
@@ -1368,10 +1361,8 @@ describe('participant Tests', () => {
|
|
1368
1361
|
await participantsDomain.postParticipantsBatch(headers, 'get', payload, Helper.mockSpan())
|
1369
1362
|
|
1370
1363
|
// Assert
|
1371
|
-
|
1372
|
-
|
1373
|
-
expect(firstCallArgs[0]).toBe('Requester FSP not found')
|
1374
|
-
expect(thirdCallArgs[0].message).toBe('unknown error')
|
1364
|
+
expect(logStub.getCall(0).firstArg).toBe(ERROR_MESSAGES.sourceFspNotFound)
|
1365
|
+
expect(logStub.getCall(2).lastArg).toEqual(cbError)
|
1375
1366
|
})
|
1376
1367
|
|
1377
1368
|
it('handles error when `oracleBatchRequest` returns no result', async () => {
|
@@ -1447,6 +1438,44 @@ describe('participant Tests', () => {
|
|
1447
1438
|
expect(firstCallArgs[4].partyList[1].errorInformation).toBeDefined()
|
1448
1439
|
expect(firstCallArgs[4].partyList[2].errorInformation).toBeDefined()
|
1449
1440
|
})
|
1441
|
+
|
1442
|
+
it('should not call oracle if source-header and fspId in payload are different, and no destination [CSI-938]', async () => {
|
1443
|
+
const headers = fixtures.participantsCallHeadersDto({ destination: '' })
|
1444
|
+
const payload = {
|
1445
|
+
requestId: '0e21b07e-3117-46ca-ae22-6ee370895697',
|
1446
|
+
currency: 'MWK',
|
1447
|
+
partyList: [
|
1448
|
+
{
|
1449
|
+
fspId: 'test-mwk-dfsp',
|
1450
|
+
partyIdType: 'MSISDN',
|
1451
|
+
partyIdentifier: '16665551002'
|
1452
|
+
}
|
1453
|
+
]
|
1454
|
+
}
|
1455
|
+
expect(headers.source).not.toBe(payload.partyList[0].fspId)
|
1456
|
+
expect(headers.destination).toBeUndefined()
|
1457
|
+
|
1458
|
+
participant.validateParticipant = sandbox.stub().resolves({})
|
1459
|
+
participant.sendRequest = sandbox.stub()
|
1460
|
+
participant.sendErrorToParticipant = sandbox.stub().resolves({})
|
1461
|
+
oracle.oracleBatchRequest = sandbox.stub().resolves({})
|
1462
|
+
|
1463
|
+
await participantsDomain.postParticipantsBatch(headers, 'put', payload, Helper.mockSpan())
|
1464
|
+
|
1465
|
+
expect(oracle.oracleBatchRequest.callCount).toBe(0)
|
1466
|
+
expect(participant.sendErrorToParticipant.callCount).toBe(0)
|
1467
|
+
expect(participant.sendRequest.callCount).toBe(1)
|
1468
|
+
|
1469
|
+
const { args } = participant.sendRequest.getCall(0)
|
1470
|
+
expect(args[0][Headers.FSPIOP.DESTINATION]).toBe(headers[Headers.FSPIOP.SOURCE])
|
1471
|
+
expect(args[0][Headers.FSPIOP.SOURCE]).toBe(Config.HUB_NAME)
|
1472
|
+
expect(args[1]).toBe(headers[Headers.FSPIOP.SOURCE])
|
1473
|
+
|
1474
|
+
const { partyList } = args[4]
|
1475
|
+
expect(partyList.length).toBe(1)
|
1476
|
+
expect(partyList[0].errorInformation).toBeDefined()
|
1477
|
+
expect(partyList[0].partyId).toBe(payload.partyList[0])
|
1478
|
+
})
|
1450
1479
|
})
|
1451
1480
|
|
1452
1481
|
describe('deleteParticipants', () => {
|
@@ -1602,9 +1631,8 @@ describe('participant Tests', () => {
|
|
1602
1631
|
it('handles the case where `validateParticipant` returns null', async () => {
|
1603
1632
|
expect.hasAssertions()
|
1604
1633
|
// Arrange
|
1634
|
+
const logStub = sandbox.stub(logger.constructor.prototype, 'error')
|
1605
1635
|
participant.validateParticipant = sandbox.stub().resolves(null)
|
1606
|
-
sandbox.stub(Logger)
|
1607
|
-
Logger.error = sandbox.stub()
|
1608
1636
|
participant.sendErrorToParticipant = sandbox.stub()
|
1609
1637
|
const headers = {
|
1610
1638
|
accept: 'application/vnd.interoperability.participants+json;version=1',
|
@@ -1625,8 +1653,8 @@ describe('participant Tests', () => {
|
|
1625
1653
|
await participantsDomain.deleteParticipants(headers, params, method, query)
|
1626
1654
|
|
1627
1655
|
// Assert
|
1628
|
-
|
1629
|
-
expect(
|
1656
|
+
expect(logStub.getCall(0).firstArg).toBe(ERROR_MESSAGES.sourceFspNotFound)
|
1657
|
+
// expect(logStub.getCall()]).toBe(ERROR_MESSAGES.sourceFspNotFound)
|
1630
1658
|
})
|
1631
1659
|
|
1632
1660
|
it('handles case where type is not in `PartyAccountTypes`', async () => {
|