Table of Contents
This is a REST API built as a software engineering assignment for webeet.io
Provided was a list of Game of Thrones characters, which the user can query.
Basic CRUD operations are implemented, as well as pagination, filtering and sorting — separately or simultaneously.
This API uses a PostgreSQL database, includes user authentication and authorization
and features some basic unit testing.
using GitHub CLI:
gh repo clone Tombunzel/webeetGotAssignment
using git:
git clone https://github.com/Tombunzel/webeetGotAssignment.git
Make sure you are in the main folder of the project, then run:
pip install -r requirements.txt
The API requires a .env file with the following variables:
JWT_KEY: secret key for secure token creation and verification (HS256)SQLALCHEMY_DATABASE_URL: connection string with necessary details for database connection. (postgresql+psycopg2://username:password@host:port/database-name)
python3 setup_database.py
python3 insert_characters_from_json_to_database.py
python3 app.py
Listed below are the API's endpoints
Use this endpoint to create a user.
URL: .../signup
METHOD: POST
BODY:
{
"username": "your-username",
"password": "your-password"
}
HTTP/1.1 201 Created
Status: 201 Created
Server: Werkzeug/2.3.7 Python/3.12.2
Date: Sat, 08 Feb 2025 16:23:38 GMT
Content-Type: application/json
Content-Length: 32
Connection: close
{"message": "User created"}
Use this endpoint to log in to an existing user and receive a token.
This token allows you to make requests to endpoints which require authorization.
The token is valid for 30 minutes.
After that, a new token must be generated by making a request to the .../login endpoint
URL: .../login
METHOD: POST
BODY:
{
"username": "your-username",
"password": "your-password"
}
HTTP/1.1 201 Created
Status: 201 Created
Server: Werkzeug/2.3.7 Python/3.12.2
Date: Sat, 08 Feb 2025 16:23:38 GMT
Content-Type: application/json
Content-Length: 133
Connection: close
{"token": "your-authorization-token"}
URL: .../api/characters
METHOD: GET
Pagination is handled through the query arguments skip and limit, e.g.:
`.../api/characters?skip=20&limit=10`
This will result in 20 characters being skipped, and the next 10 being included in the results.
The user can choose to filter through the characters by each attribute available:
age, name, house, animal, death, nickname, role, strength and symbol.
Multiple attributes can be specified in the same query. This feature is case insensitive.
Additional query arguments age_more_than and age_less_than have been implemented for more precise querying.
To fetch a character by ID, see Get character by ID
Additionally, it is possible to sort the results by a certain attribute, e.g.:
`.../api/characters?sort_by=house&sort_desc=true`
The default sorting is in ascending order.
If desired, the query argument sort_des can be passed, which orders the results in descending order.
The argument's value is irrelevant: sort_des=true and sort_des=no will both result in descending order.
If sort_des is passed without sort_by, the results will default to be ordered by ID and in descending order.
If no query arguments were provided, the API will fetch 20 random characters from the database.
URL: .../api/characters?house=baratheon&sort_by=role&sort_des=yes&limit=3
METHOD: GET
HTTP/1.1 200 OK
Status: 200 OK
Server: Werkzeug/2.3.7 Python/3.12.2
Date: Sat, 08 Feb 2025 16:23:38 GMT
Content-Type: application/json
Content-Length: 1214
Connection: close
[
{
"age": 16,
"animal": "Stag",
"death": 5,
"house": "Baratheon",
"id": 44,
"name": "Myrcella Baratheon",
"nickname": null,
"role": "Princess",
"strength": "Cunning",
"symbol": "Crowned Stag"
},
and 2 other characters...
]
.../api/characters/{character_id}
URL: http://localhost:5432/api/characters/1
METHOD: GET
HTTP/1.1 200 OK
Status: 200 OK
Server: Werkzeug/2.3.7 Python/3.12.2
Date: Sat, 08 Feb 2025 16:23:38 GMT
Content-Type: application/json
Content-Length: 218
Connection: close
{
"age": 25,
"animal": "Direwolf",
"death": null,
"house": "Stark",
"id": 1,
"name": "Jon Snow",
"nickname": "King in the North",
"role": "King",
"strength": "Physically strong",
"symbol": "Wolf"
}
This endpoint requires a token provided from user login.
Use this endpoint to add a character to the database.
Valid character attributes: age, name, house, animal, death, nickname, role, strength and symbol.
Attribute name is required, others are optional.
For a full list of attributes and value types, see Character Data Models.
URL: .../api/characters
METHOD: POST
HEADERS:
"Authorization": "your-token"
BODY:
{
"id": 51,
"name": "character-name",
"house": "character-house",
"role": "character-role",
"age": 28,
...
}
HTTP/1.1 201 Created
Status: 201 Created
Server: Werkzeug/2.3.7 Python/3.12.2
Date: Sat, 08 Feb 2025 16:23:38 GMT
Content-Type: application/json
Content-Length: 185
Connection: close
{
"name": "character-name",
"house": "character-house",
"role": "character-role",
"age": 28,
...
}
This endpoint requires a token provided from user login.
Use this endpoint to update a character's data in the database.
URL: .../api/characters/{character_id}
METHOD: PUT
HEADERS:
"Authorization": "your-token"
BODY:
{
"nickname": "updated-character-nickname",
"age": 29,
...
}
HTTP/1.1 200 OK
Status: 200 OK
Server: Werkzeug/2.3.7 Python/3.12.2
Date: Sat, 08 Feb 2025 16:23:38 GMT
Content-Type: application/json
Content-Length: 196
Connection: close
{
"id": 51,
"name": "character-name",
"nickname": "updated-character-nickname",
"age": 29,
"house": "character-house",
...
}
This endpoint requires a token provided from user login.
Use this endpoint to delete a character from the database.
URL: .../api/characters/{character_id}
METHOD: DELETE
HEADERS:
"Authorization": "your-token"
HTTP/1.1 204 No Content
Status: 204 No Content
Server: Werkzeug/2.3.7 Python/3.12.2
Date: Sat, 08 Feb 2025 16:23:38 GMT
Content-Type: application/json
Connection: close
{
"id": 1, # int
"username": "your-username", # str
"password": "your-password", # str
"created_at": 2025-02-08 18:39:31.521848+01 # timestamp with time zone
}
{
"id": 2, # int
"age": 24, # int
"death": 8, # int of what season character died, null if didn't
"animal": "Dragon", # str
"house": "Targaryen", # str
"name": "Daenerys Targaryen", # str
"nickname": "Mother of Dragons", # str
"role": "Queen", # str
"strength": "Cunning", # str
"symbol": "Dragon" # str
}
Contributions are what makes the open source community such an amazing place to learn, inspire, and create. Any contributions are greatly appreciated.
If you have a suggestion that would make this app better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement", or contact me via email.
Don't forget to give the project a star!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Thanks a lot!
Tom Bunzel - [email protected]
Project Link: https://github.com/Tombunzel/webeetGotAssignment