104 lines
4.0 KiB
Python
104 lines
4.0 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(request: Request):
|
|
return templates.TemplateResponse("login.html", {"request": request})
|
|
|
|
@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, "settings": settings})
|
|
|
|
@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, theme_override: str = None, 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")
|
|
|
|
# The theme can be forced by a query parameter for previewing
|
|
if theme_override:
|
|
theme = theme_override
|
|
else:
|
|
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"} |