account-lookup-service 17.13.0-snapshot.0 → 17.13.0-snapshot.10
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/.grype.yaml +0 -1
- package/audit-ci.jsonc +1 -0
- package/package.json +9 -8
- package/src/constants.js +1 -1
- package/src/domain/parties/putParties.js +1 -1
- package/src/domain/parties/services/BasePartiesService.js +43 -7
- package/src/domain/parties/services/GetPartiesService.js +18 -32
- package/src/domain/parties/services/PutPartiesErrorService.js +17 -21
- package/src/domain/parties/services/PutPartiesService.js +1 -1
- package/src/lib/headers.js +1 -0
- package/test/unit/domain/parties/parties.test.js +7 -4
- package/test/unit/domain/parties/services/GetPartiesService.test.js +15 -22
- package/test/unit/domain/parties/services/PutPartiesErrorService.test.js +28 -19
package/.grype.yaml
CHANGED
package/audit-ci.jsonc
CHANGED
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
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.13.0-snapshot.
|
4
|
+
"version": "17.13.0-snapshot.10",
|
5
5
|
"license": "Apache-2.0",
|
6
6
|
"author": "ModusBox",
|
7
7
|
"contributors": [
|
@@ -91,22 +91,22 @@
|
|
91
91
|
"@hapi/hapi": "21.4.3",
|
92
92
|
"@hapi/inert": "7.1.0",
|
93
93
|
"@hapi/vision": "7.0.3",
|
94
|
-
"@mojaloop/central-services-error-handling": "13.1.
|
94
|
+
"@mojaloop/central-services-error-handling": "13.1.2-snapshot.0",
|
95
95
|
"@mojaloop/central-services-health": "15.1.0",
|
96
96
|
"@mojaloop/central-services-logger": "11.9.3",
|
97
97
|
"@mojaloop/central-services-metrics": "12.7.1",
|
98
|
-
"@mojaloop/central-services-shared": "18.
|
98
|
+
"@mojaloop/central-services-shared": "18.33.0",
|
99
99
|
"@mojaloop/central-services-stream": "11.8.7",
|
100
100
|
"@mojaloop/database-lib": "^11.3.2",
|
101
101
|
"@mojaloop/event-sdk": "14.7.0",
|
102
102
|
"@mojaloop/inter-scheme-proxy-cache-lib": "2.6.0",
|
103
|
-
"@mojaloop/ml-schema-transformer-lib": "2.7.
|
104
|
-
"@mojaloop/sdk-standard-components": "19.
|
103
|
+
"@mojaloop/ml-schema-transformer-lib": "2.7.8",
|
104
|
+
"@mojaloop/sdk-standard-components": "19.17.0",
|
105
105
|
"@now-ims/hapi-now-auth": "2.1.0",
|
106
106
|
"ajv": "8.17.1",
|
107
107
|
"ajv-keywords": "5.1.0",
|
108
108
|
"blipp": "4.0.2",
|
109
|
-
"commander": "14.0.
|
109
|
+
"commander": "14.0.1",
|
110
110
|
"cron": "4.3.3",
|
111
111
|
"hapi-auth-bearer-token": "8.0.0",
|
112
112
|
"joi": "18.0.1",
|
@@ -124,6 +124,7 @@
|
|
124
124
|
"postcss": {
|
125
125
|
"nanoid": "^3.3.8"
|
126
126
|
},
|
127
|
+
"@mojaloop/central-services-error-handling": "13.1.2-snapshot.0",
|
127
128
|
"@mojaloop/central-services-health": {
|
128
129
|
"@mojaloop/central-services-logger": ">=11.4.0"
|
129
130
|
},
|
@@ -165,7 +166,7 @@
|
|
165
166
|
"devDependencies": {
|
166
167
|
"@types/jest": "30.0.0",
|
167
168
|
"audit-ci": "^7.1.0",
|
168
|
-
"axios": "1.
|
169
|
+
"axios": "1.12.2",
|
169
170
|
"axios-retry": "^4.5.0",
|
170
171
|
"docdash": "2.0.2",
|
171
172
|
"dotenv": "^17.2.2",
|
@@ -175,7 +176,7 @@
|
|
175
176
|
"jest-junit": "16.0.0",
|
176
177
|
"jsdoc": "4.0.4",
|
177
178
|
"nodemon": "3.1.10",
|
178
|
-
"npm-check-updates": "18.1.
|
179
|
+
"npm-check-updates": "18.1.1",
|
179
180
|
"nyc": "17.1.0",
|
180
181
|
"pre-commit": "1.2.2",
|
181
182
|
"proxyquire": "2.1.3",
|
package/src/constants.js
CHANGED
@@ -29,7 +29,7 @@ const { API_TYPES } = require('@mojaloop/central-services-shared').Util.Hapi
|
|
29
29
|
|
30
30
|
const ERROR_MESSAGES = Object.freeze({
|
31
31
|
emptyFilteredPartyList: 'Empty oracle partyList, filtered based on callbackEndpointType',
|
32
|
-
externalPartyError: 'External party error',
|
32
|
+
externalPartyError: 'External party resolution error',
|
33
33
|
failedToCacheSendToProxiesList: 'Failed to cache sendToProxiesList',
|
34
34
|
noDiscoveryRequestsForwarded: 'No discovery requests forwarded to participants',
|
35
35
|
sourceFspNotFound: 'Requester FSP not found',
|
@@ -47,7 +47,7 @@ const services = require('./services')
|
|
47
47
|
* @param {IProxyCache} [proxyCache] - IProxyCache instance
|
48
48
|
*/
|
49
49
|
const putPartiesByTypeAndID = async (headers, params, method, payload, dataUri, cache, proxyCache = undefined) => {
|
50
|
-
//
|
50
|
+
// think, if we need to pass span here
|
51
51
|
const component = putPartiesByTypeAndID.name
|
52
52
|
const histTimerEnd = Metrics.getHistogram(
|
53
53
|
component,
|
@@ -26,12 +26,10 @@
|
|
26
26
|
******/
|
27
27
|
|
28
28
|
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
29
|
-
const { Enum } = require('@mojaloop/central-services-shared')
|
30
|
-
const { decodePayload } = require('@mojaloop/central-services-shared').Util.StreamingProtocol
|
29
|
+
const { Enum, Util } = require('@mojaloop/central-services-shared')
|
31
30
|
const { initStepState } = require('../../../lib/util')
|
32
31
|
const { createCallbackHeaders } = require('../../../lib/headers')
|
33
32
|
const { ERROR_MESSAGES } = require('../../../constants')
|
34
|
-
const { makeAcceptContentTypeHeader } = require('@mojaloop/central-services-shared').Util.Headers
|
35
33
|
|
36
34
|
const { FspEndpointTypes, FspEndpointTemplates } = Enum.EndPoints
|
37
35
|
const { Headers, RestMethods, HeaderResources } = Enum.Http
|
@@ -170,6 +168,26 @@ class BasePartiesService {
|
|
170
168
|
this.log.info('sendErrorCallback is done', { sendTo, errorInfo })
|
171
169
|
}
|
172
170
|
|
171
|
+
/**
|
172
|
+
* @returns {Promise<{ fspId: string, partySubIdOrType?: string }[]>} List of parties from oracle response
|
173
|
+
*/
|
174
|
+
async sendOracleDiscoveryRequest () {
|
175
|
+
this.stepInProgress('#sendOracleDiscoveryRequest')
|
176
|
+
const { headers, params, query } = this.inputs
|
177
|
+
|
178
|
+
const response = await this.deps.oracle.oracleRequest(headers, RestMethods.GET, params, query, undefined, this.deps.cache)
|
179
|
+
this.log.verbose('oracle discovery raw response:', { response })
|
180
|
+
|
181
|
+
let { partyList } = response?.data || {}
|
182
|
+
if (!Array.isArray(partyList)) {
|
183
|
+
this.log.warn('invalid oracle discovery response:', { response })
|
184
|
+
// todo: maybe, it's better to throw an error
|
185
|
+
partyList = []
|
186
|
+
}
|
187
|
+
|
188
|
+
return partyList
|
189
|
+
}
|
190
|
+
|
173
191
|
async sendDeleteOracleRequest (headers, params) {
|
174
192
|
this.stepInProgress('sendDeleteOracleRequest')
|
175
193
|
const result = await this.deps.oracle.oracleRequest(headers, RestMethods.DELETE, params, null, null, this.deps.cache)
|
@@ -184,6 +202,24 @@ class BasePartiesService {
|
|
184
202
|
return isRemoved
|
185
203
|
}
|
186
204
|
|
205
|
+
async sendPartyResolutionErrorCallback () {
|
206
|
+
this.stepInProgress('sendPartyResolutionErrorCallback')
|
207
|
+
const { headers, params } = this.inputs
|
208
|
+
|
209
|
+
const error = this.createFspiopPartyResolutionError(ERROR_MESSAGES.externalPartyError)
|
210
|
+
const callbackHeaders = BasePartiesService.createErrorCallbackHeaders(headers, params)
|
211
|
+
const errorInfo = await this.deps.partiesUtils.makePutPartiesErrorPayload(this.deps.config, error, callbackHeaders, params)
|
212
|
+
this.state.destination = callbackHeaders[Headers.FSPIOP.DESTINATION]
|
213
|
+
|
214
|
+
await this.identifyDestinationForCallback()
|
215
|
+
await this.sendErrorCallback({
|
216
|
+
errorInfo,
|
217
|
+
headers: callbackHeaders,
|
218
|
+
params
|
219
|
+
})
|
220
|
+
this.log.verbose('sendPartyResolutionErrorCallback is done', { callbackHeaders, errorInfo })
|
221
|
+
}
|
222
|
+
|
187
223
|
createFspiopIdNotFoundError (errMessage, log = this.log) {
|
188
224
|
log.warn(errMessage)
|
189
225
|
return ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
@@ -194,9 +230,9 @@ class BasePartiesService {
|
|
194
230
|
return ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND, errMessage)
|
195
231
|
}
|
196
232
|
|
197
|
-
|
233
|
+
createFspiopPartyResolutionError (errMessage, log = this.log) {
|
198
234
|
log.warn(errMessage)
|
199
|
-
return ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.
|
235
|
+
return ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_RESOLUTION_FAILURE, errMessage)
|
200
236
|
}
|
201
237
|
|
202
238
|
stepInProgress (stepName) {
|
@@ -222,7 +258,7 @@ class BasePartiesService {
|
|
222
258
|
}
|
223
259
|
|
224
260
|
static decodeDataUriPayload (dataUri) {
|
225
|
-
const decoded = decodePayload(dataUri, { asParsed: false })
|
261
|
+
const decoded = Util.StreamingProtocol.decodePayload(dataUri, { asParsed: false })
|
226
262
|
return decoded.body.toString()
|
227
263
|
}
|
228
264
|
|
@@ -257,7 +293,7 @@ class BasePartiesService {
|
|
257
293
|
return {
|
258
294
|
[Headers.FSPIOP.SOURCE]: hubName,
|
259
295
|
[Headers.FSPIOP.DESTINATION]: destination,
|
260
|
-
[Headers.GENERAL.CONTENT_TYPE.value]: makeAcceptContentTypeHeader(
|
296
|
+
[Headers.GENERAL.CONTENT_TYPE.value]: Util.Headers.makeAcceptContentTypeHeader(
|
261
297
|
HeaderResources.PARTIES,
|
262
298
|
config.PROTOCOL_VERSIONS.CONTENT.DEFAULT.toString(),
|
263
299
|
config.API_TYPE
|
@@ -28,7 +28,7 @@
|
|
28
28
|
const { ERROR_MESSAGES } = require('../../../constants')
|
29
29
|
const BasePartiesService = require('./BasePartiesService')
|
30
30
|
|
31
|
-
const {
|
31
|
+
const { RestMethods } = BasePartiesService.enums()
|
32
32
|
const proxyCacheTtlSec = 40 // todo: make configurable
|
33
33
|
|
34
34
|
class GetPartiesService extends BasePartiesService {
|
@@ -45,8 +45,8 @@ class GetPartiesService extends BasePartiesService {
|
|
45
45
|
return
|
46
46
|
}
|
47
47
|
|
48
|
-
const
|
49
|
-
const isSent = await this.processOraclePartyListResponse(
|
48
|
+
const partyList = await this.sendOracleDiscoveryRequest()
|
49
|
+
const isSent = await this.processOraclePartyListResponse(partyList)
|
50
50
|
this.log.info(`getParties request is ${isSent ? '' : 'NOT '}forwarded to oracle lookup DFSP`)
|
51
51
|
if (isSent) return
|
52
52
|
|
@@ -108,7 +108,7 @@ class GetPartiesService extends BasePartiesService {
|
|
108
108
|
const isValid = await this.#validateLocalDestinationForExternalSource()
|
109
109
|
if (!isValid) {
|
110
110
|
log.warn('incorrect destination from external source', { destination })
|
111
|
-
await this
|
111
|
+
await this.sendPartyResolutionErrorCallback()
|
112
112
|
return
|
113
113
|
}
|
114
114
|
}
|
@@ -117,20 +117,14 @@ class GetPartiesService extends BasePartiesService {
|
|
117
117
|
log.info('discovery getPartiesByTypeAndID request was sent', { sendTo })
|
118
118
|
}
|
119
119
|
|
120
|
-
async
|
121
|
-
|
122
|
-
const { headers, params, query } = this.inputs
|
123
|
-
return this.deps.oracle.oracleRequest(headers, RestMethods.GET, params, query, undefined, this.deps.cache)
|
124
|
-
}
|
125
|
-
|
126
|
-
async processOraclePartyListResponse (response) {
|
127
|
-
if (!Array.isArray(response?.data?.partyList) || response.data.partyList.length === 0) {
|
120
|
+
async processOraclePartyListResponse (rawPartyList) {
|
121
|
+
if (rawPartyList.length === 0) {
|
128
122
|
this.log.verbose('oracle partyList is empty')
|
129
123
|
return false
|
130
124
|
}
|
131
125
|
|
132
126
|
this.stepInProgress('processOraclePartyList')
|
133
|
-
const partyList = this.#filterOraclePartyList(
|
127
|
+
const partyList = this.#filterOraclePartyList(rawPartyList)
|
134
128
|
|
135
129
|
let sentCount = 0
|
136
130
|
await Promise.all(partyList.map(async party => {
|
@@ -174,28 +168,20 @@ class GetPartiesService extends BasePartiesService {
|
|
174
168
|
return isLocal
|
175
169
|
}
|
176
170
|
|
177
|
-
#filterOraclePartyList (
|
171
|
+
#filterOraclePartyList (partyList) {
|
178
172
|
// Oracle's API is a standard rest-style end-point Thus a GET /party on the oracle will return all participant-party records.
|
179
173
|
// We must filter the results based on the callbackEndpointType to make sure we remove records containing partySubIdOrType when we are in FSPIOP_CALLBACK_URL_PARTIES_GET mode:
|
180
|
-
this.stepInProgress('filterOraclePartyList')
|
174
|
+
this.stepInProgress('#filterOraclePartyList')
|
181
175
|
const { params } = this.inputs
|
182
|
-
const callbackEndpointType = this.deps.partiesUtils.getPartyCbType(params.SubId)
|
183
|
-
let filteredPartyList
|
184
|
-
|
185
|
-
switch (callbackEndpointType) {
|
186
|
-
case FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_GET:
|
187
|
-
filteredPartyList = response.data.partyList.filter(party => party.partySubIdOrType == null) // Filter records that DON'T contain a partySubIdOrType
|
188
|
-
break
|
189
|
-
case FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_GET:
|
190
|
-
filteredPartyList = response.data.partyList.filter(party => party.partySubIdOrType === params.SubId) // Filter records that match partySubIdOrType
|
191
|
-
break
|
192
|
-
default:
|
193
|
-
filteredPartyList = response // Fallback to providing the standard list
|
194
|
-
}
|
195
176
|
|
196
|
-
|
177
|
+
const filteredPartyList = !params?.SubId
|
178
|
+
? partyList.filter(party => party.partySubIdOrType == null) // Filter records that DON'T contain a partySubIdOrType
|
179
|
+
: partyList.filter(party => party.partySubIdOrType === params.SubId) // Filter records that match partySubIdOrType
|
180
|
+
|
181
|
+
if (!filteredPartyList.length) {
|
197
182
|
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.emptyFilteredPartyList)
|
198
183
|
}
|
184
|
+
this.log.verbose('#filterOraclePartyList is done:', { filteredPartyList })
|
199
185
|
|
200
186
|
return filteredPartyList
|
201
187
|
}
|
@@ -338,13 +324,13 @@ class GetPartiesService extends BasePartiesService {
|
|
338
324
|
log.verbose('needOracleValidation: ', { needValidation })
|
339
325
|
if (!needValidation) return true
|
340
326
|
|
341
|
-
const
|
342
|
-
if (
|
327
|
+
const partyList = await this.sendOracleDiscoveryRequest()
|
328
|
+
if (partyList.length === 0) {
|
343
329
|
log.warn('Oracle returned empty party list')
|
344
330
|
return false
|
345
331
|
}
|
346
332
|
|
347
|
-
const isValid =
|
333
|
+
const isValid = partyList.some(party => party.fspId === state.destination)
|
348
334
|
log.verbose('#validateLocalDestinationForExternalSource is done', { isValid })
|
349
335
|
return isValid
|
350
336
|
}
|
@@ -26,13 +26,13 @@
|
|
26
26
|
******/
|
27
27
|
|
28
28
|
const BasePartiesService = require('./BasePartiesService')
|
29
|
-
const { ERROR_MESSAGES } = require('../../../constants')
|
30
29
|
|
31
30
|
class PutPartiesErrorService extends BasePartiesService {
|
32
31
|
async handleRequest () {
|
33
32
|
if (this.state.proxyEnabled && this.state.proxy) {
|
34
|
-
const alsReq = this.deps.partiesUtils.alsRequestDto(this.state.destination, this.inputs.params)
|
33
|
+
const alsReq = this.deps.partiesUtils.alsRequestDto(this.state.destination, this.inputs.params)
|
35
34
|
const isInterSchemeDiscoveryCase = await this.deps.proxyCache.isPendingCallback(alsReq)
|
35
|
+
this.log.verbose(`isInterSchemeDiscoveryCase: ${isInterSchemeDiscoveryCase}`, this.state)
|
36
36
|
|
37
37
|
if (isInterSchemeDiscoveryCase) {
|
38
38
|
const isLast = await this.checkLastProxyCallback(alsReq)
|
@@ -41,13 +41,11 @@ class PutPartiesErrorService extends BasePartiesService {
|
|
41
41
|
return
|
42
42
|
}
|
43
43
|
} else {
|
44
|
-
const
|
45
|
-
if (
|
46
|
-
this.log.info('
|
44
|
+
const isExternal = await this.#isPartyFromExternalDfsp()
|
45
|
+
if (isExternal) {
|
46
|
+
this.log.info('need to cleanup oracle coz party is from external DFSP')
|
47
47
|
await this.cleanupOracle()
|
48
|
-
await this.removeProxyGetPartiesTimeoutCache(alsReq)
|
49
|
-
await this.forwardServiceUnavailableErrorCallback()
|
50
|
-
return
|
48
|
+
await this.removeProxyGetPartiesTimeoutCache(alsReq) // think if we need this
|
51
49
|
}
|
52
50
|
}
|
53
51
|
}
|
@@ -79,20 +77,18 @@ class PutPartiesErrorService extends BasePartiesService {
|
|
79
77
|
return super.sendErrorCallback({ errorInfo, headers, params })
|
80
78
|
}
|
81
79
|
|
82
|
-
async
|
83
|
-
this.stepInProgress('
|
84
|
-
const
|
85
|
-
|
86
|
-
|
87
|
-
|
80
|
+
async #isPartyFromExternalDfsp () {
|
81
|
+
this.stepInProgress('#isPartyFromExternalDfsp')
|
82
|
+
const partyList = await super.sendOracleDiscoveryRequest()
|
83
|
+
if (!partyList.length) {
|
84
|
+
this.log.verbose('oracle returns empty partyList')
|
85
|
+
return false
|
86
|
+
}
|
87
|
+
// think, if we have several parties from oracle
|
88
|
+
const isExternal = !(await this.validateParticipant(partyList[0].fspId))
|
89
|
+
this.log.verbose('#isPartyFromExternalDfsp is done:', { isExternal, partyList })
|
88
90
|
|
89
|
-
|
90
|
-
await super.sendErrorCallback({
|
91
|
-
errorInfo,
|
92
|
-
headers: callbackHeaders,
|
93
|
-
params
|
94
|
-
})
|
95
|
-
this.log.verbose('#forwardServiceUnavailableErrorCallback is done', { callbackHeaders, errorInfo })
|
91
|
+
return isExternal
|
96
92
|
}
|
97
93
|
}
|
98
94
|
|
@@ -104,7 +104,7 @@ class PutPartiesService extends BasePartiesService {
|
|
104
104
|
fspId: source
|
105
105
|
}
|
106
106
|
await this.deps.oracle.oracleRequest(headers, RestMethods.POST, params, null, mappingPayload, this.deps.cache)
|
107
|
-
this.log.info('oracle was updated with mappingPayload',
|
107
|
+
this.log.info('oracle was updated with mappingPayload: ', mappingPayload)
|
108
108
|
}
|
109
109
|
}
|
110
110
|
|
package/src/lib/headers.js
CHANGED
@@ -41,6 +41,7 @@ const Config = require('../lib/config')
|
|
41
41
|
*/
|
42
42
|
exports.createCallbackHeaders = (params) => {
|
43
43
|
const callbackHeaders = { ...params.requestHeaders }
|
44
|
+
delete callbackHeaders[Enums.Http.Headers.FSPIOP.PROXY]
|
44
45
|
|
45
46
|
callbackHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
|
46
47
|
callbackHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = params.requestHeaders[Enums.Http.Headers.FSPIOP.SOURCE]
|
@@ -947,6 +947,7 @@ describe('Parties Tests', () => {
|
|
947
947
|
Config.PROXY_CACHE_CONFIG.enabled = true
|
948
948
|
const errorCode = MojaloopApiErrorCodes.PAYEE_IDENTIFIER_NOT_VALID.code
|
949
949
|
const payload = fixtures.errorCallbackResponseDto({ errorCode })
|
950
|
+
const dataUri = encodePayload(JSON.stringify(payload), 'application/json')
|
950
951
|
const destination = `dest-${Date.now()}`
|
951
952
|
const proxy = `proxy-${Date.now()}`
|
952
953
|
const headers = fixtures.partiesCallHeadersDto({ destination, proxy })
|
@@ -958,11 +959,13 @@ describe('Parties Tests', () => {
|
|
958
959
|
oracleEndpointCached.getOracleEndpointByType = sandbox.stub().resolves([
|
959
960
|
{ value: 'http://oracle.endpoint' }
|
960
961
|
])
|
961
|
-
oracle.oracleRequest = sandbox.stub().resolves(
|
962
|
+
oracle.oracleRequest = sandbox.stub().resolves({
|
963
|
+
data: { partyList: [{ fspId: 'fspId' }] }
|
964
|
+
})
|
962
965
|
|
963
|
-
await partiesDomain.putPartiesErrorByTypeAndID(headers, params, payload,
|
966
|
+
await partiesDomain.putPartiesErrorByTypeAndID(headers, params, payload, dataUri, null, null, proxyCache)
|
964
967
|
|
965
|
-
expect(oracle.oracleRequest.callCount).toBe(
|
968
|
+
expect(oracle.oracleRequest.callCount).toBe(2)
|
966
969
|
expect(oracle.oracleRequest.lastCall.args[1]).toBe(RestMethods.DELETE)
|
967
970
|
expect(participant.sendRequest.callCount).toBe(0)
|
968
971
|
expect(participant.sendErrorToParticipant.callCount).toBe(1)
|
@@ -970,7 +973,7 @@ describe('Parties Tests', () => {
|
|
970
973
|
const [sentTo, _, data, cbHeaders] = participant.sendErrorToParticipant.lastCall.args
|
971
974
|
expect(sentTo).toBe(proxy)
|
972
975
|
expect(cbHeaders[Headers.FSPIOP.DESTINATION]).toBe(destination)
|
973
|
-
expect(data.errorInformation.errorCode).toBe(
|
976
|
+
expect(JSON.parse(data).errorInformation.errorCode).toBe(errorCode)
|
974
977
|
})
|
975
978
|
})
|
976
979
|
})
|
@@ -28,12 +28,12 @@
|
|
28
28
|
const { setTimeout: sleep } = require('node:timers/promises')
|
29
29
|
const {
|
30
30
|
createMockDeps,
|
31
|
-
createOracleFacadeMock,
|
32
|
-
createParticipantFacadeMock,
|
31
|
+
createOracleFacadeMock,
|
32
|
+
createParticipantFacadeMock,
|
33
33
|
createProxyCacheMock,
|
34
34
|
createProxiesUtilMock,
|
35
|
-
oracleMock, // deprecated
|
36
|
-
participantMock// deprecated
|
35
|
+
oracleMock, // deprecated! use createOracleFacadeMock instead
|
36
|
+
participantMock // deprecated! use createParticipantFacadeMock instead
|
37
37
|
} = require('./deps')
|
38
38
|
// ↑ should be first require to mock external deps ↑
|
39
39
|
const { GetPartiesService } = require('#src/domain/parties/services/index')
|
@@ -44,15 +44,14 @@ const { RestMethods, Headers } = GetPartiesService.enums()
|
|
44
44
|
|
45
45
|
describe('GetPartiesService Tests -->', () => {
|
46
46
|
const { config } = createMockDeps()
|
47
|
-
|
47
|
+
const { API_TYPE } = config
|
48
48
|
|
49
49
|
beforeEach(() => {
|
50
50
|
jest.clearAllMocks()
|
51
|
-
apiType = config.API_TYPE
|
52
51
|
})
|
53
52
|
|
54
53
|
afterEach(() => {
|
55
|
-
config.API_TYPE =
|
54
|
+
config.API_TYPE = API_TYPE // to avoid side effects
|
56
55
|
})
|
57
56
|
|
58
57
|
describe('forwardRequestToDestination method', () => {
|
@@ -335,9 +334,10 @@ describe('GetPartiesService Tests -->', () => {
|
|
335
334
|
}
|
336
335
|
const headers = fixtures.partiesCallHeadersDto({ destination: '' })
|
337
336
|
const params = fixtures.partiesParamsDto()
|
338
|
-
const service = new GetPartiesService(deps, { headers, params })
|
339
337
|
|
338
|
+
const service = new GetPartiesService(deps, { headers, params })
|
340
339
|
await service.handleRequest()
|
340
|
+
|
341
341
|
expect(participantMock.sendErrorToParticipant).toHaveBeenCalledTimes(1)
|
342
342
|
const isoPayload = participantMock.sendErrorToParticipant.mock.lastCall[2]
|
343
343
|
expect(isoPayload.Assgnmt).toBeDefined()
|
@@ -353,13 +353,17 @@ describe('GetPartiesService Tests -->', () => {
|
|
353
353
|
let deps
|
354
354
|
let oracle // facade
|
355
355
|
let participant // facade
|
356
|
+
let proxyCache
|
356
357
|
let headers
|
357
358
|
let params
|
358
359
|
|
359
360
|
beforeEach(() => {
|
360
361
|
oracle = createOracleFacadeMock()
|
361
362
|
participant = createParticipantFacadeMock()
|
362
|
-
|
363
|
+
proxyCache = createProxyCacheMock({
|
364
|
+
addDfspIdToProxyMapping: jest.fn().mockResolvedValueOnce(true)
|
365
|
+
})
|
366
|
+
deps = createMockDeps({ oracle, participant, proxyCache })
|
363
367
|
headers = fixtures.partiesCallHeadersDto({
|
364
368
|
source: EXTERNAL_SOURCE_DFSP,
|
365
369
|
destination: LOCAL_DESTINATION_DFSP,
|
@@ -369,17 +373,12 @@ describe('GetPartiesService Tests -->', () => {
|
|
369
373
|
})
|
370
374
|
|
371
375
|
test('should forward request when oracle DFSP matches destination DFSP', async () => {
|
372
|
-
// Setup proxy cache to NOT find proxy mapping for local destination
|
373
|
-
deps.proxyCache.addDfspIdToProxyMapping = jest.fn().mockResolvedValueOnce(true)
|
374
|
-
deps.proxyCache.lookupProxyByDfspId = jest.fn().mockResolvedValueOnce(null)
|
375
|
-
|
376
376
|
participant.validateParticipant = jest.fn()
|
377
377
|
.mockResolvedValueOnce(null) // external source (validateRequester)
|
378
378
|
.mockResolvedValueOnce({}) // proxy exists (validateRequester)
|
379
379
|
.mockResolvedValueOnce({}) // local destination (forwardRequestToDestination)
|
380
380
|
.mockResolvedValueOnce(null) // external source (shouldValidateViaOracle)
|
381
381
|
.mockResolvedValueOnce({}) // local destination (shouldValidateViaOracle)
|
382
|
-
|
383
382
|
oracle.oracleRequest = jest.fn().mockResolvedValueOnce(
|
384
383
|
fixtures.oracleRequestResponseDto({
|
385
384
|
partyList: [{ fspId: LOCAL_DESTINATION_DFSP }]
|
@@ -412,22 +411,18 @@ describe('GetPartiesService Tests -->', () => {
|
|
412
411
|
})
|
413
412
|
|
414
413
|
test('should send error callback when oracle DFSP differs from destination DFSP', async () => {
|
415
|
-
// Setup proxy cache to NOT find proxy mapping for local destination
|
416
|
-
deps.proxyCache.addDfspIdToProxyMapping = jest.fn().mockResolvedValueOnce(true)
|
417
|
-
deps.proxyCache.lookupProxyByDfspId = jest.fn().mockResolvedValueOnce(null)
|
418
|
-
|
419
414
|
participant.validateParticipant = jest.fn()
|
420
415
|
.mockResolvedValueOnce(null) // external source (validateRequester)
|
421
416
|
.mockResolvedValueOnce({}) // proxy exists (validateRequester)
|
422
417
|
.mockResolvedValueOnce({}) // local destination (forwardRequestToDestination)
|
423
418
|
.mockResolvedValueOnce(null) // external source (shouldValidateViaOracle)
|
424
419
|
.mockResolvedValueOnce({})
|
425
|
-
|
426
420
|
oracle.oracleRequest = jest.fn().mockResolvedValueOnce(
|
427
421
|
fixtures.oracleRequestResponseDto({
|
428
422
|
partyList: [{ fspId: ORACLE_DFSP_DIFFERENT }]
|
429
423
|
})
|
430
424
|
)
|
425
|
+
proxyCache.lookupProxyByDfspId = jest.fn().mockResolvedValueOnce(PROXY_ID)
|
431
426
|
|
432
427
|
const service = new GetPartiesService(deps, { headers, params })
|
433
428
|
await service.handleRequest()
|
@@ -478,12 +473,11 @@ describe('GetPartiesService Tests -->', () => {
|
|
478
473
|
destination: 'externalDestinationDfsp',
|
479
474
|
proxy: PROXY_ID
|
480
475
|
})
|
481
|
-
|
482
476
|
participant.validateParticipant = jest.fn()
|
483
477
|
.mockResolvedValueOnce(null) // external source
|
484
478
|
.mockResolvedValueOnce({}) // proxy exists
|
485
479
|
.mockResolvedValueOnce(null) // external destination
|
486
|
-
|
480
|
+
proxyCache.lookupProxyByDfspId = jest.fn().mockResolvedValueOnce(PROXY_ID)
|
487
481
|
|
488
482
|
const service = new GetPartiesService(deps, { headers: externalDestHeaders, params })
|
489
483
|
await service.handleRequest()
|
@@ -502,7 +496,6 @@ describe('GetPartiesService Tests -->', () => {
|
|
502
496
|
.mockResolvedValueOnce(null) // external source (shouldValidateViaOracle)
|
503
497
|
.mockResolvedValueOnce({}) // local destination (shouldValidateViaOracle)
|
504
498
|
.mockResolvedValueOnce({}) // local destination (forwardRequestToDestination)
|
505
|
-
|
506
499
|
oracle.oracleRequest = jest.fn().mockResolvedValueOnce(
|
507
500
|
fixtures.oracleRequestResponseDto({
|
508
501
|
partyList: [{ fspId: ORACLE_DFSP_DIFFERENT }]
|
@@ -25,45 +25,54 @@
|
|
25
25
|
--------------
|
26
26
|
******/
|
27
27
|
|
28
|
-
const { createMockDeps, oracleMock, participantMock } = require('./deps')
|
29
|
-
// ↑ should be first require to mock external deps ↑
|
30
28
|
const { PutPartiesErrorService } = require('#src/domain/parties/services/index')
|
29
|
+
const { createMockDeps, createOracleFacadeMock, createParticipantFacadeMock } = require('./deps')
|
31
30
|
const fixtures = require('#test/fixtures/index')
|
32
31
|
|
33
32
|
const { RestMethods, Headers } = PutPartiesErrorService.enums()
|
34
33
|
|
35
34
|
describe('PutPartiesErrorService Tests -->', () => {
|
35
|
+
let oracle
|
36
|
+
let participant
|
37
|
+
|
36
38
|
beforeEach(() => {
|
37
39
|
jest.clearAllMocks()
|
40
|
+
oracle = createOracleFacadeMock()
|
41
|
+
participant = createParticipantFacadeMock()
|
38
42
|
})
|
39
43
|
|
40
|
-
test('should cleanup oracle and forward
|
41
|
-
|
42
|
-
|
44
|
+
test('should cleanup oracle and forward PARTY_RESOLUTION_FAILURE error for party from external dfsp', async () => {
|
45
|
+
participant.validateParticipant = jest.fn().mockRejectedValue(new Error('No participant found')) // external participant
|
46
|
+
oracle.oracleRequest = jest.fn().mockResolvedValue({
|
47
|
+
data: { partyList: [{ fspId: 'fspId' }] }
|
48
|
+
})
|
49
|
+
const destination = 'externalDestination'
|
43
50
|
const proxyDest = 'proxyDest'
|
44
|
-
const deps = createMockDeps()
|
51
|
+
const deps = createMockDeps({ oracle, participant })
|
45
52
|
deps.proxyCache.lookupProxyByDfspId = jest.fn().mockResolvedValue(proxyDest)
|
46
53
|
|
47
54
|
const headers = fixtures.partiesCallHeadersDto({ destination, proxy: 'proxyA' })
|
48
55
|
const params = fixtures.partiesParamsDto()
|
49
|
-
const
|
50
|
-
const
|
56
|
+
const data = { test: true }
|
57
|
+
const dataUri = fixtures.dataUriDto(data)
|
51
58
|
|
59
|
+
const service = new PutPartiesErrorService(deps, { headers, params, dataUri })
|
52
60
|
await service.handleRequest()
|
53
|
-
|
54
|
-
expect(
|
55
|
-
expect(
|
56
|
-
|
57
|
-
|
61
|
+
|
62
|
+
expect(oracle.oracleRequest).toHaveBeenCalledTimes(2)
|
63
|
+
expect(oracle.oracleRequest.mock.lastCall[1]).toBe(RestMethods.DELETE)
|
64
|
+
expect(participant.sendErrorToParticipant).toHaveBeenCalledTimes(1)
|
65
|
+
|
66
|
+
const [sentTo, , payload, cbHeaders] = participant.sendErrorToParticipant.mock.lastCall
|
58
67
|
expect(sentTo).toBe(proxyDest)
|
59
68
|
expect(cbHeaders[Headers.FSPIOP.DESTINATION]).toBe(destination)
|
60
|
-
expect(payload
|
69
|
+
expect(payload).toBe(JSON.stringify(data))
|
61
70
|
})
|
62
71
|
|
63
72
|
test('should NOT cleanup oracle if destination is local', async () => {
|
64
73
|
const destination = 'localDfsp'
|
65
|
-
|
66
|
-
deps
|
74
|
+
participant.validateParticipant = jest.fn().mockResolvedValue({})
|
75
|
+
const deps = createMockDeps({ participant })
|
67
76
|
|
68
77
|
const headers = fixtures.partiesCallHeadersDto({ destination })
|
69
78
|
const params = fixtures.partiesParamsDto()
|
@@ -71,8 +80,8 @@ describe('PutPartiesErrorService Tests -->', () => {
|
|
71
80
|
const service = new PutPartiesErrorService(deps, { headers, params, dataUri })
|
72
81
|
|
73
82
|
await service.handleRequest()
|
74
|
-
expect(
|
75
|
-
expect(
|
76
|
-
expect(
|
83
|
+
expect(oracle.oracleRequest).not.toHaveBeenCalled()
|
84
|
+
expect(participant.sendErrorToParticipant).toHaveBeenCalledTimes(1)
|
85
|
+
expect(participant.sendErrorToParticipant.mock.lastCall[0]).toBe(destination)
|
77
86
|
})
|
78
87
|
})
|