account-lookup-service 15.6.0-iso.2 → 15.6.0-iso.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +1 -1
- package/.ncurc.yaml +1 -2
- package/audit-ci.jsonc +3 -1
- package/jest.config.js +2 -0
- package/package.json +14 -16
- package/src/constants.js +2 -1
- package/src/domain/participants/participants.js +173 -130
- package/src/domain/parties/getPartiesByTypeAndID.js +15 -14
- package/src/domain/parties/parties.js +13 -12
- package/src/domain/parties/utils.js +13 -6
- package/src/domain/timeout/dto.js +4 -10
- package/src/handlers/index.js +4 -4
- package/src/handlers/monitoring/index.js +1 -1
- package/src/interface/api-swagger-iso20022-parties.yaml +7 -6
- package/src/interface/api-swagger.yaml +7 -6
- package/src/interface/fspiop-rest-v2.0-ISO20022_parties.yaml +2043 -1583
- package/src/lib/config.js +1 -1
- package/src/lib/index.js +1 -2
- package/src/models/participantEndpoint/facade.js +21 -19
- package/src/plugins.js +20 -9
- package/src/server.js +3 -19
- package/test/fixtures/index.js +30 -6
- package/test/fixtures/iso.js +1 -1
- package/test/unit/api/health.test.js +3 -0
- package/test/unit/api/participants/participants.test.js +5 -7
- package/test/unit/api/participants/{Type}/{ID}/{SubId}.test.js +0 -3
- package/test/unit/api/participants/{Type}/{ID}.test.js +0 -3
- package/test/unit/api/participants.test.js +36 -3
- package/test/unit/domain/participants/participants.test.js +76 -48
- package/test/unit/domain/parties/parties.test.js +3 -3
- package/test/unit/domain/parties/utils.test.js +60 -0
- package/test/unit/domain/timeout/dto.test.js +1 -2
- package/test/unit/lib/TransformFacades.test.js +2 -1
- package/test/unit/lib/config.test.js +7 -0
- package/test/unit/models/participantEndpoint/facade.test.js +25 -8
- package/test/unit/plugins.test.js +4 -2
- package/test/util/apiClients/BasicApiClient.js +2 -2
- package/src/handlers/monitoring/plugins/metrics.js +0 -48
- package/src/lib/requestLogger.js +0 -54
- package/src/metrics/handler.js +0 -33
- package/src/metrics/plugin.js +0 -52
- package/src/metrics/routes.js +0 -43
- package/test/unit/lib/requestLogger.test.js +0 -115
@@ -32,21 +32,22 @@ const oracle = require('../../models/oracle/facade')
|
|
32
32
|
const participant = require('../../models/participantEndpoint/facade')
|
33
33
|
const { createCallbackHeaders } = require('../../lib/headers')
|
34
34
|
const { ERROR_MESSAGES } = require('../../constants')
|
35
|
-
const {
|
35
|
+
const { logger } = require('../../lib')
|
36
36
|
const Config = require('../../lib/config')
|
37
37
|
const utils = require('./utils')
|
38
38
|
|
39
39
|
const { FspEndpointTypes, FspEndpointTemplates } = Enum.EndPoints
|
40
40
|
const { Headers, RestMethods } = Enum.Http
|
41
41
|
|
42
|
-
const
|
42
|
+
const log = logger.child('domain:get-parties')
|
43
|
+
const handleErrorOnSendingCallback = utils.createErrorHandlerOnSendingCallback(Config, log)
|
43
44
|
|
44
45
|
const proxyCacheTtlSec = 40 // todo: make configurable
|
45
46
|
|
46
47
|
const validateRequester = async ({ source, proxy, proxyCache }) => {
|
47
48
|
const sourceParticipant = await participant.validateParticipant(source)
|
48
49
|
if (sourceParticipant) {
|
49
|
-
|
50
|
+
log.debug('source is in scheme', { source })
|
50
51
|
return source
|
51
52
|
}
|
52
53
|
|
@@ -63,7 +64,7 @@ const validateRequester = async ({ source, proxy, proxyCache }) => {
|
|
63
64
|
|
64
65
|
const isCached = await proxyCache.addDfspIdToProxyMapping(source, proxy)
|
65
66
|
// think, what if isCached !== true?
|
66
|
-
|
67
|
+
log.info('source is added to proxyMapping cache:', { source, proxy, isCached })
|
67
68
|
return proxy
|
68
69
|
}
|
69
70
|
|
@@ -94,7 +95,7 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
|
|
94
95
|
const callbackEndpointType = utils.getPartyCbType(partySubId)
|
95
96
|
|
96
97
|
const childSpan = span ? span.getChild('getPartiesByTypeAndID') : undefined
|
97
|
-
|
98
|
+
log.info('parties::getPartiesByTypeAndID::begin', { source, proxy, params })
|
98
99
|
|
99
100
|
let requester
|
100
101
|
let fspiopError
|
@@ -127,7 +128,7 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
|
|
127
128
|
await participant.sendRequest(headers, destination, callbackEndpointType, RestMethods.GET, undefined, options, childSpan)
|
128
129
|
|
129
130
|
histTimerEnd({ success: true })
|
130
|
-
|
131
|
+
log.info('discovery getPartiesByTypeAndID request was sent to destination', { destination })
|
131
132
|
return
|
132
133
|
}
|
133
134
|
|
@@ -161,7 +162,7 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
|
|
161
162
|
const schemeParticipant = await participant.validateParticipant(fspId)
|
162
163
|
if (schemeParticipant) {
|
163
164
|
sentCount++
|
164
|
-
|
165
|
+
log.debug('participant is in scheme', { fspId })
|
165
166
|
return participant.sendRequest(clonedHeaders, party.fspId, callbackEndpointType, RestMethods.GET, undefined, options, childSpan)
|
166
167
|
}
|
167
168
|
|
@@ -170,20 +171,20 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
|
|
170
171
|
if (proxyEnabled) {
|
171
172
|
const proxyName = await proxyCache.lookupProxyByDfspId(fspId)
|
172
173
|
if (!proxyName) {
|
173
|
-
|
174
|
+
log.warn('no proxyMapping for participant! TODO: Delete reference in oracle...', { fspId })
|
174
175
|
// todo: delete reference in oracle
|
175
176
|
} else {
|
176
177
|
sentCount++
|
177
|
-
|
178
|
+
log.debug('participant NOT is in scheme, use proxy name', { fspId, proxyName })
|
178
179
|
return participant.sendRequest(clonedHeaders, proxyName, callbackEndpointType, RestMethods.GET, undefined, options, childSpan)
|
179
180
|
}
|
180
181
|
}
|
181
182
|
})
|
182
183
|
await Promise.all(sending)
|
183
|
-
|
184
|
+
log.info('participant.sendRequests to filtered oracle partyList are done', { sentCount })
|
184
185
|
// todo: think what if sentCount === 0 here
|
185
186
|
} else {
|
186
|
-
|
187
|
+
log.info('empty partyList form oracle, getting proxies list...', { proxyEnabled, params })
|
187
188
|
let filteredProxyNames = []
|
188
189
|
|
189
190
|
if (proxyEnabled) {
|
@@ -206,7 +207,7 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
|
|
206
207
|
fspiopError.toApiErrorObject(config.ERROR_HANDLING), callbackHeaders, params, childSpan)
|
207
208
|
} else {
|
208
209
|
const alsReq = utils.alsRequestDto(source, params)
|
209
|
-
|
210
|
+
log.info('starting setSendToProxiesList flow: ', { filteredProxyNames, alsReq, proxyCacheTtlSec })
|
210
211
|
const isCached = await proxyCache.setSendToProxiesList(alsReq, filteredProxyNames, proxyCacheTtlSec)
|
211
212
|
if (!isCached) {
|
212
213
|
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, ERROR_MESSAGES.failedToCacheSendToProxiesList)
|
@@ -221,7 +222,7 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
|
|
221
222
|
// If, at least, one request is sent to proxy, we treat the whole flow as successful.
|
222
223
|
// Failed requests should be handled by TTL expired/timeout handler
|
223
224
|
// todo: - think, if we should handle failed requests here (e.g., by calling receivedErrorResponse)
|
224
|
-
|
225
|
+
log.info('setSendToProxiesList flow is done:', { isOk, results, filteredProxyNames, alsReq })
|
225
226
|
if (!isOk) {
|
226
227
|
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, ERROR_MESSAGES.proxyConnectionError)
|
227
228
|
}
|
@@ -229,7 +230,7 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
|
|
229
230
|
}
|
230
231
|
histTimerEnd({ success: true })
|
231
232
|
} catch (err) {
|
232
|
-
fspiopError = await
|
233
|
+
fspiopError = await handleErrorOnSendingCallback(err, headers, params, requester)
|
233
234
|
histTimerEnd({ success: false })
|
234
235
|
} finally {
|
235
236
|
await utils.finishSpanWithError(childSpan, fspiopError)
|
@@ -38,12 +38,13 @@ const Metrics = require('@mojaloop/central-services-metrics')
|
|
38
38
|
const oracle = require('../../models/oracle/facade')
|
39
39
|
const participant = require('../../models/participantEndpoint/facade')
|
40
40
|
const { ERROR_MESSAGES } = require('../../constants')
|
41
|
-
const {
|
41
|
+
const { logger } = require('../../lib')
|
42
42
|
const Config = require('../../lib/config')
|
43
43
|
const utils = require('./utils')
|
44
44
|
const getPartiesByTypeAndID = require('./getPartiesByTypeAndID')
|
45
45
|
|
46
|
-
const
|
46
|
+
const log = logger.child('domain:put-parties')
|
47
|
+
const handleErrorOnSendingCallback = utils.createErrorHandlerOnSendingCallback(Config, log)
|
47
48
|
|
48
49
|
/**
|
49
50
|
* @function putPartiesByTypeAndID
|
@@ -70,7 +71,7 @@ const putPartiesByTypeAndID = async (headers, params, method, payload, dataUri,
|
|
70
71
|
const destination = headers[Headers.FSPIOP.DESTINATION]
|
71
72
|
const proxy = headers[Headers.FSPIOP.PROXY]
|
72
73
|
const proxyEnabled = !!(Config.PROXY_CACHE_CONFIG.enabled && proxyCache)
|
73
|
-
|
74
|
+
log.info('parties::putPartiesByTypeAndID::begin', { source, destination, proxy, params })
|
74
75
|
|
75
76
|
let sendTo
|
76
77
|
try {
|
@@ -82,21 +83,21 @@ const putPartiesByTypeAndID = async (headers, params, method, payload, dataUri,
|
|
82
83
|
}
|
83
84
|
const isCached = await proxyCache.addDfspIdToProxyMapping(source, proxy)
|
84
85
|
// think,if we should throw error if isCached === false?
|
85
|
-
|
86
|
+
log.info('addDfspIdToProxyMapping is done', { source, proxy, isCached })
|
86
87
|
}
|
87
88
|
|
88
89
|
if (proxyEnabled && proxy) {
|
89
90
|
const alsReq = utils.alsRequestDto(destination, params) // or source?
|
90
91
|
const isExists = await proxyCache.receivedSuccessResponse(alsReq)
|
91
92
|
if (!isExists) {
|
92
|
-
|
93
|
+
log.warn('destination is NOT in scheme, and no cached sendToProxiesList', { destination, alsReq })
|
93
94
|
// think, if we need to throw an error here
|
94
95
|
} else {
|
95
96
|
const mappingPayload = {
|
96
97
|
fspId: source
|
97
98
|
}
|
98
99
|
await oracle.oracleRequest(headers, RestMethods.POST, params, null, mappingPayload, cache)
|
99
|
-
|
100
|
+
log.info('oracle was updated with mappingPayload', { mappingPayload, params })
|
100
101
|
}
|
101
102
|
}
|
102
103
|
|
@@ -121,10 +122,10 @@ const putPartiesByTypeAndID = async (headers, params, method, payload, dataUri,
|
|
121
122
|
}
|
122
123
|
await participant.sendRequest(headers, sendTo, callbackEndpointType, RestMethods.PUT, decodedPayload.body.toString(), options)
|
123
124
|
|
124
|
-
|
125
|
+
log.info('parties::putPartiesByTypeAndID::callback was sent', { sendTo, options })
|
125
126
|
histTimerEnd({ success: true })
|
126
127
|
} catch (err) {
|
127
|
-
await
|
128
|
+
await handleErrorOnSendingCallback(err, headers, params, sendTo)
|
128
129
|
histTimerEnd({ success: false })
|
129
130
|
}
|
130
131
|
}
|
@@ -167,14 +168,14 @@ const putPartiesErrorByTypeAndID = async (headers, params, payload, dataUri, spa
|
|
167
168
|
getPartiesByTypeAndID(swappedHeaders, params, RestMethods.GET, {}, span, cache, proxyCache)
|
168
169
|
// todo: - think if we need to send errorCallback?
|
169
170
|
// - or sentCallback after getPartiesByTypeAndID is done
|
170
|
-
|
171
|
+
log.info('notValidPayee case - deleted Participants and run getPartiesByTypeAndID:', { proxy, params, payload })
|
171
172
|
return
|
172
173
|
}
|
173
174
|
|
174
175
|
const alsReq = utils.alsRequestDto(destination, params) // or source?
|
175
176
|
const isLast = await proxyCache.receivedErrorResponse(alsReq, proxy)
|
176
177
|
if (!isLast) {
|
177
|
-
|
178
|
+
log.info('got NOT last error callback from proxy:', { proxy, alsReq })
|
178
179
|
return
|
179
180
|
}
|
180
181
|
}
|
@@ -194,10 +195,10 @@ const putPartiesErrorByTypeAndID = async (headers, params, payload, dataUri, spa
|
|
194
195
|
const decodedPayload = decodePayload(dataUri, { asParsed: false })
|
195
196
|
await participant.sendErrorToParticipant(sendTo, callbackEndpointType, decodedPayload.body.toString(), headers, params, childSpan)
|
196
197
|
|
197
|
-
|
198
|
+
log.info('putPartiesErrorByTypeAndID callback was sent', { sendTo })
|
198
199
|
histTimerEnd({ success: true })
|
199
200
|
} catch (err) {
|
200
|
-
fspiopError = await
|
201
|
+
fspiopError = await handleErrorOnSendingCallback(err, headers, params, sendTo)
|
201
202
|
histTimerEnd({ success: false })
|
202
203
|
} finally {
|
203
204
|
await utils.finishSpanWithError(childSpan, fspiopError)
|
@@ -1,10 +1,9 @@
|
|
1
|
-
const { Enum } = require('@mojaloop/central-services-shared')
|
1
|
+
const { Enum, Util: { Hapi } } = require('@mojaloop/central-services-shared')
|
2
2
|
const EventSdk = require('@mojaloop/event-sdk')
|
3
3
|
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
4
4
|
|
5
5
|
const participant = require('../../models/participantEndpoint/facade')
|
6
|
-
const
|
7
|
-
const { logger } = require('../../lib')
|
6
|
+
const { TransformFacades } = require('../../lib')
|
8
7
|
|
9
8
|
const { FspEndpointTypes } = Enum.EndPoints
|
10
9
|
const { Headers } = Enum.Http
|
@@ -33,6 +32,13 @@ const finishSpanWithError = async (childSpan, fspiopError) => {
|
|
33
32
|
}
|
34
33
|
}
|
35
34
|
|
35
|
+
const makePutPartiesErrorPayload = async (config, fspiopError, headers, params) => {
|
36
|
+
const body = fspiopError.toApiErrorObject(config.ERROR_HANDLING)
|
37
|
+
return config.API_TYPE === Hapi.API_TYPES.iso20022
|
38
|
+
? (await TransformFacades.FSPIOP.parties.putError({ body, headers, params })).body
|
39
|
+
: body
|
40
|
+
}
|
41
|
+
|
36
42
|
const alsRequestDto = (sourceId, params) => ({
|
37
43
|
sourceId,
|
38
44
|
type: params.Type,
|
@@ -54,13 +60,13 @@ const swapSourceDestinationHeaders = (headers) => {
|
|
54
60
|
}
|
55
61
|
|
56
62
|
// change signature to accept object
|
57
|
-
const
|
63
|
+
const createErrorHandlerOnSendingCallback = (config, logger) => async (err, headers, params, requester) => {
|
58
64
|
try {
|
59
65
|
logger.error('error in sending parties callback', err)
|
60
66
|
const sendTo = requester || headers[Headers.FSPIOP.SOURCE]
|
61
67
|
const errorCallbackEndpointType = errorPartyCbType(params.SubId)
|
62
68
|
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
|
63
|
-
const errInfo = fspiopError
|
69
|
+
const errInfo = await makePutPartiesErrorPayload(config, fspiopError, headers, params)
|
64
70
|
|
65
71
|
await participant.sendErrorToParticipant(sendTo, errorCallbackEndpointType, errInfo, headers, params)
|
66
72
|
|
@@ -77,8 +83,9 @@ module.exports = {
|
|
77
83
|
getPartyCbType,
|
78
84
|
putPartyCbType,
|
79
85
|
errorPartyCbType,
|
86
|
+
makePutPartiesErrorPayload,
|
80
87
|
finishSpanWithError,
|
81
|
-
|
88
|
+
createErrorHandlerOnSendingCallback,
|
82
89
|
alsRequestDto,
|
83
90
|
swapSourceDestinationHeaders
|
84
91
|
}
|
@@ -8,18 +8,10 @@ const {
|
|
8
8
|
EndPoints: { FspEndpointTypes }
|
9
9
|
} = require('@mojaloop/central-services-shared').Enum
|
10
10
|
const { Tracer } = require('@mojaloop/event-sdk')
|
11
|
-
const { API_TYPES } = require('@mojaloop/central-services-shared').Util.Hapi
|
12
11
|
|
13
|
-
const { TransformFacades } = require('../../lib')
|
14
12
|
const LibUtil = require('../../lib/util')
|
15
13
|
const Config = require('../../lib/config')
|
16
|
-
|
17
|
-
const makeErrorPayload = async (headers, params) => {
|
18
|
-
const body = createFSPIOPError(FSPIOPErrorCodes.EXPIRED_ERROR).toApiErrorObject(Config.ERROR_HANDLING)
|
19
|
-
return Config.API_TYPE === API_TYPES.iso20022
|
20
|
-
? (await TransformFacades.FSPIOP.parties.putError({ body, headers, params })).body
|
21
|
-
: body
|
22
|
-
}
|
14
|
+
const partiesUtils = require('../parties/utils')
|
23
15
|
|
24
16
|
const timeoutCallbackDto = async ({ destination, partyId, partyType }) => {
|
25
17
|
const headers = {
|
@@ -30,8 +22,10 @@ const timeoutCallbackDto = async ({ destination, partyId, partyType }) => {
|
|
30
22
|
ID: partyId,
|
31
23
|
Type: partyType
|
32
24
|
}
|
25
|
+
const error = createFSPIOPError(FSPIOPErrorCodes.EXPIRED_ERROR)
|
26
|
+
|
33
27
|
const dto = {
|
34
|
-
errorInformation: await
|
28
|
+
errorInformation: await partiesUtils.makePutPartiesErrorPayload(Config, error, headers, params),
|
35
29
|
headers,
|
36
30
|
params,
|
37
31
|
endpointType: FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR
|
package/src/handlers/index.js
CHANGED
@@ -35,7 +35,7 @@ const Package = require('../../package.json')
|
|
35
35
|
const Server = require('../server')
|
36
36
|
const { HANDLER_TYPES } = require('../constants')
|
37
37
|
const Config = require('../lib/config')
|
38
|
-
const
|
38
|
+
const log = require('../lib').logger.child('ALS-timeout-handler')
|
39
39
|
|
40
40
|
const Program = new Command()
|
41
41
|
|
@@ -51,16 +51,16 @@ Program.command('handlers')
|
|
51
51
|
const handlers = []
|
52
52
|
|
53
53
|
if (args.timeout) {
|
54
|
-
|
54
|
+
log.debug('CLI: Executing --timeout')
|
55
55
|
handlers.push(HANDLER_TYPES.TIMEOUT)
|
56
56
|
}
|
57
57
|
|
58
58
|
if (handlers.length === 0) {
|
59
|
-
|
59
|
+
log.debug('CLI: No handlers specified')
|
60
60
|
return
|
61
61
|
}
|
62
62
|
|
63
|
-
module.exports = await Server.initializeHandlers(handlers, Config,
|
63
|
+
module.exports = await Server.initializeHandlers(handlers, Config, log)
|
64
64
|
})
|
65
65
|
|
66
66
|
if (Array.isArray(process.argv) && process.argv.length > 2) {
|
@@ -18,7 +18,7 @@
|
|
18
18
|
const Hapi = require('@hapi/hapi')
|
19
19
|
const Metrics = require('@mojaloop/central-services-metrics')
|
20
20
|
const { plugin: HealthPlugin } = require('./plugins/health')
|
21
|
-
const
|
21
|
+
const MetricsPlugin = require('@mojaloop/central-services-metrics').plugin
|
22
22
|
const { logger } = require('../../lib')
|
23
23
|
|
24
24
|
let server
|
@@ -890,13 +890,14 @@ components:
|
|
890
890
|
schemas:
|
891
891
|
CorrelationId:
|
892
892
|
title: CorrelationId
|
893
|
-
pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
|
894
893
|
type: string
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
894
|
+
pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[1-7][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$|^[0-9A-HJKMNP-TV-Z]{26}$
|
895
|
+
description: >-
|
896
|
+
Identifier that correlates all messages of the same sequence.
|
897
|
+
The supported identifiers formats are for
|
898
|
+
lowercase [UUID](https://datatracker.ietf.org/doc/html/rfc9562) and
|
899
|
+
uppercase [ULID](https://github.com/ulid/spec)
|
900
|
+
example: 'b51ec534-ee48-4575-b6a9-ead2955b8069'
|
900
901
|
Currency:
|
901
902
|
title: CurrencyEnum
|
902
903
|
maxLength: 3
|
@@ -889,13 +889,14 @@ components:
|
|
889
889
|
schemas:
|
890
890
|
CorrelationId:
|
891
891
|
title: CorrelationId
|
892
|
-
pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
|
893
892
|
type: string
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
893
|
+
pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[1-7][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$|^[0-9A-HJKMNP-TV-Z]{26}$
|
894
|
+
description: >-
|
895
|
+
Identifier that correlates all messages of the same sequence.
|
896
|
+
The supported identifiers formats are for
|
897
|
+
lowercase [UUID](https://datatracker.ietf.org/doc/html/rfc9562) and
|
898
|
+
uppercase [ULID](https://github.com/ulid/spec)
|
899
|
+
example: 'b51ec534-ee48-4575-b6a9-ead2955b8069'
|
899
900
|
Currency:
|
900
901
|
title: CurrencyEnum
|
901
902
|
maxLength: 3
|