account-lookup-service 17.4.1 → 17.6.0

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/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [17.6.0](https://github.com/mojaloop/account-lookup-service/compare/v17.5.0...v17.6.0) (2025-03-19)
6
+
7
+
8
+ ### Features
9
+
10
+ * **csi-1244:** add DELETE participants validation ([#539](https://github.com/mojaloop/account-lookup-service/issues/539)) ([773baa1](https://github.com/mojaloop/account-lookup-service/commit/773baa154acd38051c61b10201d6fca6a33e614e))
11
+
12
+ ## [17.5.0](https://github.com/mojaloop/account-lookup-service/compare/v17.4.1...v17.5.0) (2025-03-18)
13
+
14
+
15
+ ### Features
16
+
17
+ * rethrow with context ([#540](https://github.com/mojaloop/account-lookup-service/issues/540)) ([c1037e9](https://github.com/mojaloop/account-lookup-service/commit/c1037e9ee3d78224074ca2c7ecc24c68a81c7e9e))
18
+
5
19
  ### [17.4.1](https://github.com/mojaloop/account-lookup-service/compare/v17.3.2...v17.4.1) (2025-03-14)
6
20
 
7
21
 
@@ -106,5 +106,6 @@
106
106
  }
107
107
  },
108
108
  "API_DOC_ENDPOINTS_ENABLED": true,
109
- "FEATURE_ENABLE_EXTENDED_PARTY_ID_TYPE": false
109
+ "FEATURE_ENABLE_EXTENDED_PARTY_ID_TYPE": false,
110
+ "DELETE_PARTICIPANT_VALIDATION_ENABLED": false
110
111
  }
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.4.1",
4
+ "version": "17.6.0",
5
5
  "license": "Apache-2.0",
6
6
  "author": "ModusBox",
7
7
  "contributors": [
@@ -93,9 +93,9 @@
93
93
  "@hapi/vision": "7.0.3",
94
94
  "@mojaloop/central-services-error-handling": "13.0.7",
95
95
  "@mojaloop/central-services-health": "15.0.4",
96
- "@mojaloop/central-services-logger": "11.6.2",
97
- "@mojaloop/central-services-metrics": "12.4.5",
98
- "@mojaloop/central-services-shared": "18.22.4",
96
+ "@mojaloop/central-services-logger": "11.7.0",
97
+ "@mojaloop/central-services-metrics": "12.5.0",
98
+ "@mojaloop/central-services-shared": "18.23.0",
99
99
  "@mojaloop/central-services-stream": "11.5.1",
100
100
  "@mojaloop/database-lib": "11.1.4",
101
101
  "@mojaloop/event-sdk": "14.3.2",
@@ -625,8 +625,7 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
625
625
  try {
626
626
  const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR)
627
627
  const errorCallbackEndpointType = params.SubId ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
628
- await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
629
- fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params)
628
+ await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType, fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params)
630
629
  util.countFspiopError(fspiopError, { operation: 'deleteParticipants', step })
631
630
  } catch (exc) {
632
631
  // We can't do anything else here- we _must_ handle all errors _within_ this function because
package/src/lib/config.js CHANGED
@@ -173,7 +173,8 @@ const config = {
173
173
  API_DOC_ENDPOINTS_ENABLED: RC.API_DOC_ENDPOINTS_ENABLED || false,
174
174
  FEATURE_ENABLE_EXTENDED_PARTY_ID_TYPE: RC.FEATURE_ENABLE_EXTENDED_PARTY_ID_TYPE || false,
175
175
  PROTOCOL_VERSIONS: getProtocolVersions(DEFAULT_PROTOCOL_VERSION, RC.PROTOCOL_VERSIONS),
176
- PROXY_CACHE_CONFIG: RC.PROXY_CACHE
176
+ PROXY_CACHE_CONFIG: RC.PROXY_CACHE,
177
+ DELETE_PARTICIPANT_VALIDATION_ENABLED: RC.DELETE_PARTICIPANT_VALIDATION_ENABLED || false
177
178
  }
178
179
 
179
180
  if (config.JWS_SIGN) {
package/src/lib/util.js CHANGED
@@ -29,7 +29,9 @@ const util = require('node:util')
29
29
  const Path = require('node:path')
30
30
  const EventSdk = require('@mojaloop/event-sdk')
31
31
  const Enum = require('@mojaloop/central-services-shared').Enum
32
- const { HeaderValidation, Hapi, rethrow } = require('@mojaloop/central-services-shared').Util
32
+ const { HeaderValidation, Hapi } = require('@mojaloop/central-services-shared').Util
33
+ const rethrow = require('@mojaloop/central-services-shared').Util.rethrow.with('ALS')
34
+
33
35
  const Config = require('../lib/config')
34
36
  const { logger } = require('./index')
35
37
 
@@ -59,6 +59,8 @@ exports.oracleRequest = async (headers, method, params = {}, query = {}, payload
59
59
  const currency = (payload && payload.currency) ? payload.currency : (query && query.currency) ? query.currency : undefined
60
60
  const partySubIdOrType = (params && params.SubId) ? params.SubId : (query && query.partySubIdOrType) ? query.partySubIdOrType : undefined
61
61
  const isGetRequest = method.toUpperCase() === Enums.Http.RestMethods.GET
62
+ const isDeleteRequest = method.toUpperCase() === Enums.Http.RestMethods.DELETE
63
+
62
64
  if (currency && partySubIdOrType && isGetRequest) {
63
65
  url = await _getOracleEndpointByTypeCurrencyAndSubId(partyIdType, partyIdentifier, currency, partySubIdOrType, assertPendingAcquire)
64
66
  } else if (currency && isGetRequest) {
@@ -110,6 +112,41 @@ exports.oracleRequest = async (headers, method, params = {}, query = {}, payload
110
112
  return cachedOracleFspResponse
111
113
  }
112
114
 
115
+ if (isDeleteRequest && Config.DELETE_PARTICIPANT_VALIDATION_ENABLED) {
116
+ // If the request is a DELETE request, we need to ensure that the participant belongs to the requesting FSP
117
+ const getOracleResponse = await request.sendRequest({
118
+ url,
119
+ headers,
120
+ source: headers[Enums.Http.Headers.FSPIOP.SOURCE],
121
+ destination: headers[Enums.Http.Headers.FSPIOP.DESTINATION] || Config.HUB_NAME,
122
+ method: Enums.Http.RestMethods.GET,
123
+ payload,
124
+ hubNameRegex
125
+ })
126
+
127
+ if (getOracleResponse.status === Enums.Http.ReturnCodes.OK.CODE) {
128
+ const participant = getOracleResponse.data
129
+ if (participant?.partyList?.length > 0) {
130
+ const party = participant.partyList[0]
131
+ if (party.fspId === headers[Enums.Http.Headers.FSPIOP.SOURCE]) {
132
+ return await request.sendRequest({
133
+ url,
134
+ headers,
135
+ source: headers[Enums.Http.Headers.FSPIOP.SOURCE],
136
+ destination: headers[Enums.Http.Headers.FSPIOP.DESTINATION] || Config.HUB_NAME,
137
+ method: method.toUpperCase(),
138
+ payload,
139
+ hubNameRegex
140
+ })
141
+ } else {
142
+ throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR, `The party ${partyIdType}:${partyIdentifier} does not belong to the requesting FSP`)
143
+ }
144
+ }
145
+ }
146
+
147
+ throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND)
148
+ }
149
+
113
150
  return await request.sendRequest({
114
151
  url,
115
152
  headers,
@@ -95,7 +95,7 @@ describe('Oracle tests', () => {
95
95
  Metrics.getCounter(
96
96
  'errorCount',
97
97
  'Error count',
98
- ['code', 'system', 'operation', 'step']
98
+ ['code', 'system', 'operation', 'step', 'context', 'expected']
99
99
  )
100
100
 
101
101
  beforeEach(() => {
@@ -54,7 +54,7 @@ describe('participant Tests', () => {
54
54
  Metrics.getCounter(
55
55
  'errorCount',
56
56
  'Error count',
57
- ['code', 'system', 'operation', 'step']
57
+ ['code', 'system', 'operation', 'step', 'context', 'expected']
58
58
  )
59
59
 
60
60
  beforeEach(() => {
@@ -70,7 +70,7 @@ describe('Parties Tests', () => {
70
70
  Metrics.getCounter(
71
71
  'errorCount',
72
72
  'Error count',
73
- ['code', 'system', 'operation', 'step']
73
+ ['code', 'system', 'operation', 'step', 'context', 'expected']
74
74
  )
75
75
 
76
76
  beforeEach(async () => {
@@ -40,7 +40,7 @@ describe('Timeout Domain', () => {
40
40
  Metrics.getCounter(
41
41
  'errorCount',
42
42
  'Error count',
43
- ['code', 'system', 'operation', 'step']
43
+ ['code', 'system', 'operation', 'step', 'context', 'expected']
44
44
  )
45
45
 
46
46
  beforeEach(() => {
@@ -51,6 +51,7 @@ jest.mock('@mojaloop/central-services-shared', () => ({
51
51
  Request: { sendRequest: mockSendRequest },
52
52
  Http: { SwitchDefaultHeaders: jest.fn() },
53
53
  HeaderValidation: { getHubNameRegex: jest.fn().mockReturnValue(new RegExp(mockHubName)) },
54
+ rethrow: jest.requireActual('@mojaloop/central-services-shared').Util.rethrow,
54
55
  Hapi: jest.requireActual('@mojaloop/central-services-shared').Util.Hapi
55
56
  },
56
57
  Enum: mockEnums