Files
Focolari-Voting-System/backend-mock/main.py

192 lines
5.8 KiB
Python

"""
Focolari Voting System - Backend Mock
Sistema di controllo accessi per votazioni del Movimento dei Focolari
Utilizzo:
python main.py # Default: porta 8000, dati default
python main.py -p 9000 # Porta custom
python main.py -d data/users_test.json # Dataset custom
python main.py -p 9000 -d data/users_test.json
"""
import argparse
import json
import sys
from pathlib import Path
import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from api.routes import router, init_data
# Configurazione default
DEFAULT_PORT = 8000
DEFAULT_HOST = "0.0.0.0"
DEFAULT_DATA = "data/users_default.json"
STATIC_DIR = Path(__file__).parent.parent / "frontend" / "dist"
def load_data(data_path: str) -> dict:
"""Carica i dati dal file JSON"""
path = Path(data_path)
if not path.is_absolute():
# Path relativo alla directory del main.py
base_dir = Path(__file__).parent
path = base_dir / path
if not path.exists():
print(f"❌ Errore: File dati non trovato: {path}")
sys.exit(1)
try:
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
print(f"📂 Dati caricati da: {path}")
print(f" - Password validatore: {'*' * len(data['validator_password'])}")
print(f" - Sala: {data['room']['room_name']}")
print(f" - Utenti: {len(data['users'])}")
return data
except json.JSONDecodeError as e:
print(f"❌ Errore parsing JSON: {e}")
sys.exit(1)
except KeyError as e:
print(f"❌ Errore struttura JSON: chiave mancante {e}")
sys.exit(1)
def create_app(data: dict, serve_frontend: bool = True) -> FastAPI:
"""Crea e configura l'applicazione FastAPI"""
app = FastAPI(
title="Focolari Voting System API",
description="Backend mock per il sistema di controllo accessi",
version="1.0.0"
)
# CORS abilitato per tutti (utile in sviluppo)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Inizializza i dati nelle routes
init_data(data)
# Registra le routes API
app.include_router(router)
# Serve frontend statico se la cartella esiste
if serve_frontend and STATIC_DIR.exists():
print(f"🌐 Frontend statico servito da: {STATIC_DIR}")
# Serve index.html su /badge e sue sub-route
@app.get("/badge")
async def serve_badge_index():
return FileResponse(STATIC_DIR / "index.html")
@app.get("/badge/debug")
async def serve_badge_debug():
return FileResponse(STATIC_DIR / "index.html")
# Monta i file statici (JS, CSS, assets) sotto /badge
app.mount("/badge/assets", StaticFiles(directory=STATIC_DIR / "assets"), name="assets")
# Fallback per altri file statici sotto /badge (favicon, ecc.)
@app.get("/badge/{filename:path}")
async def serve_static(filename: str):
file_path = STATIC_DIR / filename
if file_path.exists() and file_path.is_file():
return FileResponse(file_path)
# Per route SPA sconosciute, serve index.html
return FileResponse(STATIC_DIR / "index.html")
else:
# API-only mode
@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",
"room": data["room"]["room_name"],
"frontend": "not built - run 'npm run build' in frontend/"
}
return app
def parse_args():
"""Parse degli argomenti da linea di comando"""
parser = argparse.ArgumentParser(
description="Focolari Voting System - Backend Mock Server",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Esempi:
python main.py # Avvio standard
python main.py -p 9000 # Porta 9000
python main.py -d data/users_test.json # Dataset test
python main.py --host 127.0.0.1 -p 8080 # Solo localhost
python main.py --api-only # Solo API, no frontend
"""
)
parser.add_argument(
"-p", "--port",
type=int,
default=DEFAULT_PORT,
help=f"Porta del server (default: {DEFAULT_PORT})"
)
parser.add_argument(
"-d", "--data",
type=str,
default=DEFAULT_DATA,
help=f"Path al file JSON con i dati (default: {DEFAULT_DATA})"
)
parser.add_argument(
"--host",
type=str,
default=DEFAULT_HOST,
help=f"Host di binding (default: {DEFAULT_HOST})"
)
parser.add_argument(
"--api-only",
action="store_true",
help="Avvia solo le API senza servire il frontend"
)
return parser.parse_args()
def main():
"""Entry point principale"""
args = parse_args()
print("🚀 Avvio Focolari Voting System Backend...")
print("=" * 50)
# Carica i dati
data = load_data(args.data)
print("=" * 50)
print(f"📍 Server in ascolto su http://{args.host}:{args.port}")
print(f"📚 Documentazione API su http://{args.host}:{args.port}/docs")
if not args.api_only and STATIC_DIR.exists():
print(f"🌐 Frontend disponibile su http://{args.host}:{args.port}/badge")
print("=" * 50)
# Crea e avvia l'app
app = create_app(data, serve_frontend=not args.api_only)
uvicorn.run(app, host=args.host, port=args.port)
if __name__ == "__main__":
main()