avatar: Add rate limit similar to attachments on medium avatars.

Followup on #20136
This commit is contained in:
Aman Agrawal 2022-03-28 07:42:58 +00:00 committed by Tim Abbott
parent b4feb673f1
commit 5ee4f71701
2 changed files with 24 additions and 1 deletions

View File

@ -1182,6 +1182,18 @@ class AvatarTest(UploadSerializeMixin, ZulipTestCase):
status_code=401,
)
with self.settings(RATE_LIMITING=True):
# Allow unauthenticated/spectator requests by ID for a reasonable number of requests.
add_ratelimit_rule(86400, 1000, domain="spectator_attachment_access_by_file")
response = self.client_get(f"/avatar/{cordelia.id}/medium", {"foo": "bar"})
self.assertEqual(302, response.status_code)
remove_ratelimit_rule(86400, 1000, domain="spectator_attachment_access_by_file")
# Deny file access since rate limited
add_ratelimit_rule(86400, 0, domain="spectator_attachment_access_by_file")
response = self.client_get(f"/avatar/{cordelia.id}/medium", {"foo": "bar"})
self.assertEqual(429, response.status_code)
def test_non_valid_user_avatar(self) -> None:
# It's debatable whether we should generate avatars for non-users,

View File

@ -40,10 +40,12 @@ from zerver.lib.exceptions import (
JsonableError,
MissingAuthenticationError,
OrganizationOwnerRequired,
RateLimited,
)
from zerver.lib.integrations import EMBEDDED_BOTS
from zerver.lib.rate_limiter import rate_limit_spectator_attachment_access_by_file
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.response import json_response_from_error, json_success
from zerver.lib.streams import access_stream_by_id, access_stream_by_name, subscribed_to_stream
from zerver.lib.types import ProfileDataElementValue, Validator
from zerver.lib.upload import upload_avatar_image
@ -251,6 +253,15 @@ def avatar(
# interact with fake email addresses anyway.
if is_email:
raise MissingAuthenticationError()
if settings.RATE_LIMITING:
try:
unique_avatar_key = f"{realm.id}/{email_or_id}/{medium}"
rate_limit_spectator_attachment_access_by_file(unique_avatar_key)
except RateLimited:
return json_response_from_error(
RateLimited(_("Too many attempts, please try after some time."))
)
else:
realm = maybe_user_profile.realm