Skip to content

Latest commit

Β 

History

History
380 lines (294 loc) Β· 8.55 KB

File metadata and controls

380 lines (294 loc) Β· 8.55 KB

Phase 3: REST API Implementation

Overview

Phase 3 adds a complete REST API layer built with FastAPI, enabling web and mobile client integration while maintaining the existing CLI functionality.

Key Features

  • βœ… FastAPI Framework - Modern, fast, auto-documented API
  • βœ… JWT Authentication - Secure token-based auth for all endpoints
  • βœ… Full CRUD Operations - Complete task and user management
  • βœ… Automatic OpenAPI Documentation - Swagger UI at /api/docs
  • βœ… Input Validation - Pydantic-based request/response validation
  • βœ… Error Handling - Comprehensive error responses
  • βœ… Pagination - Efficient data fetching with limits
  • βœ… CORS Support - Cross-origin requests for web clients

Architecture

FastAPI Application
β”œβ”€β”€ Authentication Routes (/api/auth)
β”‚   β”œβ”€β”€ POST /register       - User registration
β”‚   β”œβ”€β”€ POST /login          - User login (returns JWT)
β”‚   └── POST /refresh-token  - Token refresh
β”œβ”€β”€ Tasks Routes (/api/tasks)
β”‚   β”œβ”€β”€ POST /              - Create task
β”‚   β”œβ”€β”€ GET /               - List tasks (paginated)
β”‚   β”œβ”€β”€ GET /{id}           - Get task details
β”‚   β”œβ”€β”€ PUT /{id}           - Update task
β”‚   └── DELETE /{id}        - Delete task
β”œβ”€β”€ Users Routes (/api/users)
β”‚   β”œβ”€β”€ GET /me             - Get user profile
β”‚   β”œβ”€β”€ PUT /me             - Update profile
β”‚   └── POST /me/toggle-reminders - Toggle reminders
└── Health & Info
    β”œβ”€β”€ GET /              - API info
    └── GET /health        - Health check

Starting the API Server

# Development mode (with auto-reload)
python -m uvicorn task_manager_pro.api.main:app --reload --host 0.0.0.0 --port 8000

# Production mode
python -m uvicorn task_manager_pro.api.main:app --host 0.0.0.0 --port 8000 --workers 4

# View documentation
# Swagger UI: http://localhost:8000/api/docs
# ReDoc:      http://localhost:8000/api/redoc

API Endpoints Reference

Authentication

Register User

curl -X POST "http://localhost:8000/api/auth/register" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "satvik",
    "password": "securepass123",
    "email": "satvik@example.com"
  }'

Response (201):

{
  "id": "user-uuid",
  "username": "satvik",
  "email": "satvik@example.com",
  "email_reminders_enabled": true,
  "created_at": "2025-11-23T12:00:00",
  "updated_at": "2025-11-23T12:00:00"
}

Login

curl -X POST "http://localhost:8000/api/auth/login" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "satvik",
    "password": "securepass123"
  }'

Response (200):

{
  "user": {...},
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "bearer"
}

Refresh Token

curl -X POST "http://localhost:8000/api/auth/refresh-token" \
  -H "Content-Type: application/json" \
  -d '{"token": "old_token_here"}'

Tasks

Create Task

curl -X POST "http://localhost:8000/api/tasks" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Learn FastAPI",
    "description": "Read the official docs",
    "due_date": "2025-12-31",
    "priority": "high"
  }'

List Tasks

# All tasks
curl -X GET "http://localhost:8000/api/tasks" \
  -H "Authorization: Bearer YOUR_TOKEN"

# Pending tasks only
curl -X GET "http://localhost:8000/api/tasks?completed=false" \
  -H "Authorization: Bearer YOUR_TOKEN"

# With pagination
curl -X GET "http://localhost:8000/api/tasks?skip=0&limit=10" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response (200):

{
  "total": 5,
  "tasks": [
    {
      "id": "task-uuid",
      "title": "Learn FastAPI",
      "description": "Read docs",
      "due_date": "2025-12-31",
      "priority": "high",
      "completed": false,
      "created_at": "2025-11-23T12:00:00",
      "updated_at": "2025-11-23T12:00:00",
      "completed_at": null
    }
  ],
  "page": 1,
  "page_size": 10
}

Get Task Details

curl -X GET "http://localhost:8000/api/tasks/task-uuid" \
  -H "Authorization: Bearer YOUR_TOKEN"

Update Task

curl -X PUT "http://localhost:8000/api/tasks/task-uuid" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Updated Title",
    "completed": true,
    "priority": "medium"
  }'

Delete Task

curl -X DELETE "http://localhost:8000/api/tasks/task-uuid" \
  -H "Authorization: Bearer YOUR_TOKEN"

Users

Get Current User

curl -X GET "http://localhost:8000/api/users/me" \
  -H "Authorization: Bearer YOUR_TOKEN"

Update Profile

curl -X PUT "http://localhost:8000/api/users/me" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "newemail@example.com",
    "email_reminders_enabled": false
  }'

Toggle Email Reminders

curl -X POST "http://localhost:8000/api/users/me/toggle-reminders" \
  -H "Authorization: Bearer YOUR_TOKEN"

File Structure

task_manager_pro/
β”œβ”€β”€ api/
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ main.py              # FastAPI app initialization
β”‚   β”œβ”€β”€ dependencies.py      # JWT auth dependencies
β”‚   └── routes/
β”‚       β”œβ”€β”€ __init__.py
β”‚       β”œβ”€β”€ auth.py          # Authentication endpoints
β”‚       β”œβ”€β”€ tasks.py         # Task CRUD endpoints
β”‚       └── users.py         # User management endpoints
β”œβ”€β”€ schemas/                 # Pydantic models (Phase 2)
β”œβ”€β”€ storage/                 # Database layer (Phase 2)
└── utils/
    β”œβ”€β”€ security.py          # JWT and bcrypt (Phase 2)
    └── ...

Security Features

JWT Authentication

  • Token Type: HS256 (symmetric)
  • Expiration: 30 minutes (configurable)
  • Issuer: Configured via SECRET_KEY env var
  • Bearer Token Format: Authorization: Bearer <token>

Password Security

  • Hashed with bcrypt (12 rounds)
  • Never stored or transmitted in plain text
  • Validated on login

CORS

  • Configurable origins via CORS_ORIGINS env var
  • Credentials allowed
  • All methods and headers allowed

Error Handling

All errors return proper HTTP status codes:

{
  "detail": "Invalid username or password"
}

Common Status Codes

  • 200 - Success
  • 201 - Created
  • 204 - No Content (deleted)
  • 400 - Bad Request (validation error)
  • 401 - Unauthorized (invalid credentials/token)
  • 404 - Not Found
  • 500 - Server Error

Testing the API

Using httpx (Python)

import httpx

async with httpx.AsyncClient(base_url="http://localhost:8000") as client:
    # Register
    resp = await client.post("/api/auth/register", json={
        "username": "test",
        "password": "pass123",
        "email": "test@example.com"
    })
    print(resp.json())

    # Login
    resp = await client.post("/api/auth/login", json={
        "username": "test",
        "password": "pass123"
    })
    token = resp.json()["access_token"]

    # Create task
    resp = await client.post("/api/tasks",
        headers={"Authorization": f"Bearer {token}"},
        json={
            "title": "Test",
            "description": "Test task",
            "due_date": "2025-12-31"
        }
    )
    print(resp.json())

Using Pytest

See tests/test_api.py for comprehensive test examples.

Performance Considerations

  • Pagination: Limited to 100 items per request
  • Database Indexes: On user_id, due_date, completed
  • Connection Pooling: Automatic via SQLAlchemy
  • Async Support: FastAPI handles async naturally

Configuration

Environment Variables

# API
CORS_ORIGINS=http://localhost:3000,http://localhost:8080

# Security (from Phase 2)
SECRET_KEY=your-secret-key
ACCESS_TOKEN_EXPIRE_MINUTES=30

# Database (from Phase 2)
DATABASE_URL=sqlite:///./tasks.db
SQL_ECHO=false

Next Steps (Phase 4)

  • Add GitHub Actions CI/CD pipeline
  • Create comprehensive integration tests
  • Add coverage reporting
  • Load testing and performance optimization
  • Database connection pooling configuration

Troubleshooting

Port Already in Use?

# Find process using port 8000
lsof -i :8000

# Kill it
kill -9 <PID>

# Or use different port
uvicorn task_manager_pro.api.main:app --port 8001

Token Expired?

Call /api/auth/refresh-token with current token to get a new one.

CORS Errors?

Check CORS_ORIGINS env var includes your frontend URL.

Database Locked?

SQLite doesn't support concurrent writes. For production, switch to PostgreSQL.