diff --git a/zerver/tests/test_upload.py b/zerver/tests/test_upload.py index 35f0ec7bbf..13e53289c9 100644 --- a/zerver/tests/test_upload.py +++ b/zerver/tests/test_upload.py @@ -263,6 +263,15 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase): response = self.client_get(url) self.assertEqual(response.status_code, 403) + # Check that the /download/ variant works as well + download_url = url.replace("/user_uploads/", "/user_uploads/download/") + with ratelimit_rule(86400, 1000, domain="spectator_attachment_access_by_file"): + response = self.client_get(download_url) + self.assertEqual(response.status_code, 200) + with ratelimit_rule(86400, 0, domain="spectator_attachment_access_by_file"): + response = self.client_get(download_url) + self.assertEqual(response.status_code, 403) + # Deny random file access response = self.client_get( "/user_uploads/2/71/QYB7LA-ULMYEad-QfLMxmI2e/zulip-non-existent.txt" diff --git a/zerver/views/upload.py b/zerver/views/upload.py index b6b2bb612b..79fd1845c3 100644 --- a/zerver/views/upload.py +++ b/zerver/views/upload.py @@ -137,10 +137,13 @@ def serve_local( def serve_file_download_backend( - request: HttpRequest, user_profile: UserProfile, realm_id_str: str, filename: str + request: HttpRequest, + maybe_user_profile: Union[UserProfile, AnonymousUser], + realm_id_str: str, + filename: str, ) -> HttpResponseBase: return serve_file( - request, user_profile, realm_id_str, filename, url_only=False, force_download=True + request, maybe_user_profile, realm_id_str, filename, url_only=False, force_download=True ) diff --git a/zproject/urls.py b/zproject/urls.py index 4c627961fb..7a0898ebc8 100644 --- a/zproject/urls.py +++ b/zproject/urls.py @@ -646,7 +646,7 @@ urls += [ ), rest_path( "user_uploads/download//", - GET=(serve_file_download_backend, {"override_api_url_scheme"}), + GET=(serve_file_download_backend, {"override_api_url_scheme", "allow_anonymous_user_web"}), ), rest_path( "user_uploads//",