This project is a backend RESTful API of an online store application.
- Table content
- Description
- UML diagrams
- Database
- API: Overall info
- API: Reference
- API: Endpoints
- API: Error Handling
ID | Description |
---|---|
F1 | Show multiple product |
F2 | Show closely one product |
F3 | Add and remove a product from the basket |
F4 | Show the basket |
F5 | Checkout products in the basket |
F6 | Authentication user |
Version | Feature to implement |
---|---|
v1.0 | F1 to F6 |
Back-end |
---|
Nest.js |
TypeScript |
TypeORM |
MySQL |
Docker |
-
Database Foreign Key Actions:
Table Foreign Key On Delete On Update Card user_id CASCADE
CASCADE
Basket user_id CASCADE
CASCADE
Basket product_id CASCADE
CASCADE
ProductPicture product_id CASCADE
CASCADE
-
ER Diagram:
- I used
one-to-one
links for clarity
- I used
- Paradigm:
REST API
- Data structures and types:
JSON
- Authentication:
JWT
- Authorization: Each user has access to their own data only
basket
:
card
:- Description: Payment card details
- type:
object
- Properties:
firstname
:- Description: Card's firstname
- type:
string
- required:
True
lastname
:- Description: Card's lastname
- type:
string
- required:
True
digit
:- Description: Card's number
- Constrains:
- Can be managed as a string because do not need the numeric value
- Constrains:
- type:
string
- required:
True
- Description: Card's number
criteria
:- Description: Value on which to base the sorting
sort
- type:
enum
- value: See the usage
- Description: Value on which to base the sorting
limit
:- Description: The maximum number of requested resources returned
- type:
int
picture
:- Description: Link (URL or path) to access picture
- type:
string
product
:- Description: A product
- type:
object
- properties:
products
:- Description: List of
product
- type:
list
- Description: List of
page
:- Description: Indicate the position of the page to get in pagination
- Constraint:
- The position of the first page is
0
- If not given then the default page position if
0
- If the page position is outside the number of page available then the last page is returned
- The position of the first page is
- type:
int
price
:- Description: A price
- type:
object
- Properties:
value
: Price's value- type:
float
- type:
symbol
: Price's currency symbol- type:
string
- type:
sort
:- Description: To order the response
- type:
enum
- value:
asc
|desc
user
:- Description: An user
- type:
object
- properties:
id
:- Description: user's identifier
- type:
string
- required:
False
email
:- Description: user's email
- type:
string
password
:- Description: user's password
- type:
string
-
Description: Create a new user
-
Request:
-
Path:
/api/v1/user
-
Method:
POST
-
Parameter:
-
Example:
POST /api/v1/user
{ "email": "[email protected]", "password": "secret1234" }
-
-
Response:
-
Body:
id
:- Description: user's id
- type:
string
email
:- Description: user's email
- type:
string
-
Example:
{ "id": "7d6aa302-8f2c-4c10-8a37-a821181d308e", "email": "[email protected]" }
-
-
Description: Log in an user
-
Request:
-
Path:
/api/v1/user/login
-
Method:
POST
-
Parameter:
-
Example:
POST /api/v1/user/login
{ "email": "[email protected]", "password": "secret1234" }
-
-
Response:
-
Body:
id
:- Description: user's id
- type:
string
email
:- Description: user's email.
- type:
string
token
:- Description: user's JSON Web Token.
- type:
string
-
Example:
{ "id": "8f86825e-3324-4f4e-b6c1-ec59b586eba3", "email": "[email protected]", "token": "jwt-token" }
-
-
Description: Delete an user
-
Request:
-
Path:
/api/v1/user
-
Method:
DELETE
-
Parameter:
-
Example:
POST /api/v1/user/login
{ "email": "[email protected]", "password": "secret1234" }
-
-
Response:
-
Body:
isSuccess
:- Description: True if deletion succeed else will raise an error.
- type:
boolean
-
Example:
{ "isSuccess": true }
-
-
Description: To request list of product
-
Request:
-
Path:
/api/v1/products
-
Method:
GET
-
Parameter:
-
Example:
GET /api/v1/products?sort=desc&criteria=price&limit=15&page=3
-
-
Response:
-
Body:
-
Example:
{ "products": [ { "id": "abcd123", "name": "amazing product a", "pictures": [ "/api/v1/picture/1", "/api/v1/picture/2" ], "price": { "value": 14.99, "symbol": "$" } }, { "id": "efgh456", "name": "amazing product b", "pictures": [ "/api/v1/picture/3", "/api/v1/picture/4" ], "price": { "value": 7.99, "symbol": "$" } } ], "pagination": [ "/api/v1/products?sort=desc&criteria=price&limit=15&page=0", "/api/v1/products?sort=desc&criteria=price&limit=15&page=1", "/api/v1/products?sort=desc&criteria=price&limit=15&page=2", "/api/v1/products?sort=desc&criteria=price&limit=15&page=4", "/api/v1/products?sort=desc&criteria=price&limit=15&page=5" ] }
-
-
Description: To request one product
-
Request:
-
Path:
/api/v1/products/:product_id
:product_id
: The identifier of a product
-
Method:
GET
-
Parameter: None
-
Example:
GET /api/v1/products/abcd123
-
-
Response:
-
Body:
-
Example:
{ "id": "abcd123", "name": "amazing product a", "pictures": [ "/api/v1/picture/1", "/api/v1/picture/2" ], "price": { "value": 14.99, "symbol": "$" } }
-
-
Description: To get an user's basket
-
Request:
-
Path:
/api/v1/basket
-
Method:
GET
-
Parameter: None
-
Example:
GET /api/v1/basket
-
-
Response:
-
Body:
-
Example:
[ { "id": "ijkl789", "name": "amazing product c", "pictures": [ "/api/v1/picture/5", "/api/v1/picture/6" ], "price": { "value": 14.99, "symbol": "$" }, "quantity": 3 }, { "id": "abcd123", "name": "amazing product a", "pictures": [ "/api/v1/picture/1", "/api/v1/picture/2" ], "price": { "value": 18.07, "symbol": "$" }, "quantity": 2 }, { "id": "efgh456", "name": "amazing product b", "pictures": [ "/api/v1/picture/3", "/api/v1/picture/4" ], "price": { "value": 2.59, "symbol": "$" }, "quantity": 1 } ]
-
-
Description: To add products in the basket
-
Request:
-
Response:
-
Body: None
-
Example:
// Empty body
-
-
Description: To update the products in the basket
-
Request:
-
Path:
/api/v1/basket
-
Method:
PATCH
-
Body:
-
Example:
PATCH /api/v1/basket
[ { "id": "ijkl789", "quantity": 2 }, { "id": "efgh456", "quantity": 1 }, { "id": "abcd123", "quantity": 3 } ]
-
-
Response:
-
Body: None
-
Example:
// Empty body
-
-
Description: To remove products from the basket
-
Request:
-
Path:
/api/v1/basket
-
Method:
DELETE
-
Body:
- Description: List of
product
's identifier - type:
list
- Description: List of
-
Example:
DELETE /api/v1/basket
[ "ijkl789", "efgh456", "abcd123" ]
-
-
Response:
-
Body: None
-
Example:
// Empty body
-
-
Description: To checkout the basket
-
Request:
-
Path:
/api/v1/checkout
-
Method:
POST
-
Parameter:
card
:
-
Example:
POST /api/v1/checkout
{ "card": { "firstname": "john", "lastname": "doe", "digit": "0123456789101112" } }
-
-
Response:
-
Body: None
-
Example:
// Empty body
-
-
Follow RFC7807 rules
-
Parameters (
RFC7807
):type
: A URI reference that identifies the problem type.title
: A short, human-readable summary of the problem type.status
: The HTTP status codedetail
: A human-readable explanation specific to this occurrence of the problem.instance
: A URI reference that identifies the specific occurrence of the problem.- In other words, the URI used to perform the request
-
Parameters (mine):
code
: The code system of the error.error
: Where API can place all the information related to the error.
-
Example:
{ "type": "https://example.com/doc/unknown-product", "title": "Product not found", "status": 400, "detail": "Product with id '123abc' do not exist", "instance": "/api/v1/product/123abc", "code": 2300, "error": {} }
Category | HTTP Range | System Range | Description |
---|---|---|---|
System error | 500 | 1000 | Error from the server side |
Unavailable service | 500 | 1100 | Can't perform request due to a unavailable service |
Unknown service | 500 | 1200 | An undocumented error |
Client error | 400 | 2000 | Error from the client side |
Unauthorized access | 400 | 2100 | Unauthorized access to resource |
Malformed request | 400 | 2200 | Request don't respect data structure and/or type |
Invalid request | 400 | 2300 | Request's content is not valid |
Conflict state | 400 | 2400 | The current state don't allow the operation |
System Error Code | HTTP Status Code | Machine-Readable | Human-Readable |
---|---|---|---|