Implement OAuth login with Authentik integration, update user management, and enhance team functionalities

- Added OAuth login functionality using Authentik, allowing users to log in via OpenID.
- Updated user registration and login processes to handle OAuth users.
- Enhanced team management features, including joining and leaving teams, and displaying user-specific team information.
- Improved error handling and user feedback for team actions.
- Added new database migrations for OAuth-related fields in the users table.
- Updated templates to reflect changes in user authentication and team management.
- Refactored dashboard and leaderboard views to include user context and team memberships.
This commit is contained in:
Christian Krakau-Louis
2025-04-14 05:35:51 +02:00
parent fa41b24eac
commit 690065f788
15 changed files with 938 additions and 139 deletions
+46 -5
View File
@@ -6,16 +6,24 @@ from fastapi.templating import Jinja2Templates
from pathlib import Path
import os
from starlette.middleware.sessions import SessionMiddleware
from dotenv import load_dotenv
from .db import init_db, engine
from .db import init_db, engine, get_db
from . import models
from .templates_config import templates
from .views import qr, redeem, teams, admin, leaderboard, dashboard, static, pages
from .views import qr, redeem, teams, admin, leaderboard, dashboard, static, pages, auth
from .db_init import seed_db
from .db_migrations import apply_migrations
# Load environment variables
load_dotenv()
# Create tables on startup
init_db()
# Apply any pending database migrations
apply_migrations()
# Seed database with initial test data
# In a production app, you would handle this differently
seed_db()
@@ -24,7 +32,7 @@ seed_db()
app = FastAPI(title="LeagueLedger")
# Add SessionMiddleware with a secure secret key
app.add_middleware(SessionMiddleware, secret_key="your-very-secret-session-key")
app.add_middleware(SessionMiddleware, secret_key=os.getenv("SESSION_SECRET_KEY", "your-very-secret-session-key"))
# Mount static files
app.mount("/static", StaticFiles(directory="app/static"), name="static")
@@ -41,7 +49,15 @@ async def add_template_globals(request: Request, call_next):
"""Add template globals"""
try:
# Update template globals for all templates
templates.env.globals["current_user"] = None
user = None
if "user_id" in request.session and request.session.get("is_authenticated"):
# Mock user object - in a real app, you'd fetch this from the database
user = {
"id": request.session["user_id"],
"username": request.session.get("username", "User"),
"is_admin": request.session.get("is_admin", False)
}
templates.env.globals["current_user"] = user
except Exception as e:
print(f"Error setting template globals: {str(e)}")
@@ -51,13 +67,21 @@ async def add_template_globals(request: Request, call_next):
@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):
user = None
if "user_id" in request.session and request.session.get("is_authenticated"):
user = {
"id": request.session["user_id"],
"username": request.session.get("username", "User"),
"is_admin": request.session.get("is_admin", False)
}
return templates.TemplateResponse(
"index.html",
{"request": request, "user": None}
{"request": request, "user": user}
)
# Routers
app.include_router(pages.router, tags=["Pages"]) # Pages router for index and static pages
app.include_router(auth.router) # Include the auth router
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"])
@@ -70,3 +94,20 @@ app.include_router(static.router, tags=["Static"]) # Include the static router
@app.get("/scan")
async def scan_redirect():
return RedirectResponse("/redeem/scan", status_code=303)
# Add convenience routes for auth paths
@app.get("/login")
async def login_redirect():
return RedirectResponse("/auth/login", status_code=303)
@app.get("/register")
async def register_redirect():
return RedirectResponse("/auth/register", status_code=303)
@app.get("/profile")
async def profile_redirect():
return RedirectResponse("/auth/profile", status_code=303)
@app.get("/logout")
async def logout_redirect():
return RedirectResponse("/auth/logout", status_code=303)