mirror of
https://github.com/i701/sarlink-portal-api.git
synced 2025-06-27 22:03:58 +00:00
Add TemporaryUser model and related functionality for user registration and OTP verification
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 1m19s
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 1m19s
This commit is contained in:
106
api/views.py
106
api/views.py
@ -6,7 +6,7 @@ from rest_framework import generics, permissions
|
||||
from rest_framework.authtoken.serializers import AuthTokenSerializer
|
||||
from api.filters import UserFilter
|
||||
from api.mixins import StaffEditorPermissionMixin
|
||||
from api.models import User, Atoll, Island
|
||||
from api.models import User, Atoll, Island, TemporaryUser
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from rest_framework.exceptions import ValidationError
|
||||
@ -15,6 +15,8 @@ from api.serializers import (
|
||||
AtollSerializer,
|
||||
IslandSerializer,
|
||||
CustomUserByWalletBalanceSerializer,
|
||||
OTPVerificationSerializer,
|
||||
TemporaryUserSerializer,
|
||||
)
|
||||
|
||||
# knox imports
|
||||
@ -25,11 +27,12 @@ import re
|
||||
from typing import cast, Dict, Any
|
||||
from django.core.mail import send_mail
|
||||
from django.db.models import Q
|
||||
from api.sms import send_otp
|
||||
|
||||
|
||||
# local apps import
|
||||
from .serializers import (
|
||||
KnoxTokenSerializer,
|
||||
UserSerializer,
|
||||
AuthSerializer,
|
||||
CustomUserSerializer,
|
||||
CustomReadOnlyUserSerializer,
|
||||
@ -45,6 +48,7 @@ class ErrorMessages:
|
||||
USERNAME_EXISTS = "Username already exists."
|
||||
MOBILE_EXISTS = "Mobile number already exists."
|
||||
INVALID_ID_CARD = "Please enter a valid ID card number."
|
||||
ID_CARD_EXISTS = "ID card already exists."
|
||||
INVALID_MOBILE = "Please enter a valid mobile number."
|
||||
INVALID_ACCOUNT = "Please enter a valid account number."
|
||||
|
||||
@ -78,15 +82,14 @@ class UpdateUserWalletView(generics.UpdateAPIView):
|
||||
return Response({"message": "Wallet balance updated successfully."})
|
||||
|
||||
|
||||
class CreateUserView(generics.CreateAPIView):
|
||||
class CreateTemporaryUserView(generics.CreateAPIView):
|
||||
# Create user API view
|
||||
serializer_class = UserSerializer
|
||||
serializer_class = TemporaryUserSerializer
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
queryset = User.objects.all()
|
||||
queryset = TemporaryUser.objects.all()
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
# Extract required fields from request data
|
||||
password = request.data.get("password")
|
||||
username = request.data.get("username")
|
||||
address = request.data.get("address")
|
||||
mobile = request.data.get("mobile")
|
||||
@ -100,16 +103,19 @@ class CreateUserView(generics.CreateAPIView):
|
||||
firstname = request.data.get("firstname")
|
||||
lastname = request.data.get("lastname")
|
||||
|
||||
if User.objects.filter(mobile=mobile).exists():
|
||||
if TemporaryUser.objects.filter(t_mobile=mobile).exists():
|
||||
return Response({"message": ErrorMessages.MOBILE_EXISTS}, status=400)
|
||||
|
||||
if User.objects.filter(username=username).exists():
|
||||
if TemporaryUser.objects.filter(t_username=username).exists():
|
||||
return Response({"message": ErrorMessages.USERNAME_EXISTS}, status=400)
|
||||
|
||||
if TemporaryUser.objects.filter(t_id_card=id_card).exists():
|
||||
return Response({"message": ErrorMessages.ID_CARD_EXISTS}, status=400)
|
||||
|
||||
if id_card and not re.match(ID_CARD_PATTERN, id_card):
|
||||
return Response({"message": ErrorMessages.INVALID_ID_CARD}, status=400)
|
||||
|
||||
if User.objects.filter(id_card=id_card).exists():
|
||||
if TemporaryUser.objects.filter(t_id_card=id_card).exists():
|
||||
return Response({"message": "ID card already exists."}, status=400)
|
||||
|
||||
if mobile is None or not re.match(MOBILE_PATTERN, mobile):
|
||||
@ -133,23 +139,28 @@ class CreateUserView(generics.CreateAPIView):
|
||||
return Response({"message": "Island not found."}, status=404)
|
||||
|
||||
# Create user
|
||||
user = User.objects.create_user(
|
||||
first_name=firstname,
|
||||
last_name=lastname,
|
||||
username=str(username),
|
||||
password=password,
|
||||
email=None,
|
||||
address=address,
|
||||
mobile=mobile,
|
||||
acc_no=acc_no,
|
||||
id_card=id_card,
|
||||
dob=dob,
|
||||
atoll=atoll,
|
||||
island=island,
|
||||
terms_accepted=terms_accepted,
|
||||
policy_accepted=policy_accepted,
|
||||
temp_user = TemporaryUser.objects.create(
|
||||
t_first_name=firstname,
|
||||
t_last_name=lastname,
|
||||
t_username=str(username),
|
||||
t_email=None,
|
||||
t_address=address,
|
||||
t_mobile=mobile,
|
||||
t_acc_no=acc_no,
|
||||
t_id_card=id_card,
|
||||
t_dob=dob,
|
||||
t_atoll=atoll,
|
||||
t_island=island,
|
||||
t_terms_accepted=terms_accepted,
|
||||
t_policy_accepted=policy_accepted,
|
||||
)
|
||||
serializer = self.get_serializer(user)
|
||||
otp = temp_user.generate_otp()
|
||||
send_otp(
|
||||
temp_user.t_mobile,
|
||||
otp,
|
||||
f"Your Registration SARLink OTP is: {otp}, valid for 30 seconds. Please do not share it with anyone.",
|
||||
)
|
||||
serializer = self.get_serializer(temp_user)
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
return Response(
|
||||
serializer.data, status=status.HTTP_201_CREATED, headers=headers
|
||||
@ -159,7 +170,6 @@ class CreateUserView(generics.CreateAPIView):
|
||||
required_fields = {
|
||||
"firstname": "First name",
|
||||
"lastname": "Last name",
|
||||
"password": "Password",
|
||||
"username": "Username",
|
||||
"address": "Address",
|
||||
"mobile": "Mobile number",
|
||||
@ -182,6 +192,50 @@ class CreateUserView(generics.CreateAPIView):
|
||||
return None
|
||||
|
||||
|
||||
class VerifyOTPView(generics.GenericAPIView):
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
serializer_class = OTPVerificationSerializer
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
data = request.data
|
||||
print(data)
|
||||
try:
|
||||
temp_user = TemporaryUser.objects.get(t_mobile=data["mobile"])
|
||||
except TemporaryUser.DoesNotExist:
|
||||
return Response({"message": "User not found."}, status=404)
|
||||
|
||||
if temp_user.is_expired():
|
||||
return Response({"message": "OTP expired."}, status=400)
|
||||
|
||||
if not temp_user.verify_otp(data["otp"]):
|
||||
return Response({"message": "Invalid OTP."}, status=400)
|
||||
|
||||
# Create real user
|
||||
User.objects.create_user(
|
||||
first_name=temp_user.t_first_name,
|
||||
last_name=temp_user.t_last_name,
|
||||
username=temp_user.t_username,
|
||||
password="",
|
||||
address=temp_user.t_address,
|
||||
mobile=temp_user.t_mobile,
|
||||
acc_no=temp_user.t_acc_no,
|
||||
id_card=temp_user.t_id_card,
|
||||
dob=temp_user.t_dob,
|
||||
atoll=temp_user.t_atoll,
|
||||
island=temp_user.t_island,
|
||||
terms_accepted=temp_user.t_terms_accepted,
|
||||
policy_accepted=temp_user.t_policy_accepted,
|
||||
)
|
||||
|
||||
# You can now trigger registry verification as a signal or task
|
||||
temp_user.otp_verified = True
|
||||
temp_user.save()
|
||||
|
||||
return Response({"message": "User created successfully."})
|
||||
|
||||
|
||||
class LoginView(KnoxLoginView):
|
||||
# login view extending KnoxLoginView
|
||||
serializer_class = AuthSerializer
|
||||
|
Reference in New Issue
Block a user