from flask_socketio import emit, join_room, leave_room from backend.app import socketio from backend.auth.middleware import validate_jwt from backend.models import User @socketio.on('connect') def handle_connect(auth): """Handle client connection with JWT authentication""" # Extract token from auth parameter token = auth.get('token') if auth else None if not token: print('Connection rejected: No token provided') return False # Reject connection # Validate JWT claims = validate_jwt(token) if not claims: print('Connection rejected: Invalid token') return False # Reject connection # Get user user = User.query.filter_by(authelia_sub=claims['sub']).first() if not user or not user.is_active: print('Connection rejected: User not found or inactive') return False print(f'Client connected: {user.email}') emit('connected', { 'message': 'Connected to trivia game server', 'user': user.to_dict() }) @socketio.on('disconnect') def handle_disconnect(): """Handle client disconnection""" print('Client disconnected') @socketio.on('join_game') def handle_join_game(data): """Handle client joining a game room with role validation Expected data: { 'game_id': int, 'role': 'contestant' | 'admin', 'token': str } """ game_id = data.get('game_id') role = data.get('role', 'contestant') token = data.get('token') if not game_id or not token: emit('error', {'message': 'game_id and token are required'}) return # Validate JWT claims = validate_jwt(token) if not claims: emit('error', {'message': 'Invalid or expired token'}) return # Get user user = User.query.filter_by(authelia_sub=claims['sub']).first() if not user or not user.is_active: emit('error', {'message': 'User not found or inactive'}) return # Join appropriate room based on role if role == 'admin': room = f'game_{game_id}_admin' join_room(room) print(f'User {user.email} joined admin room: {room}') emit('joined', { 'game_id': game_id, 'room': 'admin', 'user': user.to_dict(), 'message': f'Joined admin room for game {game_id}' }) else: room = f'game_{game_id}_contestant' join_room(room) print(f'User {user.email} joined contestant room: {room}') emit('joined', { 'game_id': game_id, 'room': 'contestant', 'user': user.to_dict(), 'message': f'Joined contestant room for game {game_id}' }) @socketio.on('leave_game') def handle_leave_game(data): """Handle client leaving a game room Expected data: { 'game_id': int, 'role': 'contestant' | 'admin' } """ game_id = data.get('game_id') role = data.get('role', 'contestant') if not game_id: emit('error', {'message': 'game_id is required'}) return # Leave appropriate room based on role if role == 'admin': room = f'game_{game_id}_admin' leave_room(room) print(f'Client left admin room: {room}') else: room = f'game_{game_id}_contestant' leave_room(room) print(f'Client left contestant room: {room}') emit('left', {'game_id': game_id, 'message': f'Left game {game_id}'})