https://github.com/DaniDipp/W20-WebTechProject-Backend
This is the backend application for a Web Technologies project at the Alpen-Adria-University. The frontend has been written by my colleague and can be found here.
For the duration of the semester, I will be hosting this project on my server at https://webtech.danidipp.com/.
- Set up the Database
- Install Node.js
- Download the code as ZIP and unpack it or, using the git cli run
git clone https://github.com/DaniDipp/W20-WebTechProject-Backend.git
- Install the dependencies
npm install
- Start the server
npm start
Variable | Description | Default |
---|---|---|
JWT_SECRET |
The secret JWT will use to encrypt authentication tokens | "changeme" |
DB_HOST |
IP address or DNS of the database server | "localhost" |
DB_PORT |
Database server port number | 3306 |
DB_USER |
User to access database | "webtech-backend" |
DB_PASS |
User password | "changeme" |
DB_NAME |
Database to use | "webtech-backend" |
The server is running Node.js, using the following dependencies:
- bcrypt to securely hash and compare passwords
- cors for easily sending CORS headers
- express as web application framework
- jsonwebtoken to generate and check authentication tokens
- mariadb to communicate with the database
Because I already had a MariaDB database running on my server, I chose that over MySQL or PostgreSQL
You can find the SQL dump of the database with example data here.
Column | Type | Attributes |
---|---|---|
id | SMALLINT |
unsigned, primary, auto-increment |
name | VARCHAR(64) |
|
price | SMALLINT |
unsigned |
description | VARCHAR(256) |
null |
image | VARCHAR(64) |
null |
category_name | VARCHAR(32) |
foreign |
last_update | TIMESTAMP |
current timestamp on update |
Column | Type | Attributes |
---|---|---|
name | VARCHAR(32) |
primary |
last_update | TIMESTAMP |
current timestamp on update |
Column | Type | Attributes |
---|---|---|
VARCHAR(32) |
primary | |
password | CHAR(60) |
|
name | VARCHAR(32) |
|
address | VARCHAR(64) |
null |
phone | VARCHAR(256) |
null |
creditcard | VARCHAR(60) |
null |
last_update | TIMESTAMP |
current timestamp on update |
CHAR(60)
is used to save password hashes, because bcrypt hashes are always exactly 60 characters long.
Column | Type | Attributes |
---|---|---|
id | SMALLINT |
unsigned, primary, auto-increment |
time | TIMESTAMP |
|
status | VARCHAR(24) |
|
user_email | VARCHAR(32) |
foreign |
product_id | VARCHAR(64) |
null |
category_name | SMALLINT |
unsigned, foreign |
last_update | TIMESTAMP |
current timestamp on update |
Column | Type | Attributes |
---|---|---|
product_id | SMALLINT |
unsigned, primary, foreign |
user_email | VARCHAR(32) |
primary, foreign |
value | TINYINT |
unsigned |
text | VARCHAR(128) |
null |
last_update | TIMESTAMP |
current timestamp on update |
GET /products
: Returns all data about all products. (Could be a lot of data)
Authentication: none
Example:
curl --location --request GET 'https://webtech.danidipp.com/products/'
{
"status": "success",
"message": "Got products from DB",
"products": [
{
"id": 50,
"name": "Nice Dress",
"price": 2999,
"description": "Just a nice Dress.",
"image": "https://i.imgur.com/DouWP9o.png",
"category_name": "Apparels",
"average_rating": 2.5
},
...
]
}
GET /products/:id
: Returns all data about a specific product.
Authentication: none
Example:
curl --location --request GET 'https://webtech.danidipp.com/products/50'
{
"status": "success",
"message": "Got products from DB",
"product": {
"id": 50,
"name": "Nice Dress",
"price": 2999,
"description": "Just a nice Dress.",
"image": "https://i.imgur.com/DouWP9o.png",
"category_name": "Apparels",
"average_rating": 2.5
}
}
GET /products/search
: Returns products based on query parameters
Authentication: none
Optional Query Parameters:
name
case-insensitive, default:empty string
price_min
int, cents, default:0
price_max
int, cents, default:65535
description
case-insensitive, default:empty string
category
case-insensitive, comma-separated for union, default:empty string
Example:
curl --location --request GET 'https://webtech.danidipp.com/products/search?price_max=2000&description=blue'
{
"status": "success",
"message": "Got products from DB",
"products": [
{
"id": 51,
"name": "Jeans",
"price": 899,
"description": "It's jeans. They're blue.",
"image": "https://i.imgur.com/STdxvtX.jpg",
"category_name": "Apparels",
"average_rating": 2.5
}
]
}
GET /categories
: Returns list of all categories and number of items they include
Authentication: none
Example:
curl --location --request GET 'https://webtech.danidipp.com/categories'
{
"status": "success",
"message": "Got categories from DB",
"categories": [
{
"name": "Apparels",
"items": 5
},
...
]
}
GET /users
: Returns info of user
Authentication: Bearer token
Example:
curl --location --request GET 'https://webtech.danidipp.com/users' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTYxMDY0MjgzMywiZXhwIjoxNjEwNjUzNjMzfQ.Ngv2ahZl218S0VDxX-tcfsHbqQClYDqUhrJDhN2-5-U'
{
"status": "success",
"message": "Got user from DB",
"user": {
"email": "[email protected]",
"name": "Test User",
"address": "Example Street 01, 0000 Example City",
"phone": null,
"creditcard": null
}
}
POST /users
: Registers a new user and generates token
Token expires after 3 hours
Authentication: none
Required Body Parameters:
- name
- password
Example:
curl --location --request POST 'https://webtech.danidipp.com/users/' \
--header 'Content-Type: application/json' \
--data-raw '{
"name":"Test User",
"email":"[email protected]",
"password": "password123"
}'
{
"status": "success",
"message": "Added new user to DB",
"user": {
"email": "[email protected]",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTYxMDY0MjgzMywiZXhwIjoxNjEwNjUzNjMzfQ.Ngv2ahZl218S0VDxX-tcfsHbqQClYDqUhrJDhN2-5-U",
"name": "Test User"
}
}
POST /users/login
: Logs in an existing user and generates new token
Token expires after 3 hours
Authentication: none
Required Body Parameters:
- password
Example:
curl --location --request POST 'https://webtech.danidipp.com/users/login' \
--header 'Content-Type: application/json' \
--data-raw '{
"email":"[email protected]",
"password": "password123"
}'
{
"status": "success",
"message": "Added new user to DB",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTYxMDY0MjgzMywiZXhwIjoxNjEwNjUzNjMzfQ.Ngv2ahZl218S0VDxX-tcfsHbqQClYDqUhrJDhN2-5-U"
}
PATCH /users
: Updates user info
Authentication: Bearer token
Optional body parameters (at least one required):
- password
- name
- address
- phone
- creditcard
Example:
curl --location --request PATCH 'https://webtech.danidipp.com/users' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTYxMDY0MjgzMywiZXhwIjoxNjEwNjUzNjMzfQ.Ngv2ahZl218S0VDxX-tcfsHbqQClYDqUhrJDhN2-5-U' \
--header 'Content-Type: application/json' \
--data-raw '{
"address": "Example Street 01, 0000 Example City"
}'
{
"status": "success",
"message": "Updated user with email [email protected] in DB"
}
DELETE /users
: Deletes user
Authentication: Bearer token
Example:
curl --location --request DELETE 'https://webtech.danidipp.com/users' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTYxMDY0MjgzMywiZXhwIjoxNjEwNjUzNjMzfQ.Ngv2ahZl218S0VDxX-tcfsHbqQClYDqUhrJDhN2-5-U'
{
"status": "success",
"message": "Deleted user with email [email protected] from DB"
}
GET /orders
: Returns list of all orders of user
Authentication: Bearer token
Example:
curl --location --request GET 'https://webtech.danidipp.com/orders' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTYxMDY0MjgzMywiZXhwIjoxNjEwNjUzNjMzfQ.Ngv2ahZl218S0VDxX-tcfsHbqQClYDqUhrJDhN2-5-U'
{
"status": "success",
"message": "Got orders for user [email protected]",
"orders": [
{
"id": 7,
"time": "2021-01-14T02:39:00.000Z",
"status": "Waiting for Payment",
"product": {
"name": "Jeans",
"price": 899,
"description": "It's jeans. They're blue.",
"image": "https://i.imgur.com/STdxvtX.jpg",
"category": "Apparels",
"average_rating": 2.5
}
},
...
]
}
POST /orders
: Creates a new order
Authentication: Bearer token
Required body parameters:
- time (parsable by
new Date(time)
1) - status
- product_id
Example:
curl --location --request POST 'https://webtech.danidipp.com/orders' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTYxMDY0MjgzMywiZXhwIjoxNjEwNjUzNjMzfQ.Ngv2ahZl218S0VDxX-tcfsHbqQClYDqUhrJDhN2-5-U' \
--header 'Content-Type: application/json' \
--data-raw '{
"time": "2021-01-14T02:39:00Z",
"status": "Waiting for Payment",
"product_id": 51
}'
{
"status": "success",
"message": "Added new user to DB",
"order": {
"id": 7,
"time": "2021-01-14T02:39:00.000Z",
"status": "Waiting for Payment",
"product_id": 51
}
}
DELETE /orders/:id
: Deletes a specific order
Authentication: Bearer token
Example:
curl --location --request DELETE 'https://webtech.danidipp.com/orders/7' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTYxMDY0MjgzMywiZXhwIjoxNjEwNjUzNjMzfQ.Ngv2ahZl218S0VDxX-tcfsHbqQClYDqUhrJDhN2-5-U'
{
"status": "success",
"message": "Deleted order 7 from DB"
}
GET /ratings
: Returns all ratings of user
Authentication: Bearer token
Example:
curl --location --request GET 'https://webtech.danidipp.com/ratings' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTYxMDY0MjgzMywiZXhwIjoxNjEwNjUzNjMzfQ.Ngv2ahZl218S0VDxX-tcfsHbqQClYDqUhrJDhN2-5-U'
{
"status": "success",
"message": "Got ratings for user [email protected]",
"ratings": [
{
"value": 5,
"text": "Trousers 👍",
"product": {
"id": 51,
"name": "Jeans",
"price": "Jeans",
"description": "It's jeans. They're blue.",
"image": "https://i.imgur.com/STdxvtX.jpg",
"category": "Apparels",
"average_rating": 2.5
}
},
...
]
}
POST /ratings
: Creates new rating
Authentication: Bearer token
Required body parameters:
- product_id
- value
Optional body parameters:
- text
Example:
curl --location --request POST 'https://webtech.danidipp.com/ratings' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTYxMDY0MjgzMywiZXhwIjoxNjEwNjUzNjMzfQ.Ngv2ahZl218S0VDxX-tcfsHbqQClYDqUhrJDhN2-5-U' \
--header 'Content-Type: application/json' \
--data-raw '{
"product_id": "51",
"value": 5,
"text": "Trousers 👍"
}'
{
"status": "success",
"message": "Added new rating to DB",
"rating": {
"product_id": 51,
"user_email": "[email protected]",
"value": 5,
"text": "Trousers 👍"
}
}
GET /ratings/:product_id
: Returns all ratings of specific product
Authentication: none
Example:
curl --location --request POST 'https://webtech.danidipp.com/ratings/51'
{
"status": "success",
"message": "Got ratings for product 51",
"ratings": [
{
"value": 5,
"text": "Trousers 👍",
"user": {
"name": "Test User"
},
"product": {
"id": 51,
"name": "Jeans",
"price": "Jeans",
"description": "It's jeans. They're blue.",
"image": "https://i.imgur.com/STdxvtX.jpg",
"category": "Apparels",
"average_rating": 2.5
}
},
...
]
}
PATCH /ratings/:product_id
: Updates specific rating
Authorization: Bearer token
Example:
curl --location --request POST 'https://webtech.danidipp.com/ratings/51' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTYxMDY0MjgzMywiZXhwIjoxNjEwNjUzNjMzfQ.Ngv2ahZl218S0VDxX-tcfsHbqQClYDqUhrJDhN2-5-U' \
--header 'Content-Type: application/json' \
--data-raw '{
"value": 1,
"text": "too small for me"
}'
{
"status": "success",
"message": "Updated rating for product 51 by user [email protected] in DB"
}
DELETE /ratings/:product_id
: Deletes specific rating
Authentication: Bearer token
Example:
curl --location --request POST 'https://webtech.danidipp.com/ratings/51' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTYxMDY0MjgzMywiZXhwIjoxNjEwNjUzNjMzfQ.Ngv2ahZl218S0VDxX-tcfsHbqQClYDqUhrJDhN2-5-U'
{
"status": "success",
"message": "Removed rating for product 51 by user [email protected] in DB"
}