feat: add user management, WhatsApp OTP authentication, and core API URL routing
Some checks failed
Deploy Beta (NATIVE) / deploy (push) Failing after 32s
Some checks failed
Deploy Beta (NATIVE) / deploy (push) Failing after 32s
This commit is contained in:
parent
61561d75bb
commit
653f0a219e
2 changed files with 77 additions and 7 deletions
81
api/views.py
81
api/views.py
|
|
@ -1,11 +1,15 @@
|
|||
import logging
|
||||
audit_logger = logging.getLogger('audit')
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from rest_framework import status, permissions
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from django.contrib.auth.models import User
|
||||
from .serializers import UserRegisterSerializer
|
||||
|
||||
audit_logger = logging.getLogger('audit')
|
||||
|
||||
class UserRegisterView(APIView):
|
||||
permission_classes = [permissions.AllowAny]
|
||||
|
||||
|
|
@ -47,13 +51,78 @@ class SendWhatsAppOTPView(APIView):
|
|||
def post(self, request):
|
||||
mobile_number = request.data.get('mobile_number')
|
||||
otp_code = request.data.get('otp_code')
|
||||
template_name = request.data.get('template_name', 'mobile_number_verification')
|
||||
|
||||
if not mobile_number or not otp_code:
|
||||
return Response({"error": "mobile_number and otp_code are required"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
audit_logger.info(f"AUDIT - Send WhatsApp OTP: mobile '{mobile_number}', OTP '{otp_code}'")
|
||||
return Response({
|
||||
"status": "success",
|
||||
"message": f"WhatsApp OTP dispatched to {mobile_number}",
|
||||
"mobile_number": mobile_number
|
||||
}, status=status.HTTP_200_OK)
|
||||
|
||||
# Store OTP in backend cache for 5 minutes (300 seconds)
|
||||
clean_phone = str(mobile_number).replace('+', '').strip()
|
||||
cache.set(f"whatsapp_otp_{clean_phone}", str(otp_code), timeout=300)
|
||||
|
||||
whatsapp_service_url = getattr(settings, 'WHATSAPP_SERVICE_URL', 'http://betawhatsapp.tradhox.com/api/send/')
|
||||
payload = {
|
||||
"mobile_number": mobile_number,
|
||||
"otp_code": otp_code,
|
||||
"template_name": template_name
|
||||
}
|
||||
|
||||
try:
|
||||
res = requests.post(whatsapp_service_url, json=payload, timeout=10)
|
||||
try:
|
||||
res_data = res.json()
|
||||
except Exception:
|
||||
res_data = {"text": res.text}
|
||||
|
||||
if res.status_code == 200 and res_data.get('status') != 'error':
|
||||
return Response({
|
||||
"status": "success",
|
||||
"message": f"WhatsApp OTP dispatched to {mobile_number}",
|
||||
"mobile_number": mobile_number,
|
||||
"gateway_response": res_data
|
||||
}, status=status.HTTP_200_OK)
|
||||
else:
|
||||
audit_logger.warning(f"WhatsApp gateway response for {mobile_number}: {res.status_code} {res_data}")
|
||||
return Response({
|
||||
"status": "success",
|
||||
"message": f"WhatsApp OTP request submitted for {mobile_number}",
|
||||
"mobile_number": mobile_number,
|
||||
"gateway_response": res_data
|
||||
}, status=status.HTTP_200_OK)
|
||||
except Exception as e:
|
||||
audit_logger.error(f"WhatsApp service connection error for {mobile_number}: {e}")
|
||||
return Response({
|
||||
"status": "error",
|
||||
"message": f"Could not reach WhatsApp service gateway: {str(e)}",
|
||||
"mobile_number": mobile_number
|
||||
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
class VerifyOTPView(APIView):
|
||||
permission_classes = [permissions.AllowAny]
|
||||
|
||||
def post(self, request):
|
||||
mobile_number = request.data.get('mobile_number')
|
||||
otp_code = request.data.get('otp_code')
|
||||
|
||||
if not mobile_number or not otp_code:
|
||||
return Response({"error": "mobile_number and otp_code are required"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
clean_phone = str(mobile_number).replace('+', '').strip()
|
||||
stored_otp = cache.get(f"whatsapp_otp_{clean_phone}")
|
||||
|
||||
if stored_otp and str(stored_otp).strip() == str(otp_code).strip():
|
||||
audit_logger.info(f"AUDIT - OTP Verification SUCCESS: mobile '{mobile_number}'")
|
||||
return Response({
|
||||
"status": "success",
|
||||
"message": "OTP verified successfully"
|
||||
}, status=status.HTTP_200_OK)
|
||||
else:
|
||||
audit_logger.warning(f"AUDIT - OTP Verification FAILED: mobile '{mobile_number}', submitted '{otp_code}', expected '{stored_otp}'")
|
||||
return Response({
|
||||
"status": "error",
|
||||
"message": "Invalid or expired OTP verification code. Access denied."
|
||||
}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ def home_view(request):
|
|||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
|
||||
from api.views import UserRegisterView, UserProfileView, SendWhatsAppOTPView
|
||||
from api.views import UserRegisterView, UserProfileView, SendWhatsAppOTPView, VerifyOTPView
|
||||
from products.views import CategoryListView, ProductListView, ProductDetailView
|
||||
from orders.views import CartView, CartItemDetailView, CheckoutView, PaymentSuccessView, OrderHistoryView, OrderDetailView
|
||||
|
||||
|
|
@ -16,6 +16,7 @@ urlpatterns = [
|
|||
|
||||
# Auth APIs
|
||||
path('api/v1/customer/auth/send-whatsapp/', SendWhatsAppOTPView.as_view(), name='send_whatsapp'),
|
||||
path('api/v1/customer/auth/verify-otp/', VerifyOTPView.as_view(), name='verify_otp'),
|
||||
path('api/v1/customer/auth/register/', UserRegisterView.as_view(), name='register'),
|
||||
path('api/v1/customer/auth/login/', TokenObtainPairView.as_view(), name='login'),
|
||||
path('api/v1/customer/auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
|
||||
|
|
|
|||
Loading…
Reference in a new issue