From c5aa31b825c30129073f9ef790199580275a5c4d Mon Sep 17 00:00:00 2001 From: Christian Date: Sun, 1 Mar 2026 20:01:11 +0100 Subject: [PATCH] fix: container_name uses STACK_NAME + ALLOWED_EXTENSIONS CSV parsing v2.2.13 --- VERSION | 2 +- app/billing/backend/supplier_invoices.py | 10 ++++++++-- app/core/config.py | 14 ++++++++++++++ docker-compose.prod.yml | 5 ++--- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/VERSION b/VERSION index 0b6e431..f2b42fc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.11 +2.2.13 diff --git a/app/billing/backend/supplier_invoices.py b/app/billing/backend/supplier_invoices.py index 8d7e0c3..575980d 100644 --- a/app/billing/backend/supplier_invoices.py +++ b/app/billing/backend/supplier_invoices.py @@ -1982,10 +1982,16 @@ async def upload_supplier_invoice(file: UploadFile = File(...)): try: # Validate file extension suffix = Path(file.filename).suffix.lower() - if suffix not in settings.ALLOWED_EXTENSIONS: + suffix_clean = suffix.lstrip('.') + # Build allowed set — guard against pydantic parsing CSV as a single element + raw = settings.ALLOWED_EXTENSIONS + if len(raw) == 1 and ',' in raw[0]: + raw = [e.strip() for e in raw[0].split(',')] + allowed_clean = {ext.lower().lstrip('.') for ext in raw} + if suffix_clean not in allowed_clean: raise HTTPException( status_code=400, - detail=f"Filtype {suffix} ikke tilladt. Tilladte: {', '.join(settings.ALLOWED_EXTENSIONS)}" + detail=f"Filtype {suffix} ikke tilladt. Tilladte: {', '.join(sorted(allowed_clean))}" ) # Create upload directory diff --git a/app/core/config.py b/app/core/config.py index 919d9d2..35c3d30 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -110,6 +110,20 @@ class Settings(BaseSettings): EMAIL_WORKFLOWS_ENABLED: bool = True EMAIL_MAX_UPLOAD_SIZE_MB: int = 50 # Max file size for email uploads ALLOWED_EXTENSIONS: List[str] = ["pdf", "jpg", "jpeg", "png", "gif", "doc", "docx", "xls", "xlsx", "zip"] # Allowed file extensions for uploads + + @field_validator("ALLOWED_EXTENSIONS", mode="before") + @classmethod + def parse_allowed_extensions(cls, v): + """Handle both list and comma-separated string (e.g. from .env: .pdf,.jpg,...)""" + if isinstance(v, str): + # Split comma-separated and strip whitespace + leading dots + return [ext.strip().lstrip('.').lower() for ext in v.split(',') if ext.strip()] + if isinstance(v, list): + # Fix case where pydantic already wrapped entire CSV as single list element + if len(v) == 1 and ',' in str(v[0]): + return [ext.strip().lstrip('.').lower() for ext in str(v[0]).split(',') if ext.strip()] + return [ext.strip().lstrip('.').lower() for ext in v if ext] + return v # vTiger Cloud Integration VTIGER_ENABLED: bool = False diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 8199304..7aa4cb4 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -4,7 +4,7 @@ services: # PostgreSQL Database - Production postgres: image: postgres:16-alpine - container_name: bmc-hub-postgres-prod + container_name: bmc-hub-postgres-${STACK_NAME:-prod} environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} @@ -36,8 +36,7 @@ services: RELEASE_VERSION: ${RELEASE_VERSION:-latest} GITHUB_TOKEN: ${GITHUB_TOKEN} GITHUB_REPO: ${GITHUB_REPO:-ct/bmc_hub} - image: localhost/bmc-hub:${RELEASE_VERSION:-latest} - container_name: bmc-hub-api-prod + container_name: bmc-hub-api-${STACK_NAME:-prod} depends_on: postgres: condition: service_healthy