feat: add authentication, registration, and OTP API views
All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 32s

This commit is contained in:
vickytechkey 2026-10-01 15:55:09 +05:30
parent 8c692a48d6
commit d2d17d8068

View file

@ -115,14 +115,13 @@ class SendEmailOtpView(APIView):
def post(self, request):
email = request.data.get('email')
otp_code = request.data.get('otp_code')
template_name = request.data.get('template_name', 'verification')
if not email:
return Response({'error': 'email is required'}, status=status.HTTP_400_BAD_REQUEST)
if not otp_code:
otp_code = str(random.randint(100000, 999999))
# Always generate a fresh, unique 6-digit OTP code for every dispatch
otp_code = str(random.randint(100000, 999999))
user = request.user if (request.user and request.user.is_authenticated) else None
if not user:
@ -380,18 +379,34 @@ class VerifyOtpView(APIView):
'user': UserSerializer(user_obj, context={'request': request}).data
})
if not user_obj:
return Response({'verified': False, 'error': 'No active user or OTP found'}, status=status.HTTP_400_BAD_REQUEST)
record = OTPRecord.objects.filter(
user=user_obj,
type=otp_type,
used=False
).order_by('-created_at').first()
# Smart Record Lookup:
# 1. Match by user_obj AND otp_hash
record = None
if user_obj:
record = OTPRecord.objects.filter(
user=user_obj,
type=otp_type,
otp_hash=h,
used=False,
expires_at__gte=timezone.now()
).order_by('-created_at').first()
# 2. Match by type AND otp_hash across all unexpired records
if not record:
# Fallback to check record across all active unexpired records matching hash
record = OTPRecord.objects.filter(type=otp_type, otp_hash=h, used=False, expires_at__gte=timezone.now()).order_by('-created_at').first()
record = OTPRecord.objects.filter(
type=otp_type,
otp_hash=h,
used=False,
expires_at__gte=timezone.now()
).order_by('-created_at').first()
# 3. Fallback to latest unexpired record for user_obj
if not record and user_obj:
record = OTPRecord.objects.filter(
user=user_obj,
type=otp_type,
used=False
).order_by('-created_at').first()
if not record:
return Response({'verified': False, 'error': 'No active OTP found'}, status=status.HTTP_400_BAD_REQUEST)