from __future__ import annotations import io import hashlib import unittest import zipfile from types import SimpleNamespace from unittest.mock import patch from fastapi import UploadFile from govoplan_files.backend.routes.uploads import ( _validate_archive_preview_token, preview_archive_upload, ) from govoplan_files.backend.storage.common import FileStorageError def _archive_bytes() -> bytes: target = io.BytesIO() with zipfile.ZipFile(target, "w", compression=zipfile.ZIP_DEFLATED) as archive: archive.writestr("folder/report.txt", b"report") return target.getvalue() class ArchivePreviewTokenTests(unittest.TestCase): def setUp(self) -> None: self.settings = SimpleNamespace( file_upload_zip_max_bytes=10 * 1024 * 1024, file_archive_max_entries=10_000, file_archive_max_expanded_bytes=2 * 1024 * 1024 * 1024, file_archive_max_expansion_ratio=100, file_archive_preview_ttl_seconds=30 * 60, ) self.principal = SimpleNamespace( tenant_id="tenant-1", user=SimpleNamespace(id="user-1"), ) def test_preview_token_is_bound_to_actor_archive_and_destination(self) -> None: archive_data = _archive_bytes() upload = UploadFile( file=io.BytesIO(archive_data), filename="monthly.zip", ) with patch( "govoplan_files.backend.routes.uploads.settings", self.settings, ): preview = preview_archive_upload( file=upload, owner_type="user", owner_id="user-1", path="incoming", campaign_id=None, password=None, principal=self.principal, ) _validate_archive_preview_token( preview.preview_token, tenant_id="tenant-1", user_id="user-1", owner_type="user", owner_id="user-1", path="incoming", campaign_id=None, archive_format="zip", archive_sha256=hashlib.sha256(archive_data).hexdigest(), ) with self.assertRaisesRegex( FileStorageError, "does not match this upload destination" ): _validate_archive_preview_token( preview.preview_token, tenant_id="tenant-1", user_id="user-1", owner_type="user", owner_id="user-1", path="elsewhere", campaign_id=None, archive_format="zip", archive_sha256=hashlib.sha256(archive_data).hexdigest(), ) with self.assertRaisesRegex( FileStorageError, "contents changed" ): _validate_archive_preview_token( preview.preview_token, tenant_id="tenant-1", user_id="user-1", owner_type="user", owner_id="user-1", path="incoming", campaign_id=None, archive_format="zip", archive_sha256="0" * 64, ) if __name__ == "__main__": unittest.main()