Agent Zero 04d6562f5b fix(security): Fix critical permission system issues
Problem 1: Remove legacy role bypass
- Remove role="admin" string bypass in permissions.py resolve_permissions()
- Remove role="admin"/"editor" bypass in auth.py check_permission()
- Remove legacy role string fallback in deps.py require_admin/require_write
- Add migration 0112: Create Role records for built-in roles and link role_id
- KI-Kommentar: Legacy Role Bypass entfernt — alle Admins müssen echte role_id haben

Problem 2: Enforce API token scopes
- Add _token_scopes check in require_permission() in deps.py
- When _token_scopes is set (API token auth), required permission must be in scopes
- When _token_scopes not set (session auth), normal permission check applies

Problem 3: Migration chain verification
- Chain is already linear: 0027→0028_rls_force→0028_user_preferences→0029
- user_preferences table confirmed exists in DB
- No duplicate revision IDs found

Problem 4: RLS for remaining tenant tables
- Add migration 0111: Dynamic RLS activation for any remaining tables with tenant_id
- Login tables and global tables explicitly excluded
- DB check shows 0 tables currently missing RLS (safety net migration)

Problem 5: Permission cache invalidation on tenant switch
- Add invalidate_permission_cache() call in switch_tenant() for old tenant
- Stale cached permissions from old tenant no longer leak

Problem 6+7: Guest system removal
- Remove get_current_guest() from deps.py
- Remove guest_auth.py router from main.py and routes/__init__.py
- Rewrite guests.py to use regular User/UserTenant with role=guest
- Remove GuestUser/GuestInvitation from models/__init__.py
- Add migration 0113: Migrate guest_users to regular users, drop guest tables
- Update frontend GuestLogin/GuestContacts to redirect to normal pages
- KI-Kommentar: Guest-System umgebaut — Guests sind jetzt reguläre User mit role=guest
2026-08-06 11:32:14 +02:00
2026-06-29 08:00:29 +02:00
2026-06-29 08:01:35 +02:00
2026-07-23 08:42:26 +02:00

LeoCRM v1.0

Self-hosted CRM for small sales teams (525 sales reps). Stack: FastAPI + SQLAlchemy (async) + PostgreSQL + Redis + React 18 + TypeScript + Vite + TanStack Query + Zustand + Tailwind + Docker + Coolify

Quick Start (Development)

1. Clone and Setup

git clone <repo-url> leocrm
cd leocrm

# Create virtual environment
python3 -m venv .venv
source .venv/bin/activate

# Install dependencies
pip install -r requirements.txt -r requirements-dev.txt

2. Configure Environment

cp .env.example .env

# Generate a secure SECRET_KEY (min 32 chars)
python3 -c "import secrets; print('SECRET_KEY=' + secrets.token_urlsafe(48))" >> .env

# Edit .env and set DATABASE_URL, REDIS_URL, SECRET_KEY
nano .env

3. Initialize Database

# Apply migrations
alembic upgrade head

4. Run Server

# Development with auto-reload
uvicorn app.main:app --reload --port 8000

# Start ARQ worker (for background jobs)
arq app.core.jobs.WorkerSettings

Open:

Production Setup

Docker Compose

cp .env.example .env
# Edit .env — set DATABASE_URL, REDIS_URL, SECRET_KEY, CORS_ORIGINS
# Set ENVIRONMENT=production, SESSION_COOKIE_SECURE=true
docker compose up -d

# Run migrations
docker compose exec api alembic upgrade head

Manual (without Docker)

pip install -r requirements.txt
alembic upgrade head

# Start API server (2 workers)
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2

# Start ARQ worker (separate process)
arq app.core.jobs.WorkerSettings

See docs/admin-guide.md for detailed deployment, backup, and troubleshooting instructions.

API

Key Endpoints

Endpoint Method Auth Description
/api/v1/health GET No Health check (DB, Redis, storage, worker)
/api/v1/metrics GET Admin Prometheus metrics (text/plain)
/api/v1/auth/login POST No Login
/api/v1/contacts GET Yes List contacts (paginated, max page_size=100)
/api/v1/contacts/export GET Yes Stream contacts as CSV
/api/v1/companies GET Yes List companies (paginated, max page_size=100)
/api/v1/companies/export GET Yes Stream companies as CSV

Pagination

All list endpoints support pagination with page and page_size parameters. page_size is capped at 100 — values >100 return HTTP 422.

CSV Export

Contacts and companies support streaming CSV export via /export?format=csv. Uses StreamingResponse — does not buffer the entire file in memory.

Swagger UI

Interactive API documentation: http://localhost:8000/docs

See docs/api-overview.md for the full endpoint summary.

Monitoring

Health Check

curl http://localhost:8000/api/v1/health

Returns JSON with overall status (healthy/degraded) and individual checks for database, redis, storage, and worker.

Prometheus Metrics

# Requires admin authentication
curl -b "leocrm_session=<session>" http://localhost:8000/api/v1/metrics

Available metrics:

  • leocrm_http_requests_total — Total HTTP requests
  • leocrm_http_request_duration_seconds — Request duration histogram
  • leocrm_db_pool_connections — Database connection pool size
  • leocrm_arq_jobs_total — Total ARQ background jobs

Structured Logging

LeoCRM uses structlog for structured JSON logging. All API requests are logged with: timestamp, level, event, method, path, status, duration_ms, tenant_id.

Environment Profiles

Profile ENVIRONMENT Use Case
Development development Local dev (auto-reload, verbose logging)
Testing testing Test suite (separate test DB, minimal logging)
Production production Docker/Coolify deployment (JSON logging, secure cookies)

See docs/admin-guide.md for profile details.

Testing

# Run all tests
pytest -v --tb=short

# Run specific test suites
pytest tests/test_monitoring.py tests/test_performance.py tests/test_health.py -v

# Run with coverage
pytest --cov=app --cov-report=term-missing

Environment Variables

See .env.example for all variables and docs/admin-guide.md for detailed descriptions.

Key Variables

Variable Required Description
DATABASE_URL PostgreSQL async connection URL
REDIS_URL Redis connection URL
SECRET_KEY Secret key for signing (≥32 chars in prod)
CORS_ORIGINS Comma-separated allowed origins (no wildcards)
ENVIRONMENT development | testing | production
STORAGE_PATH File storage path (default: /tmp)
SMTP_HOST SMTP server hostname

Performance Testing

# Seed 200k contacts for performance testing
python scripts/seed_perf_data.py --count 200000

# Verify database indexes
python scripts/check_indexes.py

# Test pagination performance
# GET /api/v1/contacts?page=1&page_size=25 — should be <500ms with 200k records

Project Structure

leocrm/
├── app/
│   ├── main.py               # FastAPI entry point with logging middleware
│   ├── config.py             # Pydantic settings
│   ├── core/
│   │   ├── monitoring.py      # Prometheus metrics + structured logging + health checks
│   │   ├── db.py             # Async database engine
│   │   ├── middleware.py     # CSRF middleware
│   │   └── ...
│   ├── routes/
│   │   ├── health.py         # Health endpoint
│   │   ├── metrics.py        # Prometheus metrics endpoint (admin-only)
│   │   ├── contacts.py       # Contact CRUD + streaming CSV export
│   │   ├── companies.py      # Company CRUD + streaming CSV export
│   │   └── ...
│   ├── models/               # SQLAlchemy models
│   ├── schemas/              # Pydantic schemas
│   ├── services/             # Business logic
│   └── plugins/              # Plugin system
├── scripts/
│   ├── seed_perf_data.py     # Performance test data seeding
│   └── check_indexes.py      # Database index verification
├── tests/                    # Test suite (pytest + pytest-asyncio)
├── docs/
│   ├── admin-guide.md       # Admin guide (deploy, backup, restore, troubleshooting)
│   └── api-overview.md      # API endpoint summary
├── alembic/                  # Database migrations
├── requirements.txt          # Production dependencies
├── requirements-dev.txt     # Test/lint dependencies
├── .env.example              # Environment template
├── docker-compose.yml        # Docker Compose
└── README.md                # This file

Documentation

License

Internal project proprietary.

S
Description
Mini-CRM mit Login, Firmen und Kontaktpersonen. FastAPI + SQLAlchemy + SQLite
Readme MIT 26 MiB
2026-07-31 07:23:02 +00:00
Languages
Python 64.1%
TypeScript 34.7%
Shell 0.6%
PLpgSQL 0.2%
CSS 0.2%
Other 0.1%