121 lines
3.2 KiB
Python
121 lines
3.2 KiB
Python
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
from typing import List, Optional
|
|
from enum import Enum
|
|
|
|
|
|
class Environment(str, Enum):
|
|
DEVELOPMENT = "development"
|
|
STAGING = "staging"
|
|
PRODUCTION = "production"
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
model_config = SettingsConfigDict(
|
|
env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="ignore"
|
|
)
|
|
|
|
# === Environment ===
|
|
environment: Environment = Environment.DEVELOPMENT
|
|
|
|
# === JWT & Auth ===
|
|
jwt_secret: str
|
|
jwt_algorithm: str = "HS256"
|
|
access_token_expire_minutes: int = 15
|
|
refresh_token_expire_days: int = 7
|
|
csrf_token_expire_minutes: int = 60
|
|
|
|
# === Cookie Settings ===
|
|
cookie_domain: Optional[str] = None
|
|
cookie_secure: bool = True
|
|
cookie_samesite: str = "strict"
|
|
cookie_httponly: bool = True
|
|
cookie_access_token_name: str = "access_token"
|
|
cookie_refresh_token_name: str = "refresh_token"
|
|
cookie_csrf_token_name: str = "csrf_token"
|
|
|
|
# === Redis (Token Blacklist & Rate Limiting) ===
|
|
redis_url: str = "redis://localhost:6379/0"
|
|
redis_password: Optional[str] = None
|
|
redis_ssl: bool = False
|
|
token_blacklist_prefix: str = "blacklist:"
|
|
rate_limit_prefix: str = "ratelimit:"
|
|
|
|
# === Rate Limiting ===
|
|
rate_limit_login_attempts: int = 5
|
|
rate_limit_login_window_minutes: int = 15
|
|
rate_limit_api_requests: int = 100
|
|
rate_limit_api_window_seconds: int = 60
|
|
|
|
# === Security ===
|
|
password_min_length: int = 8
|
|
password_require_uppercase: bool = True
|
|
password_require_lowercase: bool = True
|
|
password_require_digit: bool = True
|
|
password_require_special: bool = True
|
|
account_lockout_threshold: int = 5
|
|
account_lockout_duration_minutes: int = 30
|
|
|
|
# === Fingerprint ===
|
|
fingerprint_secret: str = ""
|
|
fingerprint_components: List[str] = [
|
|
"user_agent",
|
|
"accept_language",
|
|
"accept_encoding",
|
|
]
|
|
|
|
# === Refresh Token Rotation ===
|
|
refresh_token_rotation_enabled: bool = True
|
|
refresh_token_reuse_window_seconds: int = 10
|
|
|
|
# === Sage Types ===
|
|
SAGE_TYPE_DEVIS: int = 0
|
|
SAGE_TYPE_BON_COMMANDE: int = 10
|
|
SAGE_TYPE_PREPARATION: int = 20
|
|
SAGE_TYPE_BON_LIVRAISON: int = 30
|
|
SAGE_TYPE_BON_RETOUR: int = 40
|
|
SAGE_TYPE_BON_AVOIR: int = 50
|
|
SAGE_TYPE_FACTURE: int = 60
|
|
|
|
# === Sage Gateway ===
|
|
sage_gateway_url: str
|
|
sage_gateway_token: str
|
|
frontend_url: str
|
|
|
|
# === Database ===
|
|
database_url: str = "sqlite+aiosqlite:///./data/sage_dataven.db"
|
|
|
|
# === SMTP ===
|
|
smtp_host: str
|
|
smtp_port: int = 587
|
|
smtp_user: str
|
|
smtp_password: str
|
|
smtp_from: str
|
|
smtp_use_tls: bool = True
|
|
|
|
# === Universign ===
|
|
universign_api_key: str
|
|
universign_api_url: str
|
|
|
|
# === API ===
|
|
api_host: str = "0.0.0.0"
|
|
api_port: int = 8000
|
|
api_reload: bool = True
|
|
|
|
# === Email Queue ===
|
|
max_email_workers: int = 3
|
|
max_retry_attempts: int = 3
|
|
retry_delay_seconds: int = 3
|
|
|
|
# === CORS ===
|
|
cors_origins: List[str] = ["*"]
|
|
|
|
@property
|
|
def is_production(self) -> bool:
|
|
return self.environment == Environment.PRODUCTION
|
|
|
|
@property
|
|
def is_development(self) -> bool:
|
|
return self.environment == Environment.DEVELOPMENT
|
|
|
|
|
|
settings = Settings()
|