Skip to content

Commit

Permalink
#828: Integrate Event Framework (#24)
Browse files Browse the repository at this point in the history
* Update dependencies.
* Resolve vulnerabilites
* Bump version
* Integrate event framework.
* Update unit tests
* Update license
* Integrate sidecar
* Log all requests through sidecar
* Add sidecar NullClient tests
* Add unit tests for sidecar
* Update sidecar tests
* Add Sidecar logRequest test
* Update cs-shared
* Add sidecar 'close' event test
* Add sidecar health status
* Fix test coverage
* Fix test coverage
* Clear audit-resolve file
* Remove sidecar config
* Remove unused dependencies and configs
* Remove unused dependencies
* Update dependencies
* Formatting
* Fix event bug. Update test
* Update span util and tests
* Resolve audit issues: ignore vulnerabilities in "minimist" for a week
* Update version to 9.4.0
  • Loading branch information
oderayi authored Mar 19, 2020
1 parent 7c9a159 commit 55e3646
Show file tree
Hide file tree
Showing 25 changed files with 20,723 additions and 12,740 deletions.
7,586 changes: 7,583 additions & 3 deletions audit-resolve.json

Large diffs are not rendered by default.

25,369 changes: 12,716 additions & 12,653 deletions package-lock.json

Large diffs are not rendered by default.

15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "transaction-requests-service",
"description": "An asynchronous pass through transaction request API for merchant payment initiated requests.",
"version": "9.3.0",
"version": "9.4.0",
"license": "Apache-2.0",
"author": "ModusBox",
"contributors": [
Expand Down Expand Up @@ -59,14 +59,15 @@
"@mojaloop/central-services-error-handling": "9.1.0",
"@mojaloop/central-services-health": "9.2.0",
"@mojaloop/central-services-logger": "9.1.0",
"@mojaloop/central-services-shared": "9.2.0",
"@mojaloop/central-services-shared": "9.4.0",
"@mojaloop/event-sdk": "9.4.0",
"blipp": "4.0.1",
"commander": "4.1.1",
"commander": "5.0.0",
"docdash": "1.2.0",
"hapi-openapi": "1.2.6",
"hapi-swagger": "11.1.0",
"jsdoc": "3.6.3",
"mustache": "4.0.0",
"mustache": "4.0.1",
"parse-strings-in-object": "2.0.0",
"rc": "1.2.8"
},
Expand All @@ -76,10 +77,10 @@
"jest-junit": "10.0.0",
"license-checker": "25.0.1",
"npm-audit-resolver": "2.2.0",
"npm-check-updates": "4.0.3",
"npm-check-updates": "4.0.4",
"pre-commit": "1.2.2",
"sinon": "9.0.0",
"standard": "14.3.1",
"sinon": "9.0.1",
"standard": "14.3.3",
"swagmock": "1.0.0"
},
"generator-swaggerize": {
Expand Down
44 changes: 36 additions & 8 deletions src/domain/authorizations/authorizations.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
optionally within square brackets <email>.
* Gates Foundation
* Donovan Changfoot <don@coil.com>
* Coil
- Donovan Changfoot <don@coil.com>
* ModusBox
- Steven Oderayi <steven.oderayi@modusbox.com>
--------------
******/
Expand All @@ -27,6 +31,7 @@ const Logger = require('@mojaloop/central-services-logger')
const ErrorHandler = require('@mojaloop/central-services-error-handling')
const Enum = require('@mojaloop/central-services-shared').Enum
const Endpoint = require('@mojaloop/central-services-shared').Util.Endpoints
const EventSdk = require('@mojaloop/event-sdk')
const requests = require('@mojaloop/central-services-shared').Util.Request
const util = require('util')

Expand All @@ -42,12 +47,14 @@ const { getStackOrInspect } = require('../../lib/util')
* @throws {FSPIOPError} Will throw an error if no endpoint to forward the authorization message to is found, if there are network errors or if there is a bad response
* @returns {Promise<true>}
*/
const forwardAuthorizationMessage = async (headers, transactionRequestId, payload, method) => {
const forwardAuthorizationMessage = async (headers, transactionRequestId, payload, method, span = null) => {
const childSpan = span ? span.getChild('forwardAuthorizationMessage') : undefined
let endpoint
const fspiopSource = headers[Enum.Http.Headers.FSPIOP.SOURCE]
const fspiopDest = headers[Enum.Http.Headers.FSPIOP.DESTINATION]
const messageType = method === Enum.Http.RestMethods.GET ? 'request' : 'response'
const payloadLocal = method === Enum.Http.RestMethods.GET ? undefined : payload
let fspiopError

try {
endpoint = await Endpoint.getEndpoint(Config.SWITCH_ENDPOINT, fspiopDest, Enum.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_AUTHORIZATIONS)
Expand All @@ -63,10 +70,14 @@ const forwardAuthorizationMessage = async (headers, transactionRequestId, payloa

Logger.info(`Forwarding authorization request to endpoint: ${fullUrl}`)

const response = await requests.sendRequest(fullUrl, headers, fspiopSource, fspiopDest, method, payloadLocal)
const response = await requests.sendRequest(fullUrl, headers, fspiopSource, fspiopDest, method, payloadLocal, Enum.Http.ResponseTypes.JSON, childSpan)

Logger.info(`Forwarding authorization ${messageType} for transactionRequestId ${transactionRequestId} from ${fspiopSource} to ${fspiopDest} got response ${response.status} ${response.statusText}`)

if (childSpan && !childSpan.isFinished) {
childSpan.finish()
}

return true
} catch (err) {
Logger.info(`Error forwarding authorization ${messageType} to endpoint ${endpoint}: ${getStackOrInspect(err)}`)
Expand All @@ -76,9 +87,15 @@ const forwardAuthorizationMessage = async (headers, transactionRequestId, payloa
'fspiop-source': Enum.Http.Headers.FSPIOP.SWITCH.value,
'fspiop-destination': fspiopSource
}
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
await forwardAuthorizationError(errorHeaders, transactionRequestId, fspiopError.toApiErrorObject(Config.ERROR_HANDLING))
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
await forwardAuthorizationError(errorHeaders, transactionRequestId, fspiopError.toApiErrorObject(Config.ERROR_HANDLING), childSpan)
throw fspiopError
} finally {
if (childSpan && !childSpan.isFinished && fspiopError) {
const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message)
await childSpan.error(fspiopError, state)
await childSpan.finish(fspiopError.message, state)
}
}
}

Expand All @@ -90,7 +107,8 @@ const forwardAuthorizationMessage = async (headers, transactionRequestId, payloa
* @throws {FSPIOPError} Will throw an error if no endpoint to forward the authorization error to is found, if there are network errors or if there is a bad response.
* @returns {Promise<true>}
*/
const forwardAuthorizationError = async (headers, transactionRequestId, payload) => {
const forwardAuthorizationError = async (headers, transactionRequestId, payload, span = null) => {
const childSpan = span ? span.getChild('forwardAuthorizationError') : undefined
let endpoint
const fspiopSource = headers[Enum.Http.Headers.FSPIOP.SOURCE]
const fspiopDestination = headers[Enum.Http.Headers.FSPIOP.DESTINATION]
Expand All @@ -106,14 +124,24 @@ const forwardAuthorizationError = async (headers, transactionRequestId, payload)

Logger.info(`Forwarding authorization error to endpoint: ${fullUrl}`)

const response = await requests.sendRequest(fullUrl, headers, fspiopSource, fspiopDestination, Enum.Http.RestMethods.PUT, payload || undefined)
const response = await requests.sendRequest(fullUrl, headers, fspiopSource, fspiopDestination, Enum.Http.RestMethods.PUT, payload || undefined, Enum.Http.ResponseTypes.JSON, childSpan)

Logger.info(`Forwarding authorization error response for transactionRequest ${transactionRequestId} from ${fspiopSource} to ${fspiopDestination} got response ${response.status} ${response.statusText}`)

if (childSpan && !childSpan.isFinished) {
childSpan.finish()
}

return true
} catch (err) {
Logger.info(`Error forwarding authorization error response to endpoint ${endpoint}: ${getStackOrInspect(err)}`)
throw ErrorHandler.Factory.reformatFSPIOPError(err)
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
if (childSpan && !childSpan.isFinished) {
const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message)
await childSpan.error(fspiopError, state)
await childSpan.finish(fspiopError.message, state)
}
throw fspiopError
}
}

Expand Down
44 changes: 35 additions & 9 deletions src/domain/transactionRequests/transactionRequests.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
optionally within square brackets <email>.
* Gates Foundation
* Rajiv Mothilal <rajiv.mothilal@modusbox.com>
* ModusBox
- Rajiv Mothilal <rajiv.mothilal@modusbox.com>
- Steven Oderayi <steven.oderayi@modusbox.com>
--------------
******/
Expand All @@ -27,6 +29,7 @@ const Logger = require('@mojaloop/central-services-logger')
const ErrorHandler = require('@mojaloop/central-services-error-handling')
const Enum = require('@mojaloop/central-services-shared').Enum
const Endpoint = require('@mojaloop/central-services-shared').Util.Endpoints
const EventSdk = require('@mojaloop/event-sdk')
const requests = require('@mojaloop/central-services-shared').Util.Request
const Mustache = require('mustache')
const util = require('util')
Expand All @@ -37,14 +40,16 @@ const { getStackOrInspect } = require('../../lib/util')
/**
* Forwards transactionRequests endpoint requests to destination FSP for processing
*
* @returns {undefined}
* @returns {boolean}
*/
const forwardTransactionRequest = async (path, headers, method, params, payload) => {
const forwardTransactionRequest = async (path, headers, method, params, payload, span = null) => {
const childSpan = span ? span.getChild('forwardTransactionRequest') : undefined
let endpoint
const fspiopSource = headers[Enum.Http.Headers.FSPIOP.SOURCE]
const fspiopDest = headers[Enum.Http.Headers.FSPIOP.DESTINATION]
const payloadLocal = payload || { transactionRequestId: params.ID }
const transactionRequestId = (payload && payload.transactionRequestId) || params.ID
let fspiopError

try {
endpoint = await Endpoint.getEndpoint(Config.SWITCH_ENDPOINT, fspiopDest, Enum.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_TRX_REQ_SERVICE)
Expand All @@ -59,16 +64,26 @@ const forwardTransactionRequest = async (path, headers, method, params, payload)
})
Logger.info(`Forwarding transaction request to endpoint: ${fullUrl}`)

const response = await requests.sendRequest(fullUrl, headers, fspiopSource, fspiopDest, method, method.toUpperCase() !== Enum.Http.RestMethods.GET ? payloadLocal : undefined)
const response = await requests.sendRequest(fullUrl, headers, fspiopSource, fspiopDest, method, method.toUpperCase() !== Enum.Http.RestMethods.GET ? payloadLocal : undefined, Enum.Http.ResponseTypes.JSON, childSpan)

Logger.info(`Forwarded transaction request ${transactionRequestId} from ${fspiopSource} to ${fspiopDest} got response ${response.status} ${response.statusText}`)

if (childSpan && !childSpan.isFinished) {
childSpan.finish()
}

return true
} catch (err) {
Logger.info(`Error forwarding transaction request to endpoint ${endpoint}: ${getStackOrInspect(err)}`)
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
await forwardTransactionRequestError(headers, fspiopSource, Enum.EndPoints.FspEndpointTemplates.TRANSACTION_REQUEST_PUT_ERROR, Enum.Http.RestMethods.PUT, transactionRequestId, fspiopError.toApiErrorObject(Config.ERROR_HANDLING))
fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
await forwardTransactionRequestError(headers, fspiopSource, Enum.EndPoints.FspEndpointTemplates.TRANSACTION_REQUEST_PUT_ERROR, Enum.Http.RestMethods.PUT, transactionRequestId, fspiopError.toApiErrorObject(Config.ERROR_HANDLING), childSpan)
throw fspiopError
} finally {
if (childSpan && !childSpan.isFinished && fspiopError) {
const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message)
await childSpan.error(fspiopError, state)
await childSpan.finish(fspiopError.message, state)
}
}
}

Expand All @@ -77,7 +92,8 @@ const forwardTransactionRequest = async (path, headers, method, params, payload)
*
* @returns {undefined}
*/
const forwardTransactionRequestError = async (headers, to, path, method, transactionRequestId, payload) => {
const forwardTransactionRequestError = async (headers, to, path, method, transactionRequestId, payload, span = null) => {
const childSpan = span ? span.getChild('forwardTransactionRequestError') : undefined
let endpoint
const fspiopSource = headers[Enum.Http.Headers.FSPIOP.SOURCE]
const fspiopDestination = headers[Enum.Http.Headers.FSPIOP.DESTINATION]
Expand All @@ -96,14 +112,24 @@ const forwardTransactionRequestError = async (headers, to, path, method, transac

Logger.info(`Forwarding transaction request error to endpoint: ${fullUrl}`)

const response = await requests.sendRequest(fullUrl, headers, fspiopSource, fspiopDestination, method, payload || undefined)
const response = await requests.sendRequest(fullUrl, headers, fspiopSource, fspiopDestination, method, payload || undefined, Enum.Http.ResponseTypes.JSON, childSpan)

Logger.info(`Forwarding transaction request error for ${transactionRequestId} from ${fspiopSource} to ${to} got response ${response.status} ${response.statusText}`)

if (childSpan && !childSpan.isFinished) {
childSpan.finish()
}

return true
} catch (err) {
Logger.info(`Error forwarding transaction request error to endpoint ${endpoint}: ${getStackOrInspect(err)}`)
throw ErrorHandler.Factory.reformatFSPIOPError(err)
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
if (childSpan && !childSpan.isFinished) {
const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message)
await childSpan.error(fspiopError, state)
await childSpan.finish(fspiopError.message, state)
}
throw fspiopError
}
}

Expand Down
30 changes: 25 additions & 5 deletions src/handlers/authorizations/{ID}.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,20 @@
optionally within square brackets <email>.
* Gates Foundation
* Donovan Changfoot <don@coil.com>
* Coil
- Donovan Changfoot <don@coil.com>
* ModusBox
- Steven Oderayi <steven.oderayi@modusbox.com>
--------------
******/
'use strict'

const EventSdk = require('@mojaloop/event-sdk')
const Enum = require('@mojaloop/central-services-shared').Enum
const authorizations = require('../../domain/authorizations/authorizations')
const LibUtil = require('../../lib/util')

/**
* Operations on /authorizations/{ID}
Expand All @@ -37,8 +43,15 @@ module.exports = {
* produces: application/json
* responses: 202, 400, 401, 403, 404, 405, 406, 501, 503
*/
get: function (request, h) {
authorizations.forwardAuthorizationMessage(request.headers, request.params.ID, request.query, Enum.Http.RestMethods.GET)
get: async (request, h) => {
const span = request.span
const tags = LibUtil.getSpanTags(request, Enum.Events.Event.Type.AUTHORIZATION, Enum.Events.Event.Action.LOOKUP)
span.setTags(tags)
await span.audit({
headers: request.headers,
payload: request.payload
}, EventSdk.AuditEventAction.start)
authorizations.forwardAuthorizationMessage(request.headers, request.params.ID, request.query, Enum.Http.RestMethods.GET, span)
return h.response().code(Enum.Http.ReturnCodes.ACCEPTED.CODE)
},
/**
Expand All @@ -48,8 +61,15 @@ module.exports = {
* produces: application/json
* responses: 200, 400, 401, 403, 404, 405, 406, 501, 503
*/
put: function (request, h) {
authorizations.forwardAuthorizationMessage(request.headers, request.params.ID, request.payload, Enum.Http.RestMethods.PUT)
put: async (request, h) => {
const span = request.span
const tags = LibUtil.getSpanTags(request, Enum.Events.Event.Type.AUTHORIZATION, Enum.Events.Event.Action.PUT)
span.setTags(tags)
await span.audit({
headers: request.headers,
payload: request.payload
}, EventSdk.AuditEventAction.start)
authorizations.forwardAuthorizationMessage(request.headers, request.params.ID, request.payload, Enum.Http.RestMethods.PUT, span)
return h.response().code(Enum.Http.ReturnCodes.OK.CODE)
}
}
19 changes: 16 additions & 3 deletions src/handlers/authorizations/{ID}/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,20 @@
optionally within square brackets <email>.
* Gates Foundation
* Donovan Changfoot <don@coil.com>
* Coil
- Donovan Changfoot <don@coil.com>
* ModusBox
- Steven Oderayi <steven.oderayi@modusbox.com>
--------------
******/
'use strict'

const EventSdk = require('@mojaloop/event-sdk')
const Enum = require('@mojaloop/central-services-shared').Enum
const authorizations = require('../../../domain/authorizations/authorizations')
const LibUtil = require('../../../lib/util')

/**
* Operations on /authorizations/{ID}/error
Expand All @@ -37,8 +43,15 @@ module.exports = {
* produces: application/json
* responses: 200, 400, 401, 403, 404, 405, 406, 501, 503
*/
put: function (request, h) {
authorizations.forwardAuthorizationError(request.headers, request.params.ID, request.payload)
put: async (request, h) => {
const span = request.span
const tags = LibUtil.getSpanTags(request, Enum.Events.Event.Type.AUTHORIZATION, Enum.Events.Event.Action.PUT)
span.setTags(tags)
await span.audit({
headers: request.headers,
payload: request.payload
}, EventSdk.AuditEventAction.start)
authorizations.forwardAuthorizationError(request.headers, request.params.ID, request.payload, span)
return h.response().code(Enum.Http.ReturnCodes.OK.CODE)
}
}
2 changes: 2 additions & 0 deletions src/handlers/health.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
optionally within square brackets <email>.
* Gates Foundation
* ModusBox
- Rajiv Mothilal <rajiv.mothilal@modusbox.com>
- Steven Oderayi <steven.oderayi@modusbox.com>
--------------
******/
Expand Down
14 changes: 12 additions & 2 deletions src/handlers/transactionRequests.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
'use strict'

const EventSdk = require('@mojaloop/event-sdk')
const Enum = require('@mojaloop/central-services-shared').Enum
const transactionRequest = require('../domain/transactionRequests/transactionRequests')
const LibUtil = require('../lib/util')

/**
* Operations on /transactionRequests
*/
Expand All @@ -13,8 +16,15 @@ module.exports = {
* produces: application/json
* responses: 202, 400, 401, 403, 404, 405, 406, 501, 503
*/
post: function (request, h) {
transactionRequest.forwardTransactionRequest(Enum.EndPoints.FspEndpointTemplates.TRANSACTION_REQUEST_POST, request.headers, Enum.Http.RestMethods.POST, request.params, request.payload)
post: async (request, h) => {
const span = request.span
const tags = LibUtil.getSpanTags(request, Enum.Events.Event.Type.TRANSACTION_REQUEST, Enum.Events.Event.Action.POST)
span.setTags(tags)
await span.audit({
headers: request.headers,
payload: request.payload
}, EventSdk.AuditEventAction.start)
transactionRequest.forwardTransactionRequest(Enum.EndPoints.FspEndpointTemplates.TRANSACTION_REQUEST_POST, request.headers, Enum.Http.RestMethods.POST, request.params, request.payload, span)
return h.response().code(Enum.Http.ReturnCodes.ACCEPTED.CODE)
}
}
Loading

0 comments on commit 55e3646

Please sign in to comment.