import uuid from pathlib import Path import openpyxl from werkzeug.utils import secure_filename ALLOWED_EXCEL_EXTENSIONS = (".xlsx", ".xlsm") def save_uploaded_excel(uploaded, upload_dir: Path): """Validate and save an uploaded Excel file with a collision-safe name.""" if not uploaded or not uploaded.filename: raise ValueError("No file uploaded.") filename = secure_filename(uploaded.filename) if not filename.lower().endswith(ALLOWED_EXCEL_EXTENSIONS): raise ValueError("Upload an .xlsx or .xlsm file.") stem = Path(filename).stem suffix = Path(filename).suffix # UUID suffixes keep simultaneous users from overwriting each other. saved_filename = f"{stem}_{uuid.uuid4().hex[:8]}{suffix}" destination = upload_dir / saved_filename uploaded.save(destination) return saved_filename, destination def read_workbook_sheets(path: Path) -> list[str]: """Read sheet names without loading workbook cell data into memory.""" workbook = openpyxl.load_workbook(path, read_only=True, data_only=False) try: return workbook.sheetnames finally: workbook.close() def resolve_allowed_path(raw_path: str, app_root: Path, allowed_roots: list[Path]) -> Path: """Resolve a user-supplied path and ensure it stays inside allowed roots.""" if not raw_path: raise ValueError("Path is required.") candidate = Path(raw_path) if not candidate.is_absolute(): candidate = app_root / candidate resolved = candidate.resolve() allowed = [root.resolve() for root in allowed_roots] # Prevent download/apply endpoints from reading arbitrary server files. if not any(resolved == root or resolved.is_relative_to(root) for root in allowed): raise ValueError("Path is outside the application data directory.") return resolved