@@ -0,0 +1,46 @@
|
||||
"""Environment configuration; production fails closed without upload authentication."""
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Settings:
|
||||
environment: str
|
||||
database_url: str
|
||||
storage_dir: Path
|
||||
api_key: str
|
||||
public_url: str
|
||||
max_upload_bytes: int
|
||||
parse_timeout: int
|
||||
link_ttl: int
|
||||
max_pending: int
|
||||
s3_bucket: str
|
||||
s3_endpoint: str | None
|
||||
s3_region: str
|
||||
|
||||
@lru_cache
|
||||
def settings():
|
||||
root = Path(os.getenv('STORAGE_DIR', './data')).resolve()
|
||||
config = Settings(
|
||||
environment=os.getenv('APP_ENV', 'development'),
|
||||
database_url=os.getenv('DATABASE_URL', f'sqlite:///{root}/jobs.db'),
|
||||
storage_dir=root,
|
||||
api_key=os.getenv('API_KEY', ''),
|
||||
public_url=os.getenv('PUBLIC_BASE_URL', 'http://127.0.0.1:8000').rstrip('/'),
|
||||
max_upload_bytes=int(os.getenv('MAX_UPLOAD_BYTES', str(32 * 1024 * 1024))),
|
||||
parse_timeout=int(os.getenv('PARSE_TIMEOUT_SECONDS', '60')),
|
||||
link_ttl=int(os.getenv('LINK_TTL_SECONDS', '604800')),
|
||||
max_pending=int(os.getenv('MAX_PENDING_JOBS', '100')),
|
||||
s3_bucket=os.getenv('S3_BUCKET', ''),
|
||||
s3_endpoint=os.getenv('S3_ENDPOINT_URL') or None,
|
||||
s3_region=os.getenv('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
)
|
||||
if config.environment == 'production' and len(config.api_key) < 32:
|
||||
raise RuntimeError('Production requires API_KEY with at least 32 characters')
|
||||
if config.environment == 'production' and not config.public_url.startswith('https://'):
|
||||
raise RuntimeError('Production requires an HTTPS PUBLIC_BASE_URL')
|
||||
if min(config.max_upload_bytes, config.parse_timeout, config.link_ttl, config.max_pending) <= 0:
|
||||
raise RuntimeError('Upload, parse, expiry and queue limits must be positive')
|
||||
root.mkdir(parents=True, exist_ok=True, mode=0o700)
|
||||
return config
|
||||
مرجع در شماره جدید
مسدود کردن کاربر