diff --git a/kirovy/settings/testing.py b/kirovy/settings/testing.py index 9f6582b..6099acd 100644 --- a/kirovy/settings/testing.py +++ b/kirovy/settings/testing.py @@ -15,4 +15,31 @@ } } +LOGGING = { + "version": 1, + "disable_existing_loggers": False, + "formatters": { + "tests_logging": { + "()": structlog.stdlib.ProcessorFormatter, + "processor": structlog.dev.ConsoleRenderer(), + }, + }, + "handlers": { + "pytest_console": { + "class": "logging.StreamHandler", + "formatter": "tests_logging", + }, + }, + "loggers": { + "kirovy": { + "handlers": ["pytest_console"], + "level": "DEBUG", + }, + "django_structlog": { + "handlers": ["pytest_console"], + "level": "DEBUG", + }, + }, +} + # MEDIA_ROOT gets modified in common_fixtures.py in the tmp_media_root fixture. diff --git a/kirovy/views/map_upload_views.py b/kirovy/views/map_upload_views.py index af13f30..e7cdc0a 100644 --- a/kirovy/views/map_upload_views.py +++ b/kirovy/views/map_upload_views.py @@ -390,7 +390,31 @@ def post(self, request: KirovyRequest, format=None) -> KirovyResponse: legacy_map_service = legacy_upload.get_legacy_service_for_slug(game.slug.lower())(uploaded_file) map_hashes = self._get_file_hashes(ContentFile(legacy_map_service.file_contents_merged.read())) - self.verify_file_does_not_exist(map_hashes) + try: + self.verify_file_does_not_exist(map_hashes) + except KirovyValidationError: + # The old database just accepts duplicate uploads as if the map didn't exist. + # The client expects a successful upload in this scenario, so we need to mirror that. + _LOGGER.debug( + "Map already exists. Backwards compatible endpoint, returning success", + map_hash=map_hashes.sha1, + client_info=self.user_log_attrs, + ) + existing_file = cnc_map.CncMapFile.objects.prefetch_related("cnc_map").get(hash_sha1=map_hashes.sha1) + + return KirovyResponse( + ResultResponseData( + message="Upload succeeded!", + result={ + "cnc_map": existing_file.cnc_map.map_name, + "cnc_map_file": existing_file.file.url, + "cnc_map_id": existing_file.cnc_map_id, + "extracted_preview_file": None, + "download_url": f"/{game.slug}/{existing_file.hash_sha1}.zip", + }, + ), + status=status.HTTP_200_OK, + ) # Make the map that we will attach the map file to. new_map = cnc_map.CncMap( diff --git a/tests/test_views/test_backwards_compatibility.py b/tests/test_views/test_backwards_compatibility.py index aea191d..2e19662 100644 --- a/tests/test_views/test_backwards_compatibility.py +++ b/tests/test_views/test_backwards_compatibility.py @@ -9,6 +9,7 @@ from kirovy import typing as t from kirovy.models import CncGame, CncMapFile, CncMap +from kirovy.objects.ui_objects import ResultResponseData from kirovy.response import KirovyResponse if t.TYPE_CHECKING: @@ -128,3 +129,38 @@ def _download_and_check_hash( assert cnc_map_file.cnc_map.map_name == expected_map_name if ip_address: assert cnc_map_file.ip_address == ip_address + + +def test_map_upload_duplicate_file_backwards_compatible( + client_anonymous, + zip_map_for_legacy_upload, + file_map_desert, + game_yuri, +): + """ + Test duplicate uploads for backwards compatible uploads. + Duplicates should just return successful like the old database. + """ + url = "/upload" + original_extension = pathlib.Path(file_map_desert.name).suffix + upload_file, file_sha1 = zip_map_for_legacy_upload(file_map_desert) + upload_response: KirovyResponse[ResultResponseData] = client_anonymous.post( + url, {"file": upload_file, "game": game_yuri.slug}, format="multipart", content_type=None, REMOTE_ADDR="2.2.2.2" + ) + + assert upload_response.status_code == status.HTTP_200_OK + assert upload_response.data["result"]["download_url"] == f"/{game_yuri.slug}/{file_sha1}.zip" + original_map_id = upload_response.data["result"]["cnc_map_id"] + + _download_and_check_hash( + client_anonymous, file_sha1, game_yuri, "desert", [original_extension], ip_address="2.2.2.2" + ) + + upload_file.seek(0) + duplicate_upload_response: KirovyResponse[ResultResponseData] = client_anonymous.post( + url, {"file": upload_file, "game": game_yuri.slug}, format="multipart", content_type=None, REMOTE_ADDR="1.2.2.2" + ) + + assert duplicate_upload_response.status_code == status.HTTP_200_OK + assert duplicate_upload_response.data["message"] == "Upload succeeded!" + assert duplicate_upload_response.data["result"]["cnc_map_id"] == original_map_id