diff --git a/api/authentication/apis.py b/api/authentication/apis.py new file mode 100644 index 0000000..455ddec --- /dev/null +++ b/api/authentication/apis.py @@ -0,0 +1,22 @@ +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_phone +from api.common.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) diff --git a/api/authentication/selectors.py b/api/authentication/selectors.py new file mode 100644 index 0000000..aeeffcc --- /dev/null +++ b/api/authentication/selectors.py @@ -0,0 +1,12 @@ +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 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 78ccf87..e0005a9 100644 --- a/api/authentication/urls.py +++ b/api/authentication/urls.py @@ -5,9 +5,12 @@ TokenVerifyView, ) +from api.authentication.apis import 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"), ] 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 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):