From 4ceb2bfc0cbc3a753e005ac34fc85afaeb179ef0 Mon Sep 17 00:00:00 2001 From: MohamedHamed12 Date: Thu, 9 May 2024 18:33:25 +0300 Subject: [PATCH] add #30 check national_id and email --- project/accounts/serializers/__init__.py | 2 +- .../serializers/{permissions.py => user.py} | 4 + project/accounts/tests/test_setup.py | 54 ++++---- .../{test_permissions.py => test_user.py} | 25 ++++ project/accounts/urls.py | 2 + project/accounts/views/__init__.py | 2 +- project/accounts/views/patient.py | 2 +- project/accounts/views/permissions.py | 45 ------- project/accounts/views/user.py | 115 ++++++++++++++++++ 9 files changed, 182 insertions(+), 69 deletions(-) rename project/accounts/serializers/{permissions.py => user.py} (73%) rename project/accounts/tests/{test_permissions.py => test_user.py} (64%) delete mode 100644 project/accounts/views/permissions.py create mode 100644 project/accounts/views/user.py diff --git a/project/accounts/serializers/__init__.py b/project/accounts/serializers/__init__.py index 7e419e6..8487f4c 100644 --- a/project/accounts/serializers/__init__.py +++ b/project/accounts/serializers/__init__.py @@ -1,5 +1,5 @@ -from .permissions import * from .patient import * from .doctor import * from .patient import * from .employee import * +from .user import * \ No newline at end of file diff --git a/project/accounts/serializers/permissions.py b/project/accounts/serializers/user.py similarity index 73% rename from project/accounts/serializers/permissions.py rename to project/accounts/serializers/user.py index 4bd5210..795316c 100644 --- a/project/accounts/serializers/permissions.py +++ b/project/accounts/serializers/user.py @@ -23,3 +23,7 @@ class Meta: # fields = '__all__' exclude = ['password'] +class CheckNationalSerializer(serializers.Serializer): + national_id =serializers.CharField(max_length=255) +class CheckEmailSerializer(serializers.Serializer): + email =serializers.CharField(max_length=255) \ No newline at end of file diff --git a/project/accounts/tests/test_setup.py b/project/accounts/tests/test_setup.py index 26a03fa..4fa37d7 100644 --- a/project/accounts/tests/test_setup.py +++ b/project/accounts/tests/test_setup.py @@ -23,37 +23,49 @@ def get_token(self,username,password): # if 'access' not in token.data: # print('no access',token.data,username,password) return token.data['access'] - def create_staff(self): - user=User.objects.create_user(username='stafftest', password='test123') + def create_staff(self,username='stafftest', password='test123'): + user=User.objects.create_user(username=username, password=password) user.is_staff = True user.save() - token=self.get_token('stafftest','test123') + token=self.get_token(username, password) return user,token def create_user(self): user = User.objects.create_user(username='test', password='test123') return user - def create_patient(self,staff_token): + def create_patient(self,staff_token,national_id='01234567890123', + email='test1@test.com', + full_name='test', + date_of_birth='2000-01-01', + gender='M', + disease_type='test', + blood_type='test', + marital_status='test', + nationality='test', + address={ + 'street':'test', + 'city':'test', + 'governorate':'test' + }, + phone={ + 'mobile':'test' + } + + ): data={ - 'marital_status':'test', - 'nationality':'test', - 'full_name':'test', - 'national_id':'01234567890123', - 'date_of_birth':'2000-01-01', - 'gender':'M', - 'disease_type':'test', - 'blood_type':'test', - - 'address':{ - 'street':'test', - 'city':'test', - 'governorate':'test' - }, - 'phone':{ - 'mobile':'test' - } + 'national_id': national_id, + 'email': email, + 'full_name': full_name, + 'date_of_birth': date_of_birth, + 'gender': gender, + 'disease_type': disease_type, + 'blood_type': blood_type, + 'marital_status': marital_status, + 'nationality': nationality, + 'address': address, + 'phone': phone diff --git a/project/accounts/tests/test_permissions.py b/project/accounts/tests/test_user.py similarity index 64% rename from project/accounts/tests/test_permissions.py rename to project/accounts/tests/test_user.py index 122f693..0fd97c4 100644 --- a/project/accounts/tests/test_permissions.py +++ b/project/accounts/tests/test_user.py @@ -40,3 +40,28 @@ def test_assign_permissions_to_user(self): self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data['user_permissions']), 2) + + +class CheckTest(TestSetup): + def setUp(self) -> None: + super().setUp() + self.staff,self.staff_token=self.create_staff(username="12345678901230") + self.patient,self.patient_token=self.create_patient(self.staff_token,national_id="1234567890123",email="test@test.com") + def test_check_national_id(self): + url = reverse('check_national_id') + data = { + 'national_id': '1234567890123' + } + response = self.client.post( + url, data, format='json', HTTP_AUTHORIZATION='Bearer ' + self.staff_token) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.data['exists'],True) + def test_check_email(self): + url = reverse('check_email') + data = { + 'email': 'test@test.com' + } + response = self.client.post( + url, data, format='json', HTTP_AUTHORIZATION='Bearer ' + self.staff_token) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.data['exists'],True) \ No newline at end of file diff --git a/project/accounts/urls.py b/project/accounts/urls.py index 2397c77..89085b6 100644 --- a/project/accounts/urls.py +++ b/project/accounts/urls.py @@ -23,5 +23,7 @@ path('token/', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'), path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), path('token/verify/', TokenVerifyView.as_view(), name='token_verify'), + path('check-national-id/', CheckNationalIdView.as_view(), name='check_national_id'), + path('check-email/',CheckEmailView().as_view(), name='check_email'), ] diff --git a/project/accounts/views/__init__.py b/project/accounts/views/__init__.py index abb8870..735abac 100644 --- a/project/accounts/views/__init__.py +++ b/project/accounts/views/__init__.py @@ -1,4 +1,4 @@ from .employee import * -from .permissions import * +from .user import * from .patient import * from .doctor import * \ No newline at end of file diff --git a/project/accounts/views/patient.py b/project/accounts/views/patient.py index b20f994..c108579 100644 --- a/project/accounts/views/patient.py +++ b/project/accounts/views/patient.py @@ -42,7 +42,7 @@ def create(self , request, *args, **kwargs): msg,user=create_user(request.data) if msg!="created": return Response(msg,status=status.HTTP_400_BAD_REQUEST) - + request.data.update({'user':user.id}) return super().create(request, *args, **kwargs) diff --git a/project/accounts/views/permissions.py b/project/accounts/views/permissions.py deleted file mode 100644 index 3271e02..0000000 --- a/project/accounts/views/permissions.py +++ /dev/null @@ -1,45 +0,0 @@ - -from rest_framework import viewsets -from rest_framework.permissions import IsAdminUser -from accounts.serializers import * -from django.contrib.auth.models import Group -from django.contrib.auth.models import Permission -from rest_framework.response import Response -from rest_framework import status -from rest_framework.views import APIView -from django.http import Http404 -from rest_framework_simplejwt.views import TokenObtainPairView - - -from rest_framework.viewsets import GenericViewSet -from rest_framework import mixins - -class GroupViewSet(viewsets.ModelViewSet): - permission_classes = [IsAdminUser] - queryset = Group.objects.all() - serializer_class = GroupSerializer - -class PermissionViewSet(viewsets.ModelViewSet): - permission_classes = [IsAdminUser] - queryset = Permission.objects.all() - serializer_class = PermissionSerializer - - - - -class UserDetails(GenericViewSet, mixins.RetrieveModelMixin, mixins.UpdateModelMixin): - queryset = User.objects.all() - serializer_class = UserSerializer - permission_classes = [IsAdminUser] - - - -class CustomTokenObtainPairView(TokenObtainPairView): - def post(self, request, *args, **kwargs): - response= super().post(request, *args, **kwargs) - try: - response.data['user']= UserSerializer(User.objects.get(username=request.data['username'])).data - except: - pass - - return response diff --git a/project/accounts/views/user.py b/project/accounts/views/user.py new file mode 100644 index 0000000..838cb67 --- /dev/null +++ b/project/accounts/views/user.py @@ -0,0 +1,115 @@ + +from rest_framework import viewsets +from rest_framework.permissions import IsAdminUser +from accounts.serializers import * +from django.contrib.auth.models import Group +from django.contrib.auth.models import Permission +from rest_framework.response import Response +from rest_framework import status +from rest_framework.views import APIView +from django.http import Http404 +from rest_framework_simplejwt.views import TokenObtainPairView +from rest_framework.permissions import AllowAny + + +from rest_framework.viewsets import GenericViewSet +from rest_framework import mixins +from rest_framework.generics import GenericAPIView + +class GroupViewSet(viewsets.ModelViewSet): + permission_classes = [IsAdminUser] + queryset = Group.objects.all() + serializer_class = GroupSerializer + +class PermissionViewSet(viewsets.ModelViewSet): + permission_classes = [IsAdminUser] + queryset = Permission.objects.all() + serializer_class = PermissionSerializer + + + + +class UserDetails(GenericViewSet, mixins.RetrieveModelMixin, mixins.UpdateModelMixin): + queryset = User.objects.all() + serializer_class = UserSerializer + permission_classes = [IsAdminUser] + + + +class CustomTokenObtainPairView(TokenObtainPairView): + """ + A custom view for obtaining token pairs (access and refresh tokens) with additional functionality. + + This class extends the TokenObtainPairView provided by the Django REST Framework, allowing customization + to include user data in the response along with the token pairs. + + Usage: + This class can be used as a view in Django REST Framework to handle token authentication. It inherits + functionality from TokenObtainPairView and adds the ability to include user data in the response. + + + """ + def post(self, request, *args, **kwargs): + """ + Handles POST requests to obtain token pairs. Additionally, it includes user data in the response + if available. + + Args: + request (HttpRequest): The HTTP request object. + *args: Variable length argument list. + **kwargs: Arbitrary keyword arguments. + + Returns: + Response: An HTTP response containing token pairs along with user data if available. + """ + response= super().post(request, *args, **kwargs) + try: + response.data['user']= UserSerializer(User.objects.get(username=request.data['username'])).data + except: + pass + + return response + +class CheckNationalIdView(GenericAPIView): + serializer_class =CheckNationalSerializer + permission_classes=[AllowAny] + def post(self,request,*args,**kwargs): + national_id=request.data['national_id'] + patient=Patient.objects.filter(national_id=national_id).exists() + doctor=Doctor.objects.filter(national_id=national_id).exists() + employee=Employee.objects.filter(national_id=national_id).exists() + if patient or doctor or employee: + return Response({'exists':True} ,status=status.HTTP_200_OK) + return Response({'exists':False} ,status=status.HTTP_200_OK) + +class CheckEmailView(GenericAPIView): + """ + A view to check if an email exists in the database. + + This class provides a POST method to check if a given email already exists in the User model. + + Usage: + This class can be used as a view in Django REST Framework to handle checking if an email exists + in the database. + + """ + serializer_class =CheckEmailSerializer + permission_classes=[AllowAny] + def post(self,request,*args,**kwargs): + """ + Handles POST requests to check if an email exists in the database. + + Args: + request (HttpRequest): The HTTP request object containing the email to check. + + Returns: + Response: An HTTP response indicating whether the email exists or not. + """ + email=request.data['email'] + patient=Patient.objects.filter(email=email).exists() + doctor=Doctor.objects.filter(email=email).exists() + employee=Employee.objects.filter(email=email).exists() + if patient or doctor or employee: + return Response({'exists':True} ,status=status.HTTP_200_OK) + return Response({'exists':False} ,status=status.HTTP_200_OK) +