115 lines
3.3 KiB
Python
115 lines
3.3 KiB
Python
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}'})
|