Files
gh-christianlouis-docuelevate/app/main.py
T
Christian Krakau-Louis 05ede35059 feat: Add license and attribution routes, update templates and documentation
- Added a new license route to serve the LGPL license text.
- Introduced a new attribution page to acknowledge third-party software used in the project.
- Updated the base HTML template to include a link to the attribution page.
- Included the license router in the main application router.
- Added the license text file for LGPL to the static licenses directory.
- Updated the NOTICE file to include detailed attributions for third-party libraries.
- Added a new requirements-dev.txt for license compliance checking.
- Updated the requirements.txt to clarify the LGPL license for Paramiko.
2025-04-11 02:39:26 +02:00

119 lines
4.0 KiB
Python

#!/usr/bin/env python3
import os
import logging
from fastapi import FastAPI, HTTPException, Request, status
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from starlette.middleware.sessions import SessionMiddleware
from starlette.config import Config
from starlette.middleware.trustedhost import TrustedHostMiddleware
from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
from pathlib import Path
from app.database import init_db
from app.config import settings
from app.utils.config_validator import check_all_configs
from app.utils.notification import init_apprise, send_notification, notify_startup, notify_shutdown
# Import the routers - now using views directly instead of frontend
from app.views import router as frontend_router
from app.api import router as api_router
from app.auth import router as auth_router
# Load configuration from .env for the session key
config = Config(".env")
SESSION_SECRET = config(
"SESSION_SECRET",
default="YOUR_DEFAULT_SESSION_SECRET_MUST_BE_32_CHARS_OR_MORE"
)
app = FastAPI(title="DocuElevate")
# 1) Session Middleware (for request.session to work)
app.add_middleware(SessionMiddleware, secret_key=SESSION_SECRET)
# 2) Respect the X-Forwarded-* headers from Traefik
app.add_middleware(ProxyHeadersMiddleware, trusted_hosts="*")
# 3) (Optional but recommended) Restrict valid hosts:
app.add_middleware(TrustedHostMiddleware, allowed_hosts=[
settings.external_hostname,
"localhost",
"127.0.0.1"
])
# Mount the static folder for CSS/JS:
frontend_static_dir = Path(__file__).parent.parent / "frontend" / "static"
app.mount("/static", StaticFiles(directory=frontend_static_dir), name="static")
@app.on_event("startup")
def on_startup():
init_db() # Create tables if they don't exist
@app.on_event("startup")
async def startup_event():
"""Run startup tasks for the application"""
# Force settings dump to log for troubleshooting
from app.utils.config_validator import dump_all_settings
dump_all_settings()
# Validate configuration
config_issues = check_all_configs()
# Log overall status
has_issues = any(config_issues['email']) or any(len(issues) > 0 for provider, issues in config_issues['storage'].items())
if has_issues:
logging.warning("Application started with configuration issues - some features may be unavailable")
else:
logging.info("Application started with valid configuration")
logging.info("Router organization: Using refactored API routers from app/api/ directory")
# Initialize notification system
init_apprise()
# Send startup notification
notify_startup()
@app.on_event("shutdown")
async def shutdown_event():
"""Run shutdown tasks for the application"""
logging.info("Application shutting down")
# Send shutdown notification
notify_shutdown()
# Custom 404 - we can still return the Jinja2 template, or the old static file:
@app.exception_handler(404)
async def custom_404_handler(request: Request, exc: HTTPException):
# Serve the 404 template directly
templates = Jinja2Templates(directory=str(frontend_static_dir.parent / "templates"))
return templates.TemplateResponse(
"404.html",
{"request": request},
status_code=status.HTTP_404_NOT_FOUND
)
@app.exception_handler(500)
async def custom_500_handler(request: Request, exc: Exception):
templates = Jinja2Templates(directory=str(frontend_static_dir.parent / "templates"))
# Option 1: Keep it simple, just show a funny 500 message:
return templates.TemplateResponse(
"500.html",
{"request": request, "exc": exc},
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
)
@app.get("/test-500")
def test_500():
raise RuntimeError("Testing forced 500 error!")
# Include the routers
app.include_router(frontend_router)
app.include_router(auth_router)
app.include_router(api_router, prefix="/api")