9a0479cb37
- Updated Dockerfile to use Python 3.13 and streamline system dependencies installation. - Enhanced user session handling in auth.py, introducing a centralized method for retrieving the current user from the session. - Removed deprecated auth routes and consolidated logic for user authentication and profile management. - Improved error handling and user feedback in redeem.py and teams.py, ensuring users are redirected to login when not authenticated. - Updated requirements.txt to include necessary packages for enhanced security and functionality. - Added phpMyAdmin service to docker-compose for easier database management.
148 lines
5.1 KiB
Python
148 lines
5.1 KiB
Python
#!/usr/bin/env python3
|
|
from fastapi import FastAPI, Request, status, Depends
|
|
from fastapi.responses import HTMLResponse, RedirectResponse
|
|
from starlette.middleware.sessions import SessionMiddleware
|
|
from datetime import datetime
|
|
import os
|
|
|
|
from .db import init_db, engine
|
|
from . import models
|
|
from .templates_config import templates
|
|
from .views import qr, redeem, teams, admin, leaderboard, dashboard
|
|
from .db_init import seed_db
|
|
from .auth import router as auth_router
|
|
from .dependencies import get_user_from_session
|
|
|
|
# Create tables on startup
|
|
init_db()
|
|
|
|
# Seed database with initial test data
|
|
# In a production app, you would handle this differently
|
|
seed_db()
|
|
|
|
# Initialize FastAPI app
|
|
app = FastAPI()
|
|
|
|
# Configure session middleware settings
|
|
secret_key = os.environ.get("SECRET_KEY", "a-default-secret-key-for-sessions-please-change-this")
|
|
if len(secret_key) < 32:
|
|
print(f"WARNING: Secret key is too short ({len(secret_key)} chars). Recommended: 32+ chars")
|
|
|
|
# IMPORTANT: Add SessionMiddleware before anything else
|
|
# This must be the FIRST middleware in the stack
|
|
app.add_middleware(
|
|
SessionMiddleware,
|
|
secret_key=secret_key,
|
|
max_age=int(os.environ.get("SESSION_MAX_AGE", "86400")), # 24 hours by default
|
|
same_site="lax",
|
|
https_only=os.environ.get("COOKIE_SECURE", "False").lower() == "true",
|
|
session_cookie="league_ledger_session",
|
|
)
|
|
|
|
# Debug middleware - ADDED AFTER SessionMiddleware
|
|
@app.middleware("http")
|
|
async def debug_session_middleware(request, call_next):
|
|
"""Debug middleware to track session state"""
|
|
try:
|
|
session_cookie = request.cookies.get("league_ledger_session")
|
|
|
|
print(f"Request path: {request.url.path}")
|
|
# First check if the session attribute exists properly
|
|
has_session = hasattr(request, "session")
|
|
is_dict = has_session and isinstance(request.session, dict)
|
|
print(f"Has session attribute: {has_session}")
|
|
print(f"Session is dict: {is_dict}")
|
|
print(f"Has session cookie: {session_cookie is not None}")
|
|
|
|
# Safely check session data
|
|
if has_session and is_dict:
|
|
print(f"Session data before: {dict(request.session)}")
|
|
except Exception as e:
|
|
print(f"Error in debug middleware (pre): {str(e)}")
|
|
|
|
response = await call_next(request)
|
|
|
|
try:
|
|
if hasattr(request, "session"):
|
|
print(f"Session data after: {dict(request.session)}")
|
|
except Exception as e:
|
|
print(f"Error in debug middleware (post): {str(e)}")
|
|
|
|
return response
|
|
|
|
# User context middleware
|
|
@app.middleware("http")
|
|
async def add_user_to_request(request: Request, call_next):
|
|
"""Add user to request state and update template globals"""
|
|
try:
|
|
# Get database connection from context
|
|
from .db import SessionLocal
|
|
db = SessionLocal()
|
|
|
|
# Get user from session with safer approach
|
|
user = None
|
|
try:
|
|
user = get_user_from_session(request, db)
|
|
except Exception as e:
|
|
print(f"Error getting user for request context: {str(e)}")
|
|
|
|
# Store user in request.state for route handlers
|
|
request.state.user = user
|
|
|
|
# Update template globals for all templates
|
|
templates.env.globals["current_user"] = user
|
|
|
|
# Debug output to check user and admin status
|
|
if user:
|
|
print(f"User in context: {user.username}, Admin: {getattr(user, 'is_admin', False)}")
|
|
except Exception as e:
|
|
print(f"Error setting user context: {str(e)}")
|
|
finally:
|
|
# Always close the DB connection
|
|
if 'db' in locals():
|
|
db.close()
|
|
|
|
# Process the request
|
|
response = await call_next(request)
|
|
return response
|
|
|
|
# Routers - include after middleware setup is complete
|
|
app.include_router(auth_router, prefix="/auth", tags=["Auth"])
|
|
app.include_router(qr.router, prefix="/qr", tags=["QR"])
|
|
app.include_router(redeem.router, prefix="/redeem", tags=["Redeem"])
|
|
app.include_router(teams.router, prefix="/teams", tags=["Teams"])
|
|
app.include_router(admin.router, prefix="/admin", tags=["Admin"])
|
|
app.include_router(leaderboard.router, prefix="/leaderboard", tags=["Leaderboard"])
|
|
app.include_router(dashboard.router, prefix="/dashboard", tags=["Dashboard"])
|
|
|
|
@app.get("/", response_class=HTMLResponse)
|
|
def index(request: Request):
|
|
return templates.TemplateResponse("index.html", {
|
|
"request": request,
|
|
"now": datetime.now
|
|
})
|
|
|
|
@app.get("/about", response_class=HTMLResponse)
|
|
def about(request: Request):
|
|
return templates.TemplateResponse("about.html", {
|
|
"request": request
|
|
})
|
|
|
|
@app.get("/contact", response_class=HTMLResponse)
|
|
def contact(request: Request):
|
|
return templates.TemplateResponse("contact.html", {
|
|
"request": request
|
|
})
|
|
|
|
@app.get("/privacy", response_class=HTMLResponse)
|
|
def privacy(request: Request):
|
|
return templates.TemplateResponse("privacy.html", {
|
|
"request": request
|
|
})
|
|
|
|
@app.get("/terms", response_class=HTMLResponse)
|
|
def terms(request: Request):
|
|
return templates.TemplateResponse("terms.html", {
|
|
"request": request
|
|
})
|