|
|
""" |
|
|
Configuration settings loaded from environment variables. |
|
|
Never hardcode credentials or secrets. |
|
|
""" |
|
|
|
|
|
import os |
|
|
from typing import Optional |
|
|
|
|
|
|
|
|
class Settings: |
|
|
""" |
|
|
Application settings with sensible defaults. |
|
|
Override via environment variables. |
|
|
""" |
|
|
|
|
|
|
|
|
SUPABASE_URL: str = os.getenv("SUPABASE_URL", "") |
|
|
SUPABASE_KEY: str = os.getenv("SUPABASE_KEY", "") |
|
|
SUPABASE_TABLE: str = os.getenv("SUPABASE_TABLE", "proofs") |
|
|
|
|
|
|
|
|
HASH_ALGORITHM: str = os.getenv("HASH_ALGORITHM", "sha256") |
|
|
|
|
|
|
|
|
MAX_FILE_SIZE_MB: int = int(os.getenv("MAX_FILE_SIZE_MB", "10")) |
|
|
ALLOWED_CONTENT_TYPES: list = [ |
|
|
"text/plain", |
|
|
"application/pdf", |
|
|
"image/png", |
|
|
"image/jpeg", |
|
|
"application/json", |
|
|
] |
|
|
|
|
|
|
|
|
OCR_ENABLED: bool = os.getenv("OCR_ENABLED", "true").lower() == "true" |
|
|
OCR_LANGUAGE: str = os.getenv("OCR_LANGUAGE", "eng") |
|
|
|
|
|
|
|
|
AI_ENABLED: bool = os.getenv("AI_ENABLED", "false").lower() == "true" |
|
|
GEMINI_API_KEY: str = os.getenv("GEMINI_API_KEY", "") |
|
|
GEMINI_MODEL: str = os.getenv("GEMINI_MODEL", "gemini-1.5-flash") |
|
|
GEMINI_TIMEOUT: int = int(os.getenv("GEMINI_TIMEOUT", "10")) |
|
|
|
|
|
@classmethod |
|
|
def validate(cls) -> bool: |
|
|
""" |
|
|
Check if required settings are present. |
|
|
Returns True if valid, False otherwise. |
|
|
""" |
|
|
if not cls.SUPABASE_URL or not cls.SUPABASE_KEY: |
|
|
return False |
|
|
return True |
|
|
|
|
|
@classmethod |
|
|
def validate_ai(cls) -> bool: |
|
|
""" |
|
|
Check if AI sidecar is properly configured. |
|
|
Returns True if AI can be enabled, False otherwise. |
|
|
""" |
|
|
if not cls.AI_ENABLED: |
|
|
return False |
|
|
if not cls.GEMINI_API_KEY: |
|
|
return False |
|
|
return True |
|
|
|
|
|
@classmethod |
|
|
def get_max_file_size_bytes(cls) -> int: |
|
|
"""Get max file size in bytes.""" |
|
|
return cls.MAX_FILE_SIZE_MB * 1024 * 1024 |
|
|
|
|
|
|
|
|
|
|
|
settings = Settings() |