refactor(uploads): centralize upload byte-limits in upload_limits.py (#3364) (#3518)

Move every per-route upload byte-limit into src/upload_limits.py as a
validated, env-overridable constant via read_byte_limit_env:

- Add GALLERY_UPLOAD_MAX_BYTES, GALLERY_TRANSFORM_UPLOAD_MAX_BYTES,
  MEMORY_IMPORT_MAX_BYTES, PERSONAL_UPLOAD_MAX_BYTES,
  EMAIL_COMPOSE_UPLOAD_MAX_BYTES, STT_MAX_AUDIO_BYTES, ICS_MAX_BYTES.
- Routes import their constant instead of defining it locally: replaces 4
  raw int(os.getenv(...)) and removes 3 hardcoded literals.
- The 3 previously-hardcoded limits (email compose, STT audio, calendar
  ICS) are now env-overridable with the same ODYSSEUS_*_MAX_BYTES naming.
- Defaults unchanged, so behavior is unchanged unless an env var is set;
  an invalid value now fails fast with a clear message instead of a bare
  int() ValueError.
- Document all env vars in .env.example and the README.

Fixes #3364
This commit is contained in:
Kenny Van de Maele
2026-06-09 01:24:30 +02:00
committed by GitHub
parent a240f28af9
commit 2404b00f18
11 changed files with 174 additions and 22 deletions
+5 -5
View File
@@ -13,7 +13,7 @@ from dateutil.rrule import rrulestr
from core.database import SessionLocal, CalendarCal, CalendarEvent
from src.auth_helpers import require_user
from src.upload_limits import read_upload_limited
from src.upload_limits import read_upload_limited, ICS_MAX_BYTES
logger = logging.getLogger(__name__)
@@ -1170,9 +1170,9 @@ def setup_calendar_routes() -> APIRouter:
finally:
db.close()
# 10 MB hard cap on ICS upload. Loading the whole file into memory is
# unavoidable with python-icalendar, so an unbounded upload would OOM.
_ICS_MAX_BYTES = 10 * 1024 * 1024
# Hard cap on ICS upload (ICS_MAX_BYTES, default 10 MB). Loading the whole
# file into memory is unavoidable with python-icalendar, so an unbounded
# upload would OOM.
@router.post("/import")
async def import_ics(request: Request, file: UploadFile = File(...), calendar_name: str = ""):
@@ -1182,7 +1182,7 @@ def setup_calendar_routes() -> APIRouter:
owner = _require_user(request)
db = SessionLocal()
try:
content = await read_upload_limited(file, _ICS_MAX_BYTES, "ICS file")
content = await read_upload_limited(file, ICS_MAX_BYTES, "ICS file")
try:
cal_data = iCal.from_ical(content)
except Exception as e: