A full-stack "vending machine" sample web application,
that allows users with a seller role to add, update or remove products,
while users with a buyer role can deposit
coins into the machine and make purchases.
The vending machine accepts only 5, 10, 20, 50 and 100 cent coins
The frontend consists of an SPA web app, built with
- React.js
- MaterialUI
- RTK toolkit
The backend is implemented using SpringBoot and the following components:
- Spring-boot-data JPA & Postgres for persistence
- Spring-boot-redis & Redis for caching
- Spring-boot-web, including validation for rest APIs
- Spring-web-security & auth0-jwt library for authentication and authorization
The application security is implemented using spring-web-security library and consists of the follwing flows:
- register flow: store user info, like username and password hash in the
usertable - login flow: validate username/password combination, and, if successful, generate a short-lived JWT
access_tokenand a long_livedrefresh_token- store a unique identifier of the
refresh_tokenin a cache, associated with the user identity - include a counter of the active-stored
refresh_tokensfor the user, indicating other active sessions
- store a unique identifier of the
- refresh flow: generate another pair of {
access_token,refresh_token} based on the submittedrefresh_token- validate that the submitted
refresh_tokenbelongs to the user requesting a token refresh - if the validation succeeds, store the new
refresh_tokenand invalidate the old one - return the generated {
access_token,refresh_token} pair
- validate that the submitted
- logout flow: prevent further token refresh actions by invalidating the provided refresh token
- event though the current
access_tokenis removed from browser storage, theoretically it's still usable until expiration
- event though the current
- logout-all flow: prevent further token refresh actions by invalidating all refresh tokens associated with a user id
- client includes a
refresh_tokenin the request and allrequest_tokensbeloging to the same tokens family will be invalidated
- client includes a
- docker environment
- jdk >= 17
The easiest way to start the backing services (database, cache) by running the docker containers from backend/dev/vending-machine-dev-containers/docker-compose.yaml
cd dev/dev-backing-services
docker-compose up -d The backend can be started
- In an IDE, by running the main class
VendingMachineApplication - In CLI mode, by running the spring boot plugin
mvn spring-boot:runtarget
cd backend
./mvnw spring-boot:runThe frontend app can be started in dev-mode npm run start command
cd frontend
npm run startThe end-to-end tests can be run against local environment, once:
- the initial setup is done
npm run cypress:install- Backing services, Backend and Frontend are up and running
cd frontend-e2e
npm run cypress:opencd frontend-e2e
npm run cypress:runThe application correctness is covered by the following categories of tests:
- Unit & functional tests w/ JUnit5
- API integration tests w/ spring-boot-test (w/ web environment) & test-containers (postgres & redis)
- End-to-end frontend tests with cypress



