User email verifications: Add rate limiting (Z#23232834) (#6219)

* User email verifications: Add rate limiting (Z#23232834)

Also, refactor rate limiting into a central utility

* Make ip block work in dev

* Review notes

* Update src/pretix/base/forms/user.py

Co-authored-by: luelista <weller@rami.io>

* Apply suggestions from code review

Co-authored-by: luelista <mira@teamwiki.de>

* Add rate limit reset

---------

Co-authored-by: luelista <weller@rami.io>
Co-authored-by: luelista <mira@teamwiki.de>
This commit is contained in:
Raphael Michel
2026-07-17 18:35:03 +02:00
committed by GitHub
co-authored by luelista luelista
parent 4295b02406
commit 5f2264daeb
9 changed files with 189 additions and 157 deletions
+7
View File
@@ -80,6 +80,7 @@ from pretix.control.permissions import (
)
from pretix.control.views.auth import get_u2f_appid, get_webauthn_rp_id
from pretix.helpers.http import redirect_to_url
from pretix.helpers.ratelimit import rate_limit, rate_limit_reset
from pretix.helpers.security import session_reauth
from pretix.helpers.u2f import websafe_encode
@@ -849,6 +850,7 @@ class UserPasswordChangeView(FormView):
msgs = []
msgs.append(_('Your password has been changed.'))
self.request.user.send_security_notice(msgs)
rate_limit_reset("pwreset", self.request.user.pk)
self.request.user.log_action('pretix.user.settings.changed', user=self.request.user, data={'new_pw': True})
@@ -879,6 +881,7 @@ class UserEmailChangeView(RecentAuthenticationRequiredMixin, FormView):
return {
**super().get_form_kwargs(),
"request": self.request,
"user": self.request.user,
}
@@ -908,6 +911,10 @@ class UserEmailVerifyView(View):
messages.success(self.request, _('Your email address was already verified.'))
return redirect(reverse('control:user.settings', kwargs={}))
if rate_limit("emailverify", self.request.user.pk, max_num=2, expire_time=300):
messages.error(self.request, _("For security reasons, please wait 5 minutes before you try again."))
return redirect(reverse('control:user.settings', kwargs={}))
self.request.user.send_confirmation_code(
session=self.request.session,
reason='email_verify',