account-lookup-service 15.6.0-iso.22 → 15.6.0-iso.24

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/audit-ci.jsonc CHANGED
@@ -29,6 +29,7 @@
29
29
  "GHSA-rv95-896h-c2vc", // https://github.com/advisories/GHSA-rv95-896h-c2vc
30
30
  "GHSA-952p-6rrq-rcjv", // https://github.com/advisories/GHSA-952p-6rrq-rcjv
31
31
  "GHSA-3xgq-45jj-v275", // https://github.com/advisories/GHSA-3xgq-45jj-v275
32
- "GHSA-rhx6-c78j-4q9w" // https://github.com/advisories/GHSA-rhx6-c78j-4q9w
32
+ "GHSA-rhx6-c78j-4q9w", // https://github.com/advisories/GHSA-rhx6-c78j-4q9w
33
+ "GHSA-mwcw-c2x4-8c55" // https://github.com/advisories/GHSA-mwcw-c2x4-8c55
33
34
  ]
34
35
  }
@@ -15,6 +15,7 @@
15
15
  "DATABASE": "account_lookup",
16
16
  "POOL_MIN_SIZE": 10,
17
17
  "POOL_MAX_SIZE": 10,
18
+ "MAX_PENDING_ACQUIRE": null,
18
19
  "ACQUIRE_TIMEOUT_MILLIS": 30000,
19
20
  "CREATE_TIMEOUT_MILLIS": 30000,
20
21
  "DESTROY_TIMEOUT_MILLIS": 5000,
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": "15.6.0-iso.22",
4
+ "version": "15.6.0-iso.24",
5
5
  "license": "Apache-2.0",
6
6
  "author": "ModusBox",
7
7
  "contributors": [
@@ -94,12 +94,12 @@
94
94
  "@mojaloop/central-services-health": "15.0.0",
95
95
  "@mojaloop/central-services-logger": "11.5.1",
96
96
  "@mojaloop/central-services-metrics": "12.4.2",
97
- "@mojaloop/central-services-shared": "18.14.1",
98
- "@mojaloop/central-services-stream": "11.3.1",
99
- "@mojaloop/database-lib": "11.0.6",
97
+ "@mojaloop/central-services-shared": "18.14.2",
98
+ "@mojaloop/central-services-stream": "11.4.1",
99
+ "@mojaloop/database-lib": "11.1.0",
100
100
  "@mojaloop/event-sdk": "14.1.1",
101
101
  "@mojaloop/inter-scheme-proxy-cache-lib": "2.3.1",
102
- "@mojaloop/ml-schema-transformer-lib": "2.4.1",
102
+ "@mojaloop/ml-schema-transformer-lib": "2.5.1",
103
103
  "@mojaloop/sdk-standard-components": "19.6.2",
104
104
  "@now-ims/hapi-now-auth": "2.1.0",
105
105
  "ajv": "8.17.1",
@@ -118,6 +118,9 @@
118
118
  "rc": "1.2.8"
119
119
  },
120
120
  "overrides": {
121
+ "postcss": {
122
+ "nanoid": "^3.3.8"
123
+ },
121
124
  "@mojaloop/central-services-health": {
122
125
  "@mojaloop/central-services-logger": ">=11.4.0"
123
126
  },
@@ -157,7 +160,7 @@
157
160
  "jest": "29.7.0",
158
161
  "jest-junit": "16.0.0",
159
162
  "jsdoc": "4.0.4",
160
- "nodemon": "3.1.7",
163
+ "nodemon": "3.1.9",
161
164
  "npm-check-updates": "17.1.11",
162
165
  "nyc": "17.1.0",
163
166
  "pre-commit": "1.2.2",
@@ -84,7 +84,7 @@ const getParticipantsByTypeAndID = async (headers, params, method, query, span,
84
84
  throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
85
85
  }
86
86
  step = 'oracleRequest-2'
87
- const response = await oracle.oracleRequest(headers, method, params, query, undefined, cache)
87
+ const response = await oracle.oracleRequest(headers, method, params, query, undefined, cache, true)
88
88
  if (response?.data && Array.isArray(response.data.partyList) && response.data.partyList.length > 0) {
89
89
  const options = {
90
90
  partyIdType: type,
@@ -91,12 +91,16 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
91
91
  const proxyEnabled = !!(Config.PROXY_CACHE_CONFIG.enabled && proxyCache)
92
92
  const type = params.Type
93
93
  const partySubId = params.SubId
94
+ const callbackEndpointType = utils.getPartyCbType(partySubId)
94
95
  const source = headers[Headers.FSPIOP.SOURCE]
95
96
  const proxy = proxyEnabled && headers[Headers.FSPIOP.PROXY]
96
- const callbackEndpointType = utils.getPartyCbType(partySubId)
97
+ let destination = headers[Headers.FSPIOP.DESTINATION]
98
+ // see https://github.com/mojaloop/design-authority/issues/79
99
+ // the requester has specified a destination routing header. We should respect that and forward the request directly to the destination
100
+ // without consulting any oracles.
97
101
 
98
102
  const childSpan = span ? span.getChild('getPartiesByTypeAndID') : undefined
99
- log.info('parties::getPartiesByTypeAndID::begin', { source, proxy, params })
103
+ log.info('parties::getPartiesByTypeAndID::begin', { source, destination, proxy, params })
100
104
 
101
105
  let requester
102
106
  let fspiopError
@@ -110,10 +114,6 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
110
114
  ...(partySubId && { partySubIdOrType: partySubId })
111
115
  }
112
116
 
113
- let destination = headers[Headers.FSPIOP.DESTINATION]
114
- // see https://github.com/mojaloop/design-authority/issues/79
115
- // the requester has specified a destination routing header. We should respect that and forward the request directly to the destination
116
- // without consulting any oracles.
117
117
  if (destination) {
118
118
  step = 'validateParticipant-1'
119
119
  const destParticipantModel = await participant.validateParticipant(destination)
@@ -122,6 +122,7 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
122
122
  const proxyId = proxyEnabled && await proxyCache.lookupProxyByDfspId(destination)
123
123
 
124
124
  if (!proxyId) {
125
+ log.warn('no destination participant, and no dfsp-to-proxy mapping', { destination })
125
126
  const errMessage = ERROR_MESSAGES.partyDestinationFspNotFound
126
127
  throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
127
128
  }
package/src/lib/config.js CHANGED
@@ -117,6 +117,7 @@ const config = {
117
117
  password: RC.DATABASE.PASSWORD,
118
118
  database: RC.DATABASE.DATABASE
119
119
  },
120
+ maxPendingAcquire: RC.DATABASE.MAX_PENDING_ACQUIRE,
120
121
  pool: {
121
122
  // minimum size
122
123
  min: getOrDefault(RC.DATABASE.POOL_MIN_SIZE, 2),
@@ -47,10 +47,11 @@ const { hubNameRegex } = require('../../lib/util').hubNameConfig
47
47
  * @param {object} params - uri parameters of the http request
48
48
  * @param {object} query - the query parameter on the uri of the http request
49
49
  * @param {object} payload - payload of the request being sent out
50
+ * @param {object} assertPendingAcquire - flag to check DB pool pending acquire limit
50
51
  *
51
52
  * @returns {object} returns the response from the oracle
52
53
  */
53
- exports.oracleRequest = async (headers, method, params = {}, query = {}, payload = undefined, cache) => {
54
+ exports.oracleRequest = async (headers, method, params = {}, query = {}, payload = undefined, cache, assertPendingAcquire) => {
54
55
  try {
55
56
  let url
56
57
  const partyIdType = params.Type
@@ -59,13 +60,13 @@ exports.oracleRequest = async (headers, method, params = {}, query = {}, payload
59
60
  const partySubIdOrType = (params && params.SubId) ? params.SubId : (query && query.partySubIdOrType) ? query.partySubIdOrType : undefined
60
61
  const isGetRequest = method.toUpperCase() === Enums.Http.RestMethods.GET
61
62
  if (currency && partySubIdOrType && isGetRequest) {
62
- url = await _getOracleEndpointByTypeCurrencyAndSubId(partyIdType, partyIdentifier, currency, partySubIdOrType)
63
+ url = await _getOracleEndpointByTypeCurrencyAndSubId(partyIdType, partyIdentifier, currency, partySubIdOrType, assertPendingAcquire)
63
64
  } else if (currency && isGetRequest) {
64
- url = await _getOracleEndpointByTypeAndCurrency(partyIdType, partyIdentifier, currency)
65
+ url = await _getOracleEndpointByTypeAndCurrency(partyIdType, partyIdentifier, currency, assertPendingAcquire)
65
66
  } else if (partySubIdOrType && isGetRequest) {
66
- url = await _getOracleEndpointByTypeAndSubId(partyIdType, partyIdentifier, partySubIdOrType)
67
+ url = await _getOracleEndpointByTypeAndSubId(partyIdType, partyIdentifier, partySubIdOrType, assertPendingAcquire)
67
68
  } else {
68
- url = await _getOracleEndpointByType(partyIdType, partyIdentifier)
69
+ url = await _getOracleEndpointByType(partyIdType, partyIdentifier, assertPendingAcquire)
69
70
  if (partySubIdOrType) {
70
71
  payload = { ...payload, partySubIdOrType }
71
72
  }
@@ -172,12 +173,13 @@ exports.oracleRequest = async (headers, method, params = {}, query = {}, payload
172
173
  * @param {string} partyIdType - party ID type (e.g MSISDN)
173
174
  * @param {string} partyIdentifier - party ID
174
175
  * @param {string} currency - currency ID
176
+ * @param {object} assertPendingAcquire - flag to check DB pool pending acquire limit
175
177
  *
176
178
  * @returns {string} returns the endpoint to the oracle
177
179
  */
178
- const _getOracleEndpointByTypeAndCurrency = async (partyIdType, partyIdentifier, currency) => {
180
+ const _getOracleEndpointByTypeAndCurrency = async (partyIdType, partyIdentifier, currency, assertPendingAcquire) => {
179
181
  let url
180
- const oracleEndpointModel = await oracleEndpointCached.getOracleEndpointByTypeAndCurrency(partyIdType, currency)
182
+ const oracleEndpointModel = await oracleEndpointCached.getOracleEndpointByTypeAndCurrency(partyIdType, currency, assertPendingAcquire)
181
183
  if (oracleEndpointModel.length > 0) {
182
184
  if (oracleEndpointModel.length > 1) {
183
185
  const defautOracle = oracleEndpointModel.filter(oracle => oracle.isDefault).pop()
@@ -207,12 +209,13 @@ const _getOracleEndpointByTypeAndCurrency = async (partyIdType, partyIdentifier,
207
209
  *
208
210
  * @param {string} partyIdType - party ID type (e.g MSISDN)
209
211
  * @param {string} partyIdentifier - party ID
212
+ * @param {object} assertPendingAcquire - flag to check DB pool pending acquire limit
210
213
  *
211
214
  * @returns {string} returns the endpoint to the oracle
212
215
  */
213
- const _getOracleEndpointByType = async (partyIdType, partyIdentifier) => {
216
+ const _getOracleEndpointByType = async (partyIdType, partyIdentifier, assertPendingAcquire) => {
214
217
  let url
215
- const oracleEndpointModel = await oracleEndpointCached.getOracleEndpointByType(partyIdType)
218
+ const oracleEndpointModel = await oracleEndpointCached.getOracleEndpointByType(partyIdType, assertPendingAcquire)
216
219
  if (oracleEndpointModel.length > 0) {
217
220
  if (oracleEndpointModel.length > 1) {
218
221
  const defaultOracle = oracleEndpointModel.filter(oracle => oracle.isDefault).pop()
@@ -243,12 +246,13 @@ const _getOracleEndpointByType = async (partyIdType, partyIdentifier) => {
243
246
  * @param {string} partyIdType - party ID type (e.g MSISDN)
244
247
  * @param {string} partyIdentifier - party ID
245
248
  * @param {string} partySubIdOrType - party subId
249
+ * @param {object} assertPendingAcquire - flag to check DB pool pending acquire limit
246
250
  *
247
251
  * @returns {string} returns the endpoint to the oracle
248
252
  */
249
- const _getOracleEndpointByTypeAndSubId = async (partyIdType, partyIdentifier, partySubIdOrType) => {
253
+ const _getOracleEndpointByTypeAndSubId = async (partyIdType, partyIdentifier, partySubIdOrType, assertPendingAcquire) => {
250
254
  let url
251
- const oracleEndpointModel = await oracleEndpointCached.getOracleEndpointByType(partyIdType)
255
+ const oracleEndpointModel = await oracleEndpointCached.getOracleEndpointByType(partyIdType, assertPendingAcquire)
252
256
  if (oracleEndpointModel.length > 0) {
253
257
  if (oracleEndpointModel.length > 1) {
254
258
  const defautOracle = oracleEndpointModel.filter(oracle => oracle.isDefault).pop()
@@ -280,12 +284,13 @@ const _getOracleEndpointByTypeAndSubId = async (partyIdType, partyIdentifier, pa
280
284
  * @param {string} partyIdentifier - party ID
281
285
  * @param {string} currency - currency ID
282
286
  * @param {string} partySubIdOrType - party subId
287
+ * @param {object} assertPendingAcquire - flag to check DB pool pending acquire limit
283
288
  *
284
289
  * @returns {string} returns the endpoint to the oracle
285
290
  */
286
- const _getOracleEndpointByTypeCurrencyAndSubId = async (partyIdType, partyIdentifier, currency, partySubIdOrType) => {
291
+ const _getOracleEndpointByTypeCurrencyAndSubId = async (partyIdType, partyIdentifier, currency, partySubIdOrType, assertPendingAcquire) => {
287
292
  let url
288
- const oracleEndpointModel = await oracleEndpointCached.getOracleEndpointByTypeAndCurrency(partyIdType, currency)
293
+ const oracleEndpointModel = await oracleEndpointCached.getOracleEndpointByTypeAndCurrency(partyIdType, currency, assertPendingAcquire)
289
294
  if (oracleEndpointModel.length > 0) {
290
295
  if (oracleEndpointModel.length > 1) {
291
296
  const defautOracle = oracleEndpointModel.filter(oracle => oracle.isDefault).pop()
@@ -233,6 +233,7 @@ const destroyOracleEndpointById = async (oracleEndpointId) => {
233
233
  }
234
234
 
235
235
  module.exports = {
236
+ assertPendingAcquires: Db.assertPendingAcquires,
236
237
  getOracleEndpointByType,
237
238
  getOracleEndpointByTypeAndCurrency,
238
239
  getOracleEndpointByCurrency,
@@ -53,6 +53,7 @@ const getOracleEndpointCached = async (params) => {
53
53
  const cacheKey = getCacheKey(params)
54
54
  let cachedEndpoints = cacheClient.get(cacheKey)
55
55
  if (!cachedEndpoints) {
56
+ if (params.assertPendingAcquire) OracleEndpointUncached.assertPendingAcquires()
56
57
  // No oracleEndpoint in the cache, so fetch from participant API
57
58
  let oracleEndpoints
58
59
  if (partyIdType && currency) {
@@ -87,9 +88,9 @@ exports.initialize = async () => {
87
88
  cacheClient = Cache.registerCacheClient(oracleEndpointCacheClientMeta)
88
89
  }
89
90
 
90
- exports.getOracleEndpointByTypeAndCurrency = async (partyIdType, currency) => {
91
+ exports.getOracleEndpointByTypeAndCurrency = async (partyIdType, currency, assertPendingAcquire) => {
91
92
  try {
92
- return await getOracleEndpointCached({ partyIdType, currency })
93
+ return await getOracleEndpointCached({ partyIdType, currency, assertPendingAcquire })
93
94
  } catch (err) {
94
95
  throw ErrorHandler.Factory.reformatFSPIOPError(
95
96
  err,
@@ -100,9 +101,9 @@ exports.getOracleEndpointByTypeAndCurrency = async (partyIdType, currency) => {
100
101
  }
101
102
  }
102
103
 
103
- exports.getOracleEndpointByType = async (partyIdType) => {
104
+ exports.getOracleEndpointByType = async (partyIdType, assertPendingAcquire) => {
104
105
  try {
105
- return await getOracleEndpointCached({ partyIdType })
106
+ return await getOracleEndpointCached({ partyIdType, assertPendingAcquire })
106
107
  } catch (err) {
107
108
  throw ErrorHandler.Factory.reformatFSPIOPError(
108
109
  err,
@@ -113,9 +114,9 @@ exports.getOracleEndpointByType = async (partyIdType) => {
113
114
  }
114
115
  }
115
116
 
116
- exports.getOracleEndpointByCurrency = async (currency) => {
117
+ exports.getOracleEndpointByCurrency = async (currency, assertPendingAcquire) => {
117
118
  try {
118
- return await getOracleEndpointCached({ currency })
119
+ return await getOracleEndpointCached({ currency, assertPendingAcquire })
119
120
  } catch (err) {
120
121
  throw ErrorHandler.Factory.reformatFSPIOPError(
121
122
  err,
@@ -58,6 +58,7 @@ describe('ParticipantCurrency cached model', () => {
58
58
  sandbox.stub(OracleEndpointUncached, 'getOracleEndpointByTypeAndCurrency').returns(oracleEndpoints)
59
59
  sandbox.stub(OracleEndpointUncached, 'getOracleEndpointByCurrency').returns(oracleEndpoints)
60
60
  sandbox.stub(OracleEndpointUncached, 'getOracleEndpointByType').returns(oracleEndpoints)
61
+ sandbox.stub(OracleEndpointUncached, 'assertPendingAcquires').returns()
61
62
  })
62
63
 
63
64
  afterEach(() => {
@@ -150,4 +151,35 @@ describe('ParticipantCurrency cached model', () => {
150
151
  await Model.getOracleEndpointByTypeAndCurrency('MSISDN', 'USD')
151
152
  expect(cacheClient.get.called).toBeTruthy()
152
153
  })
154
+ it('getOracleEndpointCached calls assertPendingAcquire when assertPendingAcquire is true', async () => {
155
+ let cache = null
156
+ const cacheClient = {
157
+ createKey: sandbox.stub().returns({}),
158
+ get: () => cache,
159
+ set: (key, x) => {
160
+ cache = { item: x } // the cache returns {item: <data>} structure
161
+ }
162
+ }
163
+ Cache.registerCacheClient.returns(cacheClient)
164
+ await Model.initialize()
165
+
166
+ await Model.getOracleEndpointByTypeAndCurrency('MSISDN', 'USD', true)
167
+ expect(OracleEndpointUncached.assertPendingAcquires.calledOnce).toBeTruthy()
168
+ })
169
+
170
+ it('getOracleEndpointCached does not call assertPendingAcquire when assertPendingAcquire is false', async () => {
171
+ let cache = null
172
+ const cacheClient = {
173
+ createKey: sandbox.stub().returns({}),
174
+ get: () => cache,
175
+ set: (key, x) => {
176
+ cache = { item: x } // the cache returns {item: <data>} structure
177
+ }
178
+ }
179
+ Cache.registerCacheClient.returns(cacheClient)
180
+ await Model.initialize()
181
+
182
+ await Model.getOracleEndpointByTypeAndCurrency('MSISDN', 'USD', false)
183
+ expect(OracleEndpointUncached.assertPendingAcquires.called).toBeFalsy()
184
+ })
153
185
  })