feat: IP & device rate limits

This commit is contained in:
2026-03-14 01:07:26 +03:00
parent 9b87eb74d7
commit ad711d1daf
7 changed files with 212 additions and 7 deletions
+31 -1
View File
@@ -16,8 +16,13 @@ from apps.accounts.serializers import (
)
from apps.accounts.services.otp import (
OtpCooldownError,
OtpDeviceRateLimitError,
OtpIpRateLimitError,
OtpRateLimitError,
build_device_signal,
create_and_send_otp,
enforce_phone_auth_request_limits,
normalize_request_ip,
verify_otp,
)
@@ -93,6 +98,25 @@ class PhoneAuthRequestView(APIView):
data = serializer.validated_data
phone_number = data["phone_number"]
email = data.get("email") or None
request_ip = normalize_request_ip(request.META.get("HTTP_X_FORWARDED_FOR") or request.META.get("REMOTE_ADDR"))
device_signal = build_device_signal(
data.get("device_id"),
request.META.get("HTTP_USER_AGENT"),
request.META.get("HTTP_ACCEPT_LANGUAGE"),
)
try:
enforce_phone_auth_request_limits(request_ip=request_ip, device_signal=device_signal)
except OtpIpRateLimitError as exc:
return Response(
{"detail": str(exc), "retry_after_seconds": exc.retry_after_seconds},
status=status.HTTP_429_TOO_MANY_REQUESTS,
)
except OtpDeviceRateLimitError as exc:
return Response(
{"detail": str(exc), "retry_after_seconds": exc.retry_after_seconds},
status=status.HTTP_429_TOO_MANY_REQUESTS,
)
user = User.objects.filter(phone_number=phone_number).first()
if not user:
@@ -110,7 +134,13 @@ class PhoneAuthRequestView(APIView):
)
try:
result = create_and_send_otp(phone_number, data["channel"], purpose=OtpPurpose.AUTH)
result = create_and_send_otp(
phone_number,
data["channel"],
purpose=OtpPurpose.AUTH,
request_ip=request_ip,
device_signal=device_signal,
)
except OtpCooldownError as exc:
return Response(
{"detail": str(exc), "retry_after_seconds": exc.retry_after_seconds},