TechUBank API server
Homepage Repository npm Download
npm install techubank-api@1.8.1
TechU Bank rest API server allows the Techubank Front to operate with Techubank.
Entities managed by the API:
The API documentation is written following the Open API v2 specification in a Swagger YAML file.
You can find all the specification versions in ws-doc folder. It's automatically rendered using swagger-ui library.
In localhost you can check the documentation and try any endpoint:
techu@techu> npm install \
npm run start
This project needs:
This API is securized via OAuth2 method; by default it is setup our own OAuth 2 Server.
techubank-api orchestate calls to techubank-mlab. techubank-mlab is the component which interact with MongoDB; and that connectivity is securized too. You have to facilitate the username and password of an admin user (by default techubank / techubank1234).
Create a .env file on the base path with the following variables
API_USERNAME=<username-with-admin-scope>
API_PASSWORD=<password>
Stay on the base path where package.json is located.
techu@techu> npm install
techu@techu> npm run test
techu@techu> npm run watcher
techu@techu> npm run coverage
Linter is a light weight static code analysis recomended to be execute in every push to a branch, and may block the push.
techu@techu> npm run lint
We have prepared a container with the software enough for run a static code analysis, execute unit tests, measure unit test coverage and upload the results to Sonarqube (free account).
You must have a Sonarqube API Key, configure properly the sonar-scanner.properties and run the command below:
$ docker run -it --env SONAR_API_KEY=<SONAR_USER_API_KEY> --mount type=bind,source="$(pwd)",target=/root/project -v "$(pwd)"/sonar-scanner.properties:/root/sonar-scanner/conf/sonar-scanner.properties davidrova/sonar-scanner:latest
To see the result click on this link.
The evaluation period has expired and we cannot upload more executions.
Don't worry, you can still perform static code analysis, but following a couple of additional steps.
$ docker run -d -p 9000:9000 -p 9092:9092 sonarqube
Generate a new API-KEY
Download sonar-scanner in localhost or use sonar-scanner Docker image sonar-scanner documentation
Run unit tests and coverage
$ npm run test
$ npm run coverage
$ SONAR_API_KEY=<SONAR_API_KEY> sonar-scanner
We encourage to enable the pre-commit hook. It will avoid commiting a change if linter or unit tests fail.
techu@techu> cp bin/pre-commit .git/hooks/pre-commit
The project is managed in bitbucket.org and we have automated an ease pipeline with the following step rules:
In order to be able to execute git commands against our repository, it is neccessary to give grants to the pipeline; it's neccessary to generate a new key pair. Follow these instructions
Our images have been built with DOCKER_HUB_USERNAME=davidrova.
docker run -p 3000:3000 -p 3443:3443 -e API_USERNAME=<admin-username> -e API_PASSWORD=<admin-password> --name techubank__testing ${DOCKER_HUB_USERNAME}/techubank-api
docker stop techubank__testing
docker rm techubank__testing
docker build -t ${DOCKER_HUB_USERNAME}/techubank-api .
docker login --username=${DOCKER_HUB_USERNAME} --password=${DOCKER_HUB_PASSWORD}
docker push ${DOCKER_HUB_USERNAME}/techubank-api
Techubank-api starts an express instance supporting http and https protocols. The component is splitted in the following pieces:
That is a big picture about how the API server is working. It's interesting to notice a couple of helpers implemented to control better the code. All these helpers are centralized in the piece techubank-commons.
Controllers excapsulate the logic called from the router. Router is configured with the function reference, and there is no choice to pass it the context (this). This is the reason why we have decided to expose static methods to the router and implement a controlled logic inside.
Let's explain it with UserController class.
user_router.get('/:username/info', UserController.getUserByUsername)
Define the static method which implements the logic
We create a user_controller object, load "admin" credentials and call the real logic.
module.exports = class UserController extends BaseController {
constructor() {
super()
}
// method exposed to the router
static getUserByUsername(req, res) {
const user_controller = new UserController()
return user_controller.load_token().then(() => {
return user_controller._getUserByUsername(req, res)
})
}
We have encapsulated calls to the backend as an instance's function to be able to mock it easily using Sinon.js (client_get, client_post, client_put). These functions returns a Promise. With the resolution of the Promise we act as neccessary.
When the Promises resolves then we control the response.statusCode and call the accurate function (passing the context with call).
/**
* The username is in the request req.params['username']
*
* @param {object} req
* @param {object} res
*/
_getUserByUsername(req, res) {
logger.info(`Fetch user ${req.params.username}`)
return this.client_get(`/v1/user/${req.params.username}/info`).then((res_post_mlab) => {
return this.request_handler.call(this, res_post_mlab, {
success_handler: this._getUser_success_handler,
error_handler: this._getUser_error_handler,
unauthorized_handler: this._getUser_error_handler
}, res)
})
}
With Sinon.js it's very easy to isolate our piece from dependencies; but you must considere one constraint; the function to replace must be a instance's function.
const user = new UserController()
const callback = sinon.stub(user, 'client_get')
callback.returns(new Promise((resolve) => {
return resolve({
statusCode: 200,
body: JSON.stringify(require('../resources/user')),
send: (data) => {
return data
}
})
}))
It is recomended to check if there is a new techubank-commons release.
$ npm update
To import the helpers
{
environment,
logger,
http_request_handler,
propagate_error_response,
get_admin_token
} = require('techubank-commons')
Further information about techubank-commons click on the link