Build Restful CRUD API for a product online store.
- Java JDK 17
- Maven version 3.8.6
- Spring Boot version 3.1.2
- Spring Data JPA, Hibernate
- Spring Security
- JSON Web Token (JWT)
- MySQL database
- Flyway migration
- JUnit testing
1. Clone the application
git clone https://github.com/bayubagusbagaswara/product-restful-api.git
2. Create PostgreSQL database
CREATE DATABASE yourdbname;
CREATE USER youruser WITH ENCRYPTED PASSWORD 'yourpass';
GRANT ALL PRIVILEGES ON DATABASE yourdbname TO youruser;
3. Change mysql username and password as per your installation
- open
src/main/resources/application.properties
- change
spring.datasource.username
andspring.datasource.password
as per your postgres installation
4. Install library
mvc clean install compile test-compile
5. Run the app using maven
mvn spring-boot:run
The app will start running at http://localhost:8080
The app defines following CRUD APIs.
- username : admin
- password : admin123
ID | Name |
---|---|
1 | ADMIN |
2 | USER |
Method | URL | Description | Request Body | Response Success | Response Error |
---|---|---|---|---|---|
POST | /api/auth/signup | Sign up | JSON | JSON | JSON |
POST | /api/auth/signin | Log in | JSON | JSON | JSON |
POST | /api/auth/refresh/token | Refresh Token | JSON | JSON | JSON |
POST | /api/auth/logout | Log out | JSON | JSON |
Method | URL | Description | Request Body | Response Success | Response Error |
---|---|---|---|---|---|
POST | /api/users | Create new user | JSON | JSON | |
PUT | /api/users/{username} | Update user (If profile belongs to logged in user or logged in user is admin) | JSON | JSON | |
PUT | /api/users/{username}/addRole | Add role to another user (only for admins) | JSON | JSON | |
DELETE | /api/users/{username} | Delete user (Only admin) | JSON | JSON | |
PUT | /api/users/{username}/giveAdmin | Give admin role to user (only for admins) | |||
PUT | /api/users/{username}/removeAdmin | Take admin role from user (only for admins) | JSON |
Method | URL | Description | Request Param | Request Body | Response Success | Response Error |
---|---|---|---|---|---|---|
POST | /api/products | Create new product | JSON | JSON | JSON | |
PUT | /api/products/{productId} | Update product (user or admin) | JSON | JSON | ||
DELETE | /api/products/{productId} | Delete product (only for admins) | - | JSON | JSON | |
GET | /api/products | Get all products | - | JSON | ||
GET | /api/products/{productId} | Get product by ID | - | JSON | ||
GET | /api/products/name/{name} | Get products by containing name | - | JSON | ||
GET | /api/products/name/{name}/price | Get products by name and price | name, priceMin, priceMax | - | JSON |
Test them using postman or any other rest client.
{
"firstName": "Bayu",
"lastName": "Bagaswara",
"username": "bayu_bagaswara",
"password": "B@gaswara12",
"email": "bayubagaswara@mail.com"
}
{
"success": true,
"message": "User registered successfully"
}
{
"usernameOrEmail": "string",
"password": "string"
}
{
"success": true,
"message": "User authenticated successfully",
"data": {
"accessToken": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwiaXNzIjoiUHJvZHVjdCBBUEkiLCJpYXQiOjE2NTQ3NzcyMDEsImV4cCI6MTY1NDc3OTAwMX0.D0ncWGECngNl0wXrwwVw9qiZlyyLJK3oGwPVlTafLORhpAokMwcAYC7vUPnsWeoVDghz-HrjpKGuPDwcfRo08g",
"refreshToken": "ca86a55f-efa1-4730-b78f-eb990bb3362e",
"expiresAt": "2022-06-09T12:50:01.804945700Z",
"tokenType": "Bearer",
"username": "bagaszwara12@gmail.com"
}
}
{
"success": false,
"message": "Bad credentials, User is not authenticated. Username or password do not match"
}
{
"success": true,
"message": "Refresh token successfully updated",
"data": {
"accessToken": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwiaXNzIjoiUHJvZHVjdCBBUEkiLCJpYXQiOjE2NTQ3NzczNTAsImV4cCI6MTY1NDc3OTE1MH0.whDrThQh2a3oDx8GprpMQOM7Do5TA38W12gjsmybJjVCNk35OzcgI0oHyqOgdMyTqVoKYVvtZyMIZ6P70W77fg",
"refreshToken": "c2017c2f-b5f5-45b4-8d89-e261d248120d",
"expiresAt": "2022-06-09T12:52:30.383943200Z",
"tokenType": "Bearer",
"username": "bayu_bagaswara"
}
}
{
"success": false,
"message": "Invalid refresh token"
}
{
"success": true,
"message": "User was created successfully",
"data": {
"id": 8,
"firstName": "Budi",
"lastName": "Anggara",
"username": "budi_anggara",
"password": "$2y$10$/NDA7IGW66y.krPuJwbcteRG4D4qjnOzMvm2OaiwN4qFrYPSuAk0W",
"email": "budi@gmail.com",
"roles": [
{
"createdAt": "2022-06-09T12:07:03.763821Z",
"updatedAt": "2022-06-09T12:07:03.763821Z",
"id": 4,
"name": "USER"
}
]
}
}
{
"success": false,
"message": "Username is already taken"
}
{
"success": false,
"message": "Email is already taken"
}
{
"success": false,
"message": "Bad Request",
"data": {
"lastName": "Lastname must not be blank",
"firstName": "Firstname must not be blank",
"password": "Password minimum length 6 characters and maximum 100 characters",
"email": "Email must not be blank",
"username": "Username must not be blank"
}
}
{
"success": true,
"message": "User updated successfully",
"data": {
"id": 3,
"firstName": "Albert update",
"lastName": "Einstein",
"username": "albert12",
"password": "$2y$10$WyyBoSYn/5usw61dNi8ZguVczhyStl483xSBsvEO.JmYX9PuGWh1C",
"email": "alberteins@gmail.com",
"roles": [
{
"createdAt": "2022-06-09T12:07:03.763821Z",
"updatedAt": "2022-06-09T12:07:03.763821Z",
"id": 4,
"name": "USER"
}
]
}
}
{
"success": false,
"message": "You don't have permission to update profile of: bayu_bagaswara"
}
{
"success": true,
"message": "Successfully added role to user: albert"
}
{
"success": false,
"message": "Access Denied. You don't have permission to access this resource"
}
{
"success": true,
"message": "You successfully deleted profile of: budi_anggara"
}
{
"success": false,
"message": "Access Denied. You don't have permission to access this resource"
}
{
"success": true,
"message": "You took ADMIN role from user: albert"
}
{
"name": "Product A",
"price": 1000000,
"quantity": 10,
"description": "Product A description"
}
{
"success": true,
"message": "Product was created successfully",
"data": {
"id": "92bf82e3-6ad8-49a8-b161-4644004c27eb",
"name": "Product A",
"price": 100000,
"quantity": 55,
"description": "Product A description",
"createdBy": "bayu@gmail.com",
"createdAt": "2022-06-09T13:37:26.245322200Z"
}
}
{
"success": false,
"message": "Bad Request",
"data": {
"price": "Price must be greater than or equal to 1",
"name": "Name must not be blank",
"description": "Description length minimum must be 10 characters"
}
}
{
"name": "Product A",
"price": 500000,
"quantity": 50,
"description": "Product A description"
}
{
"success": true,
"message": "Product updated successfully",
"data": {
"id": "92bf82e3-6ad8-49a8-b161-4644004c27eb",
"name": "Product A update",
"price": 55000000,
"quantity": 123,
"description": "Product A description",
"createdBy": "albert@gmail.com",
"createdAt": "2022-06-09T13:37:26.245322Z"
}
}
{
"success": true,
"message": "Product deleted successfully",
"data": null
}
{
"success": false,
"message": "Access Denied. You don't have permission to access this resource"
}
{
"success": true,
"message": "Product successfully retrieved based on id",
"data": {
"id": "macbook-m1-2020",
"name": "Apple MacBook Pro M1 2020",
"price": 19140000.00,
"quantity": 35,
"description": "This is Apple MacBook Pro M1 2020 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:06.311620Z"
}
}
{
"success": true,
"message": "All products successfully retrieved",
"data": {
"products": [
{
"id": "acer-aspire-3",
"name": "Acer Aspire 3 a314-32",
"price": 4937500.00,
"quantity": 50,
"description": "This is Acer Aspire 3 a314-32 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:35.893792Z"
},
{
"id": "acer-aspire-5",
"name": "Acer Aspire 5 A514",
"price": 8750000.00,
"quantity": 35,
"description": "This is Acer Aspire 5 A514 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:35.893792Z"
},
{
"id": "acer-aspire-e5",
"name": "Acer Aspire E5-475G",
"price": 6100000.00,
"quantity": 37,
"description": "This is Acer Aspire E5-475G description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:35.893792Z"
},
{
"id": "acer-nitro-5",
"name": "Acer Nitro 5",
"price": 10701000.00,
"quantity": 30,
"description": "This is Acer Nitro 5 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:35.893792Z"
},
{
"id": "hp-envy-x360",
"name": "HP Envy X360",
"price": 10149000.00,
"quantity": 8,
"description": "This is HP Envy X360 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:41.776439Z"
},
{
"id": "hp-pavilion-x360",
"name": "HP Pavilion X360",
"price": 7599000.00,
"quantity": 5,
"description": "This is HP Pavilion X360 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:41.776439Z"
},
{
"id": "lenovo-legion-5",
"name": "Lenovo Legion 5 Pro",
"price": 18199000.00,
"quantity": 27,
"description": "This is Lenovo Legion 5 Pro description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:26.958637Z"
},
{
"id": "lenovo-thinkpad-t420",
"name": "Lenovo ThinkPad T420",
"price": 16999000.00,
"quantity": 17,
"description": "This is Lenovo ThinkPad T420 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:26.958637Z"
},
{
"id": "lenovo-thinkpad-t430",
"name": "Lenovo ThinkPad T430",
"price": 6279000.00,
"quantity": 28,
"description": "This is Lenovo ThinkPad T430 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:26.958637Z"
},
{
"id": "lenovo-thinkpad-x260",
"name": "Lenovo ThinkPad X260",
"price": 15400000.00,
"quantity": 24,
"description": "This is Lenovo ThinkPad X260 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:26.958637Z"
}
],
"pageNo": 0,
"pageSize": 10,
"totalElements": 14,
"totalPages": 2,
"last": false
}
}
{
"success": true,
"message": "All products successfully retrieved",
"data": [
{
"id": "macbook-air-m1-2020",
"name": "Apple MacBook Air M1 2020",
"price": 12950000.00,
"quantity": 24,
"description": "This is Apple MacBook Air M1 2020 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:06.311620Z"
},
{
"id": "macbook-m1-2020",
"name": "Apple MacBook Pro M1 2020",
"price": 19140000.00,
"quantity": 35,
"description": "This is Apple MacBook Pro M1 2020 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:06.311620Z"
},
{
"id": "macbook-air-2019",
"name": "Apple MacBook Air 2019",
"price": 13490000.00,
"quantity": 35,
"description": "This is Apple MacBook Air 2019 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:06.311620Z"
},
{
"id": "macbook-pro-14-2021",
"name": "Apple MacBook Pro 14-inch 2021",
"price": 33390000.00,
"quantity": 20,
"description": "This is Apple MacBook Pro 14-inch 2021 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:06.311620Z"
}
]
}
{
"success": true,
"message": "All products successfully retrieved",
"data": [
{
"id": "macbook-air-m1-2020",
"name": "Apple MacBook Air M1 2020",
"price": 12950000.00,
"quantity": 24,
"description": "This is Apple MacBook Air M1 2020 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:06.311620Z"
},
{
"id": "macbook-air-2019",
"name": "Apple MacBook Air 2019",
"price": 13490000.00,
"quantity": 35,
"description": "This is Apple MacBook Air 2019 description",
"createdBy": "User",
"createdAt": "2022-06-09T13:31:06.311620Z"
}
]
}