Files
TieMeasureFlow/server/config.py
T
Adriano dd2ebf863a feat: FASE 7 - Polish & Testing (security, i18n, test suite, docs)
Security hardening: CORS lockdown, rate limiting middleware con sliding
window e eviction IP stale, security headers (CSP, HSTS, X-Frame-Options),
session cookie hardening, filename sanitization upload.

i18n completion: internazionalizzati barcode.js e csv-export.js con bridge
window.BARCODE_I18N/CSV_I18N, aggiornati .po IT/EN con 27 nuove stringhe.

Tablet UX: touch target 44px per dispositivi coarse pointer.

Test suite: 101 test totali (76 server + 25 client), copertura completa
di tutti i router API, autenticazione, ruoli, CRUD, SPC, file upload,
security integration. Infrastruttura SQLite async in-memory con fixtures.

Fix critici: MissingGreenlet in recipe_service (selectinload eager),
route ordering tasks.py, auth_service bcrypt diretto, Measurement.id
Integer per SQLite.

Documentazione: API.md (riferimento completo 40+ endpoint),
DEPLOYMENT.md (guida produzione con Docker/Nginx/SSL),
USER_GUIDE.md (manuale utente per ruolo).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 17:10:24 +01:00

56 lines
1.5 KiB
Python

"""TieMeasureFlow Server Configuration."""
from pathlib import Path
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
"""Application settings loaded from environment variables."""
# Database
db_host: str = "localhost"
db_port: int = 3306
db_name: str = "tiemeasureflow"
db_user: str = "tmflow"
db_password: str = "change_me_in_production"
# Server
server_host: str = "0.0.0.0"
server_port: int = 8000
server_secret_key: str = "change-this-to-a-random-secret-key"
server_cors_origins: str = "http://localhost:5000"
# File Storage
upload_dir: str = "uploads"
max_upload_size_mb: int = 50
# Rate Limiting (requests per minute)
rate_limit_login: int = 5
rate_limit_general: int = 100
# SSL (Production)
ssl_certfile: str | None = None
ssl_keyfile: str | None = None
@property
def database_url(self) -> str:
"""Async MySQL connection string."""
return (
f"mysql+asyncmy://{self.db_user}:{self.db_password}"
f"@{self.db_host}:{self.db_port}/{self.db_name}"
)
@property
def cors_origins(self) -> list[str]:
"""Parse CORS origins from comma-separated string."""
return [origin.strip() for origin in self.server_cors_origins.split(",")]
@property
def upload_path(self) -> Path:
"""Absolute path to upload directory."""
return Path(__file__).parent / self.upload_dir
model_config = {"env_file": "../.env", "env_file_encoding": "utf-8"}
settings = Settings()