Files
rehearshalhub/api/src/rehearsalhub/routers/ws.py
2026-04-08 15:10:52 +02:00

49 lines
1.6 KiB
Python
Executable File

"""WebSocket endpoint for real-time version room events."""
import uuid
from fastapi import APIRouter, Query, WebSocket, WebSocketDisconnect
from rehearsalhub.repositories.member import MemberRepository
from rehearsalhub.db.engine import get_session
from rehearsalhub.services.auth import decode_token
from rehearsalhub.ws import manager
router = APIRouter(tags=["websocket"])
@router.websocket("/ws/versions/{version_id}")
async def version_ws(
version_id: uuid.UUID,
websocket: WebSocket,
token: str | None = Query(None),
):
"""
WebSocket endpoint. Authentication via:
- ?token=<jwt> query parameter, or
- rh_token httpOnly cookie (sent automatically by the browser)
"""
raw_token = token or websocket.cookies.get("rh_token")
async for session in get_session():
try:
if not raw_token:
raise ValueError("no token")
payload = decode_token(raw_token)
member_id = uuid.UUID(payload["sub"])
member = await MemberRepository(session).get_by_id(member_id)
if member is None:
raise ValueError("member not found")
except Exception:
await websocket.close(code=4001)
return
await manager.connect(version_id, websocket)
try:
while True:
# Echo back any client pings; clients can send {"event": "ping"}
data = await websocket.receive_json()
if data.get("event") == "ping":
await websocket.send_json({"event": "pong"})
except WebSocketDisconnect:
manager.disconnect(version_id, websocket)