""" Focolari Voting System - Backend Mock Sistema di controllo accessi per votazioni del Movimento dei Focolari """ import random from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from typing import Optional app = FastAPI( title="Focolari Voting System API", description="Backend mock per il sistema di controllo accessi", version="1.0.0" ) # CORS abilitato per tutti app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # ============================================ # MODELLI PYDANTIC # ============================================ class LoginRequest(BaseModel): badge: str password: str class EntryRequest(BaseModel): user_badge: str validator_password: str class UserResponse(BaseModel): badge_code: str nome: str cognome: str url_foto: str ruolo: str ammesso: bool warning: Optional[str] = None class RoomInfoResponse(BaseModel): room_name: str meeting_id: str class LoginResponse(BaseModel): success: bool message: str token: Optional[str] = None class EntryResponse(BaseModel): success: bool message: str welcome_message: Optional[str] = None # ============================================ # DATI MOCK # ============================================ # Credenziali Validatore VALIDATOR_BADGE = "999999" VALIDATOR_PASSWORD = "focolari" MOCK_TOKEN = "focolare-validator-token-2024" # Lista utenti mock USERS_DB = [ { "badge_code": "000001", "nome": "Maria", "cognome": "Rossi", "url_foto": "https://randomuser.me/api/portraits/women/1.jpg", "ruolo": "Votante", "ammesso": True }, { "badge_code": "000002", "nome": "Giuseppe", "cognome": "Bianchi", "url_foto": "https://randomuser.me/api/portraits/men/2.jpg", "ruolo": "Votante", "ammesso": True }, { "badge_code": "000003", "nome": "Anna", "cognome": "Verdi", "url_foto": "https://randomuser.me/api/portraits/women/3.jpg", "ruolo": "Tecnico", "ammesso": True }, { "badge_code": "000004", "nome": "Francesco", "cognome": "Neri", "url_foto": "https://randomuser.me/api/portraits/men/4.jpg", "ruolo": "Ospite", "ammesso": False # Non ammesso! }, { "badge_code": "000005", "nome": "Lucia", "cognome": "Gialli", "url_foto": "https://randomuser.me/api/portraits/women/5.jpg", "ruolo": "Votante", "ammesso": True }, { "badge_code": "000006", "nome": "Paolo", "cognome": "Blu", "url_foto": "https://randomuser.me/api/portraits/men/6.jpg", "ruolo": "Votante", "ammesso": False # Non ammesso! }, { "badge_code": "123456", "nome": "Teresa", "cognome": "Martini", "url_foto": "https://randomuser.me/api/portraits/women/7.jpg", "ruolo": "Votante", "ammesso": True }, ] # Messaggi di benvenuto multilingua WELCOME_MESSAGES = [ "Benvenuto! / Welcome!", "Bienvenue! / Willkommen!", "Bienvenido! / Bem-vindo!", "欢迎! / 歓迎!", "Добро пожаловать! / مرحبا!" ] # ============================================ # ENDPOINTS # ============================================ @app.get("/") async def root(): """Endpoint di test per verificare che il server sia attivo""" return {"status": "ok", "message": "Focolari Voting System API is running"} @app.get("/info-room", response_model=RoomInfoResponse) async def get_room_info(): """ Restituisce le informazioni sulla sala e la riunione corrente. """ return RoomInfoResponse( room_name="Sala Assemblea", meeting_id="VOT-2024" ) @app.post("/login-validate", response_model=LoginResponse) async def login_validate(request: LoginRequest): """ Valida le credenziali del validatore. Il badge deve essere quello del validatore (999999) e la password corretta. """ # Pulisci il badge da eventuali caratteri sentinel clean_badge = request.badge.strip().replace(";", "").replace("?", "") if clean_badge != VALIDATOR_BADGE: raise HTTPException( status_code=401, detail="Badge validatore non riconosciuto" ) if request.password != VALIDATOR_PASSWORD: raise HTTPException( status_code=401, detail="Password non corretta" ) return LoginResponse( success=True, message="Login validatore effettuato con successo", token=MOCK_TOKEN ) @app.get("/anagrafica/{badge_code}", response_model=UserResponse) async def get_user_anagrafica(badge_code: str): """ Cerca un utente tramite il suo badge code. Restituisce i dati anagrafici e un warning se non è ammesso. """ # Pulisci il badge da eventuali caratteri sentinel clean_badge = badge_code.strip().replace(";", "").replace("?", "") # Normalizza: rimuovi zeri iniziali per il confronto, ma cerca anche con zeri for user in USERS_DB: if user["badge_code"] == clean_badge or user["badge_code"].lstrip("0") == clean_badge.lstrip("0"): response = UserResponse( badge_code=user["badge_code"], nome=user["nome"], cognome=user["cognome"], url_foto=user["url_foto"], ruolo=user["ruolo"], ammesso=user["ammesso"] ) # Aggiungi warning se non ammesso if not user["ammesso"]: response.warning = "ATTENZIONE: Questo utente NON è autorizzato all'ingresso!" return response # Utente non trovato raise HTTPException( status_code=404, detail=f"Utente con badge {clean_badge} non trovato nel sistema" ) @app.post("/entry-request", response_model=EntryResponse) async def process_entry_request(request: EntryRequest): """ Processa una richiesta di ingresso. Richiede il badge dell'utente e la password del validatore. """ # Pulisci i dati clean_user_badge = request.user_badge.strip().replace(";", "").replace("?", "") # Verifica password validatore if request.validator_password != VALIDATOR_PASSWORD: raise HTTPException( status_code=401, detail="Password validatore non corretta" ) # Cerca l'utente user_found = None for user in USERS_DB: if user["badge_code"] == clean_user_badge or user["badge_code"].lstrip("0") == clean_user_badge.lstrip("0"): user_found = user break if not user_found: raise HTTPException( status_code=404, detail=f"Utente con badge {clean_user_badge} non trovato" ) if not user_found["ammesso"]: raise HTTPException( status_code=403, detail=f"L'utente {user_found['nome']} {user_found['cognome']} NON è autorizzato all'ingresso" ) # Successo! Genera messaggio di benvenuto casuale welcome = random.choice(WELCOME_MESSAGES) return EntryResponse( success=True, message=f"Ingresso registrato per {user_found['nome']} {user_found['cognome']}", welcome_message=welcome ) # ============================================ # AVVIO SERVER # ============================================ if __name__ == "__main__": import uvicorn print("🚀 Avvio Focolari Voting System Backend...") print("📍 Server in ascolto su http://localhost:8000") print("📚 Documentazione API su http://localhost:8000/docs") uvicorn.run(app, host="0.0.0.0", port=8000)