registration and verify abuse WIP
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 1m27s

This commit is contained in:
i701 2025-04-15 14:01:47 +05:00
parent 9f3f586181
commit e0a80d4a00
6 changed files with 100 additions and 6 deletions

View File

@ -2,10 +2,12 @@
This is the models module for api.
"""
from datetime import timedelta
from django.contrib.auth.models import AbstractUser
from django.db import models
from .managers import CustomUserManager
from django.utils import timezone
import pyotp
class User(AbstractUser):
@ -34,6 +36,22 @@ class User(AbstractUser):
objects = CustomUserManager()
class TemporaryUser(User):
otp_secret = models.CharField(max_length=50, default=pyotp.random_base32)
otp_verified = models.BooleanField(default=False)
def generate_otp(self):
totp = pyotp.TOTP(self.otp_secret, interval=300)
return totp.now()
def verify_otp(self, otp):
totp = pyotp.TOTP(self.otp_secret, interval=300)
return totp.verify(otp)
def is_expired(self):
return self.created_at < timezone.now() - timedelta(minutes=5)
class Atoll(models.Model):
name = models.CharField(max_length=255, unique=True)
created_at = models.DateTimeField(default=timezone.now)

View File

@ -139,3 +139,8 @@ class AtollSerializer(serializers.ModelSerializer):
model = Atoll
fields = "__all__"
depth = 2
class OTPVerificationSerializer(serializers.Serializer):
mobile = serializers.CharField()
otp = serializers.CharField()

View File

@ -6,6 +6,8 @@ from django_rest_passwordreset.signals import reset_password_token_created
from django.db.models.signals import post_save
from api.models import User
from django.contrib.auth.models import Permission
from api.tasks import verify_user_with_person_api_task
from asgiref.sync import sync_to_async
@receiver(post_save, sender=User)
@ -26,6 +28,13 @@ def assign_device_permissions(sender, instance, created, **kwargs):
instance.user_permissions.add(permission)
@receiver(post_save, sender=User)
@sync_to_async
def verify_user_with_person_api(sender, instance, created, **kwargs):
if created:
verify_user_with_person_api_task(instance.id)
@receiver(reset_password_token_created)
def password_reset_token_created(
sender, instance, reset_password_token, *args, **kwargs

41
api/tasks.py Normal file
View File

@ -0,0 +1,41 @@
from django.shortcuts import get_object_or_404
from api.models import User
import requests
from apibase.env import env, BASE_DIR
import os
PERSON_API_URL = env.str("PERSON_VERIFY_BASE_URL", "")
env.read_env(os.path.join(BASE_DIR, ".env"))
def verify_user_with_person_api_task(user_id: int):
"""
Verify the user with the Person API.
:param user_id: The ID of the user to verify.
"""
user = get_object_or_404(User, id=user_id)
# Call the Person API to verify the user
response = requests.get(f"{PERSON_API_URL}/api/person/{user.id_card}")
if response.status_code == 200:
data = response.json()
print(f"Data from Person API: {data}")
print("Data from of user: ", user.__dict__)
if (
data.get("nic") == user.id_card
and data.get("name_en") == f"{user.first_name} {user.last_name}"
and data.get("house_name_en") == user.address
and data.get("dob") == user.dob.isoformat()
):
user.verified = True
user.save()
return True
else:
user.verified = False
user.save()
return False
else:
# Handle the error case
print(f"Error verifying user: {response.status_code} - {response.text}")
return False

View File

@ -43,6 +43,7 @@ ACCOUNT_NUMBER_PATTERN = r"^(7\d{12}|9\d{16})$"
class ErrorMessages:
USERNAME_EXISTS = "Username already exists."
MOBILE_EXISTS = "Mobile number already exists."
INVALID_ID_CARD = "Please enter a valid ID card number."
INVALID_MOBILE = "Please enter a valid mobile number."
INVALID_ACCOUNT = "Please enter a valid account number."
@ -99,12 +100,9 @@ class CreateUserView(generics.CreateAPIView):
firstname = request.data.get("firstname")
lastname = request.data.get("lastname")
# Validate required fields first
validation_error = self.validate_required_fields(request.data)
if validation_error:
return validation_error
if User.objects.filter(mobile=mobile).exists():
return Response({"message": ErrorMessages.MOBILE_EXISTS}, status=400)
# Check username uniqueness after validation
if User.objects.filter(username=username).exists():
return Response({"message": ErrorMessages.USERNAME_EXISTS}, status=400)
@ -120,6 +118,11 @@ class CreateUserView(generics.CreateAPIView):
if acc_no is None or not re.match(ACCOUNT_NUMBER_PATTERN, acc_no):
return Response({"message": ErrorMessages.INVALID_ACCOUNT}, status=400)
# Validate required fields first
validation_error = self.validate_required_fields(request.data)
if validation_error:
return validation_error
# Fetch Atoll and Island instances
try:
atoll = Atoll.objects.get(id=atoll_id)

View File

@ -2,24 +2,31 @@ aiohappyeyeballs==2.4.3
aiohttp==3.11.2
aiohttp-retry==2.8.3
aiosignal==1.3.1
amqp==5.3.1
anyio==4.9.0
arabic-reshaper==3.0.0
asgiref==3.8.1
asn1crypto==1.5.1
async-timeout==4.0.3
attrs==24.2.0
billiard==4.2.1
black==23.12.1
boto3==1.35.49
botocore==1.35.49
celery==5.5.1
certifi==2024.2.2
cffi==1.16.0
chardet==5.2.0
charset-normalizer==3.3.2
click==8.1.7
click-didyoumean==0.3.1
click-plugins==1.1.1
click-repl==0.3.0
colorama==0.4.6
cryptography==41.0.7
cssselect2==0.7.0
dj-database-url==2.1.0
django==5.1.2
django==5.2
django-cors-headers==4.3.1
django-debug-toolbar==4.2.0
django-easy-audit==1.3.7
@ -38,15 +45,20 @@ djangorestframework-simplejwt==5.3.1
djangorestframework-stubs==3.15.1
dnspython==2.4.2
drf-spectacular==0.27.2
exceptiongroup==1.2.2
faker==30.8.0
frozenlist==1.5.0
gunicorn==23.0.0
h11==0.14.0
html5lib==1.1
httpcore==1.0.7
httpx==0.28.1
idna==3.6
inflection==0.5.1
jmespath==1.0.1
jsonschema==4.23.0
jsonschema-specifications==2024.10.1
kombu==5.5.2
lxml==5.1.0
multidict==6.1.0
mypy-extensions==1.0.0
@ -55,6 +67,7 @@ packaging==23.2
pathspec==0.12.1
pillow==10.2.0
platformdirs==4.1.0
prompt-toolkit==3.0.50
propcache==0.2.0
psycopg==3.2.3
psycopg-binary==3.2.3
@ -70,6 +83,7 @@ pypng==0.20220715.0
python-bidi==0.4.2
python-dateutil==2.9.0.post0
python-decouple==3.8
python-telegram-bot==22.0
pytz==2023.3.post1
pyyaml==6.0.1
qrcode==7.4.2
@ -81,11 +95,13 @@ rpds-py==0.21.0
ruff==0.7.0
s3transfer==0.10.3
six==1.16.0
sniffio==1.3.1
sqlparse==0.5.1
svglib==1.5.1
tinycss2==1.2.1
tomli==2.0.2
toposort==1.10
twilio==9.3.7
types-pyyaml==6.0.12.20240917
types-requests==2.32.0.20241016
typing-extensions==4.12.2
@ -94,6 +110,8 @@ tzlocal==5.2
uritemplate==4.1.1
uritools==4.0.2
urllib3==2.2.1
vine==5.1.0
wcwidth==0.2.13
webencodings==0.5.1
whitenoise==6.7.0
yarl==1.17.2