44 lines
1.6 KiB
Python
44 lines
1.6 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
|
|
|
|
|
|
@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.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'}
|