Web application for managing and using an online library service - a project for the Databases course at AGH UST.
- Marcin Żurawel
- Kuba ĹšwiÄ…tek
- browsing and renting resources from the library
- admin panel for managing rentals and pending shipment requests
- Frontend: TypeScript, React, Chakra UI
- Backend: TypeScript, Express, JWT, bcrypt.js, Mongoose.js
- Database: MongoDB, MongoDB Atlas
We used a NoSQL database, so our schema took form of 3 MongoDB collections:
{
_id: string,
clientId: User_id,
productId: Product_id,
productName: string,
quantity: number,
isPending: boolean,
address: { street: string, zipCode: string, city: string },
borrowDate?: Date,
dueDate?: Date,
returnDate?: Date,
fine?: number,
ifProlonged?: boolean,
}
{
_id: string,
username: string,
password: string,
role: "admin" | "user",
}
{
_id: string,
name: string,
description?: string,
quantity: number,
imageUrl?: string,
}
GET /rentals/fines
None
- Admin
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Array of fine objects |
401 | application/json |
{ "message": "Unauthorized!" } |
403 | application/json |
{ "message": "No token provided!" } |
403 | application/json |
{ "message": "Unauthorized: no admin privileges" } |
GET /rentals/pending
None
- Admin
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Array of rental objects |
401 | application/json |
{ "message": "Unauthorized!" } |
403 | application/json |
{ "message": "No token provided!" } |
403 | application/json |
{ "message": "Unauthorized: no admin privileges" } |
GET /rentals
None
- User
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Array of rental objects |
403 | application/json |
{ "message": "No token provided!" } |
401 | application/json |
{ "message": "Unauthorized!" } |
404 | application/json |
{ "error": "Rental not found." } |
GET /rentals/:id
Name | Type | Description |
---|---|---|
id |
String | ID of the rental |
- User
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Rental object |
403 | application/json |
{ "message": "No token provided!" } |
401 | application/json |
{ "message": "Unauthorized!" } |
404 | application/json |
{ "error": "Rental not found." } |
POST /rentals
Name | Type | Description |
---|---|---|
userId |
String | ID of the user renting |
productId |
String | ID of the product being rented |
rentalDate |
String | Date of rental |
returnDate |
String | Date of return |
- User
HTTP Status | Content-Type | Response Body |
---|---|---|
201 | application/json |
Created rental object |
403 | application/json |
{ "message": "No token provided!" } |
401 | application/json |
{ "message": "Unauthorized!" } |
400 | application/json |
{ "error": "Insufficient quantity available for the product." } |
404 | application/json |
{ "error": "Product not found." } |
PUT /rentals/:id
Name | Type | Description |
---|---|---|
id |
String | ID of the rental |
userId |
String | Updated ID of the user renting |
productId |
String | Updated ID of the product being rented |
rentalDate |
String | Updated date of rental |
returnDate |
String | Updated date of return |
- User
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Updated rental object |
403 | application/json |
{ "message": "No token provided!" } |
401 | application/json |
{ "message": "Unauthorized!" } |
404 | application/json |
{ "error": "Rental not found." } |
DELETE /rentals/:id
Name | Type | Description |
---|---|---|
id |
String | ID of the rental |
- User
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Success message |
403 | application/json |
{ "message": "No token provided!" } |
401 | application/json |
{ "message": "Unauthorized!" } |
404 | application/json |
{ "error": "Rental not found." } |
POST /user/signup
Name | Type | Description |
---|---|---|
username |
String | User's username |
password |
String | User's password |
- User
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Object of the registered user |
POST /user/signin
Name | Type | Description |
---|---|---|
username |
String | User's username |
password |
String | User's password |
- User
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Object of the logged-in user |
GET /user/rentals
None
- User
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Array of user's rental objects |
403 | application/json |
{ "message": "No token provided!" } |
401 | application/json |
{ "message": "Unauthorized!" } |
GET /products
None
- User
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Array of product objects |
404 | application/json |
{ "error": "Product not found." } |
POST /products
Name | Type | Description |
---|---|---|
name |
String | Name of the product |
description |
String | Description of the product |
quantity |
Number | Quantity of the product |
imageUrl |
String | URL of the product image |
- Admin
HTTP Status | Content-Type | Response Body |
---|---|---|
201 | application/json |
Created product object |
403 | application/json |
{ "message": "No token provided!" } |
401 | application/json |
{ "message": "Unauthorized!" } |
404 | application/json |
{ "error": "Product not found." } |
GET /products/:id
Name | Type | Description |
---|---|---|
id |
String | ID of the product |
- User
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Product object |
403 | application/json |
{ "message": "No token provided!" } |
401 | application/json |
{ "message": "Unauthorized!" } |
404 | application/json |
{ "error": "Product not found." } |
PUT /products/:id
Name | Type | Description |
---|---|---|
id |
String | ID of the product |
name |
String | Updated name of the product |
description |
String | Updated description of the product |
quantity |
Number | Updated quantity of the product |
imageUrl |
String | Updated URL of the product image |
- Admin
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Updated product object |
403 | application/json |
{ "message": "No token provided!" } |
401 | application/json |
{ "message": "Unauthorized!" } |
404 | application/json |
{ "error": "Product not found." } |
DELETE /products/:id
Name | Type | Description |
---|---|---|
id |
String | ID of the product |
- Admin
HTTP Status | Content-Type | Response Body |
---|---|---|
200 | application/json |
Success message |
403 | application/json |
{ "message": "No token provided!" } |
401 | application/json |
{ "message": "Unauthorized!" } |
404 | application/json |
{ "error": "Product not found." } |
After opening the app we are redirected to the authorization page.
Successful sign up results in a new record being created in the database. We can also see the password being properly hashed.
After logging in, a personal homepage is being displayed, where we can view our current rentals.
We just created our account, so no rentals are being shown. Let's head to the Collection page and make our first rental! We're true fantasy connoisseurs, so we pick J.R.R. Tolkien's Silmarillion.
We can then specify the quantity.
Finally we can see our rental is succesfully displayed on the homepage.
If we log in as an admin, we can view a special panel displaying incoming orders, and enabling us to confirm successful shipments.