A RESTful API built with FastAPI for managing personal tasks, with JWT-based authentication and full user isolation.
| Library | Version | Purpose |
|---|---|---|
| FastAPI | ≥ 0.111.0 | Web framework |
| SQLAlchemy | 2.0+ | ORM |
| Alembic | ≥ 1.13.0 | Database migrations |
| Pydantic | ≥ 2.7.0 | Data validation |
| python-jose | ≥ 3.3.0 | JWT tokens |
| bcrypt | — | Password hashing |
| Uvicorn | ≥ 0.29.0 | ASGI server |
| pytest | ≥ 8.2.0 | Testing |
| Ruff | ≥ 0.4.4 | Linting |
| Black | ≥ 24.4.2 | Formatting |
The project follows a layered architecture with clear separation of concerns:
app/
├── core/ # Config, database, security, dependency injection
├── models/ # SQLAlchemy ORM entities
├── repositories/ # Data access layer (CRUD)
├── services/ # Business logic and validation
├── schemas/ # Pydantic request/response models
└── routers/ # HTTP endpoints
Each layer depends only on the layer below it. Routers call services, services call repositories, repositories talk to the database.
- Python 3.14+
- PostgreSQL
# Clone the repository
git clone https://github.com/ramon-bernardo/task-vault.git
cd task-vault
# Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Configure environment variables
cp .env.example .env
# Edit .env with your database URL and secret key
# Run database migrations
alembic upgrade head
# Start the server
uvicorn app.main:app --reloadThe API will be available at http://localhost:8000. Interactive docs at http://localhost:8000/docs.
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Health check |
| Method | Endpoint | Description |
|---|---|---|
POST |
/auth/register |
Register a new user |
POST |
/auth/login |
Login and obtain a JWT token |
Register — POST /auth/register
{
"email": "[email protected]",
"password": "strongpassword"
}Login — POST /auth/login
Content-Type: application/x-www-form-urlencoded
[email protected]&password=strongpassword
Response:
{
"access_token": "<jwt>",
"token_type": "bearer"
}All task endpoints require an Authorization: Bearer <token> header.
| Method | Endpoint | Description |
|---|---|---|
GET |
/tasks |
List tasks (paginated via skip / limit) |
POST |
/tasks |
Create a task |
GET |
/tasks/{id} |
Get a task by ID |
PATCH |
/tasks/{id} |
Partially update a task |
DELETE |
/tasks/{id} |
Delete a task |
Create Task — POST /tasks
{
"title": "Buy groceries",
"description": "Milk, eggs, bread"
}Update Task — PATCH /tasks/{id}
All fields are optional:
{
"title": "Buy groceries",
"description": "Milk, eggs, bread, butter",
"done": true
}The API returns standard HTTP status codes with a JSON detail message:
| Status | Meaning |
|---|---|
400 |
Validation error |
401 |
Missing or invalid credentials |
403 |
Authenticated but not the task owner |
404 |
Resource not found |
409 |
Conflict (duplicate email or task title) |
422 |
Unprocessable entity (request body schema error) |
Example error response:
{
"detail": "Task not found"
}Tests use an in-memory SQLite database so no external database is required.
pytestThe test suite covers:
- Auth: registration, login, duplicate email handling
- Tasks: full CRUD, ownership enforcement, pagination, task isolation between users
A Postman collection is available at Postman/Collection.json.
Import it into Postman, set base_url to http://localhost:8000, and run the Login request first — the collection's test script automatically saves the JWT token to the access_token variable for all subsequent requests.
This project is licensed under the MIT License.