diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py index f2bb8b8c76..51d8e9cb84 100644 --- a/zerver/lib/actions.py +++ b/zerver/lib/actions.py @@ -4529,6 +4529,11 @@ def do_change_password(user_profile: UserProfile, password: str, commit: bool = user_profile.set_password(password) if commit: user_profile.save(update_fields=["password"]) + + # Imported here to prevent import cycles + from zproject.backends import RateLimitedAuthenticationByUsername + + RateLimitedAuthenticationByUsername(user_profile.delivery_email).clear_history() event_time = timezone_now() RealmAuditLog.objects.create( realm=user_profile.realm, diff --git a/zerver/tests/test_auth_backends.py b/zerver/tests/test_auth_backends.py index 5e64ace1f6..0f9ccf8500 100644 --- a/zerver/tests/test_auth_backends.py +++ b/zerver/tests/test_auth_backends.py @@ -42,6 +42,7 @@ from social_django.strategy import DjangoStrategy from confirmation.models import Confirmation, create_confirmation_link from zerver.lib.actions import ( change_user_is_active, + do_change_password, do_create_realm, do_create_user, do_deactivate_realm, @@ -673,6 +674,11 @@ class RateLimitAuthenticationTests(ZulipTestCase): # But the third attempt goes over the limit: with self.assertRaises(RateLimited): attempt_authentication(username, wrong_password) + + # Resetting the password also clears the rate-limit + do_change_password(expected_user_profile, correct_password) + self.assertIsNone(attempt_authentication(username, wrong_password)) + finally: # Clean up to avoid affecting other tests. RateLimitedAuthenticationByUsername(username).clear_history()