diff --git a/freedoi/accounts/views.py b/freedoi/accounts/views.py index 98ecdca..e0c95b1 100644 --- a/freedoi/accounts/views.py +++ b/freedoi/accounts/views.py @@ -8,6 +8,7 @@ from django.views.generic import FormView, View from django.contrib.auth.tokens import default_token_generator from django.contrib.auth import logout 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.views import ObtainAuthToken @@ -15,11 +16,14 @@ from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.permissions import IsAuthenticated +from django_ratelimit.decorators import ratelimit + from .forms import EmailForm, GenerateTokenForm User = get_user_model() +@method_decorator(ratelimit(key="ip", rate="1/m", method="POST"), name="dispatch") class SendLoginEmailView(FormView): template_name = "accounts/send_login_email.html" form_class = EmailForm diff --git a/freedoi/settings.py b/freedoi/settings.py index ab2376f..434d734 100644 --- a/freedoi/settings.py +++ b/freedoi/settings.py @@ -188,3 +188,17 @@ else: EMAIL_SUBJECT_PREFIX = "[FreeDOI] " 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", + }, + } + } + diff --git a/pyproject.toml b/pyproject.toml index 6b9fd06..4e36bfd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,9 @@ django-crispy-forms = "*" crispy-bootstrap5 = "*" django-two-factor-auth = "*" phonenumbers = "*" +django-ratelimit = "*" +redis = "*" +django-redis = "*" [tool.poetry.group.mysql.dependencies] mysqlclient = "*"