Files
MultiChatOverlay/main.py

100 lines
3.8 KiB
Python

import os
from fastapi import FastAPI, Request, Depends, HTTPException
from starlette.middleware.sessions import SessionMiddleware
from starlette.staticfiles import StaticFiles
from starlette.responses import FileResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from contextlib import asynccontextmanager
from sqlalchemy.orm import Session
import models
from database import engine
import auth # Import the new auth module
import schemas
from config import settings # Import settings to get the secret key
# --- Absolute Path Configuration ---
# Get the absolute path of the directory where this file is located
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_DIR = os.path.join(BASE_DIR, "static")
TEMPLATES_DIR = os.path.join(BASE_DIR, "templates")
@asynccontextmanager
async def lifespan(app: FastAPI):
# This code runs on startup
print("Application startup: Creating database tables...")
models.Base.metadata.create_all(bind=engine)
print("Application startup: Database tables created.")
yield
# Code below yield runs on shutdown, if needed
app = FastAPI(lifespan=lifespan)
# Configure Jinja2 templates
templates = Jinja2Templates(directory=TEMPLATES_DIR)
# Mount the 'static' directory using an absolute path for reliability
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
# Add the authentication router
app.include_router(auth.router)
# Add session middleware. A secret key is required for signing the session cookie.
# We can reuse our encryption key for this, but in production you might want a separate key.
app.add_middleware(SessionMiddleware, secret_key=settings.ENCRYPTION_KEY)
@app.get("/")
async def read_root():
return FileResponse(os.path.join(STATIC_DIR, "login.html"))
@app.get("/dashboard")
async def read_dashboard(request: Request, db: Session = Depends(auth.get_db)):
# This is our protected route. It checks if a user_id exists in the session.
user_id = request.session.get('user_id')
if not user_id:
# If not, redirect them to the login page.
return RedirectResponse(url="/")
user = db.query(models.User).filter(models.User.id == user_id).first()
overlay_url = f"{settings.APP_BASE_URL}/overlay/{user.id}"
# Ensure user has settings, create if they don't for some reason
if not user.settings:
user.settings = models.Setting()
db.commit()
return templates.TemplateResponse("dashboard.html", {"request": request, "user": user, "overlay_url": overlay_url, "current_theme": user.settings.overlay_theme})
@app.get("/logout")
async def logout(request: Request):
# Clear the session cookie
request.session.clear()
return RedirectResponse(url="/")
@app.get("/overlay/{user_id}")
async def read_overlay(request: Request, user_id: int, db: Session = Depends(auth.get_db)):
# This endpoint serves the overlay page.
user = db.query(models.User).filter(models.User.id == user_id).first()
if not user:
raise HTTPException(status_code=404, detail="User not found")
theme = "dark-purple" # Default theme
if user.settings and user.settings.overlay_theme:
theme = user.settings.overlay_theme
return templates.TemplateResponse(f"overlay-{theme}.html", {"request": request})
@app.post("/api/settings")
async def update_settings(settings_data: schemas.SettingsUpdate, request: Request, db: Session = Depends(auth.get_db)):
user_id = request.session.get('user_id')
if not user_id:
raise HTTPException(status_code=401, detail="Not authenticated")
user = db.query(models.User).filter(models.User.id == user_id).first()
if not user.settings:
user.settings = models.Setting()
user.settings.overlay_theme = settings_data.overlay_theme
db.commit()
return {"message": "Settings updated successfully"}