Implement both IP and email based rate limiting.

This commit is contained in:
Waheed Ahmed
2020-04-30 20:23:12 +05:00
parent f3db71171e
commit 05d18effde
3 changed files with 87 additions and 9 deletions

View File

@@ -3,6 +3,7 @@ A utility class which wraps the RateLimitMixin 3rd party class to do bad request
which can be used for rate limiting
"""
from datetime import datetime, timedelta
from django.conf import settings
from ratelimitbackend.backends import RateLimitMixin
@@ -44,7 +45,17 @@ class PasswordResetEmailRateLimiter(RequestRateLimiter):
def key(self, request, dt):
"""
Returns cache key.
Returns IP based cache key.
"""
return '%s-%s-%s' % (
self.reset_email_cache_prefix,
self.get_ip(request),
dt.strftime('%Y%m%d%H%M'),
)
def email_key(self, request, dt):
"""
Returns email based cache key.
"""
return '%s-%s-%s' % (
self.reset_email_cache_prefix,
@@ -66,3 +77,27 @@ class PasswordResetEmailRateLimiter(RequestRateLimiter):
# Prefer logged-in user's email
email = user.email if user.is_authenticated else request.POST.get('email')
return email
def keys_to_check(self, request):
"""
Retun list of IP and email based keys.
"""
keys = super(PasswordResetEmailRateLimiter, self).keys_to_check(request)
now = datetime.now()
email_keys = [
self.email_key(
request,
now - timedelta(minutes=minute),
) for minute in range(self.minutes + 1)
]
keys.extend(email_keys)
return keys
def tick_request_counter(self, request):
"""
Ticks any counters used to compute when rate limt has been reached
"""
for key in self.keys_to_check(request):
self.cache_incr(key)