feat: add authentication, registration, and OTP API views
All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 32s
All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 32s
This commit is contained in:
parent
8c692a48d6
commit
d2d17d8068
1 changed files with 28 additions and 13 deletions
41
api/views.py
41
api/views.py
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue