Implement Phase 1: Session Management and Dashboard

This commit is contained in:
Jo Eskil
2025-11-13 17:08:24 +01:00
parent 382f0ec782
commit 90a40381ab
3 changed files with 67 additions and 5 deletions

13
auth.py
View File

@@ -4,12 +4,17 @@ from fastapi.responses import RedirectResponse
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
import httpx import httpx
from database import get_db, User from database import get_db, User
from itsdangerous import URLSafeTimedSerializer
# IMPORTANT: These must be replaced with your actual Twitch application credentials # IMPORTANT: These must be replaced with your actual Twitch application credentials
TWITCH_CLIENT_ID = "YOUR_TWITCH_CLIENT_ID" TWITCH_CLIENT_ID = "YOUR_TWITCH_CLIENT_ID"
TWITCH_CLIENT_SECRET = "YOUR_TWITCH_CLIENT_SECRET" TWITCH_CLIENT_SECRET = "YOUR_TWITCH_CLIENT_SECRET"
REDIRECT_URI = "http://localhost:8000/auth/twitch/callback" REDIRECT_URI = "http://localhost:8000/auth/twitch/callback"
# IMPORTANT: This should be a long, random string kept secret in a production environment
SECRET_KEY = "YOUR_SECRET_KEY"
serializer = URLSafeTimedSerializer(SECRET_KEY)
router = APIRouter() router = APIRouter()
@router.get("/login/twitch") @router.get("/login/twitch")
@@ -75,5 +80,9 @@ async def auth_twitch_callback(code: str, db: Session = Depends(get_db)):
user.twitch_refresh_token = refresh_token # TODO: Encrypt this user.twitch_refresh_token = refresh_token # TODO: Encrypt this
db.commit() db.commit()
# TODO: Set a session cookie to keep the user logged in # Create a session cookie
return {"message": f"Successfully logged in as {twitch_username}"} response = RedirectResponse(url="/dashboard")
session_data = {"user_id": user.id}
session_cookie = serializer.dumps(session_data)
response.set_cookie(key="session", value=session_cookie)
return response

22
dashboard.html Normal file
View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<title>MultiChat Overlay Dashboard</title>
</head>
<body>
<h1>Welcome to your Dashboard</h1>
<p>This is your personalized dashboard. You can manage your connected accounts and configure your overlay here.</p>
<h2>Your Overlay URL</h2>
<p>Use this URL as a browser source in your streaming software:</p>
<pre id="overlay-url"></pre>
<script>
// In a real application, we would fetch the user's unique overlay URL
// from an API and display it here. For now, we'll just show a placeholder.
const overlayUrlElement = document.getElementById('overlay-url');
// This would be something like `http://localhost:8000/overlay/USER_ID`
overlayUrlElement.textContent = `http://localhost:8000/overlay/YOUR_USER_ID`;
</script>
</body>
</html>

37
main.py
View File

@@ -1,14 +1,38 @@
import asyncio import asyncio
import json import json
from fastapi import FastAPI, WebSocket from fastapi import FastAPI, WebSocket, Request, Depends
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse, RedirectResponse
from starlette.websockets import WebSocketDisconnect from starlette.websockets import WebSocketDisconnect
from starlette.middleware.base import BaseHTTPMiddleware
from sqlalchemy.orm import Session
from chat_listeners import listen_youtube_chat, listen_twitch_chat from chat_listeners import listen_youtube_chat, listen_twitch_chat
from auth import router as auth_router # Import the auth router from auth import router as auth_router, serializer
from database import get_db, User
app = FastAPI() app = FastAPI()
class SessionMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
response = await call_next(request)
session_cookie = request.cookies.get("session")
if session_cookie:
try:
data = serializer.loads(session_cookie, max_age=3600 * 24 * 7) # 1 week
db = next(get_db())
user = db.query(User).filter(User.id == data["user_id"]).first()
request.state.user = user
except Exception:
request.state.user = None
else:
request.state.user = None
return response
app.add_middleware(SessionMiddleware)
def get_current_user(request: Request):
return request.state.user
app.include_router(auth_router, prefix="/auth") # Include the auth router app.include_router(auth_router, prefix="/auth") # Include the auth router
connected_clients = [] connected_clients = []
@@ -40,6 +64,13 @@ async def get_login_page():
with open("login.html", "r") as f: with open("login.html", "r") as f:
return f.read() return f.read()
@app.get("/dashboard", response_class=HTMLResponse)
async def get_dashboard(user: User = Depends(get_current_user)):
if not user:
return RedirectResponse(url="/login")
with open("dashboard.html", "r") as f:
return f.read()
@app.get("/overlay", response_class=HTMLResponse) @app.get("/overlay", response_class=HTMLResponse)
async def get_overlay(): async def get_overlay():
with open("index.html", "r") as f: with open("index.html", "r") as f: