feat: rate limiting and Redis caching setup

Added rate limiting to the SendLoginEmailView to prevent abuse by applying the `ratelimit` decorator. Configured Redis as a cache backend based on settings from the configuration file. Updated dependencies to include `django-ratelimit`, `redis`, and `django-redis` packages to support these enhancements.

These changes improve the security and performance of the application by limiting login email attempts and using Redis for caching.
This commit is contained in:
Kumi 2024-06-23 16:47:07 +02:00
parent 4f407c2d8a
commit 4f62f6eff2
Signed by: kumi
GPG key ID: ECBCC9082395383F
3 changed files with 21 additions and 0 deletions

View file

@ -8,6 +8,7 @@ from django.views.generic import FormView, View
from django.contrib.auth.tokens import default_token_generator from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth import logout from django.contrib.auth import logout
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.utils.decorators import method_decorator
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
from rest_framework.authtoken.views import ObtainAuthToken from rest_framework.authtoken.views import ObtainAuthToken
@ -15,11 +16,14 @@ from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from django_ratelimit.decorators import ratelimit
from .forms import EmailForm, GenerateTokenForm from .forms import EmailForm, GenerateTokenForm
User = get_user_model() User = get_user_model()
@method_decorator(ratelimit(key="ip", rate="1/m", method="POST"), name="dispatch")
class SendLoginEmailView(FormView): class SendLoginEmailView(FormView):
template_name = "accounts/send_login_email.html" template_name = "accounts/send_login_email.html"
form_class = EmailForm form_class = EmailForm

View file

@ -188,3 +188,17 @@ else:
EMAIL_SUBJECT_PREFIX = "[FreeDOI] " EMAIL_SUBJECT_PREFIX = "[FreeDOI] "
DEFAULT_FROM_EMAIL = "noreply@freedoi.org" DEFAULT_FROM_EMAIL = "noreply@freedoi.org"
# Redis
if (redis_host := CONFIG.get("Redis", "Host", fallback=None)) is not None:
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": f"redis://{redis_host}:{CONFIG.getint('Redis', 'Port', fallback=6379)}/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
}
}

View file

@ -28,6 +28,9 @@ django-crispy-forms = "*"
crispy-bootstrap5 = "*" crispy-bootstrap5 = "*"
django-two-factor-auth = "*" django-two-factor-auth = "*"
phonenumbers = "*" phonenumbers = "*"
django-ratelimit = "*"
redis = "*"
django-redis = "*"
[tool.poetry.group.mysql.dependencies] [tool.poetry.group.mysql.dependencies]
mysqlclient = "*" mysqlclient = "*"