Skip to content

A FastAPI template for user authentication (JWT) with a flexible repository pattern supporting SQLite, PostgreSQL, and MongoDB. Includes pytest setup and Dynaconf configuration

License

Notifications You must be signed in to change notification settings

nim444/fastapi-auth-multi-db

Repository files navigation

FastAPI User Authentication API

CI Pipeline Python 3.13 FastAPI >=0.115 Code style: ruff Tests passing Coverage: 100% MIT License

A robust FastAPI application demonstrating user registration, JWT authentication (including refresh tokens), and a flexible repository pattern supporting SQLite, PostgreSQL, and MongoDB backends.

Endpoints

Purpose

This project serves as a template or starting point for building secure and scalable FastAPI applications with a focus on:

  • Clean Architecture: Separation of concerns using API routes, core logic, database repositories, and Pydantic schemas.
  • Flexibility: Easily switch between SQL (SQLite/PostgreSQL) and NoSQL (MongoDB) databases via configuration.
  • Modern Tooling: Utilizes uv for dependency management, Dynaconf for configuration, and ruff for linting/formatting.
  • Testability: Designed with dependency injection and includes a comprehensive test suite using pytest.

Highlights

  • JWT-based authentication (login, refresh tokens).
  • User registration with password hashing (bcrypt) and validation.
  • Protected user profile endpoint (/users/me).
  • Flexible database layer using the Repository Pattern.
  • Configuration management with Dynaconf (settings.toml, .secrets.toml, environment variables with FAPI_ prefix).
  • Asynchronous support throughout (FastAPI, database drivers).
  • Automated API documentation (Swagger UI & ReDoc).
  • Comprehensive test suite with pytest (including coverage).
  • Health check endpoint (/health).

Architecture Diagram

Below is an overview of the application's architecture:

Architecture Diagram

Technology Stack

  • Python: >= 3.13
  • Framework: FastAPI (>=0.115.12)
  • Authentication: python-jose (JWT), passlib, bcrypt
  • Database ORM/Driver:
    • SQLAlchemy (>=2.0.40) for SQL databases
    • Motor (>=3.5.0, via mongodb_repository.py, requires separate install if used) for MongoDB
    • Psycopg2 (requires separate install if using PostgreSQL)
    • aiosqlite (>=0.20.0, requires separate install if using async SQLite sqlite+aiosqlite)
  • Configuration: Dynaconf (>=3.2.0)
  • Testing: pytest, pytest-asyncio, pytest-cov, httpx
  • Dependency Management: uv
  • Linting/Formatting: Ruff

Project Structure

/
├── app/                  # Main application module
│   ├── api/              # API endpoints (routers)
│   ├── core/             # Core logic (config, security, exceptions)
│   ├── db/               # Database interaction layer (repositories, models, session)
│   └── schemas/          # Pydantic schemas (data validation)
├── config/               # Configuration files
│   ├── .secrets.toml     # Secret settings (JWT secret, DB passwords) - DO NOT COMMIT
│   ├── .secrets.toml.example # Example secrets file
│   └── settings.toml     # Main application settings (DB type, etc.)
├── tests/                # Application tests (mirrors app structure)
│   └── conftest.py       # Pytest configuration and fixtures
├── .gitignore            # Git ignore rules
├── main.py               # FastAPI application entry point
├── pyproject.toml        # Project metadata and dependencies (uv)
├── README.md             # This file
├── run_tests.sh          # Helper script for running tests
├── test.db               # Default SQLite database file (if used)
└── uv.lock               # Lock file for dependencies (uv)

User Interface

Below is a preview of the application's interface:

User Interface

Setup and Installation

  1. Clone the repository:

    git clone <your-repo-url>
    cd fapi
  2. Create and activate a virtual environment:

    python -m venv .venv
    source .venv/bin/activate  # On Windows use `.venv\Scripts\activate`
  3. Install dependencies (using uv):

    # Install core dependencies
    uv pip install -e .
    
    # Install all dependencies including test extras
    uv pip install -e '.[test]'
    
    # Install DB-specific drivers if needed (not included by default)
    # uv pip install psycopg2-binary  # For PostgreSQL
    # uv pip install motor           # For MongoDB
    # uv pip install aiosqlite       # For async SQLite
  4. Configure Settings:

    • Settings are managed by Dynaconf, loading from config/settings.toml, config/.secrets.toml, and environment variables (prefixed with FAPI_, e.g., FAPI_DATABASE_TYPE, FAPI_JWT_SECRET_KEY).

    • Create config/.secrets.toml by copying config/.secrets.toml.example. Add your JWT_SECRET_KEY (must be strong and secret). Do not commit .secrets.toml.

      # config/.secrets.toml
      [default]
      JWT_SECRET_KEY="your_super_secret_strong_key_here_min_32_chars"
      
      # Optional: Add sensitive DB credentials if not using env vars
      # SQL_DATABASE_URL="postgresql+asyncpg://user:pass@host:port/dbname"
      # MONGO_DATABASE_URL="mongodb://user:pass@host:port/"
    • Edit config/settings.toml to select your database backend:

      • Set database_type to "sqlite", "postgres", or "mongodb".
      • Ensure the corresponding database URL (sql_database_url or mongo_database_url) is correctly set (either here, in .secrets.toml, or via environment variables like FAPI_SQL_DATABASE_URL). The default uses test.db.
      • If using MongoDB, set mongo_db_name.
  5. Initialize Database:

    • SQL (SQLite/PostgreSQL): This project includes alembic as a dependency for potential migrations.
      • Ensure your database exists.
      • If you have Alembic migrations set up (e.g., alembic.ini file and a migrations/ directory), run: alembic upgrade head
      • (If Alembic is not fully configured, you may need to initialize it or manage schema changes manually)
    • MongoDB: Ensure your MongoDB server is running. The application will automatically attempt to create the required unique indexes for the users collection (on username and email) when it starts up, using the database name specified by mongo_db_name in your settings.

Running the Application

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

The API will be available at http://localhost:8000.

Running Tests

Ensure test dependencies are installed (uv pip install -e '.[test]').

Using the helper script:

chmod +x run_tests.sh
./run_tests.sh

This script provides options for different test runs (verbose, coverage, etc.).

Using pytest directly:

# Run all tests (verbose)
PYTHONPATH=. pytest -v

# Run tests with coverage report
PYTHONPATH=. pytest --cov=app --cov-report=term-missing --cov-report=html

Coverage report will be in the htmlcov/ directory.

Running GitHub Actions Locally (Optional)

If you have act installed, you can simulate GitHub Actions workflows locally. This is particularly useful for testing CI/CD pipelines before pushing changes.

# Run workflows, specifying architecture if needed (e.g., for M1/M2 Macs)
act --container-architecture linux/amd64

API Documentation

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

  • Swagger UI: http://localhost:8000/docs
  • ReDoc: http://localhost:8000/redoc

Switching Databases

  1. Stop the application.
  2. Update config/settings.toml or environment variables:
    • Change database_type.
    • Ensure the correct URL (sql_database_url or mongo_database_url) is set.
    • Update mongo_db_name if switching to MongoDB.
  3. Ensure the target database server (PostgreSQL or MongoDB) is running and accessible.
  4. If switching to SQL, ensure the database exists and migrations are applied (alembic upgrade head).
  5. If switching to MongoDB, ensure indexes exist.
  6. Restart the application: uvicorn main:app --reload ...

About

A FastAPI template for user authentication (JWT) with a flexible repository pattern supporting SQLite, PostgreSQL, and MongoDB. Includes pytest setup and Dynaconf configuration

Topics

Resources

License

Stars

Watchers

Forks