Files

49 lines
1.8 KiB
Python

import sqlite3
from contextlib import asynccontextmanager
from pathlib import Path
from urllib.parse import urlsplit
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from database import initialize
from routes import dashboard, income, export
from api.routes import router as api_router
from api.trading import router as trading_api_router
from routes.trading import router as trading_router
api_router.include_router(trading_api_router)
@asynccontextmanager
async def lifespan(app):
initialize()
yield
app = FastAPI(title='Finance Dashboard', lifespan=lifespan)
app.mount('/static', StaticFiles(directory=Path(__file__).parent / 'static'), name='static')
app.include_router(dashboard.router)
app.include_router(income.router)
app.include_router(export.router)
app.include_router(api_router)
app.include_router(trading_router)
@app.middleware('http')
async def protect_forms(request: Request, call_next):
if request.method == 'POST' and not request.url.path.startswith('/api/v1/'):
origin = request.headers.get('origin')
if request.headers.get('sec-fetch-site') == 'cross-site' or (origin and urlsplit(origin).netloc != request.headers.get('host')):
return HTMLResponse('Fremder Formularursprung ist nicht erlaubt.', status_code=403)
return await call_next(request)
@app.exception_handler(sqlite3.OperationalError)
async def database_error(request, error):
return HTMLResponse('<html lang="de"><meta charset="utf-8"><h1>Datenbank vorübergehend nicht verfügbar</h1><p>Bitte in einigen Sekunden erneut versuchen.</p><a href="/">Zum Dashboard</a></html>', status_code=503, headers={'Retry-After': '5'})
@app.get('/health')
def health():
return {'status': 'ok'}