Backend: - Nouveau module auth.py avec JWT et password handling - Endpoint /api/auth/login (public) - Endpoint /api/auth/me (protégé) - TOUS les endpoints API protégés par require_auth - Variables env: ADMIN_EMAIL, ADMIN_PASSWORD, JWT_SECRET_KEY - Dependencies: python-jose, passlib Frontend: - Page de login (/login) - AuthGuard component pour redirection automatique - Axios interceptor: ajoute JWT token à chaque requête - Gestion erreur 401: redirect automatique vers /login - Bouton logout dans header - Token stocké dans localStorage Configuration: - .env.example mis à jour avec variables auth - Credentials admin configurables via env Sécurité: - Aucun endpoint public (sauf /api/auth/login et /health) - JWT expiration configurable (24h par défaut) - Password en clair dans env (à améliorer avec hash en prod) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
55 lines
1.6 KiB
Python
55 lines
1.6 KiB
Python
"""Application configuration using Pydantic Settings."""
|
|
from typing import List
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""Application settings loaded from environment variables."""
|
|
|
|
# Database
|
|
DATABASE_URL: str = "postgresql://audio_user:audio_password@localhost:5432/audio_classifier"
|
|
|
|
# API Configuration
|
|
# Comma-separated list of allowed origins, or use "*" to allow all
|
|
CORS_ORIGINS: str = "*"
|
|
API_HOST: str = "0.0.0.0"
|
|
API_PORT: int = 8000
|
|
|
|
# Audio Analysis Configuration
|
|
ANALYSIS_USE_CLAP: bool = False
|
|
ANALYSIS_NUM_WORKERS: int = 4
|
|
ESSENTIA_MODELS_PATH: str = "./models"
|
|
AUDIO_LIBRARY_PATH: str = "/audio"
|
|
|
|
# Authentication
|
|
ADMIN_EMAIL: str = "admin@example.com"
|
|
ADMIN_PASSWORD: str = "changeme"
|
|
JWT_SECRET_KEY: str = "your-secret-key-change-in-production"
|
|
JWT_EXPIRATION_HOURS: int = 24
|
|
|
|
# Application
|
|
APP_NAME: str = "Audio Classifier API"
|
|
APP_VERSION: str = "1.0.0"
|
|
DEBUG: bool = False
|
|
|
|
model_config = SettingsConfigDict(
|
|
env_file=".env",
|
|
env_file_encoding="utf-8",
|
|
case_sensitive=True
|
|
)
|
|
|
|
@property
|
|
def cors_origins_list(self) -> List[str]:
|
|
"""Parse CORS origins string to list.
|
|
|
|
If CORS_ORIGINS is "*", allow all origins.
|
|
Otherwise, parse comma-separated list.
|
|
"""
|
|
if self.CORS_ORIGINS.strip() == "*":
|
|
return ["*"]
|
|
return [origin.strip() for origin in self.CORS_ORIGINS.split(",")]
|
|
|
|
|
|
# Global settings instance
|
|
settings = Settings()
|