This project is a Spring MVC RESTful API. The app manages stock, purchases and users for a fictional record shop. It consists of three main entities: User
, Purchase
and Record
, each mapped to corresponding database tables by JPA.
The project fully integrates modern security techniques offered through Spring Security, including password hashing and salting, HTTPS, JWT tokens, CSRF tokens and CORS. As such, certain endpoints require users to be authenticated and hold certain roles in order to make successful HTTP requests.
flowchart LR;
User[User via Web Client, such as Postman] -->|HTTP request|Authorisation
Authorisation{Does the user require authorisation?} --> |Yes| Authorisation2
Authorisation --> |No - HTTP request|Controllers
Authorisation2-->|No - 401/403 Response|User
Authorisation2{Is the user authorised?}-->|Yes - HTTP request|Controllers
Controllers[User, Record & Purchase Controllers] -->|Business Logic|Services
Services -->|CRUD operation|MySQL_Database
MySQL_Database[(MySQL Database)] -->|Return data|Services
Services -->|Validation|Controllers
Controllers -->|Authorised Response|User
Controllers -->|Unhandled Exception|ErrorController[Error Controller]
ErrorController -->|Error Response|User
The application has the following endpoints:
Endpoint | Method | Authorisation Required? | User role | Description | Returns |
---|---|---|---|---|---|
"/login" | POST | No | n/a | Expects a request body of username and password, which it validates against the database | If authenticated, Ok and a JWT token as a cookie and body message. If not authenticated, Forbidden. |
"/register" | POST | No | n/a | Expects a request body of firstname, lastname, username, password and role. | If all input validated and username is not in use, creates a new user and returns Ok |
"/" | GET | No | n/a | Home route | Returns "Welcome to the Record Shop" message |
"/auth/records" | GET | Yes | Any | Requires valid JWT token, and optional params of artist or album to search | An authorised response will return a list of artist and albums matching the search params. No params will return a list of all records. Also returns CSRF token. |
"/auth/getPurchases" | GET | Yes | Any | Requires valid JWT token | Returns a list of all purchases. Also returns CSRF token. |
"/auth/deletePurchase" | DELETE | Yes | ADMIN | Requires valid JWT and CSRF token and id parameter | An authorised request will delete record with the matching id and return No Content". |
"/auth/purchase" | POST | Yes | Any | Requires valid JWT and CSRF token and body object containing customer name, record id and discount code | Authorised valid request returns Ok. |
Before you begin, please ensure you have the following:
- Java Development Kit (JDK) 17 or higher
- The latest version of Maven
- An SQL database (e.g., MySQL)
- IntelliJ Community / Ultimate
-
Clone the repository.
-
Ensure the proper dependencies are installed. Please refer to
pom.xml
in the file for your reference- Spring Boot Starter Data JPA
- Spring Boot Starter Web
- Spring Boot Starter Test
- Flyway Core
- Flyway MySQL
- MySQL Connector-J
- Spring Security
- JJWT-Api
- JJWT-Impl
- JJWT - Jackson Extension
- Flyway Maven
- OpenAPI
- Spring Mock MVC (Rest Assured)
- Java Servlet API
-
Ensure the proper plugins are installed. Please refer to
pom.xml
in the file for your reference- JaCoCo Maven Plugin
- Maven Surefire Plugin
- Spring Boot Maven plugin
- Lombok plugin
-
Configure the database:
- Go to your IntelliJ configuration
- Navigate to GroupProjectApplication, and edit the configuration to add in a new environment variable
MYSQL_ROOT_PASSWORD
and set it to your password for your database. For exampleMYSQL_ROOT_PASSWORD="your password"
- Navigate to GroupProjectApplicationTests and add in a new environment variable "MY_SQL_PASSWORD" and set it to your password for your database. For example
MYSQL_ROOT_PASSWORD="your password"
- Then run GroupProjectApplication
- The Flyway integration should automatically create the database and migrate the relevant files to create and populate the tables.
-
Debugging:
- Should you have any issue with the Flyway integration, you can manually create the database by running the MySQL script found in resources/db/migration
- You should remove Flyway Core, FlywaySQL and Flyway Maven from your pom.xml (please note: should you wish to run the docker file, you will need to replace these dependencies)
- Please add the following lines of codes at the start before running on your preferred platform:
CREATE DATABASE IF NOT EXISTS recordShop;
USE recordShop;
- Generate SSL certificates
- Run the following commands on your terminal providing the information prompted where relevant. Be sure to make note of your password.
keytool -genkeypair -alias baeldung -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore baeldung.p12 -validity 3650
- This will generate SSL certificates. Save these in
src/resources/certs
. You should be sure to add these to your .gitignore - Save your password for the certificates as an environment variable named
KEYSTORE_PASSWORD
-
Start the application: In the project's root directory, run GroupProjectApplication
-
API Endpoints:
Once the application is running, you can explore unauthorised endpoints freely and authorised with the correct credentials. We suggest using the following flow:
💡 Import our pre-made Postman collection to run the following the series of requests. You can download them here.
Endpoint URL | Method | Example Request | Expected Response |
---|---|---|---|
/auth/records | GET | - | 403 Forbidden. |
/login | POST | {"username":GillyT10","password":"goodbye"} |
200. Bearer token in body response. |
/auth/records /auth/records?artist={ARTISTNAME}&name={ALBUM} |
GET | Authorization with Bearer token provided. Optional params or artist and album. |
200. List of records. X-XSRF-TOKEN returned as cookie and header |
/auth/purchase | POST | Authorization Header: JWT token Custom header X-XSRF-TOKEN with X-XSRF token Body: {"customer" : "john","id" : 1, "discount" : "cfg"} |
200. Purchase Id in response. |
/auth/deletePurchase?id=1 | DELETE | Authorization Header: JWT token; Custom header X-XSRF-TOKEN with X-XSRF token; Param id=1 | 204 No content |
/login | POST | {"username" : "john100","password" : "password"} |
200. Bearer token in body response. |
/auth/records /auth/records?artist={ARTISTNAME}&name={ALBUM} |
GET | Authorization with Bearer token provided. Optional params or artist and album. |
200. List of records. X-XSRF-TOKEN returned as cookie and header |
/auth/purchase | POST | Authorization Header: JWT token Custom header X-XSRF-TOKEN with X-XSRF token Body: {"customer" : "john","id" : 1, "discount" : "cfg"} |
409 Conflict. Item not in stock. |
/auth/deletePurchase?id=2 | DELETE | Authorization Header: JWT token Custom header X-XSRF-TOKEN with X-XSRF token Param id=2 |
403 Forbidden |
This will help in generating interactive API documentation in order to test the API calls. Please see Open API: here.
Located here
Quick links:
To follow these instructions you have to have Docker Desktop installed on your machine.
- Start docker engine by opening Docker Desktop (or start it from IntelliJ)
- Insert your MySQL user password in the terminal
- bash terminal:
export MYSQL_ROOT_PASSWORD=your_password_here
- command prompt:
$env:MYSQL_ROOT_PASSWORD = "your_password_here"
- bash terminal:
- Run the command to build the docker containers:
docker compose up --build
- Check if the app is running by visiting http://localhost:8080/records. You should see the list of records from the database.
- Once your docker container is running, you can use Postman or a similar API tool to explore the application as described here.
Should you have an issue when exporting your password you can try the following:
MAC USERS
In the terminal run the command MYSQL_ROOT_PASSWORD=yourMySQLpassword docker compose up --build
using your own password instead of "yourMySQLpassword".
WINDOWS USERS
- In the terminal run the command
docker compose up --build
. - Click on the Services to see your docker containers
- Select mysql container and click on Dashboard. Insert your personal MySQL password for the environment variable called MYSQL_ROOT_PASSWORD.
- Should you wish to test the Github Actions maven.yml file, you should fork the repository
- Set up a Github secret with your MySQL root password with variable name "MY_SQL_PASSWORD"
- Trigger the workflow through a push or pull request to main
- Develop frontend with React