""" Focolari Voting System - API Routes """ import time from fastapi import APIRouter, HTTPException from schemas import ( LoginRequest, EntryRequest, UserResponse, RoomInfoResponse, LoginResponse, EntryResponse, ) router = APIRouter() # Timestamp di avvio del server (per invalidare sessioni frontend) SERVER_START_TIME = int(time.time() * 1000) # Dati caricati dinamicamente dal main _data = { "validator_password": "", "room": {"room_name": "", "meeting_id": ""}, "users": [] } # Caratteri sentinel da pulire (tutti i layout supportati) SENTINEL_CHARS = [";", "?", "ò", "_", "ç", "+"] def init_data(data: dict): """Inizializza i dati caricati dal file JSON""" global _data _data = data def clean_badge(badge: str) -> str: """Rimuove i caratteri sentinel dal badge""" clean = badge.strip() for char in SENTINEL_CHARS: clean = clean.replace(char, "") return clean def find_user(badge_code: str) -> dict | None: """Cerca un utente per badge code (confronto esatto come stringa)""" clean = clean_badge(badge_code) for user in _data["users"]: # Confronto esatto: il badge è una stringa, non un numero if user["badge_code"] == clean: return user return None @router.get("/api/info-room", response_model=RoomInfoResponse) async def get_room_info(): """Restituisce le informazioni sulla sala e la riunione corrente.""" return RoomInfoResponse( room_name=_data["room"]["room_name"], meeting_id=_data["room"]["meeting_id"], server_start_time=SERVER_START_TIME ) @router.post("/api/login-validate", response_model=LoginResponse) async def login_validate(request: LoginRequest): """ Valida la password del validatore. Il badge viene passato dal frontend ma attualmente non viene verificato lato server - serve solo per essere memorizzato nella sessione frontend. TODO: Concordare con committenti se il badge debba essere verificato anche lato server (es. lista badge validatori autorizzati). """ if request.password != _data["validator_password"]: raise HTTPException( status_code=401, detail="Password non corretta" ) # Il badge viene restituito per conferma, ma non è validato lato server clean = clean_badge(request.badge) if request.badge else "unknown" return LoginResponse( success=True, message="Login validatore effettuato con successo" ) @router.get("/api/anagrafica/{badge_code}", response_model=UserResponse) async def get_user_anagrafica(badge_code: str): """ Cerca un utente tramite il suo badge code. """ user = find_user(badge_code) if not user: clean = clean_badge(badge_code) raise HTTPException( status_code=404, detail=f"Utente con badge {clean} non trovato nel sistema" ) response = UserResponse( badge_code=user["badge_code"], nome=user["nome"], cognome=user["cognome"], url_foto=user["url_foto"], ruolo=user["ruolo"], ammesso=user["ammesso"] ) if not user["ammesso"]: response.warning = "ATTENZIONE: Questo utente NON è autorizzato all'ingresso!" return response @router.post("/api/entry-request", response_model=EntryResponse) async def process_entry_request(request: EntryRequest): """ Processa una richiesta di ingresso. Risposta asettica senza messaggi multilingua. """ if request.validator_password != _data["validator_password"]: raise HTTPException( status_code=401, detail="Password validatore non corretta" ) user = find_user(request.user_badge) if not user: clean = clean_badge(request.user_badge) raise HTTPException( status_code=404, detail=f"Utente con badge {clean} non trovato" ) if not user["ammesso"]: raise HTTPException( status_code=403, detail=f"L'utente {user['nome']} {user['cognome']} NON è autorizzato all'ingresso" ) return EntryResponse( success=True, message=f"Ingresso registrato per {user['nome']} {user['cognome']}" )