diff --git a/modoboa/core/api/v2/views.py b/modoboa/core/api/v2/views.py index 7366e3161..5e3a62464 100644 --- a/modoboa/core/api/v2/views.py +++ b/modoboa/core/api/v2/views.py @@ -28,6 +28,8 @@ logger = logging.getLogger("modoboa.auth") class TokenObtainPairView(jwt_views.TokenObtainPairView): """We overwrite this view to deal with password scheme update.""" + throttle_classes = ["AnonRateThrottle"] + def post(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) try: @@ -84,6 +86,8 @@ class EmailPasswordResetView(APIView): """ An Api View which provides a method to request a password reset token based on an e-mail address. """ + + throttle_scope = 'password_recovery_request' def post(self, request, *args, **kwargs): serializer = serializers.PasswordRecoveryEmailSerializer( @@ -121,6 +125,8 @@ class DefaultPasswordResetView(EmailPasswordResetView): class PasswordResetSmsTOTP(APIView): """ Check SMS Totp code. """ + throttle_scope = 'password_recovery_totp_check' + def post(self, request, *args, **kwargs): try: if request.data["type"] == "confirm": @@ -146,6 +152,8 @@ class PasswordResetSmsTOTP(APIView): class PasswordResetConfirmView(APIView): """ Get and set new user password. """ + throttle_scope = 'password_recovery_apply' + def post(self, request, *args, **kwargs): serializer = serializers.PasswordRecoveryConfirmSerializer( data=request.data) diff --git a/modoboa/core/commands/templates/settings.py.tpl b/modoboa/core/commands/templates/settings.py.tpl index d9455bcbf..9f9ab4b9c 100644 --- a/modoboa/core/commands/templates/settings.py.tpl +++ b/modoboa/core/commands/templates/settings.py.tpl @@ -193,6 +193,17 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # Rest framework settings REST_FRAMEWORK = { + 'DEFAULT_THROTTLE_CLASSES': [ + 'rest_framework.throttling.AnonRateThrottle', + 'rest_framework.throttling.ScopedRateThrottle' + ], + 'DEFAULT_THROTTLE_RATES': { + 'anon': '100/hour', + 'login': '5/hour', + 'password_recovery_request': '6/hour', + 'password_recovery_totp_check': '20/hour', + 'password_recovery_apply': '20/hour' + }, 'DEFAULT_AUTHENTICATION_CLASSES': ( 'modoboa.core.drf_authentication.JWTAuthenticationWith2FA', 'rest_framework.authentication.TokenAuthentication', diff --git a/test_project/test_project/settings.py b/test_project/test_project/settings.py index 3cbab366e..b0b09770b 100644 --- a/test_project/test_project/settings.py +++ b/test_project/test_project/settings.py @@ -186,6 +186,17 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # Rest framework settings REST_FRAMEWORK = { + 'DEFAULT_THROTTLE_CLASSES': [ + 'rest_framework.throttling.AnonRateThrottle', + 'rest_framework.throttling.ScopedRateThrottle' + ], + 'DEFAULT_THROTTLE_RATES': { + 'anon': '100/hour', + 'login': '5/hour', + 'password_recovery_request': '6/hour', + 'password_recovery_totp_check': '20/hour', + 'password_recovery_apply': '20/hour' + }, 'DEFAULT_AUTHENTICATION_CLASSES': ( 'modoboa.core.drf_authentication.JWTAuthenticationWith2FA', 'rest_framework.authentication.TokenAuthentication',