From e90c3d25603164e3e4bf158746c3f659da76124b Mon Sep 17 00:00:00 2001 From: Osama Yasser Date: Sun, 8 May 2022 02:10:52 +0200 Subject: [PATCH 1/3] feat: implement validate phone/email apis --- api/authentication/apis.py | 38 +++++++++++++++++++++++++++++++++ api/authentication/selectors.py | 19 +++++++++++++++++ api/authentication/urls.py | 4 ++++ 3 files changed, 61 insertions(+) create mode 100644 api/authentication/apis.py create mode 100644 api/authentication/selectors.py diff --git a/api/authentication/apis.py b/api/authentication/apis.py new file mode 100644 index 0000000..a9fde61 --- /dev/null +++ b/api/authentication/apis.py @@ -0,0 +1,38 @@ +from rest_framework import permissions, serializers, status +from rest_framework.response import Response +from rest_framework.views import APIView + +from api.authentication.selectors import validate_email, validate_phone +from api.users.validators import is_phone + + +class ValidatePhoneAPI(APIView): + permission_classes = [permissions.AllowAny] + + class InputSerializer(serializers.Serializer): + phone = serializers.CharField(validators=[is_phone]) + + def post(self, request): + serializer = self.InputSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + + # Raises validation error if phone is taken + validate_phone(**serializer.validated_data) + + return Response(status=status.HTTP_200_OK) + + +class ValidateEmailAPI(APIView): + permission_classes = [permissions.AllowAny] + + class InputSerializer(serializers.Serializer): + email = serializers.EmailField() + + def post(self, request): + serializer = self.InputSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + + # Raises validation error if email is taken + validate_email(**serializer.validated_data) + + return Response(status=status.HTTP_200_OK) diff --git a/api/authentication/selectors.py b/api/authentication/selectors.py new file mode 100644 index 0000000..fb77fe3 --- /dev/null +++ b/api/authentication/selectors.py @@ -0,0 +1,19 @@ +from typing import Union + +from rest_framework.exceptions import ValidationError + +from api.users.models import User + + +def validate_phone(*, phone: str) -> Union[None, ValidationError]: + if User.objects.filter(username=phone).exists(): + raise ValidationError(f"Phone number: {phone} already taken") + + return None + + +def validate_email(*, email: str) -> Union[None, ValidationError]: + if User.objects.filter(email=email).exists(): + raise ValidationError(f"Email: {email} already taken") + + return None diff --git a/api/authentication/urls.py b/api/authentication/urls.py index 78ccf87..b3d847b 100644 --- a/api/authentication/urls.py +++ b/api/authentication/urls.py @@ -5,9 +5,13 @@ TokenVerifyView, ) +from api.authentication.apis import ValidateEmailAPI, ValidatePhoneAPI + app_name = "auth" urlpatterns = [ path("token/", TokenObtainPairView.as_view(), name="obtain_token"), path("token/refresh/", TokenRefreshView.as_view(), name="refresh_token"), path("token/verify/", TokenVerifyView.as_view(), name="verify_token"), + path("phone/validate/", ValidatePhoneAPI.as_view(), name="validate_phone"), + path("email/validate/", ValidateEmailAPI.as_view(), name="validate_email"), ] From cdea9fea5581517e355ae08498799fc8e6788707 Mon Sep 17 00:00:00 2001 From: Osama Yasser Date: Sun, 8 May 2022 02:15:36 +0200 Subject: [PATCH 2/3] refactor: move validators in api.common app --- api/authentication/apis.py | 2 +- api/{users => common}/validators.py | 0 api/users/migrations/0001_initial.py | 4 ++-- api/users/models.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename api/{users => common}/validators.py (100%) diff --git a/api/authentication/apis.py b/api/authentication/apis.py index a9fde61..4d6ef11 100644 --- a/api/authentication/apis.py +++ b/api/authentication/apis.py @@ -3,7 +3,7 @@ from rest_framework.views import APIView from api.authentication.selectors import validate_email, validate_phone -from api.users.validators import is_phone +from api.common.validators import is_phone class ValidatePhoneAPI(APIView): diff --git a/api/users/validators.py b/api/common/validators.py similarity index 100% rename from api/users/validators.py rename to api/common/validators.py diff --git a/api/users/migrations/0001_initial.py b/api/users/migrations/0001_initial.py index 03e3c3a..16fd85c 100644 --- a/api/users/migrations/0001_initial.py +++ b/api/users/migrations/0001_initial.py @@ -1,6 +1,6 @@ # Generated by Django 3.2.13 on 2022-04-19 22:39 -import api.users.validators +import api.common.validators import django.contrib.auth.models from django.db import migrations, models import django.db.models.deletion @@ -29,7 +29,7 @@ class Migration(migrations.Migration): ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), ('name', models.CharField(max_length=256)), ('email', models.EmailField(blank=True, max_length=254, null=True)), - ('username', models.CharField(max_length=10, unique=True, validators=[api.users.validators.is_phone])), + ('username', models.CharField(max_length=10, unique=True, validators=[api.common.validators.is_phone])), ('id_exp_date', models.DateTimeField(blank=True, null=True)), ('id_photo_url', models.ImageField(blank=True, upload_to='id-photos/')), ('firebase_token', models.CharField(blank=True, max_length=256, unique=True)), diff --git a/api/users/models.py b/api/users/models.py index b906a50..ddccd3f 100644 --- a/api/users/models.py +++ b/api/users/models.py @@ -3,8 +3,8 @@ from django.urls import reverse from django.utils import timezone +from api.common.validators import is_phone from api.locations.models import Location -from api.users.validators import is_phone class User(AbstractUser): From 2616a5ddf3a5ec437c49f9ffcd5aafba233fc9f9 Mon Sep 17 00:00:00 2001 From: Osama Yasser Date: Sun, 8 May 2022 22:22:03 +0200 Subject: [PATCH 3/3] fix: remove email validation --- api/authentication/apis.py | 18 +----------------- api/authentication/selectors.py | 7 ------- api/authentication/tests.py | 1 - api/authentication/urls.py | 3 +-- api/authentication/views.py | 1 - 5 files changed, 2 insertions(+), 28 deletions(-) delete mode 100644 api/authentication/tests.py delete mode 100644 api/authentication/views.py diff --git a/api/authentication/apis.py b/api/authentication/apis.py index 4d6ef11..455ddec 100644 --- a/api/authentication/apis.py +++ b/api/authentication/apis.py @@ -2,7 +2,7 @@ from rest_framework.response import Response from rest_framework.views import APIView -from api.authentication.selectors import validate_email, validate_phone +from api.authentication.selectors import validate_phone from api.common.validators import is_phone @@ -20,19 +20,3 @@ def post(self, request): validate_phone(**serializer.validated_data) return Response(status=status.HTTP_200_OK) - - -class ValidateEmailAPI(APIView): - permission_classes = [permissions.AllowAny] - - class InputSerializer(serializers.Serializer): - email = serializers.EmailField() - - def post(self, request): - serializer = self.InputSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - - # Raises validation error if email is taken - validate_email(**serializer.validated_data) - - return Response(status=status.HTTP_200_OK) diff --git a/api/authentication/selectors.py b/api/authentication/selectors.py index fb77fe3..aeeffcc 100644 --- a/api/authentication/selectors.py +++ b/api/authentication/selectors.py @@ -10,10 +10,3 @@ def validate_phone(*, phone: str) -> Union[None, ValidationError]: raise ValidationError(f"Phone number: {phone} already taken") return None - - -def validate_email(*, email: str) -> Union[None, ValidationError]: - if User.objects.filter(email=email).exists(): - raise ValidationError(f"Email: {email} already taken") - - return None diff --git a/api/authentication/tests.py b/api/authentication/tests.py deleted file mode 100644 index 007eb95..0000000 --- a/api/authentication/tests.py +++ /dev/null @@ -1 +0,0 @@ -# Tests diff --git a/api/authentication/urls.py b/api/authentication/urls.py index b3d847b..e0005a9 100644 --- a/api/authentication/urls.py +++ b/api/authentication/urls.py @@ -5,7 +5,7 @@ TokenVerifyView, ) -from api.authentication.apis import ValidateEmailAPI, ValidatePhoneAPI +from api.authentication.apis import ValidatePhoneAPI app_name = "auth" urlpatterns = [ @@ -13,5 +13,4 @@ path("token/refresh/", TokenRefreshView.as_view(), name="refresh_token"), path("token/verify/", TokenVerifyView.as_view(), name="verify_token"), path("phone/validate/", ValidatePhoneAPI.as_view(), name="validate_phone"), - path("email/validate/", ValidateEmailAPI.as_view(), name="validate_email"), ] diff --git a/api/authentication/views.py b/api/authentication/views.py deleted file mode 100644 index 5873694..0000000 --- a/api/authentication/views.py +++ /dev/null @@ -1 +0,0 @@ -# Views