account-lookup-service 17.8.0-snapshot.10 → 17.8.0-snapshot.100
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 +4 -4
- package/src/domain/parties/services/BasePartiesService.js +4 -3
- package/src/domain/parties/services/GetPartiesService.js +6 -4
- package/src/server.js +16 -5
- package/test/unit/domain/parties/parties.test.js +1 -2
- package/test/unit/domain/parties/services/BasePartiesService.test.js +2 -1
- package/test/unit/domain/parties/services/GetPartiesService.test.js +35 -11
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.8.0-snapshot.
|
4
|
+
"version": "17.8.0-snapshot.100",
|
5
5
|
"license": "Apache-2.0",
|
6
6
|
"author": "ModusBox",
|
7
7
|
"contributors": [
|
@@ -92,9 +92,9 @@
|
|
92
92
|
"@hapi/vision": "7.0.3",
|
93
93
|
"@mojaloop/central-services-error-handling": "13.0.7",
|
94
94
|
"@mojaloop/central-services-health": "15.0.4",
|
95
|
-
"@mojaloop/central-services-logger": "11.8.
|
95
|
+
"@mojaloop/central-services-logger": "11.8.1",
|
96
96
|
"@mojaloop/central-services-metrics": "12.5.0",
|
97
|
-
"@mojaloop/central-services-shared": "18.23.
|
97
|
+
"@mojaloop/central-services-shared": "18.23.2",
|
98
98
|
"@mojaloop/central-services-stream": "11.5.2",
|
99
99
|
"@mojaloop/database-lib": "11.1.4",
|
100
100
|
"@mojaloop/event-sdk": "14.4.0",
|
@@ -106,7 +106,7 @@
|
|
106
106
|
"ajv-keywords": "5.1.0",
|
107
107
|
"blipp": "4.0.2",
|
108
108
|
"commander": "13.1.0",
|
109
|
-
"cron": "4.1.
|
109
|
+
"cron": "4.1.3",
|
110
110
|
"fast-safe-stringify": "^2.1.1",
|
111
111
|
"hapi-auth-bearer-token": "8.0.0",
|
112
112
|
"joi": "17.13.3",
|
@@ -100,16 +100,17 @@ class BasePartiesService {
|
|
100
100
|
get state () { return this.#state }
|
101
101
|
|
102
102
|
async handleError (error) {
|
103
|
-
const {
|
103
|
+
const { params } = this.inputs
|
104
104
|
const log = this.log.child({ method: 'handleError' })
|
105
105
|
try {
|
106
106
|
log.error('error in processing parties request: ', error)
|
107
107
|
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(error)
|
108
|
-
const
|
108
|
+
const callbackHeaders = BasePartiesService.createErrorCallbackHeaders(this.inputs.headers, params)
|
109
|
+
const errorInfo = await this.deps.partiesUtils.makePutPartiesErrorPayload(this.deps.config, fspiopError, callbackHeaders, params)
|
109
110
|
|
110
111
|
await this.sendErrorCallback({
|
111
112
|
errorInfo,
|
112
|
-
headers:
|
113
|
+
headers: callbackHeaders,
|
113
114
|
params
|
114
115
|
})
|
115
116
|
log.info('handleError in done')
|
@@ -61,10 +61,12 @@ class GetPartiesService extends BasePartiesService {
|
|
61
61
|
const log = this.log.child({ source, proxy, method: 'validateRequester' })
|
62
62
|
this.stepInProgress('validateRequester-0')
|
63
63
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
64
|
+
if (!(proxyEnabled && proxy)) {
|
65
|
+
const schemeSource = await this.validateParticipant(source)
|
66
|
+
if (schemeSource) {
|
67
|
+
log.debug('source participant is in scheme')
|
68
|
+
return source
|
69
|
+
}
|
68
70
|
}
|
69
71
|
|
70
72
|
if (!proxyEnabled || !proxy) {
|
package/src/server.js
CHANGED
@@ -45,7 +45,18 @@ const OracleEndpointCache = require('./models/oracle/oracleEndpointCached')
|
|
45
45
|
const Handlers = require('./handlers/register')
|
46
46
|
|
47
47
|
const connectDatabase = async (dbConfig) => {
|
48
|
-
|
48
|
+
await Db.connect(dbConfig)
|
49
|
+
logger.info('Database connected')
|
50
|
+
}
|
51
|
+
|
52
|
+
const initOpenApiBackend = async ({ isAdmin }) => {
|
53
|
+
const OpenAPISpecPath = Util.pathForInterface({ isAdmin, isMockInterface: false })
|
54
|
+
const apiHandlers = isAdmin
|
55
|
+
? APIHandlers.AdminHandlers
|
56
|
+
: APIHandlers.ApiHandlers
|
57
|
+
const api = await OpenapiBackend.initialise(OpenAPISpecPath, apiHandlers)
|
58
|
+
logger.verbose('OpenAPI Backend initialized', { isAdmin })
|
59
|
+
return api
|
49
60
|
}
|
50
61
|
|
51
62
|
const migrate = async () => {
|
@@ -132,8 +143,7 @@ const initializeApi = async (appConfig) => {
|
|
132
143
|
initializeInstrumentation(INSTRUMENTATION_METRICS_CONFIG)
|
133
144
|
}
|
134
145
|
await connectDatabase(DATABASE)
|
135
|
-
const
|
136
|
-
const api = await OpenapiBackend.initialise(OpenAPISpecPath, APIHandlers.ApiHandlers)
|
146
|
+
const api = await initOpenApiBackend({ isAdmin: false })
|
137
147
|
|
138
148
|
await Promise.all([
|
139
149
|
Endpoints.initializeCache(CENTRAL_SHARED_ENDPOINT_CACHE_CONFIG, Util.hubNameConfig),
|
@@ -142,6 +152,7 @@ const initializeApi = async (appConfig) => {
|
|
142
152
|
OracleEndpointCache.initialize(),
|
143
153
|
Cache.initCache()
|
144
154
|
])
|
155
|
+
logger.verbose('all caches initialized')
|
145
156
|
|
146
157
|
return createServer(API_PORT, api, Routes.APIRoutes(api), false, PROXY_CACHE_CONFIG)
|
147
158
|
}
|
@@ -161,8 +172,8 @@ const initializeAdmin = async (appConfig) => {
|
|
161
172
|
}
|
162
173
|
await connectDatabase(DATABASE)
|
163
174
|
RUN_MIGRATIONS && await migrate()
|
164
|
-
const
|
165
|
-
|
175
|
+
const api = await initOpenApiBackend({ isAdmin: true })
|
176
|
+
|
166
177
|
await Promise.all([
|
167
178
|
OracleEndpointCache.initialize(),
|
168
179
|
Cache.initCache()
|
@@ -174,8 +174,7 @@ describe('Parties Tests', () => {
|
|
174
174
|
it('should set source proxyMapping if source is not in scheme, and there is proxy-header', async () => {
|
175
175
|
Config.PROXY_CACHE_CONFIG.enabled = true
|
176
176
|
participant.validateParticipant = sandbox.stub()
|
177
|
-
.onFirstCall().resolves(
|
178
|
-
.onSecondCall().resolves({}) // proxy
|
177
|
+
.onFirstCall().resolves({}) // proxy, source is skipped
|
179
178
|
const source = `source-${Date.now()}`
|
180
179
|
const proxy = `proxy-${Date.now()}`
|
181
180
|
|
@@ -54,7 +54,8 @@ describe('BasePartiesService Tests -->', () => {
|
|
54
54
|
expect(sentTo).toBe(source)
|
55
55
|
expect(payload.Rpt.Rsn.Cd).toBe('2001')
|
56
56
|
expect(payload.Rpt.OrgnlId).toBe(`${params.Type}/${params.ID}`)
|
57
|
-
expect(payload.Assgnmt.
|
57
|
+
expect(payload.Assgnmt.Assgne.Agt.FinInstnId.Othr.Id).toBe(source)
|
58
|
+
expect(payload.Assgnmt.Assgnr.Agt.FinInstnId.Othr.Id).toBe(config.HUB_NAME)
|
58
59
|
})
|
59
60
|
|
60
61
|
test('should remove proxy getParties timeout cache key', async () => {
|
@@ -99,6 +99,9 @@ describe('GetPartiesService Tests -->', () => {
|
|
99
99
|
})
|
100
100
|
|
101
101
|
test('should cleanup oracle and trigger interScheme discovery, if no proxyMapping for external dfsp', async () => {
|
102
|
+
participantMock.validateParticipant = jest.fn()
|
103
|
+
.mockResolvedValueOnce({}) // proxy, source is skipped
|
104
|
+
|
102
105
|
proxyCache.lookupProxyByDfspId = jest.fn().mockResolvedValueOnce(null)
|
103
106
|
const headers = fixtures.partiesCallHeadersDto({
|
104
107
|
destination: '', proxy: 'proxyA'
|
@@ -114,6 +117,8 @@ describe('GetPartiesService Tests -->', () => {
|
|
114
117
|
})
|
115
118
|
|
116
119
|
test('should trigger interScheme discovery flow, if source is external', async () => {
|
120
|
+
participantMock.validateParticipant = jest.fn()
|
121
|
+
.mockResolvedValueOnce({}) // proxy, source is skipped
|
117
122
|
const headers = fixtures.partiesCallHeadersDto({
|
118
123
|
destination: '', proxy: 'proxyA'
|
119
124
|
})
|
@@ -199,15 +204,18 @@ describe('GetPartiesService Tests -->', () => {
|
|
199
204
|
expect(participantMock.sendRequest.mock.lastCall[1]).toBe(proxyOk)
|
200
205
|
})
|
201
206
|
|
202
|
-
|
203
|
-
expect.assertions(1)
|
207
|
+
const throwDelayedErrorOnNthCall = (N, delay = 1000, error = new Error('Nth call Delayed Error')) => {
|
204
208
|
let count = 0
|
205
|
-
|
209
|
+
return async () => {
|
206
210
|
count++
|
207
|
-
if (count !==
|
208
|
-
await sleep(1000)
|
209
|
-
throw
|
210
|
-
}
|
211
|
+
if (count !== N) return {}
|
212
|
+
await sleep(1000)
|
213
|
+
throw error
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
217
|
+
const prepareGetPartiesServiceForDelayedProxyError = () => {
|
218
|
+
participantMock.sendRequest = jest.fn(throwDelayedErrorOnNthCall(2)) // throw error on 2nd proxy call
|
211
219
|
const proxies = createProxiesUtilMock({
|
212
220
|
getAllProxiesNames: jest.fn().mockResolvedValue(['proxy1', 'proxy2'])
|
213
221
|
})
|
@@ -215,14 +223,31 @@ describe('GetPartiesService Tests -->', () => {
|
|
215
223
|
receivedErrorResponse: jest.fn().mockResolvedValue(true) // failed proxy request is last in inter-scheme discovery flow
|
216
224
|
})
|
217
225
|
const deps = createMockDeps({ proxies, proxyCache })
|
218
|
-
|
219
226
|
const headers = fixtures.partiesCallHeadersDto({ destination: '' })
|
220
227
|
const params = fixtures.partiesParamsDto()
|
221
|
-
|
228
|
+
|
229
|
+
return new GetPartiesService(deps, { headers, params })
|
230
|
+
}
|
231
|
+
|
232
|
+
test('should throw an error if proxyRequest failed after delay, and other proxies have already replied', async () => {
|
233
|
+
expect.assertions(1)
|
234
|
+
const service = prepareGetPartiesServiceForDelayedProxyError()
|
235
|
+
const { headers } = service.inputs
|
222
236
|
|
223
237
|
await expect(service.triggerInterSchemeDiscoveryFlow(headers))
|
224
238
|
.rejects.toThrow(ERROR_MESSAGES.noSuccessfulProxyDiscoveryResponses)
|
225
239
|
})
|
240
|
+
|
241
|
+
test('should send error callback in ISO format if proxyRequest failed after delay, and other proxies have already replied', async () => {
|
242
|
+
const service = prepareGetPartiesServiceForDelayedProxyError()
|
243
|
+
const { headers } = service.inputs
|
244
|
+
service.deps.config.API_TYPE = API_TYPES.iso20022
|
245
|
+
|
246
|
+
await service.triggerInterSchemeDiscoveryFlow(headers)
|
247
|
+
.catch(err => service.handleError(err))
|
248
|
+
expect(participantMock.sendErrorToParticipant).toHaveBeenCalledTimes(1)
|
249
|
+
expect(participantMock.sendErrorToParticipant.mock.lastCall[2].Rpt.Rsn.Cd).toBe('3200')
|
250
|
+
})
|
226
251
|
})
|
227
252
|
|
228
253
|
describe('setProxyGetPartiesTimeout Tests', () => {
|
@@ -247,8 +272,7 @@ describe('GetPartiesService Tests -->', () => {
|
|
247
272
|
|
248
273
|
test('should NOT set getParties timeout if source is external', async () => {
|
249
274
|
participantMock.validateParticipant = jest.fn()
|
250
|
-
.mockResolvedValueOnce(
|
251
|
-
.mockResolvedValueOnce({}) // proxy-src
|
275
|
+
.mockResolvedValueOnce({}) // proxy, source is skipped
|
252
276
|
const proxyCache = createProxyCacheMock({
|
253
277
|
lookupProxyByDfspId: jest.fn().mockResolvedValue('proxy-desc')
|
254
278
|
})
|