account-lookup-service 15.6.0-snapshot.2 → 16.1.0-iso.0
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/CHANGELOG.md +25 -0
- package/LICENSE.md +3 -4
- package/README.md +2 -0
- package/audit-ci.jsonc +2 -27
- package/config/default.json +1 -0
- package/docker/mock-proxy/README.md +21 -0
- package/docker/mock-proxy/src/config.ts +7 -0
- package/docs/Proxy/Discovery.md +20 -0
- package/docs/Proxy/FXAPI_POC_payer_conversion_RECEIVE.plantuml +577 -0
- package/docs/Proxy/FXAPI_POC_payer_conversion_SEND.plantuml +1423 -0
- package/docs/Proxy/P2P.md +11 -0
- package/docs/Proxy/Proxy pattern - Happy path.plantuml +98 -0
- package/docs/Proxy/Proxy pattern - Lazy Discovery - No Oracles.plantuml +105 -0
- package/docs/Proxy/Proxy pattern - Lazy Discovery - No Oracles.png +0 -0
- package/docs/Proxy/Proxy pattern - Lazy Discovery - Oracles.plantuml +130 -0
- package/docs/Proxy/Proxy pattern - Lazy Discovery - Oracles.png +0 -0
- package/docs/Proxy/Proxy pattern - Lazy Discovery Identifier Cache Invalid.plantuml +72 -0
- package/docs/Proxy/Proxy pattern - Lazy Discovery Identifier Cache Invalid.png +0 -0
- package/docs/Proxy/Proxy pattern - P2P.plantuml +186 -0
- package/docs/Proxy/Proxy pattern - P2P.png +0 -0
- package/docs/Proxy/Proxy pattern - Unhappy path.plantuml +103 -0
- package/docs/Proxy/Proxy pattern - Unhappy path.png +0 -0
- package/docs/Proxy/Proxy pattern - happy path.png +0 -0
- package/docs/Proxy/Readme.md +39 -0
- package/docs/Proxy/SettingUpProxys.plantuml +31 -0
- package/docs/Proxy/SettingUpProxys.png +0 -0
- package/package.json +33 -18
- package/src/constants.js +2 -1
- package/src/domain/oracle/oracle.js +63 -4
- package/src/domain/participants/participants.js +246 -129
- package/src/domain/parties/getPartiesByTypeAndID.js +28 -7
- package/src/domain/parties/parties.js +43 -14
- 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/lib/config.js +2 -1
- package/src/lib/db.js +2 -1
- package/src/models/currency/currency.js +10 -1
- package/src/models/endpointType/endpointType.js +10 -1
- package/src/models/oracle/facade.js +42 -16
- package/src/models/oracle/oracleEndpoint.js +65 -10
- package/src/models/oracle/oracleEndpointCached.js +29 -9
- package/src/models/participantEndpoint/facade.js +40 -4
- package/src/models/partyIdType/partyIdType.js +10 -1
- package/src/plugins.js +8 -21
- package/src/server.js +11 -0
- package/test/fixtures/index.js +30 -6
- 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 +8 -0
- package/test/unit/domain/timeout/index.test.js +8 -0
- package/test/unit/lib/config.test.js +7 -0
- package/test/unit/mocks.js +16 -11
- package/test/unit/models/oracle/oracleEndpointCached.test.js +32 -0
- package/test/unit/plugins.test.js +2 -2
- package/test/util/apiClients/BasicApiClient.js +2 -2
- 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
|
-
}
|
85
|
-
|
86
|
-
|
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, true)
|
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
|
96
|
+
}
|
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]
|
87
100
|
}
|
88
|
-
|
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?.code,
|
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?.code,
|
256
|
+
system,
|
257
|
+
operation: 'putParticipantsByTypeAndID',
|
258
|
+
step
|
259
|
+
})
|
200
260
|
histTimerEnd({ success: false })
|
201
261
|
}
|
202
262
|
}
|
@@ -220,14 +280,18 @@ 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
287
|
const callbackEndpointType = partySubIdOrType
|
226
288
|
? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
|
227
289
|
: Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
290
|
+
step = 'validateParticipant-1'
|
228
291
|
const destinationParticipant = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.DESTINATION])
|
229
292
|
if (destinationParticipant) {
|
230
293
|
const decodedPayload = decodePayload(dataUri, { asParsed: false })
|
294
|
+
step = 'sendErrorToParticipant-2'
|
231
295
|
await participant.sendErrorToParticipant(
|
232
296
|
headers[Enums.Http.Headers.FSPIOP.DESTINATION],
|
233
297
|
callbackEndpointType,
|
@@ -236,6 +300,7 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
|
|
236
300
|
params
|
237
301
|
)
|
238
302
|
} else {
|
303
|
+
step = 'sendErrorToParticipant-3'
|
239
304
|
await participant.sendErrorToParticipant(
|
240
305
|
headers[Enums.Http.Headers.FSPIOP.SOURCE],
|
241
306
|
callbackEndpointType,
|
@@ -247,20 +312,31 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
|
|
247
312
|
}
|
248
313
|
histTimerEnd({ success: true })
|
249
314
|
} catch (err) {
|
250
|
-
|
315
|
+
logger.error('error in putParticipantsErrorByTypeAndID:', err)
|
251
316
|
try {
|
252
|
-
const
|
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
|
253
321
|
await participant.sendErrorToParticipant(
|
254
322
|
headers[Enums.Http.Headers.FSPIOP.SOURCE],
|
255
323
|
callbackEndpointType,
|
256
|
-
|
324
|
+
fspiopError.toApiErrorObject(),
|
257
325
|
headers,
|
258
326
|
params
|
259
327
|
)
|
328
|
+
const extensions = err.extensions || []
|
329
|
+
const system = extensions.find((element) => element.key === 'system')?.value || ''
|
330
|
+
errorCounter.inc({
|
331
|
+
code: fspiopError?.apiErrorCode?.code,
|
332
|
+
system,
|
333
|
+
operation: 'putParticipantsErrorByTypeAndID',
|
334
|
+
step
|
335
|
+
})
|
260
336
|
} catch (exc) {
|
261
337
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
262
338
|
// we've already sent a sync response- we cannot throw.
|
263
|
-
|
339
|
+
logger.error('error in participant.sendErrorToParticipant:', exc)
|
264
340
|
}
|
265
341
|
histTimerEnd({ success: false })
|
266
342
|
}
|
@@ -283,10 +359,12 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
283
359
|
'Post participants',
|
284
360
|
['success']
|
285
361
|
).startTimer()
|
362
|
+
const errorCounter = Metrics.getCounter('errorCount')
|
286
363
|
const childSpan = span ? span.getChild('postParticipants') : undefined
|
287
364
|
let fspiopError
|
365
|
+
let step
|
288
366
|
try {
|
289
|
-
|
367
|
+
logger.info('postParticipants::begin')
|
290
368
|
const type = params.Type
|
291
369
|
const partySubIdOrType = params.SubId
|
292
370
|
const callbackEndpointType = partySubIdOrType
|
@@ -297,8 +375,10 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
297
375
|
: Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
298
376
|
|
299
377
|
if (Object.values(Enums.Accounts.PartyAccountTypes).includes(type)) {
|
378
|
+
step = 'validateParticipant-1'
|
300
379
|
const requesterParticipantModel = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], childSpan)
|
301
380
|
if (requesterParticipantModel) {
|
381
|
+
step = 'oracleRequest-2'
|
302
382
|
const response = await oracle.oracleRequest(headers, method, params, undefined, payload, cache)
|
303
383
|
if (response && response.status === Enums.Http.ReturnCodes.CREATED.CODE) {
|
304
384
|
const responsePayload = {
|
@@ -324,18 +404,21 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
324
404
|
clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = payload.fspId
|
325
405
|
clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
|
326
406
|
}
|
407
|
+
step = 'sendRequest-3'
|
327
408
|
await participant.sendRequest(clonedHeaders, clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION], callbackEndpointType, Enums.Http.RestMethods.PUT, responsePayload, options, childSpan)
|
328
409
|
if (childSpan && !childSpan.isFinished) {
|
329
410
|
await childSpan.finish()
|
330
411
|
}
|
331
412
|
} else {
|
332
413
|
fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
414
|
+
step = 'sendErrorToParticipant-4'
|
333
415
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
334
416
|
fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
|
335
417
|
}
|
336
418
|
} else {
|
337
|
-
|
338
|
-
|
419
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
420
|
+
logger.error(errMessage)
|
421
|
+
fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
339
422
|
throw fspiopError
|
340
423
|
}
|
341
424
|
} else {
|
@@ -343,11 +426,19 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
343
426
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
344
427
|
fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
|
345
428
|
}
|
346
|
-
|
429
|
+
logger.info('postParticipants::end')
|
347
430
|
histTimerEnd({ success: true })
|
348
431
|
} catch (err) {
|
349
|
-
|
432
|
+
logger.error('error in postParticipants:', err)
|
350
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?.code,
|
438
|
+
system,
|
439
|
+
operation: 'postParticipants',
|
440
|
+
step
|
441
|
+
})
|
351
442
|
try {
|
352
443
|
const errorCallbackEndpointType = params.SubId
|
353
444
|
? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
|
@@ -357,7 +448,7 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
|
|
357
448
|
} catch (exc) {
|
358
449
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
359
450
|
// we've already sent a sync response- we cannot throw.
|
360
|
-
|
451
|
+
logger.error('failed to handle exception in postParticipants:', exc)
|
361
452
|
}
|
362
453
|
histTimerEnd({ success: false })
|
363
454
|
} finally {
|
@@ -385,100 +476,108 @@ const postParticipantsBatch = async (headers, method, requestPayload, span) => {
|
|
385
476
|
'Post participants batch',
|
386
477
|
['success']
|
387
478
|
).startTimer()
|
479
|
+
const errorCounter = Metrics.getCounter('errorCount')
|
480
|
+
const requestId = requestPayload.requestId
|
481
|
+
const log = logger.child({ context: 'postParticipantsBatch', requestId })
|
388
482
|
const childSpan = span ? span.getChild('postParticipantsBatch') : undefined
|
389
483
|
let fspiopError
|
484
|
+
let step
|
390
485
|
try {
|
391
|
-
|
486
|
+
log.info('postParticipantsBatch::begin', { headers, requestPayload })
|
392
487
|
const typeMap = new Map()
|
393
488
|
const overallReturnList = []
|
394
|
-
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'
|
395
500
|
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
|
-
}
|
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
|
+
}
|
421
507
|
|
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
|
-
}
|
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)
|
435
516
|
} 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
|
-
}
|
517
|
+
typeMap.set(party.partyIdType, [party])
|
442
518
|
}
|
443
519
|
} 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
|
-
}
|
520
|
+
pushPartyError(party, FSPIOPErrorCodes.PARTY_NOT_FOUND)
|
450
521
|
}
|
522
|
+
} else {
|
523
|
+
pushPartyError(party, FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
|
451
524
|
}
|
525
|
+
}
|
526
|
+
|
527
|
+
for (const [key, value] of typeMap) {
|
452
528
|
const payload = {
|
453
|
-
|
454
|
-
|
529
|
+
requestId,
|
530
|
+
partyList: value
|
455
531
|
}
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
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
|
+
}
|
464
544
|
}
|
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
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
|
+
|
471
562
|
histTimerEnd({ success: true })
|
472
563
|
} catch (err) {
|
473
|
-
|
564
|
+
log.error('error in postParticipantsBatch', err)
|
474
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?.code,
|
570
|
+
system,
|
571
|
+
operation: 'postParticipantsBatch',
|
572
|
+
step
|
573
|
+
})
|
475
574
|
try {
|
476
575
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR,
|
477
576
|
fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, undefined, requestPayload)
|
478
577
|
} catch (exc) {
|
479
578
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
480
579
|
// we've already sent a sync response- we cannot throw.
|
481
|
-
|
580
|
+
log.error('error in participant.sendErrorToParticipant', exc)
|
482
581
|
}
|
483
582
|
histTimerEnd({ success: false })
|
484
583
|
} finally {
|
@@ -507,15 +606,20 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
|
|
507
606
|
'Delete participants',
|
508
607
|
['success']
|
509
608
|
).startTimer()
|
609
|
+
const errorCounter = Metrics.getCounter('errorCount')
|
610
|
+
const log = logger.child('deleteParticipants')
|
611
|
+
let step
|
510
612
|
try {
|
511
|
-
|
613
|
+
log.debug('deleteParticipants::begin', { headers, params })
|
512
614
|
const type = params.Type
|
513
615
|
const partySubIdOrType = params.SubId || undefined
|
514
616
|
const callbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
|
515
617
|
const errorCallbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
|
516
618
|
if (Object.values(Enums.Accounts.PartyAccountTypes).includes(type)) {
|
619
|
+
step = 'validateParticipant-1'
|
517
620
|
const requesterParticipantModel = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE])
|
518
621
|
if (requesterParticipantModel) {
|
622
|
+
step = 'oracleRequest-2'
|
519
623
|
const response = await oracle.oracleRequest(headers, method, params, query, undefined, cache)
|
520
624
|
if (response) {
|
521
625
|
const responsePayload = {
|
@@ -529,31 +633,44 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
|
|
529
633
|
const clonedHeaders = { ...headers }
|
530
634
|
clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = headers[Enums.Http.Headers.FSPIOP.SOURCE]
|
531
635
|
clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
|
636
|
+
step = 'sendRequest-3'
|
532
637
|
await participant.sendRequest(clonedHeaders, clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION], callbackEndpointType, Enums.Http.RestMethods.PUT, responsePayload, options)
|
533
638
|
} else {
|
639
|
+
step = 'sendErrorToParticipant-4'
|
534
640
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
535
641
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
536
642
|
}
|
537
643
|
} else {
|
538
|
-
|
539
|
-
|
644
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
645
|
+
log.error(errMessage)
|
646
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
540
647
|
}
|
541
648
|
} else {
|
649
|
+
step = 'sendErrorToParticipant-5'
|
542
650
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
543
651
|
ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
|
544
652
|
}
|
545
|
-
|
653
|
+
log.info('deleteParticipants::end')
|
546
654
|
histTimerEnd({ success: true })
|
547
655
|
} catch (err) {
|
548
|
-
|
656
|
+
log.error('error in deleteParticipants', err)
|
549
657
|
try {
|
658
|
+
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR)
|
550
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
|
551
660
|
await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
|
552
|
-
|
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?.code,
|
666
|
+
system,
|
667
|
+
operation: 'deleteParticipants',
|
668
|
+
step
|
669
|
+
})
|
553
670
|
} catch (exc) {
|
554
671
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
555
672
|
// we've already sent a sync response- we cannot throw.
|
556
|
-
|
673
|
+
log.error('error in participant.sendErrorToParticipant', exc)
|
557
674
|
}
|
558
675
|
histTimerEnd({ success: false })
|
559
676
|
}
|