account-lookup-service 17.6.0 → 17.7.0-snapshot.1
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 +17 -14
- package/src/constants.js +34 -2
- package/src/domain/parties/deps.js +4 -3
- package/src/domain/parties/getPartiesByTypeAndID.js +9 -13
- package/src/domain/parties/partiesUtils.js +4 -34
- package/src/domain/parties/putParties.js +26 -71
- package/src/domain/parties/services/BasePartiesService.js +137 -15
- package/src/domain/parties/services/GetPartiesService.js +190 -164
- package/src/domain/parties/services/PutPartiesErrorService.js +50 -27
- package/src/domain/parties/services/PutPartiesService.js +51 -33
- package/src/domain/timeout/index.js +11 -1
- package/src/handlers/TimeoutHandler.js +2 -2
- package/src/lib/util.js +11 -3
- package/test/fixtures/index.js +38 -0
- package/test/unit/domain/participants/participants.test.js +1 -1
- package/test/unit/domain/parties/parties.test.js +29 -21
- package/test/unit/domain/parties/partiesUtils.test.js +51 -0
- package/test/unit/domain/parties/{utils.test.js → services/BasePartiesService.test.js} +33 -34
- package/test/unit/domain/parties/services/GetPartiesService.test.js +222 -0
- package/test/unit/domain/parties/services/PutPartiesErrorService.test.js +49 -0
- package/test/unit/domain/parties/services/deps.js +49 -0
- package/test/unit/domain/timeout/index.test.js +5 -5
- package/test/util/index.js +5 -6
- package/test/util/mockDeps.js +52 -0
package/package.json
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
{
|
2
2
|
"name": "account-lookup-service",
|
3
3
|
"description": "Account Lookup Service is used to validate Party and Participant lookups.",
|
4
|
-
"version": "17.
|
4
|
+
"version": "17.7.0-snapshot.1",
|
5
5
|
"license": "Apache-2.0",
|
6
6
|
"author": "ModusBox",
|
7
7
|
"contributors": [
|
8
|
+
"Eugen Klymniuk <eugen.klymniuk@infitx.com>",
|
8
9
|
"Rajiv Mothilal <rajiv.mothilal@modusbox.com>",
|
9
10
|
"Matt Kingston <matt.kingston@modusbox.com>",
|
10
11
|
"Lewis Daly <lewisd@crosslaketech.com>",
|
@@ -44,10 +45,8 @@
|
|
44
45
|
"start:api": "node src/index.js server --api",
|
45
46
|
"start:admin": "node src/index.js server --admin",
|
46
47
|
"start:handlers": "node src/handlers/index.js handlers --timeout",
|
47
|
-
"
|
48
|
-
"
|
49
|
-
"lint": "npm run standard",
|
50
|
-
"lint:fix": "npm run standard:fix",
|
48
|
+
"lint": "standard",
|
49
|
+
"lint:fix": "standard --fix",
|
51
50
|
"dev": "nodemon src/index.js server",
|
52
51
|
"test": "npm run test:unit",
|
53
52
|
"test:unit": "NODE_OPTIONS='--experimental-vm-modules --max-old-space-size=8192' jest --runInBand",
|
@@ -95,13 +94,13 @@
|
|
95
94
|
"@mojaloop/central-services-health": "15.0.4",
|
96
95
|
"@mojaloop/central-services-logger": "11.7.0",
|
97
96
|
"@mojaloop/central-services-metrics": "12.5.0",
|
98
|
-
"@mojaloop/central-services-shared": "18.23.0",
|
99
|
-
"@mojaloop/central-services-stream": "11.5.
|
97
|
+
"@mojaloop/central-services-shared": "18.23.1-snapshot.0",
|
98
|
+
"@mojaloop/central-services-stream": "11.5.2",
|
100
99
|
"@mojaloop/database-lib": "11.1.4",
|
101
|
-
"@mojaloop/event-sdk": "14.
|
102
|
-
"@mojaloop/inter-scheme-proxy-cache-lib": "2.
|
103
|
-
"@mojaloop/ml-schema-transformer-lib": "2.
|
104
|
-
"@mojaloop/sdk-standard-components": "19.
|
100
|
+
"@mojaloop/event-sdk": "14.4.0",
|
101
|
+
"@mojaloop/inter-scheme-proxy-cache-lib": "2.4.0-snapshot.2",
|
102
|
+
"@mojaloop/ml-schema-transformer-lib": "2.6.0",
|
103
|
+
"@mojaloop/sdk-standard-components": "19.11.0",
|
105
104
|
"@now-ims/hapi-now-auth": "2.1.0",
|
106
105
|
"ajv": "8.17.1",
|
107
106
|
"ajv-keywords": "5.1.0",
|
@@ -163,7 +162,7 @@
|
|
163
162
|
"devDependencies": {
|
164
163
|
"@types/jest": "29.5.14",
|
165
164
|
"audit-ci": "^7.1.0",
|
166
|
-
"axios": "1.8.
|
165
|
+
"axios": "1.8.4",
|
167
166
|
"axios-retry": "^4.5.0",
|
168
167
|
"docdash": "2.0.2",
|
169
168
|
"dotenv": "^16.4.7",
|
@@ -173,12 +172,12 @@
|
|
173
172
|
"jest-junit": "16.0.0",
|
174
173
|
"jsdoc": "4.0.4",
|
175
174
|
"nodemon": "3.1.9",
|
176
|
-
"npm-check-updates": "17.1.
|
175
|
+
"npm-check-updates": "17.1.16",
|
177
176
|
"nyc": "17.1.0",
|
178
177
|
"pre-commit": "1.2.2",
|
179
178
|
"proxyquire": "2.1.3",
|
180
179
|
"replace": "^1.2.2",
|
181
|
-
"sinon": "
|
180
|
+
"sinon": "20.0.0",
|
182
181
|
"standard": "17.1.2",
|
183
182
|
"standard-version": "^9.5.0",
|
184
183
|
"swagmock": "1.0.0"
|
@@ -190,5 +189,9 @@
|
|
190
189
|
"scripts": {
|
191
190
|
"postchangelog": "replace '\\[mojaloop/#(\\d+)\\]\\(https://github.com/mojaloop/(.*)/issues/(\\d+)\\)' '[mojaloop/#$1](https://github.com/mojaloop/project/issues/$1)' CHANGELOG.md"
|
192
191
|
}
|
192
|
+
},
|
193
|
+
"imports": {
|
194
|
+
"#src/*": "./src/*.js",
|
195
|
+
"#test/*": "./test/*.js"
|
193
196
|
}
|
194
197
|
}
|
package/src/constants.js
CHANGED
@@ -1,9 +1,40 @@
|
|
1
|
+
/*****
|
2
|
+
License
|
3
|
+
--------------
|
4
|
+
Copyright © 2020-2025 Mojaloop Foundation
|
5
|
+
The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
10
|
+
|
11
|
+
Contributors
|
12
|
+
--------------
|
13
|
+
This is the official list of the Mojaloop project contributors for this file.
|
14
|
+
Names of the original copyright holders (individuals or organizations)
|
15
|
+
should be listed with a '*' in the first column. People who have
|
16
|
+
contributed from an organization can be listed under the organization
|
17
|
+
that actually holds the copyright for their contributions (see the
|
18
|
+
Mojaloop Foundation for an example). Those individuals should have
|
19
|
+
their names indented and be marked with a '-'. Email address can be added
|
20
|
+
optionally within square brackets <email>.
|
21
|
+
|
22
|
+
* Mojaloop Foundation
|
23
|
+
* Eugen Klymniuk <eugen.klymniuk@infitx.com>
|
24
|
+
|
25
|
+
--------------
|
26
|
+
******/
|
27
|
+
|
28
|
+
const { API_TYPES } = require('@mojaloop/central-services-shared').Util.Hapi
|
29
|
+
|
1
30
|
const ERROR_MESSAGES = Object.freeze({
|
31
|
+
emptyFilteredPartyList: 'Empty oracle partyList, filtered based on callbackEndpointType',
|
32
|
+
failedToCacheSendToProxiesList: 'Failed to cache sendToProxiesList',
|
33
|
+
noDiscoveryRequestsForwarded: 'No discovery requests forwarded to participants',
|
2
34
|
sourceFspNotFound: 'Requester FSP not found',
|
3
35
|
partyDestinationFspNotFound: 'Destination FSP not found',
|
4
36
|
partyProxyNotFound: 'Proxy not found',
|
5
|
-
proxyConnectionError: 'Proxy connection error'
|
6
|
-
failedToCacheSendToProxiesList: 'Failed to cache sendToProxiesList'
|
37
|
+
proxyConnectionError: 'Proxy connection error - no successful requests sent to proxies'
|
7
38
|
})
|
8
39
|
|
9
40
|
const HANDLER_TYPES = Object.freeze({
|
@@ -11,6 +42,7 @@ const HANDLER_TYPES = Object.freeze({
|
|
11
42
|
})
|
12
43
|
|
13
44
|
module.exports = {
|
45
|
+
API_TYPES,
|
14
46
|
ERROR_MESSAGES,
|
15
47
|
HANDLER_TYPES
|
16
48
|
}
|
@@ -26,17 +26,18 @@
|
|
26
26
|
******/
|
27
27
|
|
28
28
|
const { proxies } = require('@mojaloop/central-services-shared').Util
|
29
|
+
const { logger } = require('../../lib')
|
30
|
+
const config = require('../../lib/config')
|
29
31
|
const oracle = require('../../models/oracle/facade')
|
30
32
|
const participant = require('../../models/participantEndpoint/facade')
|
31
|
-
const config = require('../../lib/config')
|
32
33
|
const partiesUtils = require('./partiesUtils')
|
33
34
|
|
34
|
-
|
35
|
+
/** @returns {PartiesDeps} */
|
36
|
+
const createDeps = ({ cache, proxyCache, childSpan, log = logger }) => Object.freeze({
|
35
37
|
cache,
|
36
38
|
proxyCache,
|
37
39
|
childSpan,
|
38
40
|
log,
|
39
|
-
stepState,
|
40
41
|
config,
|
41
42
|
oracle,
|
42
43
|
participant,
|
@@ -50,26 +50,22 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
|
|
50
50
|
['success']
|
51
51
|
).startTimer()
|
52
52
|
const childSpan = span ? span.getChild(component) : undefined
|
53
|
-
const
|
54
|
-
const
|
55
|
-
|
56
|
-
const deps = createDeps({ cache, proxyCache, childSpan, log, stepState })
|
57
|
-
const service = new GetPartiesService(deps)
|
58
|
-
const results = {}
|
53
|
+
const deps = createDeps({ cache, proxyCache, childSpan })
|
54
|
+
const service = new GetPartiesService(deps, { headers, params, query })
|
55
|
+
let fspiopError
|
59
56
|
|
60
57
|
try {
|
61
|
-
await service.handleRequest(
|
62
|
-
|
58
|
+
await service.handleRequest()
|
59
|
+
logger.info('getPartiesByTypeAndID is done')
|
63
60
|
histTimerEnd({ success: true })
|
64
61
|
} catch (error) {
|
65
|
-
|
66
|
-
results.fspiopError = await service.handleError({ error, requester, headers, params })
|
62
|
+
fspiopError = await service.handleError(error)
|
67
63
|
histTimerEnd({ success: false })
|
68
|
-
if (
|
69
|
-
libUtil.countFspiopError(
|
64
|
+
if (fspiopError) {
|
65
|
+
libUtil.countFspiopError(fspiopError, { operation: component, step: service.currenStep })
|
70
66
|
}
|
71
67
|
} finally {
|
72
|
-
await libUtil.finishSpanWithError(childSpan,
|
68
|
+
await libUtil.finishSpanWithError(childSpan, fspiopError)
|
73
69
|
}
|
74
70
|
}
|
75
71
|
|
@@ -25,13 +25,9 @@
|
|
25
25
|
--------------
|
26
26
|
******/
|
27
27
|
|
28
|
-
const { Enum
|
29
|
-
const { MojaloopApiErrorCodes } = require('@mojaloop/sdk-standard-components').Errors
|
30
|
-
// todo: check why do we need sdk-standard-components deps here !!!
|
31
|
-
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
32
|
-
|
33
|
-
const participant = require('../../models/participantEndpoint/facade')
|
28
|
+
const { Enum } = require('@mojaloop/central-services-shared')
|
34
29
|
const { TransformFacades } = require('../../lib')
|
30
|
+
const { API_TYPES } = require('../../constants')
|
35
31
|
|
36
32
|
const { FspEndpointTypes } = Enum.EndPoints
|
37
33
|
const { Headers } = Enum.Http
|
@@ -50,7 +46,7 @@ const errorPartyCbType = (partySubId) => partySubId
|
|
50
46
|
|
51
47
|
const makePutPartiesErrorPayload = async (config, fspiopError, headers, params) => {
|
52
48
|
const body = fspiopError.toApiErrorObject(config.ERROR_HANDLING)
|
53
|
-
return config.API_TYPE ===
|
49
|
+
return config.API_TYPE === API_TYPES.iso20022
|
54
50
|
? (await TransformFacades.FSPIOP.parties.putError({ body, headers, params })).body
|
55
51
|
: body
|
56
52
|
}
|
@@ -81,38 +77,12 @@ const swapSourceDestinationHeaders = (headers) => {
|
|
81
77
|
}
|
82
78
|
}
|
83
79
|
|
84
|
-
// todo: check if we need this function
|
85
|
-
const createErrorHandlerOnSendingCallback = (config, logger) => async (err, headers, params, requester) => {
|
86
|
-
try {
|
87
|
-
logger.error('error in sending parties callback: ', err)
|
88
|
-
const sendTo = requester || headers[Headers.FSPIOP.SOURCE]
|
89
|
-
const errorCallbackEndpointType = errorPartyCbType(params.SubId)
|
90
|
-
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
|
91
|
-
const errInfo = await makePutPartiesErrorPayload(config, fspiopError, headers, params)
|
92
|
-
|
93
|
-
await participant.sendErrorToParticipant(sendTo, errorCallbackEndpointType, errInfo, headers, params)
|
94
|
-
|
95
|
-
logger.info('handleErrorOnSendingCallback in done', { sendTo, params, errInfo })
|
96
|
-
return fspiopError
|
97
|
-
} catch (exc) {
|
98
|
-
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
99
|
-
// we've already sent a sync response- we cannot throw.
|
100
|
-
logger.error('failed to handleErrorOnSendingCallback. No further processing! ', exc)
|
101
|
-
}
|
102
|
-
}
|
103
|
-
|
104
|
-
function isNotValidPayeeCase (payload) {
|
105
|
-
return payload?.errorInformation?.errorCode === MojaloopApiErrorCodes.PAYEE_IDENTIFIER_NOT_VALID.code
|
106
|
-
}
|
107
|
-
|
108
80
|
module.exports = {
|
109
81
|
getPartyCbType,
|
110
82
|
putPartyCbType,
|
111
83
|
errorPartyCbType,
|
112
84
|
makePutPartiesErrorPayload,
|
113
|
-
createErrorHandlerOnSendingCallback,
|
114
85
|
alsRequestDto,
|
115
86
|
partiesRequestOptionsDto,
|
116
|
-
swapSourceDestinationHeaders
|
117
|
-
isNotValidPayeeCase
|
87
|
+
swapSourceDestinationHeaders
|
118
88
|
}
|
@@ -29,7 +29,6 @@
|
|
29
29
|
|
30
30
|
'use strict'
|
31
31
|
|
32
|
-
const { Headers } = require('@mojaloop/central-services-shared').Enum.Http
|
33
32
|
const Metrics = require('@mojaloop/central-services-metrics')
|
34
33
|
const libUtil = require('../../lib/util')
|
35
34
|
const { logger } = require('../../lib')
|
@@ -37,9 +36,7 @@ const { createDeps } = require('./deps')
|
|
37
36
|
const services = require('./services')
|
38
37
|
|
39
38
|
/**
|
40
|
-
*
|
41
|
-
*
|
42
|
-
* @description This sends a callback to inform participant of successful lookup
|
39
|
+
* Sends a callback to inform participant of successful lookup
|
43
40
|
*
|
44
41
|
* @param {object} headers - incoming http request headers
|
45
42
|
* @param {object} params - uri parameters of the http request
|
@@ -58,45 +55,25 @@ const putPartiesByTypeAndID = async (headers, params, method, payload, dataUri,
|
|
58
55
|
['success']
|
59
56
|
).startTimer()
|
60
57
|
// const childSpan = span ? span.getChild(component) : undefined
|
61
|
-
const
|
62
|
-
const
|
63
|
-
|
64
|
-
const deps = createDeps({ cache, proxyCache, log, stepState })
|
65
|
-
const service = new services.PutPartiesService(deps)
|
66
|
-
const results = {}
|
67
|
-
|
68
|
-
const source = headers[Headers.FSPIOP.SOURCE]
|
69
|
-
const destination = headers[Headers.FSPIOP.DESTINATION]
|
70
|
-
const proxy = headers[Headers.FSPIOP.PROXY]
|
71
|
-
log.info('putPartiesByTypeAndID start', { source, destination, proxy })
|
58
|
+
const deps = createDeps({ cache, proxyCache })
|
59
|
+
const service = new services.PutPartiesService(deps, { headers, params, payload, dataUri })
|
60
|
+
let fspiopError
|
72
61
|
|
73
62
|
try {
|
74
|
-
await service.
|
75
|
-
|
76
|
-
if (proxy) {
|
77
|
-
await service.checkProxySuccessResponse({ destination, source, headers, params })
|
78
|
-
}
|
79
|
-
|
80
|
-
const sendTo = await service.identifyDestinationForSuccessCallback(destination)
|
81
|
-
results.requester = sendTo
|
82
|
-
await service.sendSuccessCallback({ sendTo, headers, params, dataUri })
|
83
|
-
|
84
|
-
log.info('putPartiesByTypeAndID callback was sent', { sendTo })
|
63
|
+
await service.handleRequest()
|
64
|
+
logger.info('putPartiesByTypeAndID is done')
|
85
65
|
histTimerEnd({ success: true })
|
86
66
|
} catch (error) {
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
libUtil.countFspiopError(results.fspiopError, { operation: component, step: stepState.step })
|
67
|
+
fspiopError = await service.handleError(error)
|
68
|
+
if (fspiopError) {
|
69
|
+
libUtil.countFspiopError(fspiopError, { operation: component, step: service.currenStep })
|
91
70
|
}
|
92
71
|
histTimerEnd({ success: false })
|
93
72
|
}
|
94
73
|
}
|
95
74
|
|
96
75
|
/**
|
97
|
-
*
|
98
|
-
*
|
99
|
-
* @description This populates the cache of endpoints
|
76
|
+
* Sends error callback to inform participant of failed lookup
|
100
77
|
*
|
101
78
|
* @param {object} headers - incoming http request headers
|
102
79
|
* @param {object} params - uri parameters of the http request
|
@@ -114,53 +91,31 @@ const putPartiesErrorByTypeAndID = async (headers, params, payload, dataUri, spa
|
|
114
91
|
['success']
|
115
92
|
).startTimer()
|
116
93
|
const childSpan = span ? span.getChild(component) : undefined
|
117
|
-
const
|
118
|
-
const
|
119
|
-
|
120
|
-
|
121
|
-
const service = new services.PutPartiesErrorService(deps)
|
122
|
-
const results = {}
|
123
|
-
|
124
|
-
const destination = headers[Headers.FSPIOP.DESTINATION]
|
125
|
-
const proxy = headers[Headers.FSPIOP.PROXY]
|
126
|
-
const proxyEnabled = !!(deps.config.PROXY_CACHE_CONFIG.enabled && proxyCache)
|
127
|
-
log.info('putPartiesErrorByTypeAndID start', { destination, proxy, proxyEnabled })
|
94
|
+
const deps = createDeps({ cache, proxyCache, childSpan })
|
95
|
+
const inputs = { headers, params, payload, dataUri }
|
96
|
+
const service = new services.PutPartiesErrorService(deps, inputs)
|
97
|
+
let fspiopError
|
128
98
|
|
129
99
|
try {
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
histTimerEnd({ success: true })
|
138
|
-
return
|
139
|
-
}
|
140
|
-
|
141
|
-
const isLast = await service.checkLastProxyCallback({ destination, proxy, params })
|
142
|
-
if (!isLast) {
|
143
|
-
log.info('putPartiesErrorByTypeAndID proxy callback was processed', { proxy })
|
144
|
-
histTimerEnd({ success: true })
|
145
|
-
return
|
146
|
-
}
|
100
|
+
const needDiscovery = await service.handleRequest()
|
101
|
+
if (needDiscovery) {
|
102
|
+
const getPartiesService = new services.GetPartiesService(deps, inputs)
|
103
|
+
await getPartiesService.triggerInterSchemeDiscoveryFlow(
|
104
|
+
services.GetPartiesService.headersWithoutDestination(headers)
|
105
|
+
)
|
106
|
+
// think, if we need to start the whole processing with getPartiesService.handleRequest() ?
|
147
107
|
}
|
148
108
|
|
149
|
-
|
150
|
-
results.requester = sendTo
|
151
|
-
await service.sendErrorCallbackToParticipant({ sendTo, headers, params, dataUri })
|
152
|
-
|
153
|
-
log.info('putPartiesErrorByTypeAndID callback was sent', { sendTo })
|
109
|
+
logger.info('putPartiesErrorByTypeAndID is done')
|
154
110
|
histTimerEnd({ success: true })
|
155
111
|
} catch (error) {
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
libUtil.countFspiopError(results.fspiopError, { operation: component, step: stepState.step })
|
112
|
+
fspiopError = await service.handleError(error)
|
113
|
+
if (fspiopError) {
|
114
|
+
libUtil.countFspiopError(fspiopError, { operation: component, step: service.currenStep })
|
160
115
|
}
|
161
116
|
histTimerEnd({ success: false })
|
162
117
|
} finally {
|
163
|
-
await libUtil.finishSpanWithError(childSpan,
|
118
|
+
await libUtil.finishSpanWithError(childSpan, fspiopError)
|
164
119
|
}
|
165
120
|
}
|
166
121
|
|
@@ -26,33 +26,93 @@
|
|
26
26
|
******/
|
27
27
|
|
28
28
|
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
29
|
-
const { decodePayload } = require('@mojaloop/central-services-shared').Util.StreamingProtocol
|
30
29
|
const { Enum } = require('@mojaloop/central-services-shared')
|
30
|
+
const { decodePayload } = require('@mojaloop/central-services-shared').Util.StreamingProtocol
|
31
|
+
const { initStepState } = require('../../../lib/util')
|
32
|
+
const { createCallbackHeaders } = require('../../../lib/headers')
|
31
33
|
|
32
34
|
const { FspEndpointTypes, FspEndpointTemplates } = Enum.EndPoints
|
33
35
|
const { Headers, RestMethods } = Enum.Http
|
34
36
|
|
37
|
+
/**
|
38
|
+
* @typedef {Object} PartiesDeps
|
39
|
+
* @property {Object} cache
|
40
|
+
* @property {Object} proxyCache
|
41
|
+
* @property {Object} log
|
42
|
+
* @property {Object} config
|
43
|
+
* @property {Object} oracle
|
44
|
+
* @property {Object} participant
|
45
|
+
* @property {Proxies} proxies
|
46
|
+
* @property {Object} partiesUtils
|
47
|
+
* @property {Object} [childSpan]
|
48
|
+
*/
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Input parameters from party lookup request
|
52
|
+
*
|
53
|
+
* @typedef {Object} PartiesInputs
|
54
|
+
* @property {Object} headers - incoming http request headers.
|
55
|
+
* @property {Object} params - uri parameters of the http request.
|
56
|
+
* @property {Object} [payload] - payload of the request being sent out.
|
57
|
+
* @property {Object} [query] - uri query parameters of the http request
|
58
|
+
* @property {string} [dataUri] - encoded payload of the request being sent out.
|
59
|
+
*/
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Any calculated values we get during request processing
|
63
|
+
*
|
64
|
+
* @typedef {Object} PartiesModelState
|
65
|
+
* @property {string} destination - The destination DFSP ID from headers
|
66
|
+
* @property {string} source - The source DFSP ID from headers
|
67
|
+
* @property {string} [proxy] - The proxy DFSP ID from headers, if present
|
68
|
+
* @property {string} requester - The entity initiating the request (either a DFSP in scheme or a proxy)
|
69
|
+
* @property {boolean} proxyEnabled - Indicates whether proxy functionality is enabled in the current configuration
|
70
|
+
* @property {StepState} stepState - Processing steps state
|
71
|
+
*/
|
72
|
+
|
35
73
|
class BasePartiesService {
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
74
|
+
#deps // see PartiesDeps
|
75
|
+
#inputs // see PartiesInputs
|
76
|
+
#state // see PartiesModelState
|
77
|
+
|
78
|
+
/**
|
79
|
+
* @param {PartiesDeps} deps - The dependencies required by the class instance.
|
80
|
+
* @param {PartiesInputs} inputs - The input parameters from incoming http request.
|
81
|
+
* @return {void}
|
82
|
+
*/
|
83
|
+
constructor (deps, inputs) {
|
84
|
+
this.#deps = Object.freeze(deps)
|
85
|
+
this.#inputs = Object.freeze(inputs)
|
86
|
+
this.#state = this.#initiateState()
|
87
|
+
this.log = this.deps.log.child({
|
88
|
+
component: this.constructor.name,
|
89
|
+
params: this.inputs.params
|
90
|
+
})
|
40
91
|
}
|
41
92
|
|
42
|
-
|
43
|
-
|
44
|
-
|
93
|
+
/** @returns {PartiesDeps} */
|
94
|
+
get deps () { return this.#deps }
|
95
|
+
|
96
|
+
/** @returns {PartiesInputs} */
|
97
|
+
get inputs () { return this.#inputs }
|
45
98
|
|
46
|
-
|
99
|
+
/** @returns {PartiesModelState} */
|
100
|
+
get state () { return this.#state }
|
101
|
+
|
102
|
+
async handleError (error) {
|
103
|
+
const { headers, params } = this.inputs
|
47
104
|
const log = this.log.child({ method: 'handleError' })
|
48
105
|
try {
|
49
106
|
log.error('error in processing parties request: ', error)
|
50
|
-
const sendTo = requester || headers[Headers.FSPIOP.SOURCE]
|
51
107
|
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(error)
|
52
108
|
const errorInfo = await this.deps.partiesUtils.makePutPartiesErrorPayload(this.deps.config, fspiopError, headers, params)
|
53
109
|
|
54
|
-
await this.sendErrorCallback({
|
55
|
-
|
110
|
+
await this.sendErrorCallback({
|
111
|
+
errorInfo,
|
112
|
+
headers: BasePartiesService.createErrorCallbackHeaders(headers, params),
|
113
|
+
params
|
114
|
+
})
|
115
|
+
log.info('handleError in done')
|
56
116
|
return fspiopError
|
57
117
|
} catch (exc) {
|
58
118
|
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
@@ -62,26 +122,88 @@ class BasePartiesService {
|
|
62
122
|
}
|
63
123
|
|
64
124
|
async validateParticipant (participantId) {
|
125
|
+
this.stepInProgress('validateParticipant')
|
65
126
|
return this.deps.participant.validateParticipant(participantId)
|
66
127
|
}
|
67
128
|
|
68
|
-
async sendErrorCallback ({
|
129
|
+
async sendErrorCallback ({ errorInfo, headers, params }) {
|
130
|
+
this.stepInProgress('sendErrorCallback')
|
131
|
+
const sendTo = this.state.requester || this.state.source
|
69
132
|
const endpointType = this.deps.partiesUtils.errorPartyCbType(params.SubId)
|
133
|
+
|
70
134
|
await this.deps.participant.sendErrorToParticipant(
|
71
|
-
sendTo, endpointType, errorInfo, headers, params,
|
135
|
+
sendTo, endpointType, errorInfo, headers, params, undefined, this.deps.childSpan
|
72
136
|
)
|
73
|
-
this.log.
|
137
|
+
this.log.info('sendErrorCallback is done', { sendTo, errorInfo })
|
74
138
|
}
|
75
139
|
|
76
140
|
async sendDeleteOracleRequest (headers, params) {
|
141
|
+
this.stepInProgress('sendDeleteOracleRequest')
|
77
142
|
return this.deps.oracle.oracleRequest(headers, RestMethods.DELETE, params, null, null, this.deps.cache)
|
78
143
|
}
|
79
144
|
|
145
|
+
async removeProxyGetPartiesTimeout (alsReq) {
|
146
|
+
const isRemoved = await this.deps.proxyCache.removeProxyGetPartiesTimeout(alsReq)
|
147
|
+
this.log.debug('removeProxyGetPartiesTimeout is done', { isRemoved, alsReq })
|
148
|
+
return isRemoved
|
149
|
+
}
|
150
|
+
|
151
|
+
createFspiopIdNotFoundError (errMessage, log = this.log) {
|
152
|
+
log.warn(errMessage)
|
153
|
+
return ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
154
|
+
}
|
155
|
+
|
156
|
+
stepInProgress (stepName) {
|
157
|
+
this.log.debug('step is in progress', { stepName })
|
158
|
+
this.state.stepState?.inProgress(stepName)
|
159
|
+
}
|
160
|
+
|
161
|
+
get currenStep () {
|
162
|
+
return this.state.stepState?.step
|
163
|
+
}
|
164
|
+
|
165
|
+
/** @returns {PartiesModelState} */
|
166
|
+
#initiateState () {
|
167
|
+
const { headers } = this.inputs
|
168
|
+
return {
|
169
|
+
destination: headers[Headers.FSPIOP.DESTINATION],
|
170
|
+
source: headers[Headers.FSPIOP.SOURCE],
|
171
|
+
proxy: headers[Headers.FSPIOP.PROXY],
|
172
|
+
requester: '', // dfsp in scheme OR proxy
|
173
|
+
proxyEnabled: !!(this.deps.config.PROXY_CACHE_CONFIG?.enabled && this.deps.proxyCache),
|
174
|
+
stepState: initStepState()
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
80
178
|
static decodeDataUriPayload (dataUri) {
|
81
179
|
const decoded = decodePayload(dataUri, { asParsed: false })
|
82
180
|
return decoded.body.toString()
|
83
181
|
}
|
84
182
|
|
183
|
+
static headersWithoutDestination (headers) {
|
184
|
+
const { [Headers.FSPIOP.DESTINATION]: _, ...restHeaders } = headers || {}
|
185
|
+
return restHeaders
|
186
|
+
}
|
187
|
+
|
188
|
+
static overrideDestinationHeader (headers, destination) {
|
189
|
+
const { [Headers.FSPIOP.DESTINATION]: _, ...restHeaders } = headers || {}
|
190
|
+
return {
|
191
|
+
...restHeaders,
|
192
|
+
...(destination && { [Headers.FSPIOP.DESTINATION]: destination })
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
static createErrorCallbackHeaders (headers, params) {
|
197
|
+
return createCallbackHeaders({
|
198
|
+
requestHeaders: headers,
|
199
|
+
partyIdType: params.Type,
|
200
|
+
partyIdentifier: params.ID,
|
201
|
+
endpointTemplate: params.SubId
|
202
|
+
? FspEndpointTemplates.PARTIES_SUB_ID_PUT_ERROR
|
203
|
+
: FspEndpointTemplates.PARTIES_PUT_ERROR
|
204
|
+
})
|
205
|
+
}
|
206
|
+
|
85
207
|
static enums () {
|
86
208
|
return {
|
87
209
|
FspEndpointTypes,
|