RV backend
To run the backend locally, you can either use Docker or run it without Docker.
For Docker, the repo contains a Dockerfile
for building a Docker image of the backend server and a Docker Compose file for running both the backend server and a PostgreSQL database inside Docker.
To set up a local environment, run the following commands:
docker-compose build
to build Docker images for the backend and database.docker-compose up
to start the server and PostgreSQL database. Note the name of the server container, as you will need it for later steps.- To create database schema, run
docker exec -it <server container name or id> npm run db-migrate
. - To seed database with data for development, run
docker exec -it <server container name or id> npm run db-seed
.
By default, the server will listen on port 8081. See .env for default configuration and Configuration for an explanation of these variables.
To shut down the local environment, run docker-compose down
. This will stop and remove any containers created by Docker Compose. Note that you will need to re-create the schema and reseed the database if you shut down your environment (steps 3 and 4) and start it up again.
On linux sudo ./restart.sh
restarts a running docker.
To run the backend without Docker, install Node.js and PostgreSQL. Then, create a database and a user in PostgreSQL for the backend to use.
Then, to run the backend server:
- Run
npm install
to install packages needed by the backend server. - Set environment variables:
DATABASE_URL
is used by the backend to connect to a database server. For example, if your local database is running on port 5432 with useruser
and passwordpassword
and databasedb
, the value would bepostgres://user:password@localhost:5432/db
.JWT_SECRET
is used to sign authentication tokens issued by the server. This can be any string.PORT
is the port the backend server listens on.- Setting
NODE_ENV
is optional since it defaults todevelopment
but you can set it if you want try out environments other than development.
- If needed, clear database by running
npm run db-rollback
. - Run
npm run db-migrate
to create or update the database schema to the latest version. - Run
npm run db-seed
to seed the database with initial data. - Finally, run
npm start-nodemon
to start the server. Nodemon will listen for changes in code and restart the server if necessary.
Generally speaking, the backend will run anywhere Docker runs or if it's run without Docker, anywhere Node.js and PostgreSQL is available.
Currently, deployment to staging and production environments in Heroku is done via Travis. Deployment to staging involves resetting and reseeding the database.
Production deployments will not automatically execute database schema changes. If a new version includes any changes to the database schema, upgrading the database needs to be coordinated with the deployment of the new server code.
Environment variables:
Variable | Description |
---|---|
DATABASE_URL | Address of database, e.g. postgres://user:password@database_url:port/database |
JWT_SECRET | Secret key for signing JWT tokens. Do not use default values in production! The security of authentication will depend on this key being kept secret, so treat it accordingly. |
PORT | Port used by the backend server |
NODE_ENV | Environment for Node, can be one of development , test or production . |
When developing, create tests for created endpoints and when felt useful. Use Mocha to write tests and mocking.
- Install REST client for VSCode
- Use
admin_auth.rest
to get your JWT - Add the following to your VSCode config, replacing TOKEN:
"rest-client.environmentVariables": {
"$shared": {
"rv_backend_admin_token": "TOKEN"
}
}
- You can now use REST client to make requests to the management 'back end.
- Install REST client for VSCode
- Use
user_auth.rest
to get your JWT - Add the following to your VSCode config, replacing TOKEN:
"rest-client.environmentVariables": {
"$shared": {
"rv_backend_user_token": "TOKEN"
}
}
- You can now use REST client to make requests to the back end.
The service uses JWT tokens for authenticating HTTP requests. All authenticated endpoints require that you include your JWT token in the request headers. The token should be included in the Authorization
header, e.g. Authorization: Bearer <JWT token here>
.
Endpoint | Method | Description |
---|---|---|
/api/v1/user/authenticate |
POST | Used for requesting access tokens. Accepts credentials username and password as JSON or parameters. If credentials are valid, returns a 200 OK response containing access token as a JSON object, otherwise returns 403 Unauthorized. |
/api/v1/user/account |
GET | Authentication required. Returns basic information about the authenticated user, such as name, email, etc. |
/api/v1/user/account/credit |
POST | Authentication required. Increase the authenticated user's account balance. Accepts parameter amount that should be an integer. Returns new account balance. |
/api/v1/user/account/debit |
POST | Authentication required. Decrease the authenticated user's account balance. Accepts parameter amount that should be an integer. Returns new account balance. |
/api/v1/user/register |
POST | Register a new account. Accepts credentials username , password , realname and email . Username and password should be at least 4 characters. On successful registration, returns a 201 Created response that includes user information. If validation fails, or a user with username or email exists, returns a 403 Unauthorized response with error message. |
/api/v1/product/purchase |
POST | Authentication required. Buy a product. Accepts parameters barcode and quantity . barcode is the barcode of the product being purchased and quantity is the amount being purchased. On successful purchase, returns product name, quantity purchased and account balance after purchase (product_name , quantity and account_balance , respectively). If the product is out of stock or doesn't exist, returns a 404 Not Found response. If the user doesn't have enough funds on their account, will return a 403 Unauthorized response. |
/api/v1/admin/products |
POST | Authentication required. Create a new product. Requires parametres descr (String), pgrpid (String), weight (Integer), barcode (String, 13 numbers), count (Integer), buyprice (Integer) and sellprice (Integer). |
/api/v1/admin/products/:barcode |
GET | Authentication required. Get a product by its barcode. Requires parameter barcode (String). |
/api/v1/admin/products/product/:productId |
GET | Authentication required. Get a product by its id. Requires parameter productId (String). |
/api/v1/user/products |
GET | Get all products. Returns an array of products. |
/api/v1/categories |
GET | Get all categories. Returns an array of categories. |
/api/v1/admin/boxes |
GET | Authentication required. Get all boxes. Returns an array of boxes. |
/api/v1/admin/boxes/:barcode |
GET | Authentication required. Get a box by its barcode. URL parameter barcode is required. |
/api/v1/admin/boxes/:barcode |
POST | Authentication required. Buy in boxes of products. URL parameter barcode is required. Requests should be JSON with these fields: boxes : how many boxes are being added, buyprice : the acquisition cost of a single iten, sellprice : selling price of a single item. Returns 200 OK if the request is successful, 4xx if the request is invalid or 500 Internal Server Error if some other error occurred. |
/api/v1/admin/boxes/:barcode |
PUT | Authentication required. Create or update a box and the product it contains. Requires JSON with fields: items_per_box , product . product should be an object with fields product_barcode , product_name , product_group , product_weight , product_buyprice , product_sellprice . Returns 201 Created if a new box is created or 200 OK if the box is updated. |