This is a fullstack tech challange for MVP match Nov 2023
The project is using docker containers orchastrated by docker compose for simple setup
setup should be as simple as running one command docker-compose up
-
frontend -> react (http: http://localhost:3000)
- tests
npm run test:dev
- tests
-
backend -> Nodejs and Express -> (http://localhost:3001/)
- tests
npm run test:dev
- tests
-
database -> MongoDB (port 27017)
- migrations
- I have opted to add some prefil scripts just to start the database with some data, this is good if someone is joing the project they already have a good starting place.
migrations will run automatically in container
- 2 users
- buyer: aBuy:passWord1
- seller: aSell:passWord1
- 4 products
- 2 buys(orders) belonging to the buyer
- 2 users
- I have opted to add some prefil scripts just to start the database with some data, this is good if someone is joing the project they already have a good starting place.
migrations will run automatically in container
- migrations
-
CI/CD -> github actions(https://github.com/blavejr/vendingMachine/actions)
- Github actions
- check if images can build
- check if tests will pass in CI
- might add uloading images to docker registry if there is time
- Github actions
Postman collection is included in the backend as a json file that can be imported into postman
be/postman/vendingMachine.postman_collection.json
- I have taken the time to write a simple postman script to automatically add the token on login to a variable which can be set globally in auth and have all other requests inherit from there
const response = pm.response.json();
const jwtToken = response.token;
pm.environment.set('jwtToken', jwtToken);
pre-script for adding some variables needed for the postman collection can also be put on the login route
pm.environment.set('be_Host', "http://localhost:3001");
pm.environment.set('fe_Host', "http://localhost:3000");
- login
- All other routes except for registration
- I have deployed a simple session management system, sessions are saved in the mongoDB as JS objects, sessions do not contain tokens but a have userID, device info and a sessionID if a token has an id that does not match even if its a valid token it will be rejected, if the id is in one of the session objects in the db but its the device info does not match it will be rejected or it should behave like this if I have time to implement it
- The app does not save the actual JWT in the database rather it will save metadata in the token and the token is only saved on the client, the same way password and username are only saved in the users head, the token is also only saved on the users device, the only thing we save is session information, the token must be returned with every request apart from login and it will be deserialized with our jwt secret to confirm that it was generated by our server but after that its the information it contains that will be used to validate the session.
- In the event of a data breach there will be no authentication information released, only session information which will not allow any access to the server. sessions can be dropped and users can authenticate
- The server is completely stateless in this manner.
Erros are handled via a global middleware, it will pick up all errors, sync and aysinc and it will respond with an appropriate response, so developers can freely throw errors and rely on the middleware to parse and return an appropriate response.
- Implement user model with username, password, deposit and role fields.
- Implement an authentication method (basic, oAuth, JWT or something else, the choice is yours).
- All of the endpoints should be authenticated unless stated otherwise.
- Implement CRUD for users (POST /user should not require authentication to allow new user registration).
- Implement product model with amountAvailable, cost, productName and sellerId fields.
- Implement CRUD for a product model (GET can be called by anyone, while POST, PUT and DELETE can be called only by the seller user who created the product).
- Implement /deposit endpoint so users with a “buyer” role can deposit only 5, 10, 20, 50 and 100 cent coins into their vending machine account.
- Implement /buy endpoint (accepts productId, amount of products) so users with a “buyer” role can buy products with the money they’ve deposited. API should return total they’ve spent, products they’ve purchased and their change if there’s any (in an array of 5, 10, 20, 50 and 100 cent coins).
- Implement /reset endpoint so users with a “buyer” role can reset their deposit back to 0.
- Create web interface for interaction with the API, design choices are left to you.
- Take time to think about possible edge cases and access issues that should be solved.