Skip to content

Commit

Permalink
Hotfix/invalid config used to number precision (#56)
Browse files Browse the repository at this point in the history
* Changes to fix config issues in the database.js file

* invalid config commited

* pass complete config into database.js so we do not have to initialise a new config

* mistakenly deleted stevens PR

* Added back Steven's name

* fixes to ensure that the amounts are formatted correctly and has currency and amount.
fix to revert request headers being used by central-services-shared

* update version

* set date to incoming header date not a new one
  • Loading branch information
rmothilal authored Oct 4, 2019
1 parent f7e89b6 commit 03bd0a8
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 12 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "quoting-service",
"description": "Quoting Service hosted by a scheme",
"license": "Apache-2.0",
"version": "8.2.1",
"version": "8.2.2",
"author": "Modusbox",
"contributors": [
"James Bush <james.bush@modusbox.com>",
Expand Down
75 changes: 65 additions & 10 deletions src/model/quotes.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
--------------
******/

const request = require('@mojaloop/central-services-shared').Util.Request
const CSutil = require('@mojaloop/central-services-shared').Util
// const request = require('@mojaloop/central-services-shared').Util.Request
// const CSutil = require('@mojaloop/central-services-shared').Util
const Enum = require('@mojaloop/central-services-shared').Enum
const ErrorHandler = require('@mojaloop/central-services-error-handling')
const Logger = require('@mojaloop/central-services-logger')
Expand Down Expand Up @@ -281,7 +281,7 @@ class QuotesModel {
const opts = {
method: Enum.Http.RestMethods.POST,
body: JSON.stringify(originalQuoteRequest),
headers: headers
headers: this.generateRequestHeaders(headers)
}

// Network errors lob an exception. Bare in mind 3xx 4xx and 5xx are not network errors
Expand Down Expand Up @@ -393,8 +393,8 @@ class QuotesModel {

// create the quote response row in the db
const newQuoteResponse = await this.db.createQuoteResponse(txn, quoteId, {
transferAmount: new MLNumber(quoteUpdateRequest.transferAmount).toFixed(envConfig.amount.scale),
payeeReceiveAmount: new MLNumber(quoteUpdateRequest.payeeReceiveAmount).toFixed(envConfig.amount.scale),
transferAmount: quoteUpdateRequest.transferAmount,
payeeReceiveAmount: quoteUpdateRequest.payeeReceiveAmount,
payeeFspFee: quoteUpdateRequest.payeeFspFee,
payeeFspCommission: quoteUpdateRequest.payeeFspCommission,
condition: quoteUpdateRequest.condition,
Expand Down Expand Up @@ -511,14 +511,14 @@ class QuotesModel {
const opts = {
method: Enum.Http.RestMethods.PUT,
body: JSON.stringify(originalQuoteResponse),
headers: headers || CSutil.Http.SwitchDefaultHeaders(fspiopDestination, Enum.Http.HeaderResources.QUOTES, Enum.Http.Headers.FSPIOP.SWITCH.value)
headers: this.generateRequestHeaders(headers)
}

// Network errors lob an exception. Bare in mind 3xx 4xx and 5xx are not network errors
// so we need to wrap the request below in a `try catch` to handle network errors
let res
try {
res = await request.sendRequest(fullUrl, opts.headers, fspiopSource, fspiopDestination, opts.method, opts.body, Enum.Http.ResponseTypes.JSON)
res = await fetch(fullUrl, opts)
} catch (err) {
throw ErrorHandler.CreateFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_COMMUNICATION_ERROR, 'Network error forwarding quote response', err, fspiopSource, [
{ key: 'url', value: fullUrl },
Expand Down Expand Up @@ -681,7 +681,7 @@ class QuotesModel {

const opts = {
method: Enum.Http.RestMethods.GET,
headers: headers
headers: this.generateRequestHeaders(headers)
}

// Network errors lob an exception. Bare in mind 3xx 4xx and 5xx are not network errors
Expand Down Expand Up @@ -769,11 +769,15 @@ class QuotesModel {
data: JSON.stringify(fspiopError.toApiErrorObject()),
// use headers of the error object if they are there...
// otherwise use sensible defaults
headers: headers || CSutil.Http.SwitchDefaultHeaders(fspiopSource, Enum.Http.HeaderResources.QUOTES, Enum.Http.Headers.FSPIOP.SWITCH.value)
headers: this.generateRequestHeaders(headers || {
'fspiop-destination': fspiopSource,
'fspiop-source': Enum.Http.Headers.FSPIOP.SWITCH.value,
'fspiop-http-method': Enum.Http.RestMethods.PUT
}, true)
}
let res
try {
res = await request.sendRequest(opts.url, opts.headers, fspiopSource, fspiopDest, opts.method, opts.data, Enum.Http.ResponseTypes.JSON)
res = await axios.request(opts)
} catch (err) {
throw ErrorHandler.CreateFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_COMMUNICATION_ERROR, `network error in sendErrorCallback: ${err.message}`, err, fspiopSource, [
{ key: 'url', value: fullCallbackUrl },
Expand Down Expand Up @@ -887,6 +891,32 @@ class QuotesModel {
}
}

/**
* Utility function to remove null and undefined keys from an object.
* This is useful for removing "nulls" that come back from database queries
* when projecting into API spec objects
*
* @returns {object}
*/
removeEmptyKeys (originalObject) {
const obj = { ...originalObject }
Object.keys(obj).forEach(key => {
if (obj[key] && typeof obj[key] === 'object') {
if (Object.keys(obj[key]).length < 1) {
// remove empty object
delete obj[key]
} else {
// recurse
obj[key] = this.removeEmptyKeys(obj[key])
}
} else if (obj[key] == null) {
// null or undefined, remove it
delete obj[key]
}
})
return obj
}

/**
* Returns the SHA-256 hash of the supplied request object
*
Expand All @@ -898,6 +928,31 @@ class QuotesModel {
return crypto.createHash('sha256').update(requestStr).digest('hex')
}

/**
* Generates and returns an object containing API spec compliant HTTP request headers
*
* @returns {object}
*/
generateRequestHeaders (headers, noAccept) {
const ret = {
'Content-Type': 'application/vnd.interoperability.quotes+json;version=1.0',
Date: headers.date,
'FSPIOP-Source': headers['fspiop-source'],
'FSPIOP-Destination': headers['fspiop-destination'],
'FSPIOP-HTTP-Method': headers['fspiop-http-method'],
'FSPIOP-Signature': headers['fspiop-signature'],
'FSPIOP-URI': headers['fspiop-uri'],
'User-Agent': null, // yuck! node-fetch INSISTS on sending a user-agent header!? infuriating!
Accept: null
}

if (!noAccept) {
ret.Accept = 'application/vnd.interoperability.quotes+json;version=1'
}

return this.removeEmptyKeys(ret)
}

/**
* Writes a formatted message to the console
*
Expand Down

0 comments on commit 03bd0a8

Please sign in to comment.