mirror of https://github.com/zulip/zulip.git
settings: Add rate limiting for email address changes.
Co-authored-by: Alex Vandiver <alexmv@zulip.com>
This commit is contained in:
parent
f0532aecc8
commit
1cad29fc3a
|
@ -194,6 +194,16 @@ class RateLimitTests(ZulipTestCase):
|
||||||
|
|
||||||
self.do_test_hit_ratelimits(lambda: self.send_api_message(user, "some stuff"))
|
self.do_test_hit_ratelimits(lambda: self.send_api_message(user, "some stuff"))
|
||||||
|
|
||||||
|
@rate_limit_rule(1, 5, domain="email_change_by_user")
|
||||||
|
def test_hit_change_email_ratelimit_as_user(self) -> None:
|
||||||
|
user = self.example_user("cordelia")
|
||||||
|
RateLimitedUser(user).clear_history()
|
||||||
|
|
||||||
|
emails = ["new-email-{n}@zulip.com" for n in range(1, 8)]
|
||||||
|
self.do_test_hit_ratelimits(
|
||||||
|
lambda: self.api_patch(user, "/api/v1/settings", {"email": emails.pop()}),
|
||||||
|
)
|
||||||
|
|
||||||
@rate_limit_rule(1, 5, domain="api_by_ip")
|
@rate_limit_rule(1, 5, domain="api_by_ip")
|
||||||
def test_hit_ratelimits_as_ip(self) -> None:
|
def test_hit_ratelimits_as_ip(self) -> None:
|
||||||
self.do_test_hit_ratelimits(self.send_unauthed_api_request)
|
self.do_test_hit_ratelimits(self.send_unauthed_api_request)
|
||||||
|
|
|
@ -36,6 +36,7 @@ from zerver.lib.email_validation import (
|
||||||
)
|
)
|
||||||
from zerver.lib.exceptions import JsonableError, RateLimited
|
from zerver.lib.exceptions import JsonableError, RateLimited
|
||||||
from zerver.lib.i18n import get_available_language_codes
|
from zerver.lib.i18n import get_available_language_codes
|
||||||
|
from zerver.lib.rate_limiter import RateLimitedUser
|
||||||
from zerver.lib.request import REQ, has_request_variables
|
from zerver.lib.request import REQ, has_request_variables
|
||||||
from zerver.lib.response import json_success
|
from zerver.lib.response import json_success
|
||||||
from zerver.lib.send_email import FromAddress, send_email
|
from zerver.lib.send_email import FromAddress, send_email
|
||||||
|
@ -269,6 +270,12 @@ def json_change_settings(
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
raise JsonableError(e.message)
|
raise JsonableError(e.message)
|
||||||
|
|
||||||
|
ratelimited, time_until_free = RateLimitedUser(
|
||||||
|
user_profile, domain="email_change_by_user"
|
||||||
|
).rate_limit()
|
||||||
|
if ratelimited:
|
||||||
|
raise RateLimited(time_until_free)
|
||||||
|
|
||||||
do_start_email_change_process(user_profile, new_email)
|
do_start_email_change_process(user_profile, new_email)
|
||||||
|
|
||||||
if user_profile.full_name != full_name and full_name.strip() != "":
|
if user_profile.full_name != full_name and full_name.strip() != "":
|
||||||
|
|
|
@ -385,6 +385,10 @@ RATE_LIMITING_RULES = {
|
||||||
"authenticate_by_username": [
|
"authenticate_by_username": [
|
||||||
(1800, 5), # 5 login attempts within 30 minutes
|
(1800, 5), # 5 login attempts within 30 minutes
|
||||||
],
|
],
|
||||||
|
"email_change_by_user": [
|
||||||
|
(3600, 2), # 2 per hour
|
||||||
|
(86400, 5), # 5 per day
|
||||||
|
],
|
||||||
"password_reset_form_by_email": [
|
"password_reset_form_by_email": [
|
||||||
(3600, 2), # 2 reset emails per hour
|
(3600, 2), # 2 reset emails per hour
|
||||||
(86400, 5), # 5 per day
|
(86400, 5), # 5 per day
|
||||||
|
|
|
@ -267,6 +267,7 @@ RATE_LIMITING_RULES: Dict[str, List[Tuple[int, int]]] = {
|
||||||
"api_by_remote_server": [],
|
"api_by_remote_server": [],
|
||||||
"authenticate_by_username": [],
|
"authenticate_by_username": [],
|
||||||
"sends_email_by_ip": [],
|
"sends_email_by_ip": [],
|
||||||
|
"email_change_by_user": [],
|
||||||
"password_reset_form_by_email": [],
|
"password_reset_form_by_email": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue