Files
syndarix/backend
Felipe Cardoso c589b565f0 Add pyproject.toml for consolidated project configuration and replace Black, isort, and Flake8 with Ruff
- Introduced `pyproject.toml` to centralize backend tool configurations (e.g., Ruff, mypy, coverage, pytest).
- Replaced Black, isort, and Flake8 with Ruff for linting, formatting, and import sorting.
- Updated `requirements.txt` to include Ruff and remove replaced tools.
- Added `Makefile` to streamline development workflows with commands for linting, formatting, type-checking, testing, and cleanup.
2025-11-10 11:55:15 +01:00
..

Backend API

FastAPI-based REST API with async SQLAlchemy, JWT authentication, and comprehensive testing.

Overview

Production-ready FastAPI backend featuring:

  • Authentication: JWT with refresh tokens, session management, device tracking
  • Database: Async PostgreSQL with SQLAlchemy 2.0, Alembic migrations
  • Security: Rate limiting, CORS, CSP headers, password hashing (bcrypt)
  • Multi-tenancy: Organization-based access control with roles (Owner/Admin/Member)
  • Testing: 97%+ coverage with security-focused test suite
  • Performance: Async throughout, connection pooling, optimized queries

Quick Start

Prerequisites

  • Python 3.11+
  • PostgreSQL 14+ (or SQLite for development)
  • pip and virtualenv

Installation

# Create virtual environment
python -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Copy environment template
cp .env.example .env
# Edit .env with your configuration

Database Setup

# Run migrations
python migrate.py apply

# Or use Alembic directly
alembic upgrade head

Run Development Server

uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

API will be available at:

Development

Project Structure

app/
├── api/              # API routes and dependencies
│   ├── routes/       # Endpoint implementations
│   └── dependencies/ # Auth, permissions, etc.
├── core/             # Core functionality
│   ├── config.py     # Settings management
│   ├── database.py   # Database engine setup
│   ├── auth.py       # JWT token handling
│   └── exceptions.py # Custom exceptions
├── crud/             # Database operations
├── models/           # SQLAlchemy ORM models
├── schemas/          # Pydantic request/response schemas
├── services/         # Business logic layer
└── utils/            # Utility functions

See docs/ARCHITECTURE.md for detailed architecture documentation.

Configuration

Environment variables (.env):

# Database
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your_password
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=app_db

# Security (IMPORTANT: Change these!)
SECRET_KEY=your-secret-key-min-32-chars-change-in-production
ENVIRONMENT=development  # development | production

# Optional
BACKEND_CORS_ORIGINS=["http://localhost:3000"]
CSP_MODE=relaxed  # strict | relaxed | disabled

# First superuser (auto-created on startup)
FIRST_SUPERUSER_EMAIL=admin@example.com
FIRST_SUPERUSER_PASSWORD=SecurePass123!

⚠️ Security Note: Never commit .env files. Use strong, unique values in production.

Database Migrations

We use Alembic for database migrations with a helper script:

# Generate migration from model changes
python migrate.py generate "add user preferences"

# Apply migrations
python migrate.py apply

# Generate and apply in one step
python migrate.py auto "add user preferences"

# Check current version
python migrate.py current

# List all migrations
python migrate.py list

Manual Alembic usage:

# Generate migration
alembic revision --autogenerate -m "description"

# Apply migrations
alembic upgrade head

# Rollback one migration
alembic downgrade -1

Testing

# Run all tests
IS_TEST=True pytest

# Run with coverage
IS_TEST=True pytest --cov=app --cov-report=term-missing -n 0

# Run specific test file
IS_TEST=True pytest tests/api/test_auth.py -v

# Run single test
IS_TEST=True pytest tests/api/test_auth.py::TestLogin::test_login_success -v

# Generate HTML coverage report
IS_TEST=True pytest --cov=app --cov-report=html -n 0
open htmlcov/index.html

Test Environment: Uses SQLite in-memory database. Tests run in parallel via pytest-xdist.

Code Quality

# Type checking
mypy app

# Linting
ruff check app

# Format code
black app
isort app

API Documentation

Once the server is running, interactive API documentation is available:

Authentication

Token-Based Authentication

The API uses JWT tokens for authentication:

  1. Login: POST /api/v1/auth/login

    • Returns access token (15 min expiry) and refresh token (7 day expiry)
    • Session tracked with device information
  2. Refresh: POST /api/v1/auth/refresh

    • Exchange refresh token for new access token
    • Validates session is still active
  3. Logout: POST /api/v1/auth/logout

    • Invalidates current session
    • Use logout-all to invalidate all user sessions

Using Protected Endpoints

Include access token in Authorization header:

curl -H "Authorization: Bearer <access_token>" \
  http://localhost:8000/api/v1/users/me

Roles & Permissions

  • Superuser: Full system access (user/org management)
  • Organization Roles:
    • Owner: Full control of organization
    • Admin: Can manage members (except owners)
    • Member: Read-only access

Common Tasks

Create a Superuser

Superusers are created automatically on startup using FIRST_SUPERUSER_EMAIL and FIRST_SUPERUSER_PASSWORD from .env.

To create additional superusers, update a user via SQL or admin API.

Add a New API Endpoint

See docs/FEATURE_EXAMPLE.md for step-by-step guide.

Quick overview:

  1. Create Pydantic schemas in app/schemas/
  2. Create CRUD operations in app/crud/
  3. Create route in app/api/routes/
  4. Register router in app/api/main.py
  5. Write tests in tests/api/

Database Health Check

# Check database connection
python migrate.py check

# Health endpoint
curl http://localhost:8000/health

Docker Support

# Development with hot reload
docker-compose -f docker-compose.dev.yml up

# Production
docker-compose up -d

# Rebuild after changes
docker-compose build backend

Troubleshooting

Common Issues

Module Import Errors

# Ensure you're in the backend directory
cd backend

# Activate virtual environment
source .venv/bin/activate

Database Connection Failed

# Check PostgreSQL is running
sudo systemctl status postgresql

# Verify credentials in .env
cat .env | grep POSTGRES

Migration Conflicts

# Check migration history
python migrate.py list

# Downgrade and retry
alembic downgrade -1
alembic upgrade head

Tests Failing

# Run with verbose output
IS_TEST=True pytest -vv

# Run single test to isolate issue
IS_TEST=True pytest tests/api/test_auth.py::TestLogin::test_login_success -vv

Getting Help

See our detailed documentation:

Performance

Database Connection Pooling

Configured in app/core/config.py:

  • Pool size: 20 connections
  • Max overflow: 50 connections
  • Pool timeout: 30 seconds
  • Connection recycling: 1 hour

Async Operations

  • All I/O operations use async/await
  • CPU-intensive operations (bcrypt) run in thread pool
  • No blocking calls in request handlers

Query Optimization

  • N+1 query prevention via eager loading
  • Bulk operations for admin actions
  • Indexed foreign keys and common lookups

Security

Built-in Security Features

  • Password Security: bcrypt hashing, strength validation, common password blocking
  • Token Security: HMAC-SHA256 signed, short-lived access tokens, algorithm validation
  • Session Management: Database-backed, device tracking, revocation support
  • Rate Limiting: Per-endpoint limits on auth/sensitive operations
  • CORS: Explicit origins, methods, and headers only
  • Security Headers: CSP, HSTS, X-Frame-Options, etc.
  • Input Validation: Pydantic schemas, SQL injection prevention (ORM)

Security Best Practices

  1. Never commit secrets: Use .env files (git-ignored)
  2. Strong SECRET_KEY: Min 32 chars, cryptographically random
  3. HTTPS in production: Required for token security
  4. Regular updates: Keep dependencies current
  5. Audit logs: Monitor authentication events

Monitoring

Health Check

curl http://localhost:8000/health

Returns:

  • API version
  • Environment
  • Database connectivity
  • Timestamp

Logging

Logs are written to stdout with structured format:

# Configure log level
logging.basicConfig(level=logging.INFO)

# In production, use JSON logs for log aggregation

Additional Resources


Note: For project-wide information (license, contributing guidelines, deployment), see the root README.