account-lookup-service 15.6.0-iso.2 → 15.6.0-iso.21
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/.circleci/config.yml +1 -1
- package/.ncurc.yaml +1 -2
- package/audit-ci.jsonc +3 -1
- package/jest.config.js +2 -0
- package/package.json +15 -17
- package/src/constants.js +2 -1
- package/src/domain/oracle/oracle.js +63 -4
- package/src/domain/participants/participants.js +259 -133
- package/src/domain/parties/getPartiesByTypeAndID.js +36 -15
- package/src/domain/parties/parties.js +44 -14
- package/src/domain/parties/utils.js +13 -6
- package/src/domain/timeout/dto.js +4 -10
- package/src/domain/timeout/index.js +12 -1
- package/src/handlers/index.js +4 -4
- package/src/handlers/monitoring/index.js +1 -1
- package/src/interface/api-swagger-iso20022-parties.yaml +7 -6
- package/src/interface/api-swagger.yaml +7 -6
- package/src/interface/fspiop-rest-v2.0-ISO20022_parties.yaml +2043 -1583
- package/src/lib/config.js +1 -1
- package/src/lib/index.js +1 -2
- package/src/models/currency/currency.js +10 -1
- package/src/models/endpointType/endpointType.js +10 -1
- package/src/models/oracle/facade.js +24 -3
- package/src/models/oracle/oracleEndpoint.js +64 -10
- package/src/models/oracle/oracleEndpointCached.js +22 -3
- package/src/models/participantEndpoint/facade.js +61 -23
- package/src/models/partyIdType/partyIdType.js +10 -1
- package/src/plugins.js +20 -9
- package/src/server.js +11 -19
- package/test/fixtures/index.js +30 -6
- package/test/fixtures/iso.js +1 -1
- package/test/unit/api/health.test.js +3 -0
- package/test/unit/api/participants/participants.test.js +5 -7
- package/test/unit/api/participants/{Type}/{ID}/{SubId}.test.js +0 -3
- package/test/unit/api/participants/{Type}/{ID}.test.js +0 -3
- package/test/unit/api/participants.test.js +36 -3
- package/test/unit/domain/oracle/oracle.test.js +8 -0
- package/test/unit/domain/participants/participants.test.js +83 -48
- package/test/unit/domain/parties/parties.test.js +11 -3
- package/test/unit/domain/parties/utils.test.js +60 -0
- package/test/unit/domain/timeout/dto.test.js +1 -2
- package/test/unit/domain/timeout/index.test.js +8 -0
- package/test/unit/lib/TransformFacades.test.js +2 -1
- package/test/unit/lib/config.test.js +7 -0
- package/test/unit/models/participantEndpoint/facade.test.js +25 -8
- package/test/unit/plugins.test.js +4 -2
- package/test/util/apiClients/BasicApiClient.js +2 -2
- package/src/handlers/monitoring/plugins/metrics.js +0 -48
- package/src/lib/requestLogger.js +0 -54
- package/src/metrics/handler.js +0 -33
- package/src/metrics/plugin.js +0 -52
- package/src/metrics/routes.js +0 -43
- package/test/unit/lib/requestLogger.test.js +0 -115
package/src/lib/config.js
CHANGED
@@ -167,7 +167,7 @@ const config = {
|
|
167
167
|
INSTRUMENTATION_METRICS_LABELS: RC.INSTRUMENTATION.METRICS.labels,
|
168
168
|
INSTRUMENTATION_METRICS_CONFIG: RC.INSTRUMENTATION.METRICS.config,
|
169
169
|
JWS_SIGN: RC.ENDPOINT_SECURITY.JWS.JWS_SIGN,
|
170
|
-
FSPIOP_SOURCE_TO_SIGN: RC.
|
170
|
+
FSPIOP_SOURCE_TO_SIGN: RC.HUB_PARTICIPANT.NAME,
|
171
171
|
JWS_SIGNING_KEY_PATH: RC.ENDPOINT_SECURITY.JWS.JWS_SIGNING_KEY_PATH,
|
172
172
|
API_DOC_ENDPOINTS_ENABLED: RC.API_DOC_ENDPOINTS_ENABLED || false,
|
173
173
|
FEATURE_ENABLE_EXTENDED_PARTY_ID_TYPE: RC.FEATURE_ENABLE_EXTENDED_PARTY_ID_TYPE || false,
|
package/src/lib/index.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
const { loggerFactory
|
1
|
+
const { loggerFactory } = require('@mojaloop/central-services-logger/src/contextLogger')
|
2
2
|
const { TransformFacades } = require('@mojaloop/ml-schema-transformer-lib')
|
3
3
|
|
4
4
|
const logger = loggerFactory('ALS') // global logger without context
|
@@ -6,6 +6,5 @@ const logger = loggerFactory('ALS') // global logger without context
|
|
6
6
|
module.exports = {
|
7
7
|
logger,
|
8
8
|
loggerFactory,
|
9
|
-
asyncStorage,
|
10
9
|
TransformFacades
|
11
10
|
}
|
@@ -39,7 +39,16 @@ const getCurrencyById = async (currencyId) => {
|
|
39
39
|
try {
|
40
40
|
return Db.from('currency').findOne({ currencyId, isActive: true })
|
41
41
|
} catch (err) {
|
42
|
-
|
42
|
+
const extensions = [{
|
43
|
+
key: 'system',
|
44
|
+
value: '["db"]'
|
45
|
+
}]
|
46
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
47
|
+
err,
|
48
|
+
undefined,
|
49
|
+
undefined,
|
50
|
+
extensions
|
51
|
+
)
|
43
52
|
}
|
44
53
|
}
|
45
54
|
|
@@ -39,7 +39,16 @@ const getEndpointTypeByType = async (type) => {
|
|
39
39
|
try {
|
40
40
|
return Db.from('endpointType').findOne({ type, isActive: true })
|
41
41
|
} catch (err) {
|
42
|
-
|
42
|
+
const extensions = [{
|
43
|
+
key: 'system',
|
44
|
+
value: '["db"]'
|
45
|
+
}]
|
46
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
47
|
+
err,
|
48
|
+
undefined,
|
49
|
+
undefined,
|
50
|
+
extensions
|
51
|
+
)
|
43
52
|
}
|
44
53
|
}
|
45
54
|
|
@@ -123,6 +123,10 @@ exports.oracleRequest = async (headers, method, params = {}, query = {}, payload
|
|
123
123
|
throw err
|
124
124
|
}
|
125
125
|
} catch (err) {
|
126
|
+
const extensions = [{
|
127
|
+
key: 'system',
|
128
|
+
value: '["@hapi/catbox-memory","http"]'
|
129
|
+
}]
|
126
130
|
Logger.isErrorEnabled && Logger.error(`error in oracleRequest: ${err?.stack}`)
|
127
131
|
// If the error was a 400 from the Oracle, we'll modify the error to generate a response to the
|
128
132
|
// initiator of the request.
|
@@ -131,15 +135,32 @@ exports.oracleRequest = async (headers, method, params = {}, query = {}, payload
|
|
131
135
|
err.apiErrorCode.code === ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_COMMUNICATION_ERROR.code
|
132
136
|
) {
|
133
137
|
if (err.extensions.some(ext => (ext.key === 'status' && ext.value === Enums.Http.ReturnCodes.BADREQUEST.CODE))) {
|
134
|
-
throw ErrorHandler.Factory.createFSPIOPError(
|
138
|
+
throw ErrorHandler.Factory.createFSPIOPError(
|
139
|
+
ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND,
|
140
|
+
undefined,
|
141
|
+
undefined,
|
142
|
+
undefined,
|
143
|
+
extensions
|
144
|
+
)
|
135
145
|
// Added error 404 to cover a special case of the Mowali implementation
|
136
146
|
// which uses mojaloop/als-oracle-pathfinder and currently returns 404
|
137
147
|
// and in which case the Mowali implementation expects back `DESTINATION_FSP_ERROR`.
|
138
148
|
} else if (err.extensions.some(ext => (ext.key === 'status' && ext.value === Enums.Http.ReturnCodes.NOTFOUND.CODE))) {
|
139
|
-
throw ErrorHandler.Factory.createFSPIOPError(
|
149
|
+
throw ErrorHandler.Factory.createFSPIOPError(
|
150
|
+
ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_FSP_ERROR,
|
151
|
+
undefined,
|
152
|
+
undefined,
|
153
|
+
undefined,
|
154
|
+
extensions
|
155
|
+
)
|
140
156
|
}
|
141
157
|
}
|
142
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
158
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
159
|
+
err,
|
160
|
+
undefined,
|
161
|
+
undefined,
|
162
|
+
extensions
|
163
|
+
)
|
143
164
|
}
|
144
165
|
}
|
145
166
|
|
@@ -27,6 +27,10 @@
|
|
27
27
|
|
28
28
|
const Db = require('../../lib/db')
|
29
29
|
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
30
|
+
const extensions = [{
|
31
|
+
key: 'system',
|
32
|
+
value: '["db"]'
|
33
|
+
}]
|
30
34
|
|
31
35
|
const getOracleEndpointByType = async (type) => {
|
32
36
|
try {
|
@@ -43,7 +47,12 @@ const getOracleEndpointByType = async (type) => {
|
|
43
47
|
'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
|
44
48
|
})
|
45
49
|
} catch (err) {
|
46
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
50
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
51
|
+
err,
|
52
|
+
undefined,
|
53
|
+
undefined,
|
54
|
+
extensions
|
55
|
+
)
|
47
56
|
}
|
48
57
|
}
|
49
58
|
|
@@ -64,7 +73,12 @@ const getOracleEndpointByTypeAndCurrency = async (type, currencyId) => {
|
|
64
73
|
'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
|
65
74
|
})
|
66
75
|
} catch (err) {
|
67
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
76
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
77
|
+
err,
|
78
|
+
undefined,
|
79
|
+
undefined,
|
80
|
+
extensions
|
81
|
+
)
|
68
82
|
}
|
69
83
|
}
|
70
84
|
|
@@ -84,7 +98,12 @@ const getOracleEndpointByCurrency = async (currencyId) => {
|
|
84
98
|
'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
|
85
99
|
})
|
86
100
|
} catch (err) {
|
87
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
101
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
102
|
+
err,
|
103
|
+
undefined,
|
104
|
+
undefined,
|
105
|
+
extensions
|
106
|
+
)
|
88
107
|
}
|
89
108
|
}
|
90
109
|
|
@@ -104,7 +123,12 @@ const getOracleEndpointById = async (oracleEndpointId) => {
|
|
104
123
|
'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
|
105
124
|
})
|
106
125
|
} catch (err) {
|
107
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
126
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
127
|
+
err,
|
128
|
+
undefined,
|
129
|
+
undefined,
|
130
|
+
extensions
|
131
|
+
)
|
108
132
|
}
|
109
133
|
}
|
110
134
|
|
@@ -122,7 +146,12 @@ const getAllOracleEndpoint = async () => {
|
|
122
146
|
'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
|
123
147
|
})
|
124
148
|
} catch (err) {
|
125
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
149
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
150
|
+
err,
|
151
|
+
undefined,
|
152
|
+
undefined,
|
153
|
+
extensions
|
154
|
+
)
|
126
155
|
}
|
127
156
|
}
|
128
157
|
|
@@ -142,7 +171,12 @@ const getAllOracleEndpointsByMatchCondition = async (oracleEndpointModel, partyI
|
|
142
171
|
'oracleEndpoint.isActive', 'oracleEndpoint.partyIdTypeId', 'oracleEndpoint.endpointTypeId', 'oracleEndpoint.currencyId')
|
143
172
|
})
|
144
173
|
} catch (err) {
|
145
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
174
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
175
|
+
err,
|
176
|
+
undefined,
|
177
|
+
undefined,
|
178
|
+
extensions
|
179
|
+
)
|
146
180
|
}
|
147
181
|
}
|
148
182
|
|
@@ -150,7 +184,12 @@ const createOracleEndpoint = async (oracleEndpointModel) => {
|
|
150
184
|
try {
|
151
185
|
return await Db.from('oracleEndpoint').insert(oracleEndpointModel)
|
152
186
|
} catch (err) {
|
153
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
187
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
188
|
+
err,
|
189
|
+
undefined,
|
190
|
+
undefined,
|
191
|
+
extensions
|
192
|
+
)
|
154
193
|
}
|
155
194
|
}
|
156
195
|
|
@@ -158,7 +197,12 @@ const updateOracleEndpointById = async (id, oracleEndpointModel) => {
|
|
158
197
|
try {
|
159
198
|
return await Db.from('oracleEndpoint').update({ oracleEndpointId: id }, oracleEndpointModel)
|
160
199
|
} catch (err) {
|
161
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
200
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
201
|
+
err,
|
202
|
+
undefined,
|
203
|
+
undefined,
|
204
|
+
extensions
|
205
|
+
)
|
162
206
|
}
|
163
207
|
}
|
164
208
|
|
@@ -166,7 +210,12 @@ const setIsActiveOracleEndpoint = async (oracleType, isActive) => {
|
|
166
210
|
try {
|
167
211
|
return await Db.from('oracleEndpoint').update({ oracleType }, { isActive })
|
168
212
|
} catch (err) {
|
169
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
213
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
214
|
+
err,
|
215
|
+
undefined,
|
216
|
+
undefined,
|
217
|
+
extensions
|
218
|
+
)
|
170
219
|
}
|
171
220
|
}
|
172
221
|
|
@@ -174,7 +223,12 @@ const destroyOracleEndpointById = async (oracleEndpointId) => {
|
|
174
223
|
try {
|
175
224
|
return await Db.from('oracleEndpoint').update({ oracleEndpointId }, { isActive: false })
|
176
225
|
} catch (err) {
|
177
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
226
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
227
|
+
err,
|
228
|
+
undefined,
|
229
|
+
undefined,
|
230
|
+
extensions
|
231
|
+
)
|
178
232
|
}
|
179
233
|
}
|
180
234
|
|
@@ -31,6 +31,10 @@ const Metrics = require('@mojaloop/central-services-metrics')
|
|
31
31
|
const OracleEndpointUncached = require('./oracleEndpoint')
|
32
32
|
|
33
33
|
let cacheClient
|
34
|
+
const extensions = [{
|
35
|
+
key: 'system',
|
36
|
+
value: '["db","@hapi/catbox-memory"]'
|
37
|
+
}]
|
34
38
|
|
35
39
|
const getCacheKey = (params) => {
|
36
40
|
return cacheClient.createKey(`${Object.values(params).join('__')}`)
|
@@ -87,7 +91,12 @@ exports.getOracleEndpointByTypeAndCurrency = async (partyIdType, currency) => {
|
|
87
91
|
try {
|
88
92
|
return await getOracleEndpointCached({ partyIdType, currency })
|
89
93
|
} catch (err) {
|
90
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
94
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
95
|
+
err,
|
96
|
+
undefined,
|
97
|
+
undefined,
|
98
|
+
extensions
|
99
|
+
)
|
91
100
|
}
|
92
101
|
}
|
93
102
|
|
@@ -95,7 +104,12 @@ exports.getOracleEndpointByType = async (partyIdType) => {
|
|
95
104
|
try {
|
96
105
|
return await getOracleEndpointCached({ partyIdType })
|
97
106
|
} catch (err) {
|
98
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
107
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
108
|
+
err,
|
109
|
+
undefined,
|
110
|
+
undefined,
|
111
|
+
extensions
|
112
|
+
)
|
99
113
|
}
|
100
114
|
}
|
101
115
|
|
@@ -103,6 +117,11 @@ exports.getOracleEndpointByCurrency = async (currency) => {
|
|
103
117
|
try {
|
104
118
|
return await getOracleEndpointCached({ currency })
|
105
119
|
} catch (err) {
|
106
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(
|
120
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
121
|
+
err,
|
122
|
+
undefined,
|
123
|
+
undefined,
|
124
|
+
extensions
|
125
|
+
)
|
107
126
|
}
|
108
127
|
}
|
@@ -33,7 +33,9 @@ const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
33
33
|
const JwsSigner = require('@mojaloop/sdk-standard-components').Jws.signer
|
34
34
|
const Metrics = require('@mojaloop/central-services-metrics')
|
35
35
|
const Config = require('../../lib/config')
|
36
|
+
const { logger } = require('../../lib')
|
36
37
|
const { hubNameRegex } = require('../../lib/util').hubNameConfig
|
38
|
+
|
37
39
|
const uriRegex = /(?:^.*)(\/(participants|parties|quotes|transfers)(\/.*)*)$/
|
38
40
|
|
39
41
|
/**
|
@@ -47,7 +49,7 @@ const defineJwsSigner = (config, headers, requestedEndpoint) => {
|
|
47
49
|
// We need below 2 headers for JWS
|
48
50
|
headers[Enums.Http.Headers.FSPIOP.HTTP_METHOD] = headers[Enums.Http.Headers.FSPIOP.HTTP_METHOD] || Enums.Http.RestMethods.PUT
|
49
51
|
headers[Enums.Http.Headers.FSPIOP.URI] = headers[Enums.Http.Headers.FSPIOP.URI] || uriRegex.exec(requestedEndpoint)[1]
|
50
|
-
|
52
|
+
logger.debug('JWS is enabled, getting JwsSigner')
|
51
53
|
jwsSigner = new JwsSigner({
|
52
54
|
logger: Logger,
|
53
55
|
signingKey: config.JWS_SIGNING_KEY
|
@@ -83,10 +85,10 @@ exports.sendRequest = async (headers, requestedParticipant, endpointType, method
|
|
83
85
|
try {
|
84
86
|
requestedEndpoint = await Util.Endpoints.getEndpoint(Config.SWITCH_ENDPOINT, requestedParticipant, endpointType, options || undefined)
|
85
87
|
histTimerEndGetParticipantEndpoint({ success: true, endpointType, participantName: requestedParticipant })
|
86
|
-
|
88
|
+
logger.debug('participant requestedEndpoint and endpointType: ', { requestedEndpoint, endpointType })
|
87
89
|
} catch (err) {
|
88
90
|
histTimerEndGetParticipantEndpoint({ success: false, endpointType, participantName: requestedParticipant })
|
89
|
-
|
91
|
+
logger.warn('error in getEndpoint: ', err)
|
90
92
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
91
93
|
}
|
92
94
|
|
@@ -102,9 +104,7 @@ exports.sendRequest = async (headers, requestedParticipant, endpointType, method
|
|
102
104
|
content: Config.PROTOCOL_VERSIONS.CONTENT.DEFAULT.toString(),
|
103
105
|
accept: Config.PROTOCOL_VERSIONS.ACCEPT.DEFAULT.toString()
|
104
106
|
}
|
105
|
-
const
|
106
|
-
|
107
|
-
const resp = await Util.Request.sendRequest({
|
107
|
+
const params = {
|
108
108
|
url: requestedEndpoint,
|
109
109
|
headers,
|
110
110
|
source: headers[Enums.Http.Headers.FSPIOP.SOURCE],
|
@@ -113,18 +113,29 @@ exports.sendRequest = async (headers, requestedParticipant, endpointType, method
|
|
113
113
|
payload,
|
114
114
|
responseType: Enums.Http.ResponseTypes.JSON,
|
115
115
|
span,
|
116
|
-
jwsSigner,
|
117
116
|
protocolVersions,
|
118
117
|
hubNameRegex,
|
119
118
|
apiType: Config.API_TYPE
|
120
|
-
}
|
119
|
+
}
|
120
|
+
logger.debug('participant - sendRequest params:', { params })
|
121
|
+
params.jwsSigner = defineJwsSigner(Config, headers, requestedEndpoint)
|
122
|
+
|
123
|
+
const resp = await Util.Request.sendRequest(params)
|
121
124
|
histTimerEndSendRequestToParticipant({ success: true, endpointType, participantName: requestedParticipant })
|
122
125
|
return resp
|
123
126
|
} catch (err) {
|
124
127
|
histTimerEndSendRequestToParticipant({ success: false, endpointType, participantName: requestedParticipant })
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
+
logger.warn('error in sendRequest: ', err)
|
129
|
+
const extensions = [{
|
130
|
+
key: 'system',
|
131
|
+
value: '["http"]'
|
132
|
+
}]
|
133
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
134
|
+
err,
|
135
|
+
undefined,
|
136
|
+
undefined,
|
137
|
+
extensions
|
138
|
+
)
|
128
139
|
}
|
129
140
|
}
|
130
141
|
|
@@ -148,8 +159,17 @@ exports.validateParticipant = async (fsp) => {
|
|
148
159
|
return resp
|
149
160
|
} catch (err) {
|
150
161
|
histTimerEnd({ success: false })
|
151
|
-
|
152
|
-
|
162
|
+
logger.warn('error in validateParticipant: ', err)
|
163
|
+
const extensions = [{
|
164
|
+
key: 'system',
|
165
|
+
value: '["http"]'
|
166
|
+
}]
|
167
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
168
|
+
err,
|
169
|
+
undefined,
|
170
|
+
undefined,
|
171
|
+
extensions
|
172
|
+
)
|
153
173
|
}
|
154
174
|
}
|
155
175
|
|
@@ -188,8 +208,17 @@ exports.sendErrorToParticipant = async (participantName, endpointType, errorInfo
|
|
188
208
|
histTimerEndGetParticipantEndpoint({ success: true, endpointType, participantName })
|
189
209
|
} catch (err) {
|
190
210
|
histTimerEndGetParticipantEndpoint({ success: false, endpointType, participantName })
|
191
|
-
|
192
|
-
|
211
|
+
logger.warn('error in getEndpoint: ', err)
|
212
|
+
const extensions = [{
|
213
|
+
key: 'system',
|
214
|
+
value: '["http"]'
|
215
|
+
}]
|
216
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
217
|
+
err,
|
218
|
+
undefined,
|
219
|
+
undefined,
|
220
|
+
extensions
|
221
|
+
)
|
193
222
|
}
|
194
223
|
|
195
224
|
// Send error to participant
|
@@ -212,10 +241,7 @@ exports.sendErrorToParticipant = async (participantName, endpointType, errorInfo
|
|
212
241
|
clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
|
213
242
|
}
|
214
243
|
|
215
|
-
|
216
|
-
const jwsSigner = defineJwsSigner(Config, clonedHeaders, requesterErrorEndpoint)
|
217
|
-
|
218
|
-
await Util.Request.sendRequest({
|
244
|
+
const params = {
|
219
245
|
url: requesterErrorEndpoint,
|
220
246
|
headers: clonedHeaders,
|
221
247
|
source: clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE],
|
@@ -225,14 +251,26 @@ exports.sendErrorToParticipant = async (participantName, endpointType, errorInfo
|
|
225
251
|
responseType: Enums.Http.ResponseTypes.JSON,
|
226
252
|
hubNameRegex,
|
227
253
|
span,
|
228
|
-
jwsSigner,
|
229
254
|
protocolVersions,
|
230
255
|
apiType: Config.API_TYPE
|
231
|
-
}
|
256
|
+
}
|
257
|
+
logger.debug('participant - sendErrorToParticipant params: ', { params })
|
258
|
+
params.jwsSigner = defineJwsSigner(Config, clonedHeaders, requesterErrorEndpoint)
|
259
|
+
|
260
|
+
await Util.Request.sendRequest(params)
|
232
261
|
histTimerEndSendRequestToParticipant({ success: true, endpointType, participantName })
|
233
262
|
} catch (err) {
|
234
263
|
histTimerEndSendRequestToParticipant({ success: false, endpointType, participantName })
|
235
|
-
|
236
|
-
|
264
|
+
logger.warn('error in sendErrorToParticipant: ', err)
|
265
|
+
const extensions = [{
|
266
|
+
key: 'system',
|
267
|
+
value: '["http"]'
|
268
|
+
}]
|
269
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
270
|
+
err,
|
271
|
+
undefined,
|
272
|
+
undefined,
|
273
|
+
extensions
|
274
|
+
)
|
237
275
|
}
|
238
276
|
}
|
@@ -32,7 +32,16 @@ const getPartyIdTypeByName = async (name) => {
|
|
32
32
|
try {
|
33
33
|
return Db.from('partyIdType').findOne({ name, isActive: true })
|
34
34
|
} catch (err) {
|
35
|
-
|
35
|
+
const extensions = [{
|
36
|
+
key: 'system',
|
37
|
+
value: '["db"]'
|
38
|
+
}]
|
39
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(
|
40
|
+
err,
|
41
|
+
undefined,
|
42
|
+
undefined,
|
43
|
+
extensions
|
44
|
+
)
|
36
45
|
}
|
37
46
|
}
|
38
47
|
|
package/src/plugins.js
CHANGED
@@ -24,16 +24,22 @@
|
|
24
24
|
******/
|
25
25
|
'use strict'
|
26
26
|
|
27
|
-
const Config = require('./lib/config')
|
28
27
|
const Inert = require('@hapi/inert')
|
29
28
|
const Vision = require('@hapi/vision')
|
30
29
|
const Blipp = require('blipp')
|
31
30
|
const ErrorHandling = require('@mojaloop/central-services-error-handling')
|
32
|
-
const
|
33
|
-
const
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
const MetricsPlugin = require('@mojaloop/central-services-metrics').plugin
|
32
|
+
const {
|
33
|
+
APIDocumentation,
|
34
|
+
FSPIOPHeaderValidation,
|
35
|
+
HapiEventPlugin,
|
36
|
+
HapiRawPayload,
|
37
|
+
OpenapiBackendValidator,
|
38
|
+
loggingPlugin
|
39
|
+
} = require('@mojaloop/central-services-shared').Util.Hapi
|
40
|
+
|
41
|
+
const { logger } = require('./lib')
|
42
|
+
const Config = require('./lib/config')
|
37
43
|
|
38
44
|
const registerPlugins = async (server, openAPIBackend) => {
|
39
45
|
await server.register(OpenapiBackendValidator)
|
@@ -121,10 +127,10 @@ const registerPlugins = async (server, openAPIBackend) => {
|
|
121
127
|
Inert,
|
122
128
|
Vision,
|
123
129
|
ErrorHandling,
|
124
|
-
|
125
|
-
|
130
|
+
HapiRawPayload,
|
131
|
+
HapiEventPlugin,
|
126
132
|
{
|
127
|
-
plugin:
|
133
|
+
plugin: FSPIOPHeaderValidation.plugin,
|
128
134
|
options: getOptionsForFSPIOPHeaderValidation()
|
129
135
|
}
|
130
136
|
])
|
@@ -132,6 +138,11 @@ const registerPlugins = async (server, openAPIBackend) => {
|
|
132
138
|
if (Config.DISPLAY_ROUTES === true) {
|
133
139
|
await server.register([Blipp])
|
134
140
|
}
|
141
|
+
|
142
|
+
await server.register({
|
143
|
+
plugin: loggingPlugin,
|
144
|
+
options: { log: logger }
|
145
|
+
})
|
135
146
|
}
|
136
147
|
|
137
148
|
module.exports = {
|
package/src/server.js
CHANGED
@@ -23,7 +23,6 @@
|
|
23
23
|
******/
|
24
24
|
'use strict'
|
25
25
|
|
26
|
-
const { randomUUID } = require('node:crypto')
|
27
26
|
const Hapi = require('@hapi/hapi')
|
28
27
|
const Boom = require('@hapi/boom')
|
29
28
|
|
@@ -37,7 +36,6 @@ const { name, version } = require('../package.json')
|
|
37
36
|
const Db = require('./lib/db')
|
38
37
|
const Util = require('./lib/util')
|
39
38
|
const Plugins = require('./plugins')
|
40
|
-
const RequestLogger = require('./lib/requestLogger')
|
41
39
|
const Migrator = require('./lib/migrator')
|
42
40
|
const APIHandlers = require('./api')
|
43
41
|
const Routes = require('./api/routes')
|
@@ -104,26 +102,17 @@ const createServer = async (port, api, routes, isAdmin, proxyCacheConfig, proxyM
|
|
104
102
|
}
|
105
103
|
}
|
106
104
|
|
107
|
-
await server.ext([
|
108
|
-
{
|
109
|
-
type: 'onPreHandler',
|
110
|
-
method: (request, h) => {
|
111
|
-
request.headers.traceid = request.headers.traceid || randomUUID()
|
112
|
-
RequestLogger.logRequest(request)
|
113
|
-
return h.continue
|
114
|
-
}
|
115
|
-
},
|
116
|
-
{
|
117
|
-
type: 'onPreResponse',
|
118
|
-
method: (request, h) => {
|
119
|
-
RequestLogger.logResponse(request)
|
120
|
-
return h.continue
|
121
|
-
}
|
122
|
-
}
|
123
|
-
])
|
124
105
|
await Plugins.registerPlugins(server, api, isAdmin)
|
125
106
|
|
126
107
|
server.route(routes)
|
108
|
+
|
109
|
+
// Initialize the error count metric
|
110
|
+
Metrics.getCounter(
|
111
|
+
'errorCount',
|
112
|
+
'Error count',
|
113
|
+
['code', 'system', 'operation', 'step']
|
114
|
+
)
|
115
|
+
|
127
116
|
// TODO: follow instructions https://github.com/anttiviljami/openapi-backend/blob/master/DOCS.md#postresponsehandler-handler
|
128
117
|
await server.start()
|
129
118
|
|
@@ -148,6 +137,9 @@ const initializeApi = async (appConfig) => {
|
|
148
137
|
} = appConfig
|
149
138
|
|
150
139
|
if (!INSTRUMENTATION_METRICS_DISABLED) {
|
140
|
+
if (INSTRUMENTATION_METRICS_CONFIG.defaultLabels) {
|
141
|
+
INSTRUMENTATION_METRICS_CONFIG.defaultLabels.serviceVersion = version
|
142
|
+
}
|
151
143
|
initializeInstrumentation(INSTRUMENTATION_METRICS_CONFIG)
|
152
144
|
}
|
153
145
|
await connectDatabase(DATABASE)
|
package/test/fixtures/index.js
CHANGED
@@ -9,14 +9,15 @@ const headersDto = ({
|
|
9
9
|
destination = 'toDfsp',
|
10
10
|
proxy = '',
|
11
11
|
date = '2024-05-24 08:52:19',
|
12
|
-
accept
|
12
|
+
accept,
|
13
|
+
contentType
|
13
14
|
} = {}) => Object.freeze({
|
14
15
|
[Headers.FSPIOP.SOURCE]: source,
|
15
16
|
...(destination && { [Headers.FSPIOP.DESTINATION]: destination }),
|
16
17
|
...(proxy && { [Headers.FSPIOP.PROXY]: proxy }),
|
17
18
|
date,
|
18
19
|
accept,
|
19
|
-
'content-type': accept
|
20
|
+
'content-type': contentType || accept
|
20
21
|
})
|
21
22
|
|
22
23
|
const protocolVersionsDto = () => ({
|
@@ -40,22 +41,29 @@ const partiesCallHeadersDto = ({
|
|
40
41
|
destination,
|
41
42
|
proxy,
|
42
43
|
date,
|
43
|
-
accept: '
|
44
|
+
accept: interopHeader('parties', '1'),
|
45
|
+
contentType: interopHeader('parties', '1.1')
|
44
46
|
})
|
45
47
|
|
46
48
|
const participantsCallHeadersDto = ({
|
47
49
|
source,
|
48
50
|
destination,
|
49
51
|
proxy,
|
50
|
-
date
|
52
|
+
date,
|
53
|
+
acceptVersion = '1',
|
54
|
+
contentTypeVersion = '1.1'
|
51
55
|
} = {}) => headersDto({
|
52
56
|
source,
|
53
57
|
destination,
|
54
58
|
proxy,
|
55
59
|
date,
|
56
|
-
accept: '
|
60
|
+
accept: interopHeader('participants', acceptVersion),
|
61
|
+
contentType: interopHeader('participants', contentTypeVersion)
|
57
62
|
})
|
58
63
|
|
64
|
+
// todo: add ISO mode support
|
65
|
+
const interopHeader = (resource, version = '1') => `application/vnd.interoperability.${resource}+json;version=${version}`
|
66
|
+
|
59
67
|
const oracleRequestResponseDto = ({
|
60
68
|
partyList = [{ fspId: 'dfspFromOracle' }]
|
61
69
|
} = {}) => ({
|
@@ -83,6 +91,20 @@ const putPartiesSuccessResponseDto = ({
|
|
83
91
|
}
|
84
92
|
})
|
85
93
|
|
94
|
+
const postParticipantsPayloadDto = ({
|
95
|
+
requestId = randomUUID(), // '01JE8SG3F4WNHY8B9876THQ344',
|
96
|
+
partyList = [{
|
97
|
+
partyIdType: 'MSISDN',
|
98
|
+
partyIdentifier: '123456',
|
99
|
+
fspId: 'fspId123'
|
100
|
+
}],
|
101
|
+
currency = 'XXX'
|
102
|
+
} = {}) => Object.freeze({
|
103
|
+
requestId,
|
104
|
+
partyList,
|
105
|
+
...(currency && { currency })
|
106
|
+
})
|
107
|
+
|
86
108
|
const errorCallbackResponseDto = ({
|
87
109
|
errorCode = '1234',
|
88
110
|
errorDescription = 'Error description',
|
@@ -124,8 +146,10 @@ module.exports = {
|
|
124
146
|
participantsCallHeadersDto,
|
125
147
|
oracleRequestResponseDto,
|
126
148
|
putPartiesSuccessResponseDto,
|
149
|
+
postParticipantsPayloadDto,
|
127
150
|
errorCallbackResponseDto,
|
128
151
|
mockAlsRequestDto,
|
129
152
|
protocolVersionsDto,
|
130
|
-
mockHapiRequestDto
|
153
|
+
mockHapiRequestDto,
|
154
|
+
interopHeader
|
131
155
|
}
|