mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
Fixed default throttle class
This commit is contained in:
@@ -9,14 +9,14 @@ from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||
from rest_framework import (
|
||||
filters, mixins, parsers, pagination, permissions, response, status, viewsets
|
||||
)
|
||||
from rest_framework.decorators import action, throttle_classes
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
|
||||
from modoboa.admin.api.v1 import viewsets as v1_viewsets
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.lib import renderers as lib_renderers
|
||||
from modoboa.lib import viewsets as lib_viewsets
|
||||
from modoboa.lib.throttle import UserDosThrottle
|
||||
from modoboa.lib.throttle import UserDosThrottleViewset
|
||||
|
||||
from ... import lib
|
||||
from ... import models
|
||||
@@ -52,7 +52,7 @@ class DomainViewSet(lib_viewsets.RevisionModelMixin,
|
||||
permission_classes = (
|
||||
permissions.IsAuthenticated, permissions.DjangoModelPermissions,
|
||||
)
|
||||
throttle_classes = [UserDosThrottle]
|
||||
throttle_classes = [UserDosThrottleViewset]
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter queryset based on current user."""
|
||||
@@ -161,7 +161,7 @@ class AccountViewSet(v1_viewsets.AccountViewSet):
|
||||
|
||||
filter_backends = (filters.SearchFilter, dj_filters.DjangoFilterBackend)
|
||||
filterset_class = AccountFilterSet
|
||||
throttle_classes = [UserDosThrottle]
|
||||
throttle_classes = [UserDosThrottleViewset]
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action in ["create", "validate", "update", "partial_update"]:
|
||||
@@ -216,7 +216,7 @@ class IdentityViewSet(viewsets.ViewSet):
|
||||
|
||||
permission_classes = (permissions.IsAuthenticated, )
|
||||
serializer_class = None
|
||||
throttle_classes = [UserDosThrottle]
|
||||
throttle_classes = [UserDosThrottleViewset]
|
||||
|
||||
def list(self, request, **kwargs):
|
||||
"""Return all identities."""
|
||||
@@ -256,7 +256,7 @@ class AliasViewSet(v1_viewsets.AliasViewSet):
|
||||
"""Viewset for Alias."""
|
||||
|
||||
serializer_class = serializers.AliasSerializer
|
||||
throttle_classes = [UserDosThrottle]
|
||||
throttle_classes = [UserDosThrottleViewset]
|
||||
|
||||
@action(methods=["post"], detail=False)
|
||||
def validate(self, request, **kwargs):
|
||||
@@ -278,7 +278,7 @@ class AliasViewSet(v1_viewsets.AliasViewSet):
|
||||
class UserAccountViewSet(viewsets.ViewSet):
|
||||
"""Viewset for current user operations."""
|
||||
|
||||
throttle_classes = [UserDosThrottle]
|
||||
throttle_classes = [UserDosThrottleViewset]
|
||||
|
||||
@action(methods=["get", "post"], detail=False)
|
||||
def forward(self, request, **kwargs):
|
||||
@@ -341,7 +341,7 @@ class AlarmViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
)
|
||||
search_fields = ["domain__name", "title"]
|
||||
serializer_class = serializers.AlarmSerializer
|
||||
throttle_classes = [UserDosThrottle]
|
||||
throttle_classes = [UserDosThrottleViewset]
|
||||
|
||||
def get_queryset(self):
|
||||
return models.Alarm.objects.select_related("domain").filter(
|
||||
|
||||
@@ -12,9 +12,10 @@ from drf_spectacular.utils import extend_schema
|
||||
from rest_framework import response, status
|
||||
from rest_framework_simplejwt import views as jwt_views
|
||||
from rest_framework_simplejwt.exceptions import InvalidToken, TokenError
|
||||
from rest_framework.throttling import ScopedRateThrottle
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from modoboa.lib.throttle import UserDosThrottle
|
||||
from modoboa.lib.throttle import UserDosThrottleView
|
||||
from modoboa.core.password_hashers import get_password_hasher
|
||||
from modoboa.core.utils import check_for_updates
|
||||
from modoboa.parameters import tools as param_tools
|
||||
@@ -28,7 +29,8 @@ logger = logging.getLogger("modoboa.auth")
|
||||
|
||||
class TokenObtainPairView(jwt_views.TokenObtainPairView):
|
||||
"""We overwrite this view to deal with password scheme update."""
|
||||
|
||||
|
||||
throttle_classes = [ScopedRateThrottle]
|
||||
throttle_scope = "login"
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
@@ -87,7 +89,8 @@ class EmailPasswordResetView(APIView):
|
||||
"""
|
||||
An Api View which provides a method to request a password reset token based on an e-mail address.
|
||||
"""
|
||||
|
||||
|
||||
throttle_classes = [ScopedRateThrottle]
|
||||
throttle_scope = 'password_recovery_request'
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
@@ -126,6 +129,7 @@ class DefaultPasswordResetView(EmailPasswordResetView):
|
||||
class PasswordResetSmsTOTP(APIView):
|
||||
""" Check SMS Totp code. """
|
||||
|
||||
throttle_classes = [ScopedRateThrottle]
|
||||
throttle_scope = 'password_recovery_totp_check'
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
@@ -153,6 +157,7 @@ class PasswordResetSmsTOTP(APIView):
|
||||
class PasswordResetConfirmView(APIView):
|
||||
""" Get and set new user password. """
|
||||
|
||||
throttle_classes = [ScopedRateThrottle]
|
||||
throttle_scope = 'password_recovery_apply'
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
@@ -174,7 +179,7 @@ class PasswordResetConfirmView(APIView):
|
||||
class ComponentsInformationAPIView(APIView):
|
||||
"""Retrieve information about installed components."""
|
||||
|
||||
throttle_classes = [UserDosThrottle]
|
||||
throttle_classes = [UserDosThrottleView]
|
||||
|
||||
@extend_schema(responses=serializers.ModoboaComponentSerializer(many=True))
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
||||
@@ -193,11 +193,6 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
# Rest framework settings
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_THROTTLE_CLASSES': [
|
||||
'rest_framework.throttling.AnonRateThrottle',
|
||||
'rest_framework.throttling.ScopedRateThrottle',
|
||||
'modoboa.lib.throttle.UserDosThrottle'
|
||||
],
|
||||
'DEFAULT_THROTTLE_RATES': {
|
||||
'anon': '100/hour',
|
||||
'login': '3/minute',
|
||||
|
||||
@@ -4,7 +4,7 @@ from rest_framework import permissions, response, viewsets
|
||||
from rest_framework.decorators import action
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.lib.throttle import UserDosThrottle
|
||||
from modoboa.lib.throttle import UserDosThrottleViewset
|
||||
|
||||
from . import serializers
|
||||
|
||||
@@ -13,7 +13,7 @@ class DNSViewSet(viewsets.GenericViewSet):
|
||||
"""A viewset to provide extra routes related to DNS information."""
|
||||
|
||||
permission_classes = (permissions.IsAuthenticated, )
|
||||
throttle_classes = [UserDosThrottle]
|
||||
throttle_classes = [UserDosThrottleViewset]
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter queryset based on current user."""
|
||||
|
||||
+18
-2
@@ -1,6 +1,6 @@
|
||||
from rest_framework.throttling import SimpleRateThrottle
|
||||
|
||||
class UserDosThrottle(SimpleRateThrottle):
|
||||
class UserDosThrottleViewset(SimpleRateThrottle):
|
||||
"""Custom Throttle class for rest_framework. The throttling is applied on a per view basis for authentificated users."""
|
||||
|
||||
scope = "ddos"
|
||||
@@ -12,6 +12,22 @@ class UserDosThrottle(SimpleRateThrottle):
|
||||
ident = self.get_ident(request)
|
||||
|
||||
return self.cache_format % {
|
||||
'scope': id(view.action),
|
||||
'scope': hash(f"{view.basename}_{view.name}"),
|
||||
'ident': ident
|
||||
}
|
||||
|
||||
class UserDosThrottleView(SimpleRateThrottle):
|
||||
"""Custom Throttle class for rest_framework. The throttling is applied on a per view basis for authentificated users."""
|
||||
|
||||
scope = "ddos"
|
||||
|
||||
def get_cache_key(self, request, view):
|
||||
if request.user and request.user.is_authenticated:
|
||||
ident = request.user.pk
|
||||
else:
|
||||
ident = self.get_ident(request)
|
||||
|
||||
return self.cache_format % {
|
||||
'scope': id(view),
|
||||
'ident': ident
|
||||
}
|
||||
@@ -9,7 +9,7 @@ from rest_framework import filters, permissions, response, viewsets
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.lib import pagination
|
||||
from modoboa.lib.throttle import UserDosThrottle
|
||||
from modoboa.lib.throttle import UserDosThrottleViewset
|
||||
|
||||
from ... import models
|
||||
from ... import signals
|
||||
@@ -20,7 +20,7 @@ class StatisticsViewSet(viewsets.ViewSet):
|
||||
"""A viewset to provide extra route related to mail statistics."""
|
||||
|
||||
permission_classes = (permissions.IsAuthenticated, )
|
||||
throttle_classes = [UserDosThrottle]
|
||||
throttle_classes = [UserDosThrottleViewset]
|
||||
|
||||
@extend_schema(
|
||||
parameters=[serializers.StatisticsInputSerializer],
|
||||
@@ -63,7 +63,7 @@ class MaillogViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
permissions = (permissions.IsAuthenticated, )
|
||||
search_fields = ["queue_id", "sender", "rcpt", "original_rcpt", "status"]
|
||||
serializer_class = serializers.MaillogSerializer
|
||||
throttle_classes = [UserDosThrottle]
|
||||
throttle_classes = [UserDosThrottleViewset]
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter queryset based on current user."""
|
||||
|
||||
@@ -4,7 +4,7 @@ from drf_spectacular.utils import extend_schema, OpenApiParameter
|
||||
from rest_framework import response, viewsets
|
||||
from rest_framework.decorators import action
|
||||
|
||||
from modoboa.lib.throttle import UserDosThrottle
|
||||
from modoboa.lib.throttle import UserDosThrottleViewset
|
||||
|
||||
from . import serializers
|
||||
from ... import tools
|
||||
@@ -15,7 +15,7 @@ class ParametersViewSet(viewsets.ViewSet):
|
||||
|
||||
lookup_value_regex = r"\w+"
|
||||
serializer_class = None
|
||||
throttle_classes = [UserDosThrottle]
|
||||
throttle_classes = [UserDosThrottleViewset]
|
||||
|
||||
@extend_schema(responses=serializers.ApplicationSerializer(many=True))
|
||||
@action(methods=["get"], detail=False)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from drf_spectacular.utils import extend_schema
|
||||
from rest_framework import permissions, response, viewsets
|
||||
|
||||
from modoboa.lib.throttle import UserDosThrottle
|
||||
from modoboa.lib.throttle import UserDosThrottleViewset
|
||||
|
||||
from . import serializers
|
||||
from ... import backends
|
||||
@@ -13,7 +13,7 @@ class TransportViewSet(viewsets.ViewSet):
|
||||
"""Viewset for Transport."""
|
||||
|
||||
permissions = (permissions.IsAuthenticated, )
|
||||
throttle_classes = [UserDosThrottle]
|
||||
throttle_classes = [UserDosThrottleViewset]
|
||||
|
||||
@extend_schema(
|
||||
responses={200: serializers.TransportBackendSerializer}
|
||||
|
||||
@@ -186,11 +186,6 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
# Rest framework settings
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_THROTTLE_CLASSES': [
|
||||
'rest_framework.throttling.AnonRateThrottle',
|
||||
'rest_framework.throttling.ScopedRateThrottle',
|
||||
'modoboa.lib.throttle.UserDosThrottle'
|
||||
],
|
||||
'DEFAULT_THROTTLE_RATES': {
|
||||
'anon': '100/hour',
|
||||
'login': '3/minute',
|
||||
|
||||
Reference in New Issue
Block a user