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 CHANGED
@@ -3,7 +3,6 @@ disabled: false
3
3
 
4
4
  ignore:
5
5
 
6
-
7
6
  # Set output format defaults
8
7
  output:
9
8
  - "table"
package/audit-ci.jsonc CHANGED
@@ -5,5 +5,6 @@
5
5
  "moderate": true,
6
6
  // NOTE: Please add as much information as possible to any items added to the allowList
7
7
  "allowlist": [
8
+ "GHSA-4hjh-wcwx-xvwj" // todo: update axios - https://github.com/advisories/GHSA-4hjh-wcwx-xvwj
8
9
  ]
9
10
  }
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.0",
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.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.32.0",
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.7",
104
- "@mojaloop/sdk-standard-components": "19.16.7",
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.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.11.0",
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.0",
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', // todo: think better message
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
- // todo: think, if we need to pass span here
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
- createFspiopServiceUnavailableError (errMessage, log = this.log) {
233
+ createFspiopPartyResolutionError (errMessage, log = this.log) {
198
234
  log.warn(errMessage)
199
- return ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.SERVICE_CURRENTLY_UNAVAILABLE, errMessage)
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 { FspEndpointTypes, RestMethods } = BasePartiesService.enums()
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 response = await this.sendOracleDiscoveryRequest()
49
- const isSent = await this.processOraclePartyListResponse(response)
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.#sendPartyNotFoundErrorCallback(headers)
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 sendOracleDiscoveryRequest () {
121
- this.stepInProgress('#sendOracleDiscoveryRequest')
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(response)
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 (response) {
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
- if (!Array.isArray(filteredPartyList) || !filteredPartyList.length) {
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 oracleResponse = await this.sendOracleDiscoveryRequest()
342
- if (!Array.isArray(oracleResponse?.data?.partyList) || oracleResponse.data.partyList.length === 0) {
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 = oracleResponse.data.partyList.some(party => party.fspId === state.destination)
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) // or source?
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 schemeParticipant = await this.validateParticipant(this.state.destination)
45
- if (!schemeParticipant) {
46
- this.log.info('Need to cleanup oracle and forward SERVICE_CURRENTLY_UNAVAILABLE error')
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 forwardServiceUnavailableErrorCallback () {
83
- this.stepInProgress('forwardServiceUnavailableErrorCallback')
84
- const { headers, params } = this.inputs
85
- const error = super.createFspiopServiceUnavailableError(ERROR_MESSAGES.externalPartyError)
86
- const callbackHeaders = BasePartiesService.createErrorCallbackHeaders(headers, params, this.state.destination)
87
- const errorInfo = await this.deps.partiesUtils.makePutPartiesErrorPayload(this.deps.config, error, callbackHeaders, params)
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
- await this.identifyDestinationForCallback()
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', { mappingPayload })
107
+ this.log.info('oracle was updated with mappingPayload: ', mappingPayload)
108
108
  }
109
109
  }
110
110
 
@@ -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, '', null, null, proxyCache)
966
+ await partiesDomain.putPartiesErrorByTypeAndID(headers, params, payload, dataUri, null, null, proxyCache)
964
967
 
965
- expect(oracle.oracleRequest.callCount).toBe(1)
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('2003')
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, // use it instead of oracleMock
32
- createParticipantFacadeMock, // use it instead of participantMock
31
+ createOracleFacadeMock,
32
+ createParticipantFacadeMock,
33
33
  createProxyCacheMock,
34
34
  createProxiesUtilMock,
35
- oracleMock, // deprecated - use createOracleFacadeMock
36
- participantMock// deprecated - use createParticipantFacadeMock
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
- let apiType
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 = apiType // to avoid side effects
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
- deps = createMockDeps({ oracle, participant })
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
- deps.proxyCache.lookupProxyByDfspId = jest.fn().mockResolvedValueOnce(PROXY_ID)
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 SERVICE_CURRENTLY_UNAVAILABLE error for party from external dfsp', async () => {
41
- participantMock.validateParticipant = jest.fn().mockRejectedValue(new Error('No participant found')) // external participant
42
- const destination = 'externalDfsp'
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 dataUri = fixtures.dataUriDto()
50
- const service = new PutPartiesErrorService(deps, { headers, params, dataUri })
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
- expect(oracleMock.oracleRequest).toHaveBeenCalledTimes(1)
54
- expect(oracleMock.oracleRequest.mock.lastCall[1]).toBe(RestMethods.DELETE)
55
- expect(participantMock.sendErrorToParticipant).toHaveBeenCalledTimes(1)
56
- // eslint-disable-next-line no-unused-vars
57
- const [sentTo, _, payload, cbHeaders] = participantMock.sendErrorToParticipant.mock.lastCall
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.errorInformation.errorCode).toBe('2003')
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
- const deps = createMockDeps()
66
- deps.participant.validateParticipant = jest.fn().mockResolvedValue({})
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(oracleMock.oracleRequest).not.toHaveBeenCalled()
75
- expect(participantMock.sendErrorToParticipant).toHaveBeenCalledTimes(1)
76
- expect(participantMock.sendErrorToParticipant.mock.lastCall[0]).toBe(destination)
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
  })