account-lookup-service 17.13.0-snapshot.3 → 17.13.0-snapshot.4
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 +3 -3
- package/src/domain/parties/services/BasePartiesService.js +20 -0
- package/src/domain/parties/services/GetPartiesService.js +16 -31
- package/src/domain/parties/services/PutPartiesErrorService.js +17 -3
- package/test/unit/domain/parties/parties.test.js +4 -2
- package/test/unit/domain/parties/services/PutPartiesErrorService.test.js +23 -15
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.4",
|
5
5
|
"license": "Apache-2.0",
|
6
6
|
"author": "ModusBox",
|
7
7
|
"contributors": [
|
@@ -95,13 +95,13 @@
|
|
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
103
|
"@mojaloop/ml-schema-transformer-lib": "2.7.8",
|
104
|
-
"@mojaloop/sdk-standard-components": "19.16.
|
104
|
+
"@mojaloop/sdk-standard-components": "19.16.9",
|
105
105
|
"@now-ims/hapi-now-auth": "2.1.0",
|
106
106
|
"ajv": "8.17.1",
|
107
107
|
"ajv-keywords": "5.1.0",
|
@@ -170,6 +170,26 @@ class BasePartiesService {
|
|
170
170
|
this.log.info('sendErrorCallback is done', { sendTo, errorInfo })
|
171
171
|
}
|
172
172
|
|
173
|
+
/**
|
174
|
+
* @returns {Promise<{ fspId: string, partySubIdOrType?: string }[]>} List of parties from oracle response
|
175
|
+
*/
|
176
|
+
async sendOracleDiscoveryRequest () {
|
177
|
+
this.stepInProgress('#sendOracleDiscoveryRequest')
|
178
|
+
const { headers, params, query } = this.inputs
|
179
|
+
|
180
|
+
const response = await this.deps.oracle.oracleRequest(headers, RestMethods.GET, params, query, undefined, this.deps.cache)
|
181
|
+
this.log.debug('oracle discovery raw response:', { response })
|
182
|
+
|
183
|
+
let { partyList } = response?.data || {}
|
184
|
+
if (!Array.isArray(partyList)) {
|
185
|
+
this.log.warn('invalid oracle discovery response:', { response })
|
186
|
+
// todo: maybe, it's better to throw an error
|
187
|
+
partyList = []
|
188
|
+
}
|
189
|
+
|
190
|
+
return partyList
|
191
|
+
}
|
192
|
+
|
173
193
|
async sendDeleteOracleRequest (headers, params) {
|
174
194
|
this.stepInProgress('sendDeleteOracleRequest')
|
175
195
|
const result = await this.deps.oracle.oracleRequest(headers, RestMethods.DELETE, params, null, null, this.deps.cache)
|
@@ -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
|
|
@@ -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,26 +168,17 @@ 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
|
}
|
199
184
|
|
@@ -338,13 +323,13 @@ class GetPartiesService extends BasePartiesService {
|
|
338
323
|
log.verbose('needOracleValidation: ', { needValidation })
|
339
324
|
if (!needValidation) return true
|
340
325
|
|
341
|
-
const
|
342
|
-
if (
|
326
|
+
const partyList = await this.sendOracleDiscoveryRequest()
|
327
|
+
if (partyList.length === 0) {
|
343
328
|
log.warn('Oracle returned empty party list')
|
344
329
|
return false
|
345
330
|
}
|
346
331
|
|
347
|
-
const isValid =
|
332
|
+
const isValid = partyList.some(party => party.fspId === state.destination)
|
348
333
|
log.verbose('#validateLocalDestinationForExternalSource is done', { isValid })
|
349
334
|
return isValid
|
350
335
|
}
|
@@ -41,9 +41,9 @@ class PutPartiesErrorService extends BasePartiesService {
|
|
41
41
|
return
|
42
42
|
}
|
43
43
|
} else {
|
44
|
-
const
|
45
|
-
if (
|
46
|
-
this.log.info('Need to cleanup oracle and forward
|
44
|
+
const isExternal = await this.#isPartyFromExternalDfsp()
|
45
|
+
if (isExternal) {
|
46
|
+
this.log.info('Need to cleanup oracle and forward PARTY_RESOLUTION_FAILURE error')
|
47
47
|
await this.cleanupOracle()
|
48
48
|
await this.removeProxyGetPartiesTimeoutCache(alsReq)
|
49
49
|
await this.#sendPartyResolutionErrorCallback()
|
@@ -79,6 +79,20 @@ class PutPartiesErrorService extends BasePartiesService {
|
|
79
79
|
return super.sendErrorCallback({ errorInfo, headers, params })
|
80
80
|
}
|
81
81
|
|
82
|
+
async #isPartyFromExternalDfsp () {
|
83
|
+
this.stepInProgress('#isPartyFromExternalDfsp')
|
84
|
+
const partyList = await super.sendOracleDiscoveryRequest()
|
85
|
+
if (!partyList.length) {
|
86
|
+
this.log.verbose('oracle returns empty partyList')
|
87
|
+
return false
|
88
|
+
}
|
89
|
+
// think, if we have several parties from oracle
|
90
|
+
const isExternal = !(await this.validateParticipant(partyList[0].fspId))
|
91
|
+
this.log.verbose('#isPartyFromExternalDfsp is done:', { isExternal, partyList })
|
92
|
+
|
93
|
+
return isExternal
|
94
|
+
}
|
95
|
+
|
82
96
|
async #sendPartyResolutionErrorCallback () {
|
83
97
|
this.stepInProgress('#sendPartyResolutionErrorCallback')
|
84
98
|
const { headers, params } = this.inputs
|
@@ -958,11 +958,13 @@ describe('Parties Tests', () => {
|
|
958
958
|
oracleEndpointCached.getOracleEndpointByType = sandbox.stub().resolves([
|
959
959
|
{ value: 'http://oracle.endpoint' }
|
960
960
|
])
|
961
|
-
oracle.oracleRequest = sandbox.stub().resolves(
|
961
|
+
oracle.oracleRequest = sandbox.stub().resolves({
|
962
|
+
data: { partyList: [{ fspId: 'fspId' }] }
|
963
|
+
})
|
962
964
|
|
963
965
|
await partiesDomain.putPartiesErrorByTypeAndID(headers, params, payload, '', null, null, proxyCache)
|
964
966
|
|
965
|
-
expect(oracle.oracleRequest.callCount).toBe(
|
967
|
+
expect(oracle.oracleRequest.callCount).toBe(2)
|
966
968
|
expect(oracle.oracleRequest.lastCall.args[1]).toBe(RestMethods.DELETE)
|
967
969
|
expect(participant.sendRequest.callCount).toBe(0)
|
968
970
|
expect(participant.sendErrorToParticipant.callCount).toBe(1)
|
@@ -25,36 +25,44 @@
|
|
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
44
|
test('should cleanup oracle and forward PARTY_RESOLUTION_FAILURE error for party from external dfsp', async () => {
|
41
|
-
|
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
|
+
})
|
42
49
|
const destination = 'externalDfsp'
|
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
56
|
const dataUri = fixtures.dataUriDto()
|
50
|
-
const service = new PutPartiesErrorService(deps, { headers, params, dataUri })
|
51
57
|
|
58
|
+
const service = new PutPartiesErrorService(deps, { headers, params, dataUri })
|
52
59
|
await service.handleRequest()
|
53
|
-
|
54
|
-
expect(
|
55
|
-
expect(
|
56
|
-
|
57
|
-
|
60
|
+
|
61
|
+
expect(oracle.oracleRequest).toHaveBeenCalledTimes(2)
|
62
|
+
expect(oracle.oracleRequest.mock.lastCall[1]).toBe(RestMethods.DELETE)
|
63
|
+
expect(participant.sendErrorToParticipant).toHaveBeenCalledTimes(1)
|
64
|
+
|
65
|
+
const [sentTo, , payload, cbHeaders] = participant.sendErrorToParticipant.mock.lastCall
|
58
66
|
expect(sentTo).toBe(proxyDest)
|
59
67
|
expect(cbHeaders[Headers.FSPIOP.DESTINATION]).toBe(destination)
|
60
68
|
expect(payload.errorInformation.errorCode).toBe('2006')
|
@@ -62,8 +70,8 @@ describe('PutPartiesErrorService Tests -->', () => {
|
|
62
70
|
|
63
71
|
test('should NOT cleanup oracle if destination is local', async () => {
|
64
72
|
const destination = 'localDfsp'
|
65
|
-
|
66
|
-
deps
|
73
|
+
participant.validateParticipant = jest.fn().mockResolvedValue({})
|
74
|
+
const deps = createMockDeps({ participant })
|
67
75
|
|
68
76
|
const headers = fixtures.partiesCallHeadersDto({ destination })
|
69
77
|
const params = fixtures.partiesParamsDto()
|
@@ -71,8 +79,8 @@ describe('PutPartiesErrorService Tests -->', () => {
|
|
71
79
|
const service = new PutPartiesErrorService(deps, { headers, params, dataUri })
|
72
80
|
|
73
81
|
await service.handleRequest()
|
74
|
-
expect(
|
75
|
-
expect(
|
76
|
-
expect(
|
82
|
+
expect(oracle.oracleRequest).not.toHaveBeenCalled()
|
83
|
+
expect(participant.sendErrorToParticipant).toHaveBeenCalledTimes(1)
|
84
|
+
expect(participant.sendErrorToParticipant.mock.lastCall[0]).toBe(destination)
|
77
85
|
})
|
78
86
|
})
|