Skip to content

Commit

Permalink
Add external file configuration. (#870)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmetoz committed Nov 25, 2021
1 parent 255a9d1 commit 3191374
Show file tree
Hide file tree
Showing 13 changed files with 362 additions and 30 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ secrets.yaml
.nyc_output/

*.zip
.extensionrc
.notificationrc
5 changes: 5 additions & 0 deletions extension/docs/HowToRun.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [Adyen](#adyen)
- [commercetools](#commercetools)
- [Other Configurations](#other-configurations)
- [External file configuration](#external-file-configuration)
- [Commercetools project requirements](#commercetools-project-requirements)
- [Other requirements](#other-requirements)
- [Affirm payment](#affirm-payment)
Expand Down Expand Up @@ -148,6 +149,10 @@ Other configurations can be set as direct child attributes in `ADYEN_INTEGRATION
| `basicAuth` | Boolean attribute to enable/disable basic authentication to prevent unauthorized 3rd-party from accessing extension endpoint | NO | false |
| `removeSensitiveData` | Boolean attribute. When set to "false", Adyen fields with additional information about the payment will be saved in the interface interaction and in the custom fields. | NO | true |

### External file configuration

In case you have a huge configuration that reaches above the environment limits (e.g the total size of all environment variables on AWS Lambda can't exceed 4 KB.), you could use the external file configuration instead of setting `ADYEN_INTEGRATION_CONFIG` environment variable. The extension module will look for the `.extensionrc` file in the `extension` folder. The file should contain the same JSON content as it's defined with environment variable.

## Commercetools project requirements

Resources below are required for the extension module to operate correctly.
Expand Down
74 changes: 68 additions & 6 deletions extension/package-lock.json

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

5 changes: 3 additions & 2 deletions extension/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "commercetools-adyen-integration-extension",
"version": "9.2.0",
"version": "9.3.0",
"description": "Integration between commercetools and Adyen payment service provider",
"license": "MIT",
"scripts": {
Expand All @@ -17,7 +17,7 @@
"check": "npm run lint && prettier --check .",
"doctoc": "doctoc . --github",
"format": "prettier --write .",
"zip-google-function": "cp index.googleFunction.js index.js && zip -r extension-module.zip src resources index.js package.json && rm index.js",
"zip-google-function": "cp index.googleFunction.js index.js && zip -r extension-module.zip src resources .extensionrc index.js package.json && rm index.js",
"zip-lambda-function": "cp index.lambda.js index.js && npm ci --production && zip -r extension-module.zip . && rm index.js",
"setup-resources": "node -e 'require(\"./src/setup.js\").setupExtensionResources()'"
},
Expand Down Expand Up @@ -80,6 +80,7 @@
"lockfile-lint": "4.6.2",
"lodash": "4.17.21",
"node-fetch": "2.6.6",
"rc": "^1.2.8",
"serialize-error": "8.1.0"
},
"mocha": {
Expand Down
34 changes: 34 additions & 0 deletions extension/src/config/config-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
function loadConfig() {
if (process.env.ADYEN_INTEGRATION_CONFIG) {
return loadFromAdyenIntegrationEnvVar()
}

return loadFromExternalFile()
}

function loadFromAdyenIntegrationEnvVar() {
try {
return JSON.parse(process.env.ADYEN_INTEGRATION_CONFIG)
} catch (e) {
throw new Error(
'Adyen integration configuration is not provided in the JSON format'
)
}
}

function loadFromExternalFile() {
/*
see: https://github.com/dominictarr/rc#standards for file precedence.
*/
const appName = 'extension'
/* eslint-disable global-require */
const configFromExternalFile = require('rc')(appName)
/* eslint-enable global-require */
const hasConfig = configFromExternalFile?.configs?.length > 0
if (!hasConfig) {
throw new Error('Adyen integration configuration is not provided.')
}
return configFromExternalFile
}

module.exports = loadConfig
10 changes: 3 additions & 7 deletions extension/src/config/config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const loadConfig = require('./config-loader')

let config

function getModuleConfig() {
Expand Down Expand Up @@ -98,13 +100,7 @@ function getAdyenPaymentMethodsToNames() {
}

function loadAndValidateConfig() {
try {
config = JSON.parse(process.env.ADYEN_INTEGRATION_CONFIG)
} catch (e) {
throw new Error(
'Adyen integration configuration is not provided in the JSON format'
)
}
config = loadConfig()

const numberOfCtpConfigs = Object.keys(config.commercetools).length
const numberOfAdyenConfigs = Object.keys(config.adyen).length
Expand Down
74 changes: 74 additions & 0 deletions extension/test/unit/config/config.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const { expect } = require('chai')
const fs = require('fs')
const homedir = require('os').homedir()

describe('::config::', () => {
it('when config is provided, it should load correctly', () => {
Expand Down Expand Up @@ -436,4 +438,76 @@ describe('::config::', () => {
expect(config.getModuleConfig().removeSensitiveData).to.eql(true)
}
)

it('when ADYEN_INTEGRATION_CONFIG is not valid JSON, it should throw error', () => {
process.env.ADYEN_INTEGRATION_CONFIG = '{"a"}'
try {
requireUncached('../../../src/config/config')
expect.fail('This test should throw an error, but it did not')
} catch (e) {
expect(e.message).to.contain(
'configuration is not provided in the JSON format'
)
}
})

it(
'when ADYEN_INTEGRATION_CONFIG is not set but external file is configured, ' +
'then it should load configuration correctly',
() => {
const filePath = `${homedir}/.extensionrc`
try {
delete process.env.ADYEN_INTEGRATION_CONFIG
const config = {
commercetools: {
ctpProjectKey1: {
clientId: 'clientId',
clientSecret: 'clientSecret',
apiUrl: 'host',
authUrl: 'authUrl',
authentication: {
scheme: 'basic',
username: 'username',
password: 'password',
},
},
},
adyen: {
adyenMerchantAccount1: {
apiBaseUrl: 'apiBaseUrl',
apiKey: 'apiKey',
clientKey: 'clientKey',
legacyApiBaseUrl: 'legacyApiBaseUrl',
},
},
logLevel: 'DEBUG',
}
fs.writeFileSync(filePath, JSON.stringify(config), 'utf-8')

const loadedConfig = requireUncached('../../../src/config/config')
expect(loadedConfig.getCtpConfig('ctpProjectKey1')).to.deep.equal({
clientId: 'clientId',
clientSecret: 'clientSecret',
apiUrl: 'host',
authUrl: 'authUrl',
projectKey: 'ctpProjectKey1',
authentication: {
scheme: 'basic',
username: 'username',
password: 'password',
},
})
expect(
loadedConfig.getAdyenConfig('adyenMerchantAccount1')
).to.deep.equal({
apiBaseUrl: 'apiBaseUrl',
apiKey: 'apiKey',
clientKey: 'clientKey',
legacyApiBaseUrl: 'legacyApiBaseUrl',
})
} finally {
fs.unlinkSync(filePath)
}
}
)
})
5 changes: 5 additions & 0 deletions notification/docs/HowToRun.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [Adyen](#adyen)
- [commercetools](#commercetools)
- [Other Configurations](#other-configurations)
- [External file configuration](#external-file-configuration)
- [Commercetools project requirements](#commercetools-project-requirements)
- [Running](#running)
- [Docker](#docker)
Expand Down Expand Up @@ -139,6 +140,10 @@ Other configurations can be set as direct child attributes in `ADYEN_INTEGRATION
| `keepAliveTimeout` | Milliseconds to keep a socket alive after the last response ([Node.js docs](https://nodejs.org/dist/latest/docs/api/http.html#http_server_keepalivetimeout)). | NO | Node.js default (5 seconds) |
| `removeSensitiveData` | Boolean attribute. When set to "false", Adyen fields with additional information about the payment will be saved in the interface interaction and in the custom fields. | NO | true |

### External file configuration

In case you have a huge configuration that reaches above the environment limits (e.g the total size of all environment variables on AWS Lambda can't exceed 4 KB.), you could use the external file configuration instead of setting `ADYEN_INTEGRATION_CONFIG` environment variable. The notification module will look for the `.notificationrc` file in the `notification` folder. The file should contain the same JSON content as it's defined with environment variable.

## Commercetools project requirements

Resources below are required for the notification module to operate correctly.
Expand Down

0 comments on commit 3191374

Please sign in to comment.