Skip to content
This repository was archived by the owner on May 11, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions modules/investec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
const axios = require('axios')
const InvestecSandbox = require('./investec_sandbox')
const logError = (error) => console.log(error.toJSON())
const logError = (error) => {
console.log(error.toJSON ? error.toJSON() : error)
return error.response
}

// Simple adapter to fetch bearer tokens and proxy requests to Investec's API

Expand Down Expand Up @@ -61,7 +64,7 @@ class Investec {
}

async get(path) {
await axios.get(path, this.axiosConfig()).catch(logError)
return await axios.get(path, this.axiosConfig()).catch(logError)
}

async getWithAuth(path) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "node tests/sandbox-smoke.js"
},
"keywords": [],
"author": "",
Expand Down
14 changes: 11 additions & 3 deletions routes/investec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ router.use('/special', require('./investec/special'))
const Investec = require('../modules/investec')
const cardPartitions = require('./investec/card_partitions')

function sendInvestecResponse(_res, response) {
if (!response) {
return _res.status(502).json({ error: 'No response received from Investec API' })
}

return _res.status(response.status || 200).json(response.data)
}

// This route is not a pure proxy because we want to filter the results if there is a partition i.e. when sharing a single account with many users while only showing them particular cards
router.get('/za/v1/cards', async (_req, _res) => {
const investec = new Investec(_req.currentUser.token)
Expand All @@ -31,15 +39,15 @@ router.get('/za/v1/cards', async (_req, _res) => {
router.get('/*', async (_req, _res) => {
const investec = new Investec(_req.currentUser.token)
const response = await investec.getWithAuth(_req.url)
_res.json(response.data)
sendInvestecResponse(_res, response)
})
Comment on lines 39 to 43

// proxies any POST request to the investec adapter
// with a valid bearer token added in
router.post('/*', async (_req, _res) => {
const investec = new Investec(_req.currentUser.token)
const response = await investec.postWithAuth(_req.url, _req.body)
_res.json(response.data)
sendInvestecResponse(_res, response)
})

module.exports = router
module.exports = router
8 changes: 5 additions & 3 deletions routes/investec/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ function splitPartitionFromToken(partitionedToken) {
// pulls out an optional partition (subfolder) from API credentials
// which is used when filtering Investec API responses to show only
// certain cards
if (partitionedToken == "SANDBOX") {
return { token: "SANDBOX", username: "SANDBOX", partition: undefined }
}

const partitionedCredentials = new Buffer(partitionedToken, 'base64').toString()
const partitionedCredentials = Buffer.from(partitionedToken, 'base64').toString()
const [partitionedUsername, password] = partitionedCredentials.split(":")
const [username, partition] = partitionedUsername.split("/")
const token = (new Buffer.from(`${username}:${password}`)).toString('base64')
const token = Buffer.from(`${username}:${password}`).toString('base64')
return { token, username, partition }
}

Expand All @@ -16,7 +19,6 @@ function getAuth(_req, _res, next) {
if (authType == "Basic") {
let { token, username, partition } = splitPartitionFromToken(partitionedToken)
_req.currentUser = { username, partition, token }
console.log(_req.currentUser)
}

if (authType == "RootCard") {
Expand Down
41 changes: 41 additions & 0 deletions tests/sandbox-smoke.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const assert = require('assert')
const Investec = require('../modules/investec')
const getAuth = require('../routes/investec/auth')

async function testSandboxAdapter() {
const sandbox = new Investec('SANDBOX')

const accountsResponse = await sandbox.getWithAuth('/za/pb/v1/accounts')
assert.strictEqual(accountsResponse.status, 200)
assert.strictEqual(accountsResponse.data.data.accounts.length, 1)

const accountId = accountsResponse.data.data.accounts[0].accountId
const transactionsResponse = await sandbox.getWithAuth(`/za/pb/v1/accounts/${accountId}/transactions`)
assert.strictEqual(transactionsResponse.status, 200)
assert.strictEqual(transactionsResponse.data.data.transactions.length, 2)

const missingResponse = await sandbox.getWithAuth('/za/pb/v1/cards')
assert.strictEqual(missingResponse.status, 404)
assert.strictEqual(missingResponse.data.data.path, '/za/pb/v1/cards')
}

function testSandboxAuthHeader() {
const req = {
headers: { authorization: 'Basic SANDBOX' }
}

getAuth(req, {}, () => {})

assert.deepStrictEqual(req.currentUser, {
username: 'SANDBOX',
partition: undefined,
token: 'SANDBOX'
})
}

async function run() {
await testSandboxAdapter()
testSandboxAuthHeader()
}

run()