Files
Business-Management/README.md
T
curo1305 d423bea134 Isolate backend and db from host: two Docker networks
- backend-net (internal: true): db ↔ backend ↔ frontend reverse proxy
- frontend-net: frontend only; single host port binding (80 prod / 5173 dev)
- Remove ports: from db (5432) and backend (8000) — unreachable from host
- Security auditor: hard rule to never add host ports to db or backend

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 00:06:38 +02:00

4.2 KiB

destroying_sap

A fullstack SaaS web application built with FastAPI, React, and PostgreSQL.

Stack

Layer Tech
Backend FastAPI (async), SQLAlchemy 2, Alembic, PostgreSQL 16
Auth JWT bearer tokens, bcrypt password hashing
Frontend React 18, TypeScript, Vite, React Router v6, TanStack Query

Current State

  • User registration and login (JWT auth)
  • Protected dashboard with nav bar (Dashboard | Profile | Logout)
  • /api/users/me — authenticated user info
  • /api/profile/me — GET/PUT personal profile (position, phone, date of birth, address)
  • Profile data stored in a dedicated profiles table; auto-created on first access
  • Admin role flag (is_superuser) stored in users table; exposed as is_admin in API (false for regular users, true for admins)
  • Admin-only user management at /admin: list all users, add users, delete users, toggle active status
  • All input sanitized before reaching the DB (null-byte rejection, length caps, format validation)
  • 3 separate Docker containers: db (PostgreSQL), backend (FastAPI), frontend (nginx)
  • All containers run as non-root users (UID 1001 for backend and frontend, UID 70 for db)
  • Network-isolated: only the frontend exposes a host port (80/5173); db and backend are unreachable from outside Docker
  • Dev environment seeds a test user automatically on startup (test@example.com / Test123!)
  • Password policy: min 8 chars, upper + lowercase, digit, special character, no common words
  • Pre-commit security hook (scripts/security_check.py) runs inside Docker on every commit

Containers

Container Image Host port Network User (UID:GID) Description
db postgres:16-alpine none backend-net 70:70 PostgreSQL database
backend custom (python:3.12-slim) none backend-net 1001:1001 FastAPI management API
frontend custom (nginxinc/nginx-unprivileged:alpine) 80 (prod) / 5173 (dev) backend-net + frontend-net 1001:1001 React UI + nginx reverse proxy

Networks:

  • backend-net (internal: true) — db, backend, and frontend reverse proxy communicate here; no host routing
  • frontend-net — frontend only; this is where the single host port (80/5173) is bound

The frontend nginx proxies /api/* to backend:8000 via backend-net. No backend or database port is ever exposed to the host.

Installation

Prerequisites

  • Docker + Docker Compose

Production

git clone <repo>
cd destroying_sap
cp .env.example backend/.env
python scripts/generate_jwt_keys.py  # paste output into backend/.env
docker compose up --build -d
  • Frontend: http://localhost
  • API docs: not directly accessible from host (backend port not exposed); access via docker compose exec backend or add a dev-only port mapping

Development (hot reload)

docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
  • Frontend (Vite): http://localhost:5173
  • Backend: reachable by frontend via Docker network only (not exposed to host)

Local (no Docker)

1. Start PostgreSQL

docker compose up db -d

2. Backend

cd backend
python -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
cp ../.env.example .env
alembic upgrade head
uvicorn app.main:app --reload

3. Frontend

cd frontend && npm install && npm run dev

Environment Variables

Copy .env.example to backend/.env and adjust:

Variable Default Description
DATABASE_URL postgresql+asyncpg://postgres:password@localhost:5432/destroying_sap Async PostgreSQL URL
JWT_PRIVATE_KEY RS256 private key PEM (generate with scripts/generate_jwt_keys.py)
JWT_PUBLIC_KEY RS256 public key PEM (generate with scripts/generate_jwt_keys.py)
CORS_ORIGINS ["http://localhost:5173"] Allowed frontend origins

Development

# Backend lint + format
cd backend && ruff check . && ruff format .

# Backend tests
cd backend && pytest

# Frontend type check + lint
cd frontend && npm run typecheck && npm run lint

# New DB migration (after changing models)
cd backend && alembic revision --autogenerate -m "describe change"
cd backend && alembic upgrade head