LBS contains two directories; server (a nodejs/expresjs api folder), web (a reactjs frontend folder). Both built using typescript with aim of usiing less package dependencies as possible.
-
Currently the authentication process is flawed as both refresh and access to kens are sent via request body and stored in localStorage making the api valnurable to CSRF, getting tokens when routes are intercepted and much more. A better approach would be having the access token in the request header and refresh token stored in the cookie with a shorter duration (user's don't need to stay signed in for long)
-
Formdata and requests leaving the frontend are currently not validated which may lead to unexpected errors on both the server and web if not handled correctly.
-
The database model is designed based on requirements and method in which the frontend is espected to consume the data ( currently not indexed properly). i.e, each
BorrowHistory
document includes aborrowedBy
andborrowedbook
fields which areFK
pointing to user and book respectively. Why include anarray of history IDs
to both user and books, when history would likely be fetched alone more frequently? Also indexing both fields (especially userId - borrowedBy) would be more appropriate.
Validations are performs using express middleware,
requestValidator
validates incoming request payload using a zod schemadeserialiseUser
grabs and validates any incomingBearer
token; saves the verified user to a request-level variable or returns a null. ThedeserialzedUser
is always used beforeauthValidator
.authValidator
denies access to an endpoint if no user object is present in the request. i.eres.locals?.user
.roleValidator
Always comes afterdeserializeUser
->authValidator
since it depends on theres.local?.user
request-level variables. Middleware checks theres.locals?.user?.role
against the given role.
Endpoint | Method | Description | Request Body | Response Body | Error Codes |
---|---|---|---|---|---|
/api/auth/signup | POST | Registers a new user if unique username doesn't exist. A user role, access and refresh token is returned | {username, password, role} | objects: {user : {role}, token, refresh} | 401: Unauthorized, 500: Internal Server Error |
/api/auth/signin | POST | Assigns a authentication tokens to user if provided credentials are correct | {username,password} | {user: {role}, token, refreshToken} | 404: Not Found, 500: Internal Server Error |
/api/auth/refresh | POST | Assigns a new refresh token to user. tokens only last for about 3mins | N/A | { token, refreshToken} | |
/api/auth/logout | POST | Removes user token from header and cookie (currently no implemented) | N/A | N/A |
Endpoint | Method | Description | Request Body | Response Body | Error Codes |
---|---|---|---|---|---|
/api/books | GET | Fetchs all books | |||
/api/books | POST | Creates a new book (admin & liberian) | |||
/api/boooks/genre | POST | Creates a new book genre | N/A | ||
/api/boooks/genre | GET | Gets all book genre | N/A | ||
/api/boooks/borrow | GET | Gets all borrowed books (member) | N/A | ||
/api/boooks/borrow/:id | PSOT | Creates a new request to borrow a book (member) | N/A | ||
/api/boooks/:id | PUT | updates a book (member) | N/A | ||
/api/boooks/:id | DELETE | deletes a book (member) | N/A |
Endpoint | Method | Description | Request Body | Response Body | Error Codes |
---|---|---|---|---|---|
/api/admin/users | GET | Fetchs all users | |||
/api/admin/users/:id | DELETE | Deletes a user | |||
/api/admin/users/:id | PATCH | Updates a user | |||
/api/boooks/genre | POST | Creates a new book genre | N/A | ||
/api/admin/users | POST | Adds new user | N/A |
- Frontend: React, SWR + axios (http calls and request caching)
- Backend:
- Expressjs (http api),
- zod (validating requests),
- CORs (cross origin resource sharing)
- Prisma (database ORM)
- MongoDB document-based/No-SQL database