Documenting, restructure and expand API
This commit is contained in:
684
README.md
684
README.md
@@ -6,7 +6,685 @@ The most hackable Web Shop!
|
|||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
## Internal structure
|
## Database
|
||||||
|
|
||||||
### Database
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
## Backend API endpoints
|
||||||
|
|
||||||
|
The application host it's data in a SQLite database. The access is managed by an [ExpressJs](https://expressjs.com/) server which offers many REST-API endpoints for the frontend. The REST-API server runs on port 3000.
|
||||||
|
|
||||||
|
### `/api`
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #70AFFD; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #70AFFD; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">Server check</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Check if server is available
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>GET /api</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Parameter</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #70AFFD; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #70AFFD; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">Database reset</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Delete and refill the database with example values
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>GET /api/resetdatabase</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Parameter</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### `/categories`
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #70AFFD; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #70AFFD; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">All categories</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Get all categories
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>GET /categories</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Parameter</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h4>Example Response</h4>
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"name": "Electronic",
|
||||||
|
"icon": "mdi-chip",
|
||||||
|
"createdAt": "2024-09-13T07:51:40.118Z",
|
||||||
|
"updatedAt": "2024-09-13T07:51:40.118Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Sports",
|
||||||
|
"icon": "mdi-soccer",
|
||||||
|
"createdAt": "2024-09-13T07:51:40.118Z",
|
||||||
|
"updatedAt": "2024-09-13T07:51:40.118Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #69CA92; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #69CA92; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">Add new category</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Add a new category
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>POST /categories</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Body Parameters</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>name</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Name of the category</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>icon</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Material Design Icon</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #EB5246; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #EB5246; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">Delete category</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Delete a category by it's id
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>DELETE /categories/:id</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Parameter</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>id</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Database ID of CategoryModel</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### `/products`
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #70AFFD; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #70AFFD; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">All products</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Get all products
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>GET /products</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Parameter</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h4>Example Response</h4>
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"brand": "Lenovo",
|
||||||
|
"name": "Thinkpad T14",
|
||||||
|
"categoryId": 0,
|
||||||
|
"price": 799.99,
|
||||||
|
"discount": 10,
|
||||||
|
"rating": 4.6,
|
||||||
|
"imageUrl": "thinkpad-t14s.jpg",
|
||||||
|
"description": "Die stabile Arbeitsmaschine. Mit AMD Ryzen 7 89029U, 128 GB RAM und 8 TB M.2 SSD!",
|
||||||
|
"createdAt": "2024-09-13T07:51:40.119Z",
|
||||||
|
"updatedAt": "2024-09-13T07:51:40.119Z",
|
||||||
|
"category": {
|
||||||
|
"id": 0,
|
||||||
|
"name": "Electronic",
|
||||||
|
"icon": "mdi-chip",
|
||||||
|
"createdAt": "2024-09-13T07:51:40.118Z",
|
||||||
|
"updatedAt": "2024-09-13T07:51:40.118Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #70AFFD; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #70AFFD; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">Request one product</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Get a specific product by it's id
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>GET /products/:id</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Parameter</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>id</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>ID of the product in the database table</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h4>Example Response</h4>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"brand": "Lenovo",
|
||||||
|
"name": "Thinkpad T14",
|
||||||
|
"categoryId": 0,
|
||||||
|
"price": 799.99,
|
||||||
|
"discount": 10,
|
||||||
|
"rating": 4.6,
|
||||||
|
"imageUrl": "thinkpad-t14s.jpg",
|
||||||
|
"description": "Die stabile Arbeitsmaschine. Mit AMD Ryzen 7 89029U, 128 GB RAM und 8 TB M.2 SSD!",
|
||||||
|
"createdAt": "2024-09-13T07:51:40.119Z",
|
||||||
|
"updatedAt": "2024-09-13T07:51:40.119Z",
|
||||||
|
"category": {
|
||||||
|
"id": 0,
|
||||||
|
"name": "Electronic",
|
||||||
|
"icon": "mdi-chip",
|
||||||
|
"createdAt": "2024-09-13T07:51:40.118Z",
|
||||||
|
"updatedAt": "2024-09-13T07:51:40.118Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #69CA92; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #69CA92; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">Add new product</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Add a new product to the database
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>POST /products</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Body Parameters</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>brand</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Brand of the product</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>name</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Name of the product</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>description</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Description of the product</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>categoryId</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>ID of a Category from database</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>price</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Name of the product</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>discount</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Procentual discount, 0 to 100</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>rating</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Product rating from 1 to 5</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>imageUrl</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Name of the uploaded image file</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #EB5246; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #EB5246; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">Delete product</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Delete a product by it's id
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>DELETE /products/:id</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Parameter</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>id</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Database ID of ProductModel</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
### `/orders`
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #70AFFD; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #70AFFD; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">Request orders of user</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Get all orders from a user
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>GET /orders/:id</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Parameter</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>id</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>ID of the user in the database table</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h4>Example Response</h4>
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"accountId": 3,
|
||||||
|
"totalPrice": 7.99,
|
||||||
|
"shippingProgress": 5,
|
||||||
|
"createdAt": "2024-09-09T12:24:24.225Z",
|
||||||
|
"updatedAt": "2024-09-13T07:51:40.120Z",
|
||||||
|
"orderItem": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"orderId": 1,
|
||||||
|
"quantity": 1,
|
||||||
|
"productId": 6,
|
||||||
|
"createdAt": "2024-09-13T07:51:40.120Z",
|
||||||
|
"updatedAt": "2024-09-13T07:51:40.120Z",
|
||||||
|
"product": {
|
||||||
|
"id": 6,
|
||||||
|
"brand": "Aldous Huxley",
|
||||||
|
"name": "Brave New World",
|
||||||
|
"categoryId": 3,
|
||||||
|
"price": 7.99,
|
||||||
|
"discount": 0,
|
||||||
|
"rating": 4.4,
|
||||||
|
"imageUrl": "brave-new-world.jpg",
|
||||||
|
"description": "Brave New World beschreibt eine genormte Gesellschaft, in der Föten genetisch manipuliert und Menschen konditioniert werden. Ziel des Staates ist Zufriedenheit und Stabilität, und dies wird durch Gleichheit, Drogen und Propaganda erreicht. Gott und Religion...",
|
||||||
|
"createdAt": "2024-09-13T07:51:40.119Z",
|
||||||
|
"updatedAt": "2024-09-13T07:51:40.119Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #69CA92; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #69CA92; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">Place a new order</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Place a new order to the database
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>POST /orders</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Query Parameters</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>accountId</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>ID of account who created this order</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>shippingProgress</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Progress of shipping, 1 to 5</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>orderItem</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>List of ordered items (objects). Needs parameter <code>quantity</code> and <code>productId</code></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### `/accounts`
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #70AFFD; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #70AFFD; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">Login user</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Login process for user
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>GET /accounts</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Query Parameters</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>username</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Name of user account</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>password</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Password of user account</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h4>Example Response</h4>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"loginSuccessful": true,
|
||||||
|
"userId": 3,
|
||||||
|
"message": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #69CA92; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #69CA92; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">Add an user</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Place a new account to the database
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>POST /accounts</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Body Parameters</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>username</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Login username</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>password</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Login password</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>firstName</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>First name of user</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>lastName</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Last name of user</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>street</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Street where the user lives</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>houseNumber</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>House number of user</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>postalCode</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Postal code of users home</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>city</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Name of users city</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details style="border: solid; border-radius: 10px; border-color: #F3A63D; margin-bottom: 20px">
|
||||||
|
<summary style="background-color: #F3A63D; color: #FFFFFF; border: none; padding: 10px 20px; border-radius: 6px 6px 0px 0px; font-weight: bold">Update account</summary>
|
||||||
|
<div style="padding: 0px 20px 10px">
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
Updating values of an existing account
|
||||||
|
|
||||||
|
<h4>Request</h4>
|
||||||
|
<code>PATCH /account</code>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<header>
|
||||||
|
<th>Body Parameters</th>
|
||||||
|
<th>Required?</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</header>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>id</code></td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Identifier of dataset</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>username</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Login username</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>password</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Login password</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>firstName</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>First name of user</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>lastName</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Last name of user</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>street</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Street where the user lives</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>houseNumber</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>House number of user</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>postalCode</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Postal code of users home</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>city</code></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>Name of users city</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,19 +11,19 @@ export class Account extends Model {
|
|||||||
password: string
|
password: string
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
firstName: string
|
firstName: string = ""
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
lastName: string
|
lastName: string = ""
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
street: string
|
street: string = ""
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
houseNumber: number
|
houseNumber: number = 0
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
postalCode: number
|
postalCode: number = 0
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
city: string
|
city: string
|
||||||
|
|||||||
@@ -4,57 +4,82 @@ import { validateString } from "../scripts/validateHelper";
|
|||||||
|
|
||||||
export const account = Router()
|
export const account = Router()
|
||||||
|
|
||||||
// Request all user from the database
|
// Login user
|
||||||
account.get("/", (req: Request, res: Response, next: NextFunction) => {
|
account.get("/", (req: Request, res: Response) => {
|
||||||
Account.findAll()
|
Account.findOne({
|
||||||
.then(accounts => {
|
raw: true,
|
||||||
res.json(accounts)
|
where: { username: req.body.username }
|
||||||
})
|
})
|
||||||
.catch(next)
|
.then(account => {
|
||||||
|
if (account != null) {
|
||||||
|
if (account.password == req.body.password) {
|
||||||
|
// Status: 200 Created
|
||||||
|
res.status(201).json({
|
||||||
|
loginSuccessful: true,
|
||||||
|
userId: account.id,
|
||||||
|
message: ""
|
||||||
|
}).send()
|
||||||
|
} else {
|
||||||
|
// Status: 401 Unauthorized
|
||||||
|
res.status(401).json({
|
||||||
|
loginSuccessful: false,
|
||||||
|
userId: -1,
|
||||||
|
message: "Wrong password"
|
||||||
|
}).send()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Status: 401 Unauthorized
|
||||||
|
res.status(401).json({
|
||||||
|
loginSuccessful: false,
|
||||||
|
userId: -1,
|
||||||
|
message: "Username doesn't exists"
|
||||||
|
}).send()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Creating a new user
|
// Creating a new user
|
||||||
account.post("/register", (req: Request, res: Response, next: NextFunction) => {
|
account.post("/", (req: Request, res: Response) => {
|
||||||
if (!validateString(req.body.username, 4))
|
if (!validateString(req.body.username, 4))
|
||||||
{
|
{
|
||||||
// Status: 400 Bad request
|
// Status: 400 Bad request
|
||||||
res.status(400).send({ error: "Username too short!" })
|
res.status(400).json({
|
||||||
|
message: "Username too short!"
|
||||||
|
}).send()
|
||||||
}
|
}
|
||||||
else if (!validateString(req.body.password, 8))
|
else if (!validateString(req.body.password, 8))
|
||||||
{
|
{
|
||||||
// Status: 400 Bad request
|
// Status: 400 Bad request
|
||||||
res.status(400).send({ error: "Password too short!" })
|
res.status(400).json({
|
||||||
|
message: "Password too short!"
|
||||||
|
}).send()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Account.create(req.body)
|
Account.create(req.body)
|
||||||
.then(account => {
|
.then(account => {
|
||||||
res.json(account)
|
res.status(200).json(account).send()
|
||||||
|
|
||||||
// Status: 200 OK
|
|
||||||
res.status(200).send()
|
|
||||||
}).catch(reason => {
|
}).catch(reason => {
|
||||||
// Status: 400 Bad request
|
// Status: 400 Bad request
|
||||||
res.status(400).send({ error: reason })
|
res.status(400).json({
|
||||||
|
message: reason
|
||||||
|
}).send()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
account.post("/login", (req: Request, res: Response, next: NextFunction) => {
|
account.patch("/", (req: Request, res: Response) => {
|
||||||
Account.findOne({ raw: true, where: { username: req.body.username }})
|
Account.update(req.body,
|
||||||
|
{
|
||||||
|
where: { id: req.body.id }
|
||||||
|
})
|
||||||
.then(account => {
|
.then(account => {
|
||||||
if (account != null) {
|
res.status(200).send()
|
||||||
if (account.password == req.body.password) {
|
})
|
||||||
// Status: 200 OK
|
.catch(error => {
|
||||||
res.status(200).send({ userAccountId: account.id })
|
res.status(400).json({
|
||||||
} else {
|
message: error
|
||||||
// Status: 401 Unauthorized
|
}).send()
|
||||||
res.status(401).send()
|
})
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Status: 401 Unauthorized
|
|
||||||
res.status(401).send()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
@@ -4,7 +4,7 @@ import { deleteAllTables, prepopulateDatabase } from '../scripts/databaseHelper'
|
|||||||
export const api = Router()
|
export const api = Router()
|
||||||
|
|
||||||
api.get("/", (req: Request, res: Response, next: NextFunction) => {
|
api.get("/", (req: Request, res: Response, next: NextFunction) => {
|
||||||
res.send("Hello World!")
|
res.status(200).send()
|
||||||
})
|
})
|
||||||
|
|
||||||
api.get("/resetdatabase", (req: Request, res: Response, next: NextFunction) => {
|
api.get("/resetdatabase", (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
|||||||
@@ -3,19 +3,41 @@ import { Category } from "../models/category.model";
|
|||||||
|
|
||||||
export const category = Router()
|
export const category = Router()
|
||||||
|
|
||||||
|
// Get all categories
|
||||||
category.get("/", (req: Request, res: Response, next: NextFunction) => {
|
category.get("/", (req: Request, res: Response, next: NextFunction) => {
|
||||||
Category.findAll()
|
Category.findAll()
|
||||||
.then(categories => {
|
.then(categories => {
|
||||||
res.json(categories)
|
res.status(200).json(categories).send()
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
res.status(400).json({ message: error }).send()
|
||||||
})
|
})
|
||||||
.catch(next)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Add new category
|
||||||
category.post("/", (req: Request, res: Response, next: NextFunction) => {
|
category.post("/", (req: Request, res: Response, next: NextFunction) => {
|
||||||
try {
|
Category.create(req.body)
|
||||||
const category = Category.create(req.body)
|
.then(category => {
|
||||||
res.status(201).json(category)
|
res.status(201).send()
|
||||||
} catch (e) {
|
})
|
||||||
next(e)
|
.catch(error => {
|
||||||
}
|
res.status(400).json({
|
||||||
|
message: error
|
||||||
|
}).send()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Delete category
|
||||||
|
category.delete("/:id", (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
Category.destroy({
|
||||||
|
where: { id: req.params.id }
|
||||||
|
})
|
||||||
|
.then(category => {
|
||||||
|
res.status(200).send()
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
res.status(406).json({
|
||||||
|
message: error
|
||||||
|
}).send()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
@@ -1,18 +1,53 @@
|
|||||||
import { Router, Request, Response, NextFunction } from "express";
|
import { Router, Request, Response } from "express";
|
||||||
import { Order } from "../models/order.model";
|
import { Order } from "../models/order.model";
|
||||||
import { Product } from "../models/product.model";
|
import { Product } from "../models/product.model";
|
||||||
import { OrderItem } from "../models/orderItem.model";
|
import { OrderItem } from "../models/orderItem.model";
|
||||||
|
|
||||||
export const order = Router()
|
export const order = Router()
|
||||||
|
|
||||||
order.get("/", (req: Request, res: Response, next: NextFunction) => {
|
// Get all orders of one account by it's user id
|
||||||
|
order.get("/:id", (req: Request, res: Response) => {
|
||||||
Order.findAll({
|
Order.findAll({
|
||||||
where: { accountId: req.query.accountId },
|
where: { accountId: req.params.id },
|
||||||
include: [
|
include: [
|
||||||
{ model: OrderItem, include: [ Product ] }
|
{ model: OrderItem, include: [ Product ] }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
.then(orders => {
|
.then(orders => {
|
||||||
res.send(orders)
|
res.status(200).send(orders)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Place a new order
|
||||||
|
order.post("/", (req: Request, res: Response) => {
|
||||||
|
let totalPrice = 0
|
||||||
|
|
||||||
|
Order.create(req.body)
|
||||||
|
.then(order => {
|
||||||
|
|
||||||
|
for (let orderItem of req.body.orderItem) {
|
||||||
|
OrderItem.create({
|
||||||
|
"orderId": order.id,
|
||||||
|
"quantity": orderItem.quantity,
|
||||||
|
"productId": orderItem.productId
|
||||||
|
})
|
||||||
|
|
||||||
|
Product.findOne({
|
||||||
|
raw: true,
|
||||||
|
where: { id: orderItem.productId }
|
||||||
|
})
|
||||||
|
.then(product => {
|
||||||
|
totalPrice += product.price * orderItem.quantity
|
||||||
|
|
||||||
|
Order.update({
|
||||||
|
totalPrice: totalPrice
|
||||||
|
}, {
|
||||||
|
where: { id: order.id },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Created
|
||||||
|
res.status(201).send()
|
||||||
|
})
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { Product } from "../models/product.model";
|
|
||||||
import { OrderItem } from "../models/orderItem.model";
|
|
||||||
import { Router, Request, Response, NextFunction } from "express";
|
|
||||||
|
|
||||||
export const orderItem = Router()
|
|
||||||
|
|
||||||
@@ -1,19 +1,51 @@
|
|||||||
import { Router, Request, Response, NextFunction } from "express";
|
import { Router, Request, Response, NextFunction } from "express";
|
||||||
import { Product } from "../models/product.model";
|
import { Product } from "../models/product.model";
|
||||||
|
import { Category } from "../models/category.model";
|
||||||
|
|
||||||
export const product = Router()
|
export const product = Router()
|
||||||
|
|
||||||
product.get("/", (req: Request, res: Response, next: NextFunction) => {
|
// Get all products
|
||||||
Product.findAll()
|
product.get("/", (req: Request, res: Response) => {
|
||||||
|
Product.findAll({
|
||||||
|
include: [ Category ]
|
||||||
|
})
|
||||||
.then(products => {
|
.then(products => {
|
||||||
res.json(products)
|
res.status(200).json(products)
|
||||||
})
|
})
|
||||||
.catch(next)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
product.get("/:productId", (req: Request, res: Response, next: NextFunction) => {
|
// Get a product by id
|
||||||
|
product.get("/:productId", (req: Request, res: Response) => {
|
||||||
Product.findByPk(req.params.productId)
|
Product.findByPk(req.params.productId)
|
||||||
.then(product => {
|
.then(product => {
|
||||||
res.json(product)
|
res.status(200).json(product)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add a new product
|
||||||
|
product.post("/", (req: Request, res: Response) => {
|
||||||
|
Product.create(req.body)
|
||||||
|
.then(product => {
|
||||||
|
res.status(200).send()
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
res.status(400).json({
|
||||||
|
message: error
|
||||||
|
}).send()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Remove a product
|
||||||
|
product.delete("/:id", (req: Request, res: Response) => {
|
||||||
|
Product.destroy({
|
||||||
|
where: { id: req.params.id }
|
||||||
|
})
|
||||||
|
.then(product => {
|
||||||
|
res.status(200).send()
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
res.status(406).json({
|
||||||
|
message: error
|
||||||
|
}).send()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -7,7 +7,6 @@ import { category } from './routes/category.routes'
|
|||||||
import { product } from './routes/product.routes'
|
import { product } from './routes/product.routes'
|
||||||
import { order } from './routes/order.routes'
|
import { order } from './routes/order.routes'
|
||||||
import { account } from './routes/account.routes'
|
import { account } from './routes/account.routes'
|
||||||
import { orderItem } from './routes/orderItem.routes'
|
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
const port = 3000
|
const port = 3000
|
||||||
@@ -27,7 +26,6 @@ app.use("/categories", category)
|
|||||||
app.use("/products", product)
|
app.use("/products", product)
|
||||||
app.use("/orders", order)
|
app.use("/orders", order)
|
||||||
app.use("/accounts", account)
|
app.use("/accounts", account)
|
||||||
app.use("/orderItems", orderItem)
|
|
||||||
|
|
||||||
// Static files
|
// Static files
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export class CategoryModel {
|
export class CategoryModel {
|
||||||
id: number = -1
|
id: number = -1
|
||||||
name: string = "All"
|
name: string
|
||||||
icon: string = "mdi-all-inclusive"
|
icon: string
|
||||||
createdAt: string = ""
|
createdAt: string = ""
|
||||||
updatedAt: string = ""
|
updatedAt: string = ""
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
export class ProductModel {
|
export class ProductModel {
|
||||||
id: number = -1
|
id: number = -1
|
||||||
brand: string = ""
|
brand: string
|
||||||
name: string = ""
|
name: string
|
||||||
description: string = ""
|
description: string = ""
|
||||||
categoryId: number = 0
|
categoryId: number
|
||||||
price: number = 0
|
price: number = 0
|
||||||
discount: number = 0
|
discount: number = 0
|
||||||
rating: number = 1
|
rating: number = 1
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
"product": {
|
"product": {
|
||||||
"product": "Produkt",
|
"product": "Produkt",
|
||||||
"products": "Produkte",
|
"products": "Produkte",
|
||||||
"productName": "Product Name",
|
"productName": "Produkt Name",
|
||||||
"brand": "Marke",
|
"brand": "Marke",
|
||||||
"productPrice": "Einzelpreis",
|
"productPrice": "Einzelpreis",
|
||||||
"category": "Kategorie"
|
"category": "Kategorie"
|
||||||
|
|||||||
@@ -1,6 +1,25 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
|
||||||
|
axios.get("http://127.0.0.1:3000/")
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
Account Page
|
<v-container>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<v-card>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<v-text-field :label="$t('account.username')" disabled />
|
||||||
|
</v-col>
|
||||||
|
<v-col>
|
||||||
|
<v-text-field />
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
Reference in New Issue
Block a user