account-lookup-service 15.5.0-iso.0
Sign up to get free protection for your applications and to get access to all the features.
- package/.circleci/config.yml +11 -0
- package/.ncurc.yaml +6 -0
- package/.nvmrc +1 -0
- package/.nycrc.yml +20 -0
- package/.versionrc +15 -0
- package/CHANGELOG.md +330 -0
- package/CODEOWNERS +38 -0
- package/Dockerfile +45 -0
- package/LICENSE.md +10 -0
- package/README.md +252 -0
- package/audit-ci.jsonc +32 -0
- package/audit-resolve.json +161 -0
- package/config/default.json +109 -0
- package/config/knexfile.js +21 -0
- package/docker/account-lookup-service/default.json +106 -0
- package/docker/account-lookup-service/make-default-json.sh +5 -0
- package/docker/account-lookup-service/override.json +15 -0
- package/docker/central-ledger/default.json +458 -0
- package/docker/config-modifier/account-lookup-service.js +31 -0
- package/docker/kafka/consumer.properties +26 -0
- package/docker/kafka/producer.properties +45 -0
- package/docker/kafka/server.properties +143 -0
- package/docker/kafka/tools-log4j.properties +21 -0
- package/docker/mock-proxy/Dockerfile +15 -0
- package/docker/mock-proxy/package-lock.json +4986 -0
- package/docker/mock-proxy/package.json +24 -0
- package/docker/mock-proxy/src/config.ts +14 -0
- package/docker/mock-proxy/src/server.ts +94 -0
- package/docker/mock-proxy/src/utils.ts +29 -0
- package/docker/mock-proxy/tsconfig.json +24 -0
- package/docker/sql-init/01_permissions.sql +2 -0
- package/docker/sql-init-central-ledger/01_permissions.sql +2 -0
- package/docker/wait-for/wait-for-account-lookup-service.sh +10 -0
- package/docker/wait-for/wait-for-central-ledger.sh +11 -0
- package/docker/wait-for/wait-for-kafka.sh +7 -0
- package/docker/wait-for/wait-for-ml-api-adapter.sh +9 -0
- package/docker/wait-for/wait-for-mockserver.sh +20 -0
- package/docker/wait-for/wait-for-mysql-als.sh +14 -0
- package/docker/wait-for/wait-for-mysql-central-ledger.sh +11 -0
- package/docker/wait-for/wait-for-mysql.sh +11 -0
- package/docker/wait-for/wait-for-objstore.sh +12 -0
- package/docker/wait-for/wait-for.env +18 -0
- package/docker/wait-for/wait-for.sh +81 -0
- package/docker-compose.integration.yml +29 -0
- package/docker-compose.yml +243 -0
- package/jest-int.config.js +8 -0
- package/jest.config.js +16 -0
- package/jsdoc.json +38 -0
- package/migrations/01_currency.js +42 -0
- package/migrations/02_endpointType.js +43 -0
- package/migrations/03_endpointType-indexes.js +37 -0
- package/migrations/04_partyIdType.js +43 -0
- package/migrations/05_partyIdType-indexes.js +38 -0
- package/migrations/08_oracleEndpoint.js +51 -0
- package/migrations/09_oracleEndpoint-indexes.js +41 -0
- package/migrations/10_oracleEndpoint-remove-constraints.js +38 -0
- package/package.json +180 -0
- package/scripts/_wait4_all.js +143 -0
- package/scripts/test-functional.sh +76 -0
- package/secrets/jwsSigningKey.key +27 -0
- package/seeds/currency.js +765 -0
- package/seeds/endpointType.js +65 -0
- package/seeds/partyIdType.js +79 -0
- package/src/api/endpointcache.js +67 -0
- package/src/api/health.js +66 -0
- package/src/api/index.js +85 -0
- package/src/api/oracles/{ID}.js +100 -0
- package/src/api/oracles.js +96 -0
- package/src/api/participants/{ID}/error.js +44 -0
- package/src/api/participants/{ID}.js +44 -0
- package/src/api/participants/{Type}/{ID}/error.js +74 -0
- package/src/api/participants/{Type}/{ID}/{SubId}/error.js +68 -0
- package/src/api/participants/{Type}/{ID}/{SubId}.js +113 -0
- package/src/api/participants/{Type}/{ID}.js +133 -0
- package/src/api/participants.js +63 -0
- package/src/api/parties/{Type}/{ID}/error.js +66 -0
- package/src/api/parties/{Type}/{ID}/{SubId}/error.js +56 -0
- package/src/api/parties/{Type}/{ID}/{SubId}.js +77 -0
- package/src/api/parties/{Type}/{ID}.js +98 -0
- package/src/api/routes.js +294 -0
- package/src/constants.js +16 -0
- package/src/domain/oracle/index.js +33 -0
- package/src/domain/oracle/oracle.js +234 -0
- package/src/domain/participants/index.js +35 -0
- package/src/domain/participants/participants.js +560 -0
- package/src/domain/parties/getPartiesByTypeAndID.js +239 -0
- package/src/domain/parties/index.js +32 -0
- package/src/domain/parties/parties.js +215 -0
- package/src/domain/parties/utils.js +84 -0
- package/src/domain/timeout/dto.js +48 -0
- package/src/domain/timeout/index.js +104 -0
- package/src/handlers/TimeoutHandler.js +94 -0
- package/src/handlers/index.js +70 -0
- package/src/handlers/monitoring/index.js +51 -0
- package/src/handlers/monitoring/plugins/health.js +61 -0
- package/src/handlers/monitoring/plugins/metrics.js +48 -0
- package/src/handlers/register.js +102 -0
- package/src/index.js +66 -0
- package/src/interface/admin-swagger.yaml +804 -0
- package/src/interface/admin_swagger.json +959 -0
- package/src/interface/api-swagger-iso20022-parties.yaml +1734 -0
- package/src/interface/api-swagger.yaml +1733 -0
- package/src/interface/api_swagger.json +3046 -0
- package/src/interface/fspiop-rest-v2.0-ISO20022_parties.yaml +2256 -0
- package/src/interface/thirdparty/admin-swagger.yaml +808 -0
- package/src/interface/thirdparty/admin_swagger.json +961 -0
- package/src/interface/thirdparty/api-swagger.yaml +1739 -0
- package/src/interface/thirdparty/api_swagger.json +3142 -0
- package/src/lib/argv.js +39 -0
- package/src/lib/cache.js +126 -0
- package/src/lib/config.js +183 -0
- package/src/lib/db.js +26 -0
- package/src/lib/headers.js +53 -0
- package/src/lib/healthCheck/subServiceHealth.js +84 -0
- package/src/lib/index.js +11 -0
- package/src/lib/migrator.js +17 -0
- package/src/lib/requestLogger.js +54 -0
- package/src/lib/util.js +66 -0
- package/src/metrics/handler.js +33 -0
- package/src/metrics/plugin.js +52 -0
- package/src/metrics/routes.js +43 -0
- package/src/models/currency/currency.js +48 -0
- package/src/models/currency/index.js +32 -0
- package/src/models/endpointType/endpointType.js +48 -0
- package/src/models/endpointType/index.js +32 -0
- package/src/models/misc/migrationLock.js +49 -0
- package/src/models/oracle/facade.js +341 -0
- package/src/models/oracle/index.js +41 -0
- package/src/models/oracle/oracleEndpoint.js +192 -0
- package/src/models/oracle/oracleEndpointCached.js +108 -0
- package/src/models/participantEndpoint/facade.js +238 -0
- package/src/models/partyIdType/index.js +32 -0
- package/src/models/partyIdType/partyIdType.js +41 -0
- package/src/plugins.js +139 -0
- package/src/server.js +199 -0
- package/test/fixtures/index.js +131 -0
- package/test/fixtures/iso.js +110 -0
- package/test/integration/.env +8 -0
- package/test/integration/api/parties.test.js +137 -0
- package/test/integration/constants.js +20 -0
- package/test/integration/domain/oracle/index.test.js +324 -0
- package/test/integration/domain/timeout/index.test.js +75 -0
- package/test/integration/env.sh +15 -0
- package/test/integration/example.test.js +12 -0
- package/test/integration/models/currency/currency.test.js +68 -0
- package/test/integration/plugins.test.js +62 -0
- package/test/integration/prepareTestParticipants.js +30 -0
- package/test/integration/setup.js +5 -0
- package/test/integration-config.json +81 -0
- package/test/integration-runner.sh +108 -0
- package/test/unit/api/health.test.js +142 -0
- package/test/unit/api/oracles/{ID}.test.js +264 -0
- package/test/unit/api/oracles.test.js +173 -0
- package/test/unit/api/participants/participants.test.js +117 -0
- package/test/unit/api/participants/{Type}/{ID}/error.test.js +155 -0
- package/test/unit/api/participants/{Type}/{ID}/{SubId}/error.test.js +131 -0
- package/test/unit/api/participants/{Type}/{ID}/{SubId}.test.js +377 -0
- package/test/unit/api/participants/{Type}/{ID}.test.js +383 -0
- package/test/unit/api/participants.test.js +108 -0
- package/test/unit/api/parties/endpointcache.test.js +83 -0
- package/test/unit/api/parties/parties.test.js +102 -0
- package/test/unit/api/parties/{Type}/{ID}/error.test.js +145 -0
- package/test/unit/api/parties/{Type}/{ID}/{SubId}/error.test.js +141 -0
- package/test/unit/api/parties/{Type}/{ID}/{SubId}.test.js +241 -0
- package/test/unit/api/parties/{Type}/{ID}.test.js +240 -0
- package/test/unit/domain/oracle/oracle.test.js +505 -0
- package/test/unit/domain/participants/participants.test.js +1724 -0
- package/test/unit/domain/parties/parties.test.js +940 -0
- package/test/unit/domain/timeout/dto.test.js +28 -0
- package/test/unit/domain/timeout/index.test.js +81 -0
- package/test/unit/handlers/TimeoutHandler.test.js +125 -0
- package/test/unit/handlers/index.test.js +56 -0
- package/test/unit/handlers/register.test.js +90 -0
- package/test/unit/index.test.js +139 -0
- package/test/unit/iso20022/partiesValidation.test.js +129 -0
- package/test/unit/lib/TransformFacades.test.js +18 -0
- package/test/unit/lib/argv.test.js +40 -0
- package/test/unit/lib/cache.test.js +172 -0
- package/test/unit/lib/config.test.js +108 -0
- package/test/unit/lib/healthCheck/subServiceHealth.test.js +89 -0
- package/test/unit/lib/migrator.test.js +52 -0
- package/test/unit/lib/requestLogger.test.js +115 -0
- package/test/unit/lib/util.test.js +68 -0
- package/test/unit/mocks.js +66 -0
- package/test/unit/models/currency/currency.test.js +91 -0
- package/test/unit/models/endpointType/endpointType.test.js +69 -0
- package/test/unit/models/misc/migrationLock.test.js +96 -0
- package/test/unit/models/oracle/facade.test.js +546 -0
- package/test/unit/models/oracle/oracleEndpoint.test.js +409 -0
- package/test/unit/models/oracle/oracleEndpointCached.test.js +153 -0
- package/test/unit/models/participantEndpoint/facade.test.js +295 -0
- package/test/unit/models/partyIdType/partyIdType.test.js +88 -0
- package/test/unit/plugins.test.js +89 -0
- package/test/unit/setup.js +7 -0
- package/test/util/apiClients/AlsApiClient.js +44 -0
- package/test/util/apiClients/BasicApiClient.js +34 -0
- package/test/util/apiClients/ProxyApiClient.js +25 -0
- package/test/util/apiClients/index.js +7 -0
- package/test/util/helper.js +332 -0
- package/test/util/index.js +11 -0
- package/test/util/mockgen.js +43 -0
- package/test/util/onboarding.js +132 -0
- package/test/util/scripts/addAlsDb.sh +33 -0
- package/test/util/scripts/configureMockServer.sh +35 -0
- package/test/util/scripts/env.sh +19 -0
- package/test/util/scripts/populateTestData.sh +62 -0
- package/test/util/scripts/startMockCentralServer.sh +45 -0
- package/test/util/scripts/startMockOracleServer.sh +45 -0
- package/test/util/testConfig.js +44 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
###
|
4
|
+
# integration-runner.sh
|
5
|
+
#
|
6
|
+
# A basic integration test runner using docker-compose
|
7
|
+
###
|
8
|
+
|
9
|
+
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
10
|
+
|
11
|
+
##
|
12
|
+
# TEST_MODE
|
13
|
+
# Options:
|
14
|
+
# - default runs the tests as usual
|
15
|
+
# - wait sets up the docker-compose environment, but don't do anything (this allows for repeat tests)
|
16
|
+
# - rm same as default, but stops and removes docker-compose containers afterwards
|
17
|
+
###
|
18
|
+
TEST_MODE="${TEST_MODE:-"default"}"
|
19
|
+
|
20
|
+
|
21
|
+
# Controls where Jest places test outputs inside of `als_account-lookup-service-int` container
|
22
|
+
JEST_JUNIT_OUTPUT_DIR="${JEST_JUNIT_OUTPUT_DIR:-"/tmp"}"
|
23
|
+
JEST_JUNIT_OUTPUT_NAME="${JEST_JUNIT_OUTPUT_NAME:-"junit.xml"}"
|
24
|
+
|
25
|
+
# Test output on host machine
|
26
|
+
RESULTS_DIR="${RESULTS_DIR:-"/tmp"}"
|
27
|
+
|
28
|
+
function startDocker() {
|
29
|
+
docker-compose \
|
30
|
+
-f ${DIR}/../docker-compose.yml \
|
31
|
+
-f ${DIR}/../docker-compose.integration.yml \
|
32
|
+
up -d
|
33
|
+
}
|
34
|
+
|
35
|
+
function waitForDocker() {
|
36
|
+
echo 'Waiting for docker services to be healthy'
|
37
|
+
HEALTHY_COUNT=$(docker ps | grep "healthy" | wc -l)
|
38
|
+
EXPECTED_HEALTHY_COUNT=5
|
39
|
+
EXPECTED_SERVICE_COUNT=6
|
40
|
+
while [ $(docker ps | grep "healthy" | wc -l) -lt $EXPECTED_HEALTHY_COUNT ]; do
|
41
|
+
TOTAL_SERVICES=$(docker ps | grep "als_*" | wc -l)
|
42
|
+
# exit early if we don't have the required services
|
43
|
+
if [ ${TOTAL_SERVICES} -lt ${EXPECTED_SERVICE_COUNT} ]; then
|
44
|
+
echo 'Not all docker-compose services are running. Check the logs and try again.'
|
45
|
+
exit 1
|
46
|
+
fi
|
47
|
+
|
48
|
+
echo "."
|
49
|
+
sleep 5
|
50
|
+
done
|
51
|
+
}
|
52
|
+
|
53
|
+
function runMigration() {
|
54
|
+
docker exec -it als_account-lookup-service sh -c "npm run migrate"
|
55
|
+
}
|
56
|
+
|
57
|
+
function runTests() {
|
58
|
+
docker exec -it als_account-lookup-service-int sh -c "JEST_JUNIT_OUTPUT_DIR=${JEST_JUNIT_OUTPUT_DIR} JEST_JUNIT_OUTPUT_NAME=${JEST_JUNIT_OUTPUT_NAME} npm run test:int"
|
59
|
+
}
|
60
|
+
|
61
|
+
function copyResults() {
|
62
|
+
echo "Copying results from: ${JEST_JUNIT_OUTPUT_DIR}/${JEST_JUNIT_OUTPUT_NAME} to: ${RESULTS_DIR}"
|
63
|
+
docker cp als_account-lookup-service-int:${JEST_JUNIT_OUTPUT_DIR}/${JEST_JUNIT_OUTPUT_NAME} ${RESULTS_DIR}
|
64
|
+
}
|
65
|
+
|
66
|
+
function tearDown() {
|
67
|
+
docker-compose \
|
68
|
+
-f ${DIR}/../docker-compose.yml \
|
69
|
+
-f ${DIR}/../docker-compose.integration.yml \
|
70
|
+
stop
|
71
|
+
docker-compose \
|
72
|
+
-f ${DIR}/../docker-compose.yml \
|
73
|
+
-f ${DIR}/../docker-compose.integration.yml \
|
74
|
+
down -v
|
75
|
+
docker-compose \
|
76
|
+
-f ${DIR}/../docker-compose.yml \
|
77
|
+
-f ${DIR}/../docker-compose.integration.yml \
|
78
|
+
rm -f
|
79
|
+
}
|
80
|
+
|
81
|
+
startDocker
|
82
|
+
waitForDocker
|
83
|
+
runMigration
|
84
|
+
|
85
|
+
case ${TEST_MODE} in
|
86
|
+
default)
|
87
|
+
runTests
|
88
|
+
EXIT_RESULT=$?
|
89
|
+
copyResults
|
90
|
+
exit ${EXIT_RESULT}
|
91
|
+
;;
|
92
|
+
|
93
|
+
wait)
|
94
|
+
echo 'Running tests in `wait` mode'
|
95
|
+
;;
|
96
|
+
|
97
|
+
rm)
|
98
|
+
runTests
|
99
|
+
EXIT_RESULT=$?
|
100
|
+
copyResults
|
101
|
+
tearDown
|
102
|
+
exit ${EXIT_RESULT}
|
103
|
+
;;
|
104
|
+
|
105
|
+
*)
|
106
|
+
echo "Unsupported TEST_MODE: ${TEST_MODE}"
|
107
|
+
exit 1
|
108
|
+
esac
|
@@ -0,0 +1,142 @@
|
|
1
|
+
/*****
|
2
|
+
License
|
3
|
+
--------------
|
4
|
+
Copyright © 2017 Bill & Melinda Gates Foundation
|
5
|
+
The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
8
|
+
Contributors
|
9
|
+
--------------
|
10
|
+
This is the official list of the Mojaloop project contributors for this file.
|
11
|
+
Names of the original copyright holders (individuals or organizations)
|
12
|
+
should be listed with a '*' in the first column. People who have
|
13
|
+
contributed from an organization can be listed under the organization
|
14
|
+
that actually holds the copyright for their contributions (see the
|
15
|
+
Gates Foundation organization for an example). Those individuals should have
|
16
|
+
their names indented and be marked with a '-'. Email address can be added
|
17
|
+
optionally within square brackets <email>.
|
18
|
+
* Gates Foundation
|
19
|
+
- Name Surname <name.surname@gatesfoundation.com>
|
20
|
+
|
21
|
+
* ModusBox
|
22
|
+
- Rajiv Mothilal <rajiv.mothilal@modusbox.com>
|
23
|
+
- Steven Oderayi <steven.oderayi@modusbox.com>
|
24
|
+
|
25
|
+
* Crosslake
|
26
|
+
- Lewis Daly <lewisd@crosslaketech.com>
|
27
|
+
|
28
|
+
--------------
|
29
|
+
******/
|
30
|
+
|
31
|
+
'use strict'
|
32
|
+
|
33
|
+
const Helper = require('../../util/helper')
|
34
|
+
const Db = require('../../../src/lib/db')
|
35
|
+
const initServer = require('../../../src/server').initializeApi
|
36
|
+
const getPort = require('get-port')
|
37
|
+
const Sinon = require('sinon')
|
38
|
+
const MigrationLockModel = require('../../../src/models/misc/migrationLock')
|
39
|
+
const Logger = require('@mojaloop/central-services-logger')
|
40
|
+
const Config = require('../../../src/lib/config')
|
41
|
+
|
42
|
+
Logger.isDebugEnabled = jest.fn(() => true)
|
43
|
+
Logger.isErrorEnabled = jest.fn(() => true)
|
44
|
+
Logger.isInfoEnabled = jest.fn(() => true)
|
45
|
+
let sandbox
|
46
|
+
let server
|
47
|
+
|
48
|
+
describe('/health', () => {
|
49
|
+
beforeEach(async () => {
|
50
|
+
Config.PROXY_CACHE_CONFIG.enabled = false
|
51
|
+
sandbox = Sinon.createSandbox()
|
52
|
+
sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
|
53
|
+
Config.API_PORT = await getPort()
|
54
|
+
server = await initServer(Config)
|
55
|
+
})
|
56
|
+
|
57
|
+
afterEach(async () => {
|
58
|
+
await server.stop()
|
59
|
+
sandbox.restore()
|
60
|
+
})
|
61
|
+
|
62
|
+
/**
|
63
|
+
* summary: Get Health
|
64
|
+
* description: The HTTP request GET /health is used to get the status of the server
|
65
|
+
* parameters: type, currency, accept, content-type, date
|
66
|
+
* produces: application/json
|
67
|
+
* responses: 200, 400, 401, 403, 404, 405, 406, 501, 503
|
68
|
+
*/
|
69
|
+
it('GET /health', async () => {
|
70
|
+
// Arrange
|
71
|
+
sandbox.stub(MigrationLockModel, 'getIsMigrationLocked').returns(false)
|
72
|
+
const mock = await Helper.generateMockRequest('/health', 'get')
|
73
|
+
|
74
|
+
const options = {
|
75
|
+
method: 'get',
|
76
|
+
url: mock.request.path,
|
77
|
+
headers: Helper.defaultAdminHeaders()
|
78
|
+
}
|
79
|
+
|
80
|
+
// Act
|
81
|
+
const response = await server.inject(options)
|
82
|
+
|
83
|
+
// Assert
|
84
|
+
expect(response.statusCode).toBe(200)
|
85
|
+
const payload = JSON.parse(response.payload)
|
86
|
+
expect(payload.status).toBe('OK')
|
87
|
+
expect(payload.services.length).toBe(1)
|
88
|
+
expect(payload.services[0].name).toBe('datastore')
|
89
|
+
})
|
90
|
+
|
91
|
+
it('GET /health service unavailable', async () => {
|
92
|
+
// Arrange
|
93
|
+
sandbox.stub(MigrationLockModel, 'getIsMigrationLocked').returns(true)
|
94
|
+
const mock = await Helper.generateMockRequest('/health', 'get')
|
95
|
+
|
96
|
+
const options = {
|
97
|
+
method: 'get',
|
98
|
+
url: mock.request.path,
|
99
|
+
headers: Helper.defaultAdminHeaders()
|
100
|
+
}
|
101
|
+
|
102
|
+
// Act
|
103
|
+
const response = await server.inject(options)
|
104
|
+
|
105
|
+
// Assert
|
106
|
+
expect(response.statusCode).toBe(503)
|
107
|
+
const payload = JSON.parse(response.payload)
|
108
|
+
expect(payload.status).toBe('DOWN')
|
109
|
+
expect(payload.services.length).toBe(1)
|
110
|
+
expect(payload.services[0].name).toBe('datastore')
|
111
|
+
})
|
112
|
+
|
113
|
+
it('GET /health should include proxy health', async () => {
|
114
|
+
// Arrange
|
115
|
+
Config.PROXY_CACHE_CONFIG.enabled = true
|
116
|
+
Config.API_PORT = await getPort()
|
117
|
+
Config.proxyMap = { proxied: 'proxy' }
|
118
|
+
let serverWithProxy
|
119
|
+
try {
|
120
|
+
serverWithProxy = await initServer(Config)
|
121
|
+
sandbox.stub(MigrationLockModel, 'getIsMigrationLocked').resolves(false)
|
122
|
+
const mock = await Helper.generateMockRequest('/health', 'get')
|
123
|
+
|
124
|
+
const options = {
|
125
|
+
method: 'get',
|
126
|
+
url: mock.request.path,
|
127
|
+
headers: Helper.defaultAdminHeaders()
|
128
|
+
}
|
129
|
+
|
130
|
+
// Act
|
131
|
+
const response = await serverWithProxy.inject(options)
|
132
|
+
|
133
|
+
// Assert
|
134
|
+
const payload = JSON.parse(response.payload)
|
135
|
+
expect(response.statusCode).toBe(200)
|
136
|
+
expect(payload.services.length).toBe(2)
|
137
|
+
expect(payload.services[1].name).toBe('proxyCache')
|
138
|
+
} finally {
|
139
|
+
serverWithProxy && await serverWithProxy.stop()
|
140
|
+
}
|
141
|
+
})
|
142
|
+
})
|
@@ -0,0 +1,264 @@
|
|
1
|
+
/*****
|
2
|
+
License
|
3
|
+
--------------
|
4
|
+
Copyright © 2017 Bill & Melinda Gates Foundation
|
5
|
+
The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
8
|
+
Contributors
|
9
|
+
--------------
|
10
|
+
This is the official list of the Mojaloop project contributors for this file.
|
11
|
+
Names of the original copyright holders (individuals or organizations)
|
12
|
+
should be listed with a '*' in the first column. People who have
|
13
|
+
contributed from an organization can be listed under the organization
|
14
|
+
that actually holds the copyright for their contributions (see the
|
15
|
+
Gates Foundation organization for an example). Those individuals should have
|
16
|
+
their names indented and be marked with a '-'. Email address can be added
|
17
|
+
optionally within square brackets <email>.
|
18
|
+
* Gates Foundation
|
19
|
+
- Name Surname <name.surname@gatesfoundation.com>
|
20
|
+
|
21
|
+
* ModusBox
|
22
|
+
- Rajiv Mothilal <rajiv.mothilal@modusbox.com>
|
23
|
+
|
24
|
+
* Crosslake
|
25
|
+
- Lewis Daly <lewisd@crosslaketech.com>
|
26
|
+
|
27
|
+
--------------
|
28
|
+
******/
|
29
|
+
|
30
|
+
'use strict'
|
31
|
+
|
32
|
+
const Mockgen = require('../../../util/mockgen.js')
|
33
|
+
const helper = require('../../../util/helper.js')
|
34
|
+
const Sinon = require('sinon')
|
35
|
+
const oracle = require('../../../../src/domain/oracle/index.js')
|
36
|
+
const initServer = require('../../../../src/server.js').initializeAdmin
|
37
|
+
const getPort = require('get-port')
|
38
|
+
const Db = require('../../../../src/lib/db.js')
|
39
|
+
const Migrator = require('../../../../src/lib/migrator.js')
|
40
|
+
const Logger = require('@mojaloop/central-services-logger')
|
41
|
+
const Config = require('../../../../src/lib/config.js')
|
42
|
+
|
43
|
+
Logger.isDebugEnabled = jest.fn(() => true)
|
44
|
+
Logger.isErrorEnabled = jest.fn(() => true)
|
45
|
+
Logger.isInfoEnabled = jest.fn(() => true)
|
46
|
+
let sandbox
|
47
|
+
let server
|
48
|
+
|
49
|
+
describe('/oracles/{ID} handler', () => {
|
50
|
+
beforeAll(async () => {
|
51
|
+
sandbox = Sinon.createSandbox()
|
52
|
+
sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
|
53
|
+
sandbox.stub(Migrator, 'migrate').returns(Promise.resolve({}))
|
54
|
+
Config.ADMIN_PORT = await getPort()
|
55
|
+
server = await initServer(Config)
|
56
|
+
})
|
57
|
+
|
58
|
+
afterAll(async () => {
|
59
|
+
await server.stop()
|
60
|
+
sandbox.restore()
|
61
|
+
})
|
62
|
+
|
63
|
+
/**
|
64
|
+
* summary: Update Oracle
|
65
|
+
* description: The HTTP request PUT /oracles/{ID} is used to update information in the server regarding the provided oracle. This request should be used for individual update of Oracle information.
|
66
|
+
* parameters: body, ID, content-length, content-type, date
|
67
|
+
* produces: application/json
|
68
|
+
* responses: 204, 400, 401, 403, 404, 405, 406, 501, 503
|
69
|
+
*/
|
70
|
+
it('PUT /oracles/{ID}', async () => {
|
71
|
+
expect.hasAssertions()
|
72
|
+
// Arrange
|
73
|
+
const requests = new Promise((resolve, reject) => {
|
74
|
+
Mockgen(false).requests({
|
75
|
+
path: '/oracles/{ID}',
|
76
|
+
operation: 'put'
|
77
|
+
}, function (error, mock) {
|
78
|
+
return error ? reject(error) : resolve(mock)
|
79
|
+
})
|
80
|
+
})
|
81
|
+
|
82
|
+
const mock = await requests
|
83
|
+
|
84
|
+
/*
|
85
|
+
Get the resolved path from mock request
|
86
|
+
Mock request Path templates({}) are resolved using path parameters
|
87
|
+
*/
|
88
|
+
const options = {
|
89
|
+
method: 'put',
|
90
|
+
url: mock.request.path,
|
91
|
+
headers: helper.defaultAdminHeaders()
|
92
|
+
}
|
93
|
+
if (mock.request.body) {
|
94
|
+
// Send the request body
|
95
|
+
options.payload = mock.request.body
|
96
|
+
} else if (mock.request.formData) {
|
97
|
+
// Send the request form data
|
98
|
+
options.payload = mock.request.formData
|
99
|
+
// Set the Content-Type as application/x-www-form-urlencoded
|
100
|
+
options.headers = options.headers || {}
|
101
|
+
options.headers = helper.defaultAdminHeaders()
|
102
|
+
}
|
103
|
+
// If headers are present, set the headers.
|
104
|
+
if (mock.request.headers && mock.request.headers.length > 0) {
|
105
|
+
options.headers = mock.request.headers
|
106
|
+
}
|
107
|
+
sandbox.stub(oracle, 'updateOracle').returns(Promise.resolve({}))
|
108
|
+
|
109
|
+
// Act
|
110
|
+
const response = await server.inject(options)
|
111
|
+
|
112
|
+
// Assert
|
113
|
+
expect(response.statusCode).toBe(204)
|
114
|
+
oracle.updateOracle.restore()
|
115
|
+
})
|
116
|
+
|
117
|
+
it('PUT /oracles/{ID} error', async () => {
|
118
|
+
expect.hasAssertions()
|
119
|
+
// Arrange
|
120
|
+
const requests = new Promise((resolve, reject) => {
|
121
|
+
Mockgen(false).requests({
|
122
|
+
path: '/oracles/{ID}',
|
123
|
+
operation: 'put'
|
124
|
+
}, function (error, mock) {
|
125
|
+
return error ? reject(error) : resolve(mock)
|
126
|
+
})
|
127
|
+
})
|
128
|
+
|
129
|
+
const mock = await requests
|
130
|
+
|
131
|
+
/*
|
132
|
+
Get the resolved path from mock request
|
133
|
+
Mock request Path templates({}) are resolved using path parameters
|
134
|
+
*/
|
135
|
+
const options = {
|
136
|
+
method: 'put',
|
137
|
+
url: mock.request.path,
|
138
|
+
headers: helper.defaultAdminHeaders()
|
139
|
+
}
|
140
|
+
if (mock.request.body) {
|
141
|
+
// Send the request body
|
142
|
+
options.payload = mock.request.body
|
143
|
+
} else if (mock.request.formData) {
|
144
|
+
// Send the request form data
|
145
|
+
options.payload = mock.request.formData
|
146
|
+
// Set the Content-Type as application/x-www-form-urlencoded
|
147
|
+
options.headers = options.headers || {}
|
148
|
+
options.headers = helper.defaultAdminHeaders()
|
149
|
+
}
|
150
|
+
// If headers are present, set the headers.
|
151
|
+
if (mock.request.headers && mock.request.headers.length > 0) {
|
152
|
+
options.headers = mock.request.headers
|
153
|
+
}
|
154
|
+
sandbox.stub(oracle, 'updateOracle').throws()
|
155
|
+
|
156
|
+
// Act
|
157
|
+
const response = await server.inject(options)
|
158
|
+
|
159
|
+
// Assert
|
160
|
+
expect(response.statusCode).toBe(500)
|
161
|
+
oracle.updateOracle.restore()
|
162
|
+
})
|
163
|
+
|
164
|
+
/**
|
165
|
+
* summary: Delete Oracle
|
166
|
+
* description: The HTTP request DELETE /oracles/{ID} is used to delete information in the server regarding the provided oracle.
|
167
|
+
* parameters: accept, ID, content-type, date
|
168
|
+
* produces: application/json
|
169
|
+
* responses: 204, 400, 401, 403, 404, 405, 406, 501, 503
|
170
|
+
*/
|
171
|
+
it('delete /oracles/{ID}', async () => {
|
172
|
+
expect.hasAssertions()
|
173
|
+
// Arrange
|
174
|
+
const requests = new Promise((resolve, reject) => {
|
175
|
+
Mockgen(false).requests({
|
176
|
+
path: '/oracles/{ID}',
|
177
|
+
operation: 'delete'
|
178
|
+
}, function (error, mock) {
|
179
|
+
return error ? reject(error) : resolve(mock)
|
180
|
+
})
|
181
|
+
})
|
182
|
+
|
183
|
+
const mock = await requests
|
184
|
+
|
185
|
+
/*
|
186
|
+
Get the resolved path from mock request
|
187
|
+
Mock request Path templates({}) are resolved using path parameters
|
188
|
+
*/
|
189
|
+
const options = {
|
190
|
+
method: 'delete',
|
191
|
+
url: '' + mock.request.path,
|
192
|
+
headers: helper.defaultAdminHeaders()
|
193
|
+
}
|
194
|
+
if (mock.request.body) {
|
195
|
+
// Send the request body
|
196
|
+
options.payload = mock.request.body
|
197
|
+
} else if (mock.request.formData) {
|
198
|
+
// Send the request form data
|
199
|
+
options.payload = mock.request.formData
|
200
|
+
// Set the Content-Type as application/x-www-form-urlencoded
|
201
|
+
options.headers = options.headers || {}
|
202
|
+
options.headers = helper.defaultAdminHeaders()
|
203
|
+
}
|
204
|
+
// If headers are present, set the headers.
|
205
|
+
if (mock.request.headers && mock.request.headers.length > 0) {
|
206
|
+
options.headers = mock.request.headers
|
207
|
+
}
|
208
|
+
sandbox.stub(oracle, 'deleteOracle').returns(Promise.resolve({}))
|
209
|
+
|
210
|
+
// Act
|
211
|
+
const response = await server.inject(options)
|
212
|
+
|
213
|
+
// Assert
|
214
|
+
expect(response.statusCode).toBe(204)
|
215
|
+
oracle.deleteOracle.restore()
|
216
|
+
})
|
217
|
+
|
218
|
+
it('delete /oracles/{ID} error', async () => {
|
219
|
+
expect.hasAssertions()
|
220
|
+
// Arrange
|
221
|
+
const requests = new Promise((resolve, reject) => {
|
222
|
+
Mockgen(false).requests({
|
223
|
+
path: '/oracles/{ID}',
|
224
|
+
operation: 'delete'
|
225
|
+
}, function (error, mock) {
|
226
|
+
return error ? reject(error) : resolve(mock)
|
227
|
+
})
|
228
|
+
})
|
229
|
+
|
230
|
+
const mock = await requests
|
231
|
+
|
232
|
+
/*
|
233
|
+
Get the resolved path from mock request
|
234
|
+
Mock request Path templates({}) are resolved using path parameters
|
235
|
+
*/
|
236
|
+
const options = {
|
237
|
+
method: 'delete',
|
238
|
+
url: '' + mock.request.path,
|
239
|
+
headers: helper.defaultAdminHeaders()
|
240
|
+
}
|
241
|
+
if (mock.request.body) {
|
242
|
+
// Send the request body
|
243
|
+
options.payload = mock.request.body
|
244
|
+
} else if (mock.request.formData) {
|
245
|
+
// Send the request form data
|
246
|
+
options.payload = mock.request.formData
|
247
|
+
// Set the Content-Type as application/x-www-form-urlencoded
|
248
|
+
options.headers = options.headers || {}
|
249
|
+
options.headers = helper.defaultAdminHeaders()
|
250
|
+
}
|
251
|
+
// If headers are present, set the headers.
|
252
|
+
if (mock.request.headers && mock.request.headers.length > 0) {
|
253
|
+
options.headers = mock.request.headers
|
254
|
+
}
|
255
|
+
sandbox.stub(oracle, 'deleteOracle').throws()
|
256
|
+
|
257
|
+
// Act
|
258
|
+
const response = await server.inject(options)
|
259
|
+
|
260
|
+
// Assert
|
261
|
+
expect(response.statusCode).toBe(500)
|
262
|
+
oracle.deleteOracle.restore()
|
263
|
+
})
|
264
|
+
})
|
@@ -0,0 +1,173 @@
|
|
1
|
+
/*****
|
2
|
+
License
|
3
|
+
--------------
|
4
|
+
Copyright © 2017 Bill & Melinda Gates Foundation
|
5
|
+
The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
8
|
+
Contributors
|
9
|
+
--------------
|
10
|
+
This is the official list of the Mojaloop project contributors for this file.
|
11
|
+
Names of the original copyright holders (individuals or organizations)
|
12
|
+
should be listed with a '*' in the first column. People who have
|
13
|
+
contributed from an organization can be listed under the organization
|
14
|
+
that actually holds the copyright for their contributions (see the
|
15
|
+
Gates Foundation organization for an example). Those individuals should have
|
16
|
+
their names indented and be marked with a '-'. Email address can be added
|
17
|
+
optionally within square brackets <email>.
|
18
|
+
* Gates Foundation
|
19
|
+
- Name Surname <name.surname@gatesfoundation.com>
|
20
|
+
|
21
|
+
* ModusBox
|
22
|
+
- Rajiv Mothilal <rajiv.mothilal@modusbox.com>
|
23
|
+
|
24
|
+
* Crosslake
|
25
|
+
- Lewis Daly <lewisd@crosslaketech.com>
|
26
|
+
|
27
|
+
--------------
|
28
|
+
******/
|
29
|
+
|
30
|
+
'use strict'
|
31
|
+
|
32
|
+
const Sinon = require('sinon')
|
33
|
+
const getPort = require('get-port')
|
34
|
+
const Logger = require('@mojaloop/central-services-logger')
|
35
|
+
const oracle = require('../../../src/domain/oracle')
|
36
|
+
const Helper = require('../../util/helper')
|
37
|
+
const initServer = require('../../../src/server').initializeAdmin
|
38
|
+
const Db = require('../../../src/lib/db')
|
39
|
+
const Migrator = require('../../../src/lib/migrator')
|
40
|
+
const Config = require('../../../src/lib/config')
|
41
|
+
|
42
|
+
Logger.isDebugEnabled = jest.fn(() => true)
|
43
|
+
Logger.isErrorEnabled = jest.fn(() => true)
|
44
|
+
Logger.isInfoEnabled = jest.fn(() => true)
|
45
|
+
|
46
|
+
const getResponse = [{
|
47
|
+
oracleId: '1',
|
48
|
+
oracleIdType: 'MSISDN',
|
49
|
+
endpoint: {
|
50
|
+
value: 'http://localhost:8444',
|
51
|
+
endpointType: 'URL'
|
52
|
+
},
|
53
|
+
isDefault: true
|
54
|
+
}]
|
55
|
+
|
56
|
+
let sandbox
|
57
|
+
let server
|
58
|
+
|
59
|
+
describe('/oracles', () => {
|
60
|
+
beforeAll(async () => {
|
61
|
+
sandbox = Sinon.createSandbox()
|
62
|
+
sandbox.stub(Db, 'connect').returns(Promise.resolve({}))
|
63
|
+
sandbox.stub(Migrator, 'migrate').returns(Promise.resolve({}))
|
64
|
+
Config.ADMIN_PORT = await getPort()
|
65
|
+
server = await initServer(Config)
|
66
|
+
})
|
67
|
+
|
68
|
+
afterAll(async () => {
|
69
|
+
await server.stop()
|
70
|
+
sandbox.restore()
|
71
|
+
})
|
72
|
+
|
73
|
+
/**
|
74
|
+
* summary: Get Oracles
|
75
|
+
* description: The HTTP request GET /oracles is used to return the list of all oracle endpoints. There are optional fields for type and currency i.e. /admin/oracles?type=MSISDN&currency=USD which can be used to get more filtered results or a specific entry
|
76
|
+
* parameters: type, currency, accept, content-type, date
|
77
|
+
* produces: application/json
|
78
|
+
* responses: 200, 400, 401, 403, 404, 405, 406, 501, 503
|
79
|
+
*/
|
80
|
+
it('GET /oracle', async () => {
|
81
|
+
// Arrange
|
82
|
+
const mock = await Helper.generateMockRequest('/oracles', 'get', false)
|
83
|
+
|
84
|
+
// Get the resolved path from mock request
|
85
|
+
// Mock request Path templates({}) are resolved using path parameters
|
86
|
+
const options = {
|
87
|
+
method: 'get',
|
88
|
+
url: mock.request.path,
|
89
|
+
headers: Helper.defaultAdminHeaders()
|
90
|
+
}
|
91
|
+
sandbox.stub(oracle, 'getOracle').returns(Promise.resolve(getResponse))
|
92
|
+
|
93
|
+
// Act
|
94
|
+
const response = await server.inject(options)
|
95
|
+
|
96
|
+
// Assert
|
97
|
+
expect(response.statusCode).toBe(200)
|
98
|
+
oracle.getOracle.restore()
|
99
|
+
})
|
100
|
+
|
101
|
+
it('GET /oracle throws on error', async () => {
|
102
|
+
// Arrange
|
103
|
+
const mock = await Helper.generateMockRequest('/oracles', 'get', false)
|
104
|
+
|
105
|
+
// Get the resolved path from mock request
|
106
|
+
// Mock request Path templates({}) are resolved using path parameters
|
107
|
+
const options = {
|
108
|
+
method: 'get',
|
109
|
+
url: mock.request.path,
|
110
|
+
headers: Helper.defaultAdminHeaders()
|
111
|
+
}
|
112
|
+
sandbox.stub(oracle, 'getOracle').throws(new Error('Error Thrown'))
|
113
|
+
|
114
|
+
// Act
|
115
|
+
const response = await server.inject(options)
|
116
|
+
|
117
|
+
// Assert
|
118
|
+
expect(response.statusCode).toBe(500)
|
119
|
+
oracle.getOracle.restore()
|
120
|
+
})
|
121
|
+
|
122
|
+
/**
|
123
|
+
* summary: Create Oracles
|
124
|
+
* description: The HTTP request POST /oracles is used to create information in the server regarding the provided oracles. This request should be used for creation of Oracle information.
|
125
|
+
* parameters: body, accept, content-length, content-type, date
|
126
|
+
* produces: application/json
|
127
|
+
* responses: 201, 400, 401, 403, 404, 405, 406, 501, 503
|
128
|
+
*/
|
129
|
+
it('POST /oracle', async () => {
|
130
|
+
// Arrange
|
131
|
+
const mock = await Helper.generateMockRequest('/oracles', 'post', false)
|
132
|
+
|
133
|
+
// Get the resolved path from mock request
|
134
|
+
// Mock request Path templates({}) are resolved using path parameters
|
135
|
+
const options = {
|
136
|
+
method: 'post',
|
137
|
+
url: mock.request.path,
|
138
|
+
headers: Helper.defaultAdminHeaders(),
|
139
|
+
payload: mock.request.body
|
140
|
+
}
|
141
|
+
|
142
|
+
sandbox.stub(oracle, 'createOracle').returns(Promise.resolve({}))
|
143
|
+
|
144
|
+
// Act
|
145
|
+
const response = await server.inject(options)
|
146
|
+
|
147
|
+
// Assert
|
148
|
+
expect(response.statusCode).toBe(201)
|
149
|
+
oracle.createOracle.restore()
|
150
|
+
})
|
151
|
+
|
152
|
+
it('POST /oracle throws error', async () => {
|
153
|
+
// Arrange
|
154
|
+
const mock = await Helper.generateMockRequest('/oracles', 'post', false)
|
155
|
+
|
156
|
+
// Get the resolved path from mock request
|
157
|
+
// Mock request Path templates({}) are resolved using path parameters
|
158
|
+
const options = {
|
159
|
+
method: 'post',
|
160
|
+
url: mock.request.path,
|
161
|
+
headers: Helper.defaultAdminHeaders(),
|
162
|
+
payload: mock.request.body
|
163
|
+
}
|
164
|
+
sandbox.stub(oracle, 'createOracle').throws(new Error('Error Thrown'))
|
165
|
+
|
166
|
+
// Act
|
167
|
+
const response = await server.inject(options)
|
168
|
+
|
169
|
+
// Assert
|
170
|
+
expect(response.statusCode).toBe(500)
|
171
|
+
oracle.createOracle.restore()
|
172
|
+
})
|
173
|
+
})
|