Initial commit – TimeMaster Zeiterfassung & HR-Tool
Stand: agent-06 (Audit-Log), agent-05 (Krankmeldung), agent-07 Phase 1 (Personalnummer), Busylight-Pull-Integration, TOTP/2FA, Abwesenheiten, Zeiterfassung, Kiosk-Grundgerüst. Migrations 0001–0023 deployed auf 192.168.1.137 + .164. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.middleware.trustedhost import TrustedHostMiddleware
|
||||
from slowapi import _rate_limit_exceeded_handler
|
||||
from slowapi.errors import RateLimitExceeded
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.database import engine, Base
|
||||
from app.core.limiter import limiter
|
||||
from app.routers import auth, users, companies
|
||||
from app.routers import time_entries, absences, reports, ldap, smtp, caldav
|
||||
from app.routers import import_kimai
|
||||
from app.routers import kiosk
|
||||
from app.routers import busylight
|
||||
from app.routers import audit
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
# Startup: Tabellen anlegen falls noch nicht vorhanden (Alembic übernimmt das in Prod)
|
||||
async with engine.begin() as conn:
|
||||
await conn.run_sync(Base.metadata.create_all)
|
||||
yield
|
||||
# Shutdown
|
||||
await engine.dispose()
|
||||
|
||||
|
||||
app = FastAPI(
|
||||
title=settings.app_name,
|
||||
version="0.1.0",
|
||||
docs_url="/docs" if not settings.is_production else None,
|
||||
redoc_url="/redoc" if not settings.is_production else None,
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
app.state.limiter = limiter
|
||||
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
|
||||
|
||||
# ── Middleware ────────────────────────────────────────────────────────────────
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=[settings.frontend_url],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# TODO (M-07): TrustedHostMiddleware – set ALLOWED_HOSTS env variable (comma-separated) in production.
|
||||
# Example: ALLOWED_HOSTS=timemaster.example.com,www.timemaster.example.com
|
||||
# The placeholder "yourdomain.com" has been replaced with a config-driven approach.
|
||||
if settings.is_production and settings.allowed_hosts:
|
||||
app.add_middleware(TrustedHostMiddleware, allowed_hosts=settings.allowed_hosts)
|
||||
|
||||
# ── Routers ───────────────────────────────────────────────────────────────────
|
||||
|
||||
API_PREFIX = "/api/v1"
|
||||
|
||||
app.include_router(auth.router, prefix=API_PREFIX)
|
||||
app.include_router(users.router, prefix=API_PREFIX)
|
||||
app.include_router(companies.router, prefix=API_PREFIX)
|
||||
app.include_router(time_entries.router, prefix=API_PREFIX)
|
||||
app.include_router(absences.router, prefix=API_PREFIX)
|
||||
app.include_router(reports.router, prefix=API_PREFIX)
|
||||
app.include_router(ldap.router, prefix=API_PREFIX)
|
||||
app.include_router(smtp.router, prefix=API_PREFIX)
|
||||
app.include_router(caldav.router, prefix=API_PREFIX)
|
||||
app.include_router(import_kimai.router, prefix=API_PREFIX)
|
||||
app.include_router(kiosk.router, prefix=API_PREFIX)
|
||||
app.include_router(busylight.router, prefix=API_PREFIX)
|
||||
app.include_router(audit.router, prefix=API_PREFIX)
|
||||
|
||||
|
||||
# ── Health ────────────────────────────────────────────────────────────────────
|
||||
|
||||
@app.get("/health", tags=["System"])
|
||||
async def health():
|
||||
return {"status": "ok", "app": settings.app_name, "env": settings.app_env}
|
||||
Reference in New Issue
Block a user