From a16fecb1c94ffe3d2d12312a0ed5fa71858ae721 Mon Sep 17 00:00:00 2001 From: jain Date: Thu, 13 Jul 2023 16:37:42 +0530 Subject: [PATCH 01/14] changes in image size --- account/views.py | 8 ++------ guardian/views.py | 8 ++------ junior/views.py | 4 +--- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/account/views.py b/account/views.py index 3a5f974..9d56de8 100644 --- a/account/views.py +++ b/account/views.py @@ -169,9 +169,7 @@ class UpdateProfileImage(views.APIView): def put(self, request, format=None): try: image = request.data['image'] - img = Image.open(image) - width, height = img.size - if width == NUMBER['zero'] or height == NUMBER['zero']: + if image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) filename = f"images/{image.name}" image_url = upload_image_to_alibaba(image, filename) @@ -435,9 +433,7 @@ class UploadImageAPIViewSet(viewsets.ModelViewSet): """profile view""" image_data = request.data['image_url'] filename = f"default_task_images/{image_data.name}" - img = Image.open(image_data) - width, height = img.size - if width == NUMBER['zero'] or height == NUMBER['zero']: + if image_data.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) image = upload_image_to_alibaba(image_data, filename) image_data = image diff --git a/guardian/views.py b/guardian/views.py index 420e521..409de89 100644 --- a/guardian/views.py +++ b/guardian/views.py @@ -56,9 +56,7 @@ class UpdateGuardianProfile(viewsets.ViewSet): data = request.data image = request.data.get('image') image_url = '' - img = Image.open(image) - width, height = img.size - if width == NUMBER['zero'] or height == NUMBER['zero']: + if image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) if image: filename = f"images/{image.name}" @@ -120,9 +118,7 @@ class CreateTaskAPIView(viewsets.ModelViewSet): image_data = image else: filename = f"images/{image}" - img = Image.open(image) - width, height = img.size - if width == NUMBER['zero'] or height == NUMBER['zero']: + if image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) image_url = upload_image_to_alibaba(image, filename) image_data = image_url diff --git a/junior/views.py b/junior/views.py index 0dcdbbe..1dfe5d3 100644 --- a/junior/views.py +++ b/junior/views.py @@ -25,9 +25,7 @@ class UpdateJuniorProfile(viewsets.ViewSet): request_data = request.data image = request.data.get('image') image_url = '' - img = Image.open(image) - width, height = img.size - if width == NUMBER['zero'] or height == NUMBER['zero']: + if image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) if image: filename = f"images/{image.name}" From 52a0f4b590d46d83da5556a442f4adf52d3eb2ea Mon Sep 17 00:00:00 2001 From: jain Date: Thu, 13 Jul 2023 17:31:05 +0530 Subject: [PATCH 02/14] referral code --- account/views.py | 30 ++++++++++++------------------ guardian/serializers.py | 15 ++++++--------- guardian/views.py | 6 +++--- junior/serializers.py | 16 ++++++---------- junior/views.py | 4 ++-- 5 files changed, 29 insertions(+), 42 deletions(-) diff --git a/account/views.py b/account/views.py index 9d56de8..4e71ecd 100644 --- a/account/views.py +++ b/account/views.py @@ -27,7 +27,8 @@ from rest_framework_simplejwt.tokens import RefreshToken from base.messages import ERROR_CODE, SUCCESS_CODE from base.constants import NUMBER from guardian.tasks import generate_otp -from account.utils import send_otp_email, send_support_email, custom_response, custom_error_response +from account.utils import (send_otp_email, send_support_email, custom_response, custom_error_response, + generate_alphanumeric_code) from rest_framework.permissions import IsAuthenticated from templated_email import send_templated_mail import google.oauth2.credentials @@ -89,19 +90,15 @@ class GoogleLoginMixin: if str(user_type) == '1': junior_query = Junior.objects.create(auth=user_obj, is_verified=True, is_active=True, image=profile_picture, signup_method='2', - junior_code=''.join( - [str(random.randrange(9)) for _ in range(6)]), - referral_code=''.join( - [str(random.randrange(9)) for _ in range(6)]) + junior_code=generate_alphanumeric_code(6), + referral_code=generate_alphanumeric_code(6) ) serializer = JuniorSerializer(junior_query) if str(user_type) == '2': guardian_query = Guardian.objects.create(user=user_obj, is_verified=True, is_active=True, image=profile_picture,signup_method='2', - guardian_code=''.join( - [str(random.randrange(9)) for _ in range(6)]), - referral_code=''.join( - [str(random.randrange(9)) for _ in range(6)]) + guardian_code=generate_alphanumeric_code(6), + referral_code=generate_alphanumeric_code(6) ) serializer = GuardianSerializer(guardian_query) # Return a JSON response with the user's email and name @@ -143,18 +140,15 @@ class SigninWithApple(views.APIView): user = User.objects.create(**user_data) if str(user_type) == '1': junior_query = Junior.objects.create(auth=user, is_verified=True, is_active=True, - signup_method='3',junior_code=''.join( - [str(random.randrange(9)) for _ in range(6)]), - referral_code=''.join( - [str(random.randrange(9)) for _ in range(6)])) + signup_method='3', + junior_code=generate_alphanumeric_code(6), + referral_code=generate_alphanumeric_code(6)) serializer = JuniorSerializer(junior_query) if str(user_type) == '2': guardian_query = Guardian.objects.create(user=user, is_verified=True, is_active=True, signup_method='3', - guardian_code=''.join( - [str(random.randrange(9)) for _ in range(6)]), - referral_code=''.join( - [str(random.randrange(9)) for _ in range(6)])) + guardian_code=generate_alphanumeric_code(6), + referral_code=generate_alphanumeric_code(6)) serializer = GuardianSerializer(guardian_query) return custom_response(SUCCESS_CODE['3003'], serializer.data, response_status=status.HTTP_200_OK) @@ -169,7 +163,7 @@ class UpdateProfileImage(views.APIView): def put(self, request, format=None): try: image = request.data['image'] - if image.size == NUMBER['zero']: + if image and image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) filename = f"images/{image.name}" image_url = upload_image_to_alibaba(image, filename) diff --git a/guardian/serializers.py b/guardian/serializers.py index 592502e..65def21 100644 --- a/guardian/serializers.py +++ b/guardian/serializers.py @@ -9,6 +9,7 @@ from django.contrib.auth.models import User """Import Django app""" from .models import Guardian, JuniorTask from account.models import UserProfile, UserEmailOtp, UserNotification +from account.utils import generate_alphanumeric_code from account.serializers import JuniorSerializer from junior.serializers import JuniorDetailSerializer from base.messages import ERROR_CODE, SUCCESS_CODE @@ -38,11 +39,11 @@ class UserSerializer(serializers.ModelSerializer): user = User.objects.create_user(username=email, email=email, password=password) UserNotification.objects.create(user=user) if user_type == '1': - Junior.objects.create(auth=user, junior_code=''.join([str(random.randrange(9)) for _ in range(6)]), - referral_code=''.join([str(random.randrange(9)) for _ in range(6)])) + Junior.objects.create(auth=user, junior_code=generate_alphanumeric_code(6), + referral_code=generate_alphanumeric_code(6)) if user_type == '2': - Guardian.objects.create(user=user, guardian_code=''.join([str(random.randrange(9)) for _ in range(6)]), - referral_code=''.join([str(random.randrange(9)) for _ in range(6)])) + Guardian.objects.create(user=user, guardian_code=generate_alphanumeric_code(6), + referral_code=generate_alphanumeric_code(6)) return user except Exception as e: """Error handling""" @@ -99,11 +100,7 @@ class CreateGuardianSerializer(serializers.ModelSerializer): user.last_name = self.context.get('last_name') user.save() """Create guardian data""" - guardian, created = Guardian.objects.get_or_create(user=self.context['user']) - if created: - """Create referral code and guardian code""" - guardian.referral_code = ''.join([str(random.randrange(9)) for _ in range(4)]) - guardian.guardian_code = ''.join([str(random.randrange(9)) for _ in range(4)]) + guardian = Guardian.objects.filter(user=self.context['user']).last() if guardian: """update details according to the data get from request""" guardian.gender = validated_data.get('gender',guardian.gender) diff --git a/guardian/views.py b/guardian/views.py index 409de89..61bf9b9 100644 --- a/guardian/views.py +++ b/guardian/views.py @@ -56,9 +56,9 @@ class UpdateGuardianProfile(viewsets.ViewSet): data = request.data image = request.data.get('image') image_url = '' - if image.size == NUMBER['zero']: - return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) if image: + if image and image.size == NUMBER['zero']: + return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) filename = f"images/{image.name}" image_url = upload_image_to_alibaba(image, filename) data = {"image":image_url} @@ -118,7 +118,7 @@ class CreateTaskAPIView(viewsets.ModelViewSet): image_data = image else: filename = f"images/{image}" - if image.size == NUMBER['zero']: + if image and image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) image_url = upload_image_to_alibaba(image, filename) image_data = image_url diff --git a/junior/serializers.py b/junior/serializers.py index 1f08674..2df13ca 100644 --- a/junior/serializers.py +++ b/junior/serializers.py @@ -8,7 +8,7 @@ from django.utils import timezone from rest_framework_simplejwt.tokens import RefreshToken """Import django app""" -from account.utils import send_otp_email +from account.utils import send_otp_email, generate_alphanumeric_code from junior.models import Junior, JuniorPoints from guardian.tasks import generate_otp from base.messages import ERROR_CODE, SUCCESS_CODE @@ -76,11 +76,7 @@ class CreateJuniorSerializer(serializers.ModelSerializer): user.last_name = self.context.get('last_name') user.save() """Create junior data""" - junior, created = Junior.objects.get_or_create(auth=self.context['user']) - if created: - """Create referral code and junior code""" - junior.referral_code = ''.join([str(random.randrange(9)) for _ in range(4)]) - junior.junior_code = ''.join([str(random.randrange(9)) for _ in range(4)]) + junior = Junior.objects.filter(auth=self.context['user']).last() if junior: """update details according to the data get from request""" junior.gender = validated_data.get('gender',junior.gender) @@ -134,8 +130,8 @@ class JuniorDetailSerializer(serializers.ModelSerializer): """Meta info""" model = Junior fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob', - 'guardian_code', 'is_invited', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image', - 'updated_at'] + 'guardian_code', 'is_invited', 'referral_code','is_active', 'is_complete_profile', 'created_at', + 'image', 'updated_at'] class JuniorDetailListSerializer(serializers.ModelSerializer): """junior serializer""" @@ -279,8 +275,8 @@ class AddJuniorSerializer(serializers.ModelSerializer): junior_data = Junior.objects.create(auth=user_data, gender=validated_data.get('gender'), dob=validated_data.get('dob'), is_invited=True, relationship=validated_data.get('relationship'), - junior_code=''.join([str(random.randrange(9)) for _ in range(4)]), - referral_code=''.join([str(random.randrange(9)) for _ in range(4)]), + junior_code=generate_alphanumeric_code(6), + referral_code=generate_alphanumeric_code(6), referral_code_used=guardian_data.referral_code) """Generate otp""" otp_value = generate_otp() diff --git a/junior/views.py b/junior/views.py index 1dfe5d3..a1053d4 100644 --- a/junior/views.py +++ b/junior/views.py @@ -25,9 +25,9 @@ class UpdateJuniorProfile(viewsets.ViewSet): request_data = request.data image = request.data.get('image') image_url = '' - if image.size == NUMBER['zero']: - return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) if image: + if image.size == NUMBER['zero']: + return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) filename = f"images/{image.name}" image_url = upload_image_to_alibaba(image, filename) request_data = {"image": image_url} From 5d528b885abbb139237627dfe200431491fa050f Mon Sep 17 00:00:00 2001 From: jain Date: Thu, 13 Jul 2023 19:24:33 +0530 Subject: [PATCH 03/14] jira-18 approval API --- account/utils.py | 6 ++++++ base/messages.py | 4 +++- guardian/serializers.py | 16 ++++++++++++++++ guardian/urls.py | 4 +++- guardian/views.py | 26 +++++++++++++++++++++++++- 5 files changed, 53 insertions(+), 3 deletions(-) diff --git a/account/utils.py b/account/utils.py index 3b74d24..846add9 100644 --- a/account/utils.py +++ b/account/utils.py @@ -187,3 +187,9 @@ def generate_alphanumeric_code(length): code = ''.join(secrets.choice(alphabet) for _ in range(length)) return code + +def generate_code(value, user_id): + alphabet = value + user_id.zfill(3) + return alphabet + + diff --git a/base/messages.py b/base/messages.py index 2c0d9cd..ffbbbec 100644 --- a/base/messages.py +++ b/base/messages.py @@ -93,7 +93,9 @@ SUCCESS_CODE = { "3019": "Support Email sent successfully", "3020": "Logged out successfully.", "3021": "Add junior successfully", - "3022": "Remove junior successfully" + "3022": "Remove junior successfully", + "3023": "Approved junior successfully", + "3024": "Reject junior request successfully" } STATUS_CODE_ERROR = { diff --git a/guardian/serializers.py b/guardian/serializers.py index 65def21..9d2a676 100644 --- a/guardian/serializers.py +++ b/guardian/serializers.py @@ -241,3 +241,19 @@ class GuardianProfileSerializer(serializers.ModelSerializer): 'guardian_code', 'notification_count', 'total_count', 'complete_field_count', 'referral_code', 'is_active', 'is_complete_profile', 'created_at', 'image', 'signup_method', 'updated_at', 'passcode'] + +class ApproveJuniorSerializer(serializers.ModelSerializer): + """approve junior serializer""" + class Meta(object): + """Meta info""" + model = Junior + fields = ['id', 'guardian_code'] + + def create(self, validated_data): + """update guardian code""" + instance = self.context['junior'] + instance.guardian_code = [self.context['guardian_code']] + instance.save() + return instance + + diff --git a/guardian/urls.py b/guardian/urls.py index b69b041..168610b 100644 --- a/guardian/urls.py +++ b/guardian/urls.py @@ -2,7 +2,7 @@ """Django import""" from django.urls import path, include from .views import (SignupViewset, UpdateGuardianProfile, AllTaskListAPIView, CreateTaskAPIView, TaskListAPIView, - SearchTaskListAPIView, TopJuniorListAPIView) + SearchTaskListAPIView, TopJuniorListAPIView, ApproveJuniorAPIView) """Third party import""" from rest_framework import routers @@ -24,6 +24,8 @@ router.register('task-list', TaskListAPIView, basename='task-list') router.register('top-junior', TopJuniorListAPIView, basename='top-junior') """Search Task list on the bases of status, due date, and task title API""" router.register('filter-task', SearchTaskListAPIView, basename='filter-task') +"""Approve junior API""" +router.register('approve-junior', ApproveJuniorAPIView, basename='approve-junior') """Define Url pattern""" urlpatterns = [ path('api/v1/', include(router.urls)), diff --git a/guardian/views.py b/guardian/views.py index 61bf9b9..f060732 100644 --- a/guardian/views.py +++ b/guardian/views.py @@ -9,7 +9,7 @@ from PIL import Image from datetime import datetime, timedelta """Import Django app""" from .serializers import (UserSerializer, CreateGuardianSerializer, TaskSerializer, TaskDetailsSerializer, - TopJuniorSerializer) + TopJuniorSerializer, ApproveJuniorSerializer) from .models import Guardian, JuniorTask from junior.models import Junior, JuniorPoints from junior.serializers import JuniorDetailSerializer @@ -114,6 +114,7 @@ class CreateTaskAPIView(viewsets.ModelViewSet): def create(self, request, *args, **kwargs): image = request.data['default_image'] data = request.data + print("data===>",data,'==>',type(data)) if 'https' in str(image): image_data = image else: @@ -178,3 +179,26 @@ class TopJuniorListAPIView(viewsets.ModelViewSet): return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) +class ApproveJuniorAPIView(viewsets.ViewSet): + """approve junior by guardian""" + serializer_class = ApproveJuniorSerializer + permission_classes = [IsAuthenticated] + + def get_queryset(self): + """Get the queryset for the view""" + guardian = Guardian.objects.filter(user__email=self.request.user).last() + junior_queryset = Junior.objects.filter(id=self.request.data.get('junior_id')).last() + return guardian, junior_queryset + + def create(self, request, *args, **kwargs): + """ junior list""" + queryset = self.get_queryset() + if request.data['action'] == '1': + serializer = ApproveJuniorSerializer(context={"guardian_code": queryset[0].guardian_code, + "junior": queryset[1], "action": request.data['action']}, + data=request.data) + if serializer.is_valid(): + serializer.save() + return custom_response(SUCCESS_CODE['3023'], serializer.data, response_status=status.HTTP_200_OK) + else: + return custom_response(SUCCESS_CODE['3024'], response_status=status.HTTP_200_OK) From 7b9b5a2c6ff188965dbdfb28ffd3636c63f360bc Mon Sep 17 00:00:00 2001 From: jain Date: Fri, 14 Jul 2023 12:05:28 +0530 Subject: [PATCH 04/14] sonar issues --- account/admin.py | 10 +--------- account/models.py | 4 ++++ account/utils.py | 6 ++++-- account/views.py | 23 +++++++++++++---------- base/constants.py | 3 +++ base/messages.py | 3 ++- guardian/models.py | 24 +++++++++++++++++++++--- guardian/serializers.py | 12 ++++++------ junior/models.py | 16 ++++++++++++++++ junior/serializers.py | 8 ++++---- junior/utils.py | 16 +++------------- 11 files changed, 77 insertions(+), 48 deletions(-) diff --git a/account/admin.py b/account/admin.py index 7b59c84..e31076e 100644 --- a/account/admin.py +++ b/account/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin """Import django app""" -from .models import UserEmailOtp, UserPhoneOtp, DefaultTaskImages, UserNotification, UserDelete +from .models import UserEmailOtp, DefaultTaskImages, UserNotification, UserDelete # Register your models here. @admin.register(UserDelete) @@ -37,11 +37,3 @@ class UserEmailOtpAdmin(admin.ModelAdmin): """Return object in email and otp format""" return self.email + '-' + self.otp -@admin.register(UserPhoneOtp) -class UserPhoneOtpAdmin(admin.ModelAdmin): - """User Phone otp admin""" - list_display = ['phone'] - - def __str__(self): - """Return object in phone number and otp format""" - return self.phone + '-' + self.otp diff --git a/account/models.py b/account/models.py index 60184c5..d89f499 100644 --- a/account/models.py +++ b/account/models.py @@ -90,6 +90,8 @@ class DefaultTaskImages(models.Model): class Meta(object): """ Meta information """ db_table = 'default_task_image' + verbose_name = 'Default Task images' + verbose_name_plural = 'Default Task images' def __str__(self): """return phone as an object""" @@ -112,6 +114,8 @@ class UserDelete(models.Model): class Meta(object): """ Meta information """ db_table = 'user_delete_information' + verbose_name = 'Deleted User' + verbose_name_plural = 'Deleted User' def __str__(self): return self.user.email diff --git a/account/utils.py b/account/utils.py index 846add9..b925b49 100644 --- a/account/utils.py +++ b/account/utils.py @@ -183,13 +183,15 @@ def get_token(data: dict = dict): def generate_alphanumeric_code(length): + """Generate alphanumeric code""" alphabet = string.ascii_letters + string.digits code = ''.join(secrets.choice(alphabet) for _ in range(length)) return code def generate_code(value, user_id): - alphabet = value + user_id.zfill(3) - return alphabet + """generate referral, junior and guardian code""" + code = value + str(user_id).zfill(3) + return code diff --git a/account/views.py b/account/views.py index 4e71ecd..0adc33c 100644 --- a/account/views.py +++ b/account/views.py @@ -25,10 +25,10 @@ from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSeriali UserNotificationSerializer, UpdateUserNotificationSerializer, UserPhoneOtpSerializer) from rest_framework_simplejwt.tokens import RefreshToken from base.messages import ERROR_CODE, SUCCESS_CODE -from base.constants import NUMBER +from base.constants import NUMBER, ZOD, JUN, GRD from guardian.tasks import generate_otp from account.utils import (send_otp_email, send_support_email, custom_response, custom_error_response, - generate_alphanumeric_code) + generate_code) from rest_framework.permissions import IsAuthenticated from templated_email import send_templated_mail import google.oauth2.credentials @@ -42,6 +42,7 @@ from guardian.serializers import GuardianProfileSerializer class GoogleLoginMixin: """google login mixin""" + @staticmethod def google_login(self, request): """google login function""" access_token = request.data.get('access_token') @@ -90,15 +91,15 @@ class GoogleLoginMixin: if str(user_type) == '1': junior_query = Junior.objects.create(auth=user_obj, is_verified=True, is_active=True, image=profile_picture, signup_method='2', - junior_code=generate_alphanumeric_code(6), - referral_code=generate_alphanumeric_code(6) + junior_code=generate_code(JUN, user_obj.id), + referral_code=generate_code(ZOD, user_obj.id) ) serializer = JuniorSerializer(junior_query) if str(user_type) == '2': guardian_query = Guardian.objects.create(user=user_obj, is_verified=True, is_active=True, image=profile_picture,signup_method='2', - guardian_code=generate_alphanumeric_code(6), - referral_code=generate_alphanumeric_code(6) + guardian_code=generate_code(GRD, user_obj.id), + referral_code=generate_code(ZOD, user_obj.id) ) serializer = GuardianSerializer(guardian_query) # Return a JSON response with the user's email and name @@ -141,14 +142,14 @@ class SigninWithApple(views.APIView): if str(user_type) == '1': junior_query = Junior.objects.create(auth=user, is_verified=True, is_active=True, signup_method='3', - junior_code=generate_alphanumeric_code(6), - referral_code=generate_alphanumeric_code(6)) + junior_code=generate_code(JUN, user.id), + referral_code=generate_code(ZOD, user.id)) serializer = JuniorSerializer(junior_query) if str(user_type) == '2': guardian_query = Guardian.objects.create(user=user, is_verified=True, is_active=True, signup_method='3', - guardian_code=generate_alphanumeric_code(6), - referral_code=generate_alphanumeric_code(6)) + guardian_code=generate_code(GRD, user.id), + referral_code=generate_code(ZOD, user.id)) serializer = GuardianSerializer(guardian_query) return custom_response(SUCCESS_CODE['3003'], serializer.data, response_status=status.HTTP_200_OK) @@ -181,6 +182,7 @@ class UpdateProfileImage(views.APIView): return custom_response(SUCCESS_CODE['3017'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: + logging.error(e) return custom_error_response(ERROR_CODE['2036'],response_status=status.HTTP_400_BAD_REQUEST) class ChangePasswordAPIView(views.APIView): @@ -512,6 +514,7 @@ class SendSupportEmail(views.APIView): class LogoutAPIView(views.APIView): + """Log out API""" permission_classes = (IsAuthenticated,) def post(self, request): diff --git a/base/constants.py b/base/constants.py index 7c83134..6025e0b 100644 --- a/base/constants.py +++ b/base/constants.py @@ -6,6 +6,9 @@ import os # GOOGLE_URL used for interact with google server to verify user existence. #GOOGLE_URL = "https://www.googleapis.com/plus/v1/" +ZOD = 'ZOD' +JUN = 'JUN' +GRD = 'GRD' NUMBER = { 'point_zero': 0.0, 'zero': 0, diff --git a/base/messages.py b/base/messages.py index ffbbbec..49deaf9 100644 --- a/base/messages.py +++ b/base/messages.py @@ -61,6 +61,7 @@ ERROR_CODE = { "2035": "Image should not be 0 kb", "2036": "Choose valid user" } +"""Success message code""" SUCCESS_CODE = { # Success code for password "3001": "Sign up successfully", @@ -97,7 +98,7 @@ SUCCESS_CODE = { "3023": "Approved junior successfully", "3024": "Reject junior request successfully" } - +"""status code error""" STATUS_CODE_ERROR = { # Status code for Invalid Input "4001": ["Invalid input."], diff --git a/guardian/models.py b/guardian/models.py index 921138a..5636a80 100644 --- a/guardian/models.py +++ b/guardian/models.py @@ -4,6 +4,7 @@ from django.db import models from django.contrib.auth import get_user_model """Import Django app""" from base.constants import GENDERS, TASK_STATUS, PENDING, TASK_POINTS, SIGNUP_METHODS +"""import Junior model""" from junior.models import Junior """Add user model""" User = get_user_model() @@ -15,23 +16,31 @@ class Guardian(models.Model): """Contact details""" country_code = models.IntegerField(blank=True, null=True) phone = models.CharField(max_length=31, null=True, blank=True, default=None) + """country name of the guardian""" country_name = models.CharField(max_length=100, null=True, blank=True, default=None) """Image info""" image = models.URLField(null=True, blank=True, default=None) """Personal info""" family_name = models.CharField(max_length=50, null=True, blank=True, default=None) + """gender of the guardian""" gender = models.CharField(choices=GENDERS, max_length=15, null=True, blank=True, default=None) + """date of birth of the guardian""" dob = models.DateField(max_length=15, null=True, blank=True, default=None) """Profile activity""" is_active = models.BooleanField(default=True) + """guardian is verified or not""" is_verified = models.BooleanField(default=False) + """guardian profile is complete or not""" is_complete_profile = models.BooleanField(default=False) + """passcode of the guardian profile""" passcode = models.IntegerField(null=True, blank=True, default=None) """Sign up method""" signup_method = models.CharField(max_length=31, choices=SIGNUP_METHODS, default='1') - """Codes""" + """Guardian Codes""" guardian_code = models.CharField(max_length=10, null=True, blank=True, default=None) + """Referral code""" referral_code = models.CharField(max_length=10, null=True, blank=True, default=None) + """Referral code that is used by guardian while signup""" referral_code_used = models.CharField(max_length=10, null=True, blank=True, default=None) """Profile created and updated time""" created_at = models.DateTimeField(auto_now_add=True) @@ -40,7 +49,10 @@ class Guardian(models.Model): class Meta(object): """ Meta class """ db_table = 'guardians' + """verbose name of the model""" verbose_name = 'Guardian' + """change another name""" + verbose_name_plural = 'Guardian' def __str__(self): """Return email id""" @@ -51,19 +63,23 @@ class JuniorTask(models.Model): guardian = models.ForeignKey(Guardian, on_delete=models.CASCADE, related_name='guardian', verbose_name='Guardian') """task details""" task_name = models.CharField(max_length=100) + """task description""" task_description = models.CharField(max_length=500) """points of the task""" points = models.IntegerField(default=TASK_POINTS) + """last date of the task""" due_date = models.DateField(auto_now_add=False, null=True, blank=True) - """Images of task""" + """Images of task that is upload by guardian""" default_image = models.URLField(null=True, blank=True, default=None) + """image that is uploaded by junior""" image = models.URLField(null=True, blank=True, default=None) """associated junior with the task""" junior = models.ForeignKey(Junior, on_delete=models.CASCADE, related_name='junior', verbose_name='Junior') """task status""" task_status = models.CharField(choices=TASK_STATUS, max_length=15, default=PENDING) - """task stage""" + """task is active or not""" is_active = models.BooleanField(default=True) + """Task is approved or not""" is_approved = models.BooleanField(default=False) """Profile created and updated time""" created_at = models.DateTimeField(auto_now_add=True) @@ -72,7 +88,9 @@ class JuniorTask(models.Model): class Meta(object): """ Meta class """ db_table = 'junior_task' + """verbose name of the model""" verbose_name = 'Junior Task' + verbose_name_plural = 'Junior Task' def __str__(self): """Return email id""" diff --git a/guardian/serializers.py b/guardian/serializers.py index 9d2a676..055d738 100644 --- a/guardian/serializers.py +++ b/guardian/serializers.py @@ -9,11 +9,11 @@ from django.contrib.auth.models import User """Import Django app""" from .models import Guardian, JuniorTask from account.models import UserProfile, UserEmailOtp, UserNotification -from account.utils import generate_alphanumeric_code +from account.utils import generate_code from account.serializers import JuniorSerializer from junior.serializers import JuniorDetailSerializer from base.messages import ERROR_CODE, SUCCESS_CODE -from base.constants import NUMBER +from base.constants import NUMBER, JUN, ZOD, GRD from junior.models import Junior, JuniorPoints class UserSerializer(serializers.ModelSerializer): """User serializer""" @@ -39,11 +39,11 @@ class UserSerializer(serializers.ModelSerializer): user = User.objects.create_user(username=email, email=email, password=password) UserNotification.objects.create(user=user) if user_type == '1': - Junior.objects.create(auth=user, junior_code=generate_alphanumeric_code(6), - referral_code=generate_alphanumeric_code(6)) + Junior.objects.create(auth=user, junior_code=generate_code(JUN, user.id), + referral_code=generate_code(ZOD, user.id)) if user_type == '2': - Guardian.objects.create(user=user, guardian_code=generate_alphanumeric_code(6), - referral_code=generate_alphanumeric_code(6)) + Guardian.objects.create(user=user, guardian_code=generate_code(GRD, user.id), + referral_code=generate_code(ZOD, user.id)) return user except Exception as e: """Error handling""" diff --git a/junior/models.py b/junior/models.py index 58b1ae3..381bbf4 100644 --- a/junior/models.py +++ b/junior/models.py @@ -1,10 +1,13 @@ """Junior model """ """Import django""" from django.db import models +"""Import get_user_model function""" from django.contrib.auth import get_user_model +"""Import ArrayField""" from django.contrib.postgres.fields import ArrayField """Import django app""" from base.constants import GENDERS, SIGNUP_METHODS, RELATIONSHIP +"""Define User model""" User = get_user_model() # Create your models here. @@ -14,10 +17,13 @@ class Junior(models.Model): """Contact details""" phone = models.CharField(max_length=31, null=True, blank=True, default=None) country_code = models.IntegerField(blank=True, null=True) + """country name of the guardian""" country_name = models.CharField(max_length=100, null=True, blank=True, default=None) """Personal info""" gender = models.CharField(max_length=10, choices=GENDERS, null=True, blank=True, default=None) + """Date of birth""" dob = models.DateField(max_length=15, null=True, blank=True, default=None) + """Image of the junior""" image = models.URLField(null=True, blank=True, default=None) """relationship""" relationship = models.CharField(max_length=31, choices=RELATIONSHIP, null=True, blank=True, @@ -26,15 +32,21 @@ class Junior(models.Model): signup_method = models.CharField(max_length=31, choices=SIGNUP_METHODS, default='1') """Codes""" junior_code = models.CharField(max_length=10, null=True, blank=True, default=None) + """Guardian Codes""" guardian_code = ArrayField(models.CharField(max_length=10, null=True, blank=True, default=None),null=True) + """Referral code""" referral_code = models.CharField(max_length=10, null=True, blank=True, default=None) + """Referral code that is used by junior while signup""" referral_code_used = models.CharField(max_length=10, null=True, blank=True, default=None) """invited junior""" is_invited = models.BooleanField(default=False) """Profile activity""" is_active = models.BooleanField(default=True) + """junior profile is complete or not""" is_complete_profile = models.BooleanField(default=False) + """passcode of the junior profile""" passcode = models.IntegerField(null=True, blank=True, default=None) + """junior is verified or not""" is_verified = models.BooleanField(default=False) """Profile created and updated time""" created_at = models.DateTimeField(auto_now_add=True) @@ -44,6 +56,8 @@ class Junior(models.Model): """ Meta class """ db_table = 'junior' verbose_name = 'Junior' + """another name of the model""" + verbose_name_plural = 'Junior' def __str__(self): """Return email id""" @@ -64,6 +78,8 @@ class JuniorPoints(models.Model): """ Meta class """ db_table = 'junior_task_points' verbose_name = 'Junior Task Points' + """another name of the model""" + verbose_name_plural = 'Junior Task Points' def __str__(self): """Return email id""" diff --git a/junior/serializers.py b/junior/serializers.py index 2df13ca..013cd58 100644 --- a/junior/serializers.py +++ b/junior/serializers.py @@ -8,11 +8,11 @@ from django.utils import timezone from rest_framework_simplejwt.tokens import RefreshToken """Import django app""" -from account.utils import send_otp_email, generate_alphanumeric_code +from account.utils import send_otp_email, generate_code from junior.models import Junior, JuniorPoints from guardian.tasks import generate_otp from base.messages import ERROR_CODE, SUCCESS_CODE -from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER +from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER, JUN, ZOD from guardian.models import Guardian, JuniorTask from account.models import UserEmailOtp from junior.utils import junior_notification_email, junior_approval_mail @@ -275,8 +275,8 @@ class AddJuniorSerializer(serializers.ModelSerializer): junior_data = Junior.objects.create(auth=user_data, gender=validated_data.get('gender'), dob=validated_data.get('dob'), is_invited=True, relationship=validated_data.get('relationship'), - junior_code=generate_alphanumeric_code(6), - referral_code=generate_alphanumeric_code(6), + junior_code=generate_code(JUN, user_data.id), + referral_code=generate_code(ZOD, user_data.id), referral_code_used=guardian_data.referral_code) """Generate otp""" otp_value = generate_otp() diff --git a/junior/utils.py b/junior/utils.py index 7d19a2d..41c393d 100644 --- a/junior/utils.py +++ b/junior/utils.py @@ -1,28 +1,17 @@ """Account utils""" """Import django""" from django.conf import settings -from rest_framework import viewsets, status -from rest_framework.response import Response """Third party Django app""" from templated_email import send_templated_mail -import jwt -import string -from datetime import datetime -from calendar import timegm -from uuid import uuid4 -import secrets -from rest_framework import serializers -from junior.models import Junior -from guardian.models import Guardian -from account.models import UserDelete -from base.messages import ERROR_CODE def junior_notification_email(recipient_email, full_name, email, password): """Notification email""" from_email = settings.EMAIL_FROM_ADDRESS + """recipient email""" recipient_list = [recipient_email] + """use send template mail for sending email""" send_templated_mail( template_name='junior_notification_email.email', from_email=from_email, @@ -40,6 +29,7 @@ def junior_approval_mail(guardian, full_name): """junior approval mail""" from_email = settings.EMAIL_FROM_ADDRESS recipient_list = [guardian] + """use send tempolate mail for sending email""" send_templated_mail( template_name='junior_approval_mail.email', from_email=from_email, From d163f43c852113bcb4f2885b00ca5b7d84afebf0 Mon Sep 17 00:00:00 2001 From: jain Date: Fri, 14 Jul 2023 15:02:53 +0530 Subject: [PATCH 05/14] jira-25 access token API --- account/serializers.py | 25 ++++++++++++++++++------- account/urls.py | 5 +++-- account/views.py | 24 +++++++++++++++++++++--- zod_bank/settings.py | 4 ++-- 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/account/serializers.py b/account/serializers.py index d75039a..bbde6a0 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -125,12 +125,17 @@ class GuardianSerializer(serializers.ModelSerializer): first_name = serializers.SerializerMethodField('get_first_name') last_name = serializers.SerializerMethodField('get_last_name') auth_token = serializers.SerializerMethodField('get_auth_token') + refresh_token = serializers.SerializerMethodField('get_refresh_token') def get_auth_token(self, obj): refresh = RefreshToken.for_user(obj.user) access_token = str(refresh.access_token) return access_token + def get_refresh_token(self, obj): + refresh = RefreshToken.for_user(obj.user) + refresh_token = str(refresh) + return refresh_token def get_user_type(self, obj): """user type""" @@ -154,9 +159,9 @@ class GuardianSerializer(serializers.ModelSerializer): class Meta(object): """Meta info""" model = Guardian - fields = ['id', 'auth_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'family_name', - 'gender', 'dob', 'referral_code', 'is_active', 'is_complete_profile', 'passcode', 'image', - 'created_at', 'updated_at', 'user_type', 'country_name'] + fields = ['id', 'auth_token', 'refresh_token', 'email', 'first_name', 'last_name', 'country_code', + 'phone', 'family_name', 'gender', 'dob', 'referral_code', 'is_active', + 'is_complete_profile', 'passcode', 'image', 'created_at', 'updated_at', 'user_type', 'country_name'] class JuniorSerializer(serializers.ModelSerializer): @@ -166,15 +171,21 @@ class JuniorSerializer(serializers.ModelSerializer): first_name = serializers.SerializerMethodField('get_first_name') last_name = serializers.SerializerMethodField('get_last_name') auth_token = serializers.SerializerMethodField('get_auth_token') + refresh_token = serializers.SerializerMethodField('get_refresh_token') def get_auth_token(self, obj): refresh = RefreshToken.for_user(obj.auth) access_token = str(refresh.access_token) return access_token + def get_refresh_token(self, obj): + refresh = RefreshToken.for_user(obj.user) + refresh_token = str(refresh) + return refresh_token + def get_user_type(self, obj): email_verified = UserEmailOtp.objects.filter(email=obj.auth.username).last() - if email_verified and email_verified.user_type != None: + if email_verified and email_verified.user_type is not None: return email_verified.user_type return '1' @@ -190,9 +201,9 @@ class JuniorSerializer(serializers.ModelSerializer): class Meta(object): """Meta info""" model = Junior - fields = ['id', 'auth_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob', - 'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image', - 'updated_at', 'user_type', 'country_name','is_invited'] + fields = ['id', 'auth_token', 'refresh_token', 'email', 'first_name', 'last_name', 'country_code', + 'phone', 'gender', 'dob', 'guardian_code', 'referral_code','is_active', + 'is_complete_profile', 'created_at', 'image', 'updated_at', 'user_type', 'country_name','is_invited'] class EmailVerificationSerializer(serializers.ModelSerializer): """Email verification serializer""" diff --git a/account/urls.py b/account/urls.py index f2a1d62..9977658 100644 --- a/account/urls.py +++ b/account/urls.py @@ -8,7 +8,7 @@ from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVer ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage, GoogleLoginViewSet, SigninWithApple, ProfileAPIViewSet, UploadImageAPIViewSet, DefaultImageAPIViewSet, DeleteUserProfileAPIViewSet, UserNotificationAPIViewSet, - UpdateUserNotificationAPIViewSet, SendSupportEmail, LogoutAPIView) + UpdateUserNotificationAPIViewSet, SendSupportEmail, LogoutAPIView, AccessTokenAPIView) """Router""" router = routers.SimpleRouter() @@ -45,5 +45,6 @@ urlpatterns = [ path('api/v1/update-profile-image/', UpdateProfileImage.as_view()), path('api/v1/apple-login/', SigninWithApple.as_view(), name='signup_with_apple'), path('api/v1/send-support-email/', SendSupportEmail.as_view(), name='send-support-email'), - path('api/v1/logout/', LogoutAPIView.as_view(), name='logout') + path('api/v1/logout/', LogoutAPIView.as_view(), name='logout'), + path('api/v1/generate-token/', AccessTokenAPIView.as_view(), name='generate-token') ] diff --git a/account/views.py b/account/views.py index 0adc33c..fcc5ecb 100644 --- a/account/views.py +++ b/account/views.py @@ -37,6 +37,7 @@ from rest_framework import status import requests from rest_framework.response import Response from django.conf import settings +from rest_framework_simplejwt.tokens import RefreshToken from junior.serializers import JuniorProfileSerializer from guardian.serializers import GuardianProfileSerializer @@ -302,7 +303,8 @@ class UserLogin(viewsets.ViewSet): email_verified = UserEmailOtp.objects.filter(email=username).last() refresh = RefreshToken.for_user(user) access_token = str(refresh.access_token) - data = {"auth_token":access_token, "is_profile_complete": False, + refresh_token = str(refresh) + data = {"auth_token":access_token, "refresh_token":refresh_token, "is_profile_complete": False, "user_type": email_verified.user_type, } is_verified = False @@ -336,7 +338,8 @@ class UserLogin(viewsets.ViewSet): logging.error(e) refresh = RefreshToken.for_user(user) access_token = str(refresh.access_token) - data = {"auth_token": access_token, "user_role": '3'} + refresh_token = str(refresh) + data = {"auth_token": access_token, "refresh_token":refresh_token, "user_type": '3'} return custom_response(None, data, response_status=status.HTTP_200_OK) class UserEmailVerification(viewsets.ModelViewSet): @@ -373,7 +376,8 @@ class UserEmailVerification(viewsets.ModelViewSet): guardian_data.save() refresh = RefreshToken.for_user(user_obj) access_token = str(refresh.access_token) - return custom_response(SUCCESS_CODE['3011'], {"auth_token":access_token}, + refresh_token = str(refresh) + return custom_response(SUCCESS_CODE['3011'], {"auth_token":access_token, "refresh_token":refresh_token}, response_status=status.HTTP_200_OK) else: return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST) @@ -521,3 +525,17 @@ class LogoutAPIView(views.APIView): logout(request) request.session.flush() return custom_response(SUCCESS_CODE['3020'], response_status=status.HTTP_200_OK) + + +class AccessTokenAPIView(views.APIView): + """generate access token API""" + + def post(self, request): + # Assuming you have a refresh_token string + refresh_token = request.data['refresh_token'] + # Create a RefreshToken instance from the refresh token string + refresh = RefreshToken(refresh_token) + # Generate a new access token + access_token = str(refresh.access_token) + data = {"auth_token": access_token} + return custom_response(None, data, response_status=status.HTTP_200_OK) diff --git a/zod_bank/settings.py b/zod_bank/settings.py index d98d2db..687b42b 100644 --- a/zod_bank/settings.py +++ b/zod_bank/settings.py @@ -97,8 +97,8 @@ REST_FRAMEWORK = { 'PAGE_SIZE': 5, } SIMPLE_JWT = { - 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=50), - 'REFRESH_TOKEN_LIFETIME': timedelta(days=7), + 'ACCESS_TOKEN_LIFETIME': timedelta(hours=2, minutes=59, seconds=59, microseconds=999999), + 'REFRESH_TOKEN_LIFETIME': timedelta(hours=71, minutes=59, seconds=59, microseconds=999999), } # Database # https://docs.djangoproject.com/en/3.0/ref/settings/#databases From c7983579527c9a63c651ab08a7a2b2664934e5af Mon Sep 17 00:00:00 2001 From: jain Date: Fri, 14 Jul 2023 15:05:18 +0530 Subject: [PATCH 06/14] migrations files --- ...lter_defaulttaskimages_options_and_more.py | 21 +++++++++++++++++++ ...ardian_options_alter_juniortask_options.py | 21 +++++++++++++++++++ ...nior_options_alter_juniorpoints_options.py | 21 +++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 account/migrations/0007_alter_defaulttaskimages_options_and_more.py create mode 100644 guardian/migrations/0015_alter_guardian_options_alter_juniortask_options.py create mode 100644 junior/migrations/0013_alter_junior_options_alter_juniorpoints_options.py diff --git a/account/migrations/0007_alter_defaulttaskimages_options_and_more.py b/account/migrations/0007_alter_defaulttaskimages_options_and_more.py new file mode 100644 index 0000000..4c134d7 --- /dev/null +++ b/account/migrations/0007_alter_defaulttaskimages_options_and_more.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.2 on 2023-07-14 09:34 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0006_alter_useremailotp_options_and_more'), + ] + + operations = [ + migrations.AlterModelOptions( + name='defaulttaskimages', + options={'verbose_name': 'Default Task images', 'verbose_name_plural': 'Default Task images'}, + ), + migrations.AlterModelOptions( + name='userdelete', + options={'verbose_name': 'Deleted User', 'verbose_name_plural': 'Deleted User'}, + ), + ] diff --git a/guardian/migrations/0015_alter_guardian_options_alter_juniortask_options.py b/guardian/migrations/0015_alter_guardian_options_alter_juniortask_options.py new file mode 100644 index 0000000..45edd24 --- /dev/null +++ b/guardian/migrations/0015_alter_guardian_options_alter_juniortask_options.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.2 on 2023-07-14 09:34 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('guardian', '0014_guardian_signup_method'), + ] + + operations = [ + migrations.AlterModelOptions( + name='guardian', + options={'verbose_name': 'Guardian', 'verbose_name_plural': 'Guardian'}, + ), + migrations.AlterModelOptions( + name='juniortask', + options={'verbose_name': 'Junior Task', 'verbose_name_plural': 'Junior Task'}, + ), + ] diff --git a/junior/migrations/0013_alter_junior_options_alter_juniorpoints_options.py b/junior/migrations/0013_alter_junior_options_alter_juniorpoints_options.py new file mode 100644 index 0000000..266d53c --- /dev/null +++ b/junior/migrations/0013_alter_junior_options_alter_juniorpoints_options.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.2 on 2023-07-14 09:34 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('junior', '0012_junior_is_invited'), + ] + + operations = [ + migrations.AlterModelOptions( + name='junior', + options={'verbose_name': 'Junior', 'verbose_name_plural': 'Junior'}, + ), + migrations.AlterModelOptions( + name='juniorpoints', + options={'verbose_name': 'Junior Task Points', 'verbose_name_plural': 'Junior Task Points'}, + ), + ] From a0e1dc11fae65f15d87590c711162efb2d4770e8 Mon Sep 17 00:00:00 2001 From: jain Date: Fri, 14 Jul 2023 15:07:54 +0530 Subject: [PATCH 07/14] migrations files --- guardian/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/guardian/views.py b/guardian/views.py index f060732..f35ca90 100644 --- a/guardian/views.py +++ b/guardian/views.py @@ -114,7 +114,6 @@ class CreateTaskAPIView(viewsets.ModelViewSet): def create(self, request, *args, **kwargs): image = request.data['default_image'] data = request.data - print("data===>",data,'==>',type(data)) if 'https' in str(image): image_data = image else: From 485dc8391147696bd06048a5c34e770f4cb361a2 Mon Sep 17 00:00:00 2001 From: jain Date: Fri, 14 Jul 2023 16:04:43 +0530 Subject: [PATCH 08/14] authenticate the api --- account/views.py | 11 +++++++++++ junior/views.py | 2 ++ 2 files changed, 13 insertions(+) diff --git a/account/views.py b/account/views.py index fcc5ecb..59260c2 100644 --- a/account/views.py +++ b/account/views.py @@ -208,6 +208,7 @@ class ResetPasswordAPIView(views.APIView): class ForgotPasswordAPIView(views.APIView): """Forgot password""" + def post(self, request): serializer = ForgotPasswordSerializer(data=request.data) if serializer.is_valid(): @@ -346,6 +347,7 @@ class UserEmailVerification(viewsets.ModelViewSet): """User Email verification""" serializer_class = EmailVerificationSerializer queryset = UserEmailOtp.objects.all() + permission_classes = [IsAuthenticated] def list(self, request, *args, **kwargs): try: @@ -389,6 +391,8 @@ class ReSendEmailOtp(viewsets.ModelViewSet): """Send otp on phone""" queryset = UserEmailOtp.objects.all() serializer_class = EmailVerificationSerializer + permission_classes = [IsAuthenticated] + def create(self, request, *args, **kwargs): otp = generate_otp() if User.objects.filter(email=request.data['email']): @@ -410,6 +414,8 @@ class ProfileAPIViewSet(viewsets.ModelViewSet): """Profile viewset""" queryset = User.objects.all() serializer_class = JuniorProfileSerializer + permission_classes = [IsAuthenticated] + def list(self, request, *args, **kwargs): """profile view""" if str(self.request.GET.get('user_type')) == '1': @@ -448,6 +454,7 @@ class DefaultImageAPIViewSet(viewsets.ModelViewSet): """Profile viewset""" queryset = DefaultTaskImages.objects.all() serializer_class = DefaultTaskImagesDetailsSerializer + permission_classes = [IsAuthenticated] def list(self, request, *args, **kwargs): """profile view""" queryset = DefaultTaskImages.objects.all() @@ -478,6 +485,7 @@ class UserNotificationAPIViewSet(viewsets.ModelViewSet): """notification viewset""" queryset = UserNotification.objects.all() serializer_class = UserNotificationSerializer + permission_classes = [IsAuthenticated] def list(self, request, *args, **kwargs): """profile view""" queryset = self.queryset.filter(user=request.user) @@ -489,6 +497,7 @@ class UpdateUserNotificationAPIViewSet(viewsets.ModelViewSet): """Update notification viewset""" queryset = UserNotification.objects.all() serializer_class = UpdateUserNotificationSerializer + permission_classes = [IsAuthenticated] def create(self, request, *args, **kwargs): """profile view""" @@ -502,6 +511,8 @@ class UpdateUserNotificationAPIViewSet(viewsets.ModelViewSet): class SendSupportEmail(views.APIView): """support email api""" + permission_classes = (IsAuthenticated,) + def post(self, request): name = request.data.get('name') sender = request.data.get('email') diff --git a/junior/views.py b/junior/views.py index a1053d4..5766c82 100644 --- a/junior/views.py +++ b/junior/views.py @@ -62,6 +62,8 @@ class JuniorListAPIView(viewsets.ModelViewSet): serializer_class = JuniorDetailListSerializer queryset = Junior.objects.all() + permission_classes = [IsAuthenticated] + def list(self, request, *args, **kwargs): """ junior list""" guardian_data = Guardian.objects.filter(user__email=request.user).last() From 5bd865a685b979fcace94794c55068d0f94d7341 Mon Sep 17 00:00:00 2001 From: jain Date: Fri, 14 Jul 2023 19:38:58 +0530 Subject: [PATCH 09/14] login in only single device at a time --- account/admin.py | 9 ++++- account/custom_middleware.py | 36 ++++++++++++++++++ account/migrations/0008_userdevicedetails.py | 31 ++++++++++++++++ account/models.py | 20 ++++++++++ account/views.py | 39 ++++++++++---------- base/messages.py | 3 +- guardian/urls.py | 10 ++++- zod_bank/settings.py | 1 + 8 files changed, 126 insertions(+), 23 deletions(-) create mode 100644 account/custom_middleware.py create mode 100644 account/migrations/0008_userdevicedetails.py diff --git a/account/admin.py b/account/admin.py index e31076e..b67b88a 100644 --- a/account/admin.py +++ b/account/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin """Import django app""" -from .models import UserEmailOtp, DefaultTaskImages, UserNotification, UserDelete +from .models import UserEmailOtp, DefaultTaskImages, UserNotification, UserDelete, UserDeviceDetails # Register your models here. @admin.register(UserDelete) @@ -37,3 +37,10 @@ class UserEmailOtpAdmin(admin.ModelAdmin): """Return object in email and otp format""" return self.email + '-' + self.otp +@admin.register(UserDeviceDetails) +class UserDeviceDetailsAdmin(admin.ModelAdmin): + """User profile admin""" + list_display = ['user', 'device_id'] + + def __str__(self): + return self.user.email diff --git a/account/custom_middleware.py b/account/custom_middleware.py new file mode 100644 index 0000000..3bd5e60 --- /dev/null +++ b/account/custom_middleware.py @@ -0,0 +1,36 @@ +"""middleware file""" +"""Django import""" +from rest_framework import status +from rest_framework.response import Response +from rest_framework.renderers import JSONRenderer +"""App django""" +from account.utils import custom_error_response +from account.models import UserDeviceDetails +from base.messages import ERROR_CODE, SUCCESS_CODE + +"""Custom middleware +when user login with +multiple device simultaneously""" +class CustomMiddleware: + """Custom middleware""" + def __init__(self, get_response): + """response""" + self.get_response = get_response + + def __call__(self, request): + # Code to be executed before the view is called + response = self.get_response(request) + # Code to be executed after the view is called + device_id = request.META['HTTP_DEVICE_ID'] + if request.user.is_authenticated: + """device details""" + device_details = UserDeviceDetails.objects.filter(user=request.user, device_id=device_id).last() + if not device_details: + custom_error = custom_error_response(ERROR_CODE['2037'], response_status=status.HTTP_404_NOT_FOUND) + response = Response(custom_error.data, status=status.HTTP_404_NOT_FOUND) + # Set content type header to "application/json" + response['Content-Type'] = 'application/json' + # Render the response as JSON + renderer = JSONRenderer() + response.content = renderer.render(response.data) + return response diff --git a/account/migrations/0008_userdevicedetails.py b/account/migrations/0008_userdevicedetails.py new file mode 100644 index 0000000..0b655f6 --- /dev/null +++ b/account/migrations/0008_userdevicedetails.py @@ -0,0 +1,31 @@ +# Generated by Django 4.2.2 on 2023-07-14 11:08 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('account', '0007_alter_defaulttaskimages_options_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='UserDeviceDetails', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('device_id', models.CharField(max_length=500)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='user_device_details', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'User Device Details', + 'verbose_name_plural': 'User Device Details', + 'db_table': 'user_device_details', + }, + ), + ] diff --git a/account/models.py b/account/models.py index d89f499..d515e01 100644 --- a/account/models.py +++ b/account/models.py @@ -145,3 +145,23 @@ class UserNotification(models.Model): def __str__(self): return self.user.email + +class UserDeviceDetails(models.Model): + """ + User notification details + """ + user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_device_details') + """Device ID""" + device_id = models.CharField(max_length=500) + + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + class Meta(object): + """ Meta information """ + db_table = 'user_device_details' + verbose_name = 'User Device Details' + verbose_name_plural = 'User Device Details' + + def __str__(self): + return self.user.email diff --git a/account/views.py b/account/views.py index 59260c2..b6fc821 100644 --- a/account/views.py +++ b/account/views.py @@ -5,17 +5,23 @@ from rest_framework import viewsets, status, views from rest_framework.decorators import action import random import logging -from PIL import Image -from django.views.decorators.csrf import csrf_exempt from django.utils import timezone import jwt from django.contrib.auth import logout -"""App Import""" -from guardian.utils import upload_image_to_alibaba from django.contrib.auth import authenticate, login +from rest_framework.permissions import IsAuthenticated +from templated_email import send_templated_mail +import google.oauth2.credentials +import google.auth.transport.requests +from rest_framework import status +import requests +from rest_framework.response import Response +from django.conf import settings +"""App Import""" from guardian.models import Guardian from junior.models import Junior -from account.models import UserProfile, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification +from guardian.utils import upload_image_to_alibaba +from account.models import UserDeviceDetails, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification from django.contrib.auth.models import User """Account serializer""" from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer, @@ -29,15 +35,6 @@ from base.constants import NUMBER, ZOD, JUN, GRD from guardian.tasks import generate_otp from account.utils import (send_otp_email, send_support_email, custom_response, custom_error_response, generate_code) -from rest_framework.permissions import IsAuthenticated -from templated_email import send_templated_mail -import google.oauth2.credentials -import google.auth.transport.requests -from rest_framework import status -import requests -from rest_framework.response import Response -from django.conf import settings -from rest_framework_simplejwt.tokens import RefreshToken from junior.serializers import JuniorProfileSerializer from guardian.serializers import GuardianProfileSerializer @@ -229,7 +226,6 @@ class ForgotPasswordAPIView(views.APIView): 'verification_code': verification_code } ) - expiry = timezone.now() + timezone.timedelta(days=1) user_data, created = UserEmailOtp.objects.get_or_create(email=email) if created: @@ -285,6 +281,7 @@ class UserLogin(viewsets.ViewSet): def login(self, request): username = request.data.get('username') password = request.data.get('password') + device_id = request.META.get('HTTP_DEVICE_ID') user = authenticate(request, username=username, password=password) try: @@ -296,6 +293,10 @@ class UserLogin(viewsets.ViewSet): junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last() if junior_data: serializer = JuniorSerializer(junior_data).data + device_details, created = UserDeviceDetails.objects.get_or_create(user=user) + if device_details: + device_details.device_id = device_id + device_details.save() return custom_response(SUCCESS_CODE['3003'], serializer, response_status=status.HTTP_200_OK) else: return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED) @@ -347,7 +348,6 @@ class UserEmailVerification(viewsets.ModelViewSet): """User Email verification""" serializer_class = EmailVerificationSerializer queryset = UserEmailOtp.objects.all() - permission_classes = [IsAuthenticated] def list(self, request, *args, **kwargs): try: @@ -379,7 +379,8 @@ class UserEmailVerification(viewsets.ModelViewSet): refresh = RefreshToken.for_user(user_obj) access_token = str(refresh.access_token) refresh_token = str(refresh) - return custom_response(SUCCESS_CODE['3011'], {"auth_token":access_token, "refresh_token":refresh_token}, + return custom_response(SUCCESS_CODE['3011'], {"auth_token":access_token, + "refresh_token":refresh_token}, response_status=status.HTTP_200_OK) else: return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST) @@ -429,8 +430,6 @@ class ProfileAPIViewSet(viewsets.ModelViewSet): serializer = GuardianProfileSerializer(guardian_data) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) - - class UploadImageAPIViewSet(viewsets.ModelViewSet): """Profile viewset""" queryset = DefaultTaskImages.objects.all() @@ -527,7 +526,6 @@ class SendSupportEmail(views.APIView): else: return custom_error_response(ERROR_CODE['2033'], response_status=status.HTTP_400_BAD_REQUEST) - class LogoutAPIView(views.APIView): """Log out API""" permission_classes = (IsAuthenticated,) @@ -550,3 +548,4 @@ class AccessTokenAPIView(views.APIView): access_token = str(refresh.access_token) data = {"auth_token": access_token} return custom_response(None, data, response_status=status.HTTP_200_OK) + diff --git a/base/messages.py b/base/messages.py index 49deaf9..02b0e34 100644 --- a/base/messages.py +++ b/base/messages.py @@ -59,7 +59,8 @@ ERROR_CODE = { "2033": "Missing required fields", "2034": "Junior is not associated", "2035": "Image should not be 0 kb", - "2036": "Choose valid user" + "2036": "Choose valid user", + "2037": "You are already log in another device" } """Success message code""" SUCCESS_CODE = { diff --git a/guardian/urls.py b/guardian/urls.py index 168610b..14398f2 100644 --- a/guardian/urls.py +++ b/guardian/urls.py @@ -9,7 +9,15 @@ from rest_framework import routers """Define Router""" router = routers.SimpleRouter() -"""API End points with router""" +"""API End points with router +in this file +we define various api end point +that is covered in this guardian +section API:- like +sign-up, create guardian profile, +create-task, +all task list, top junior, +filter-task""" """Sign up API""" router.register('sign-up', SignupViewset, basename='sign-up') """Create guardian profile API""" diff --git a/zod_bank/settings.py b/zod_bank/settings.py index 687b42b..b052a4f 100644 --- a/zod_bank/settings.py +++ b/zod_bank/settings.py @@ -67,6 +67,7 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'account.custom_middleware.CustomMiddleware' ] ROOT_URLCONF = 'zod_bank.urls' From 32e52e17f4b5cb9daae5ed5af978e37af8abc278 Mon Sep 17 00:00:00 2001 From: jain Date: Sat, 15 Jul 2023 23:07:12 +0530 Subject: [PATCH 10/14] sonar issue --- account/admin.py | 3 +++ account/custom_middleware.py | 10 +++++----- base/messages.py | 2 ++ guardian/urls.py | 18 +++++++++--------- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/account/admin.py b/account/admin.py index b67b88a..cf3ff23 100644 --- a/account/admin.py +++ b/account/admin.py @@ -19,6 +19,7 @@ class UserNotificationAdmin(admin.ModelAdmin): list_display = ['user', 'push_notification', 'email_notification', 'sms_notification'] def __str__(self): + """Return image url""" return self.image_url @admin.register(DefaultTaskImages) class DefaultTaskImagesAdmin(admin.ModelAdmin): @@ -26,6 +27,7 @@ class DefaultTaskImagesAdmin(admin.ModelAdmin): list_display = ['task_name', 'image_url'] def __str__(self): + """Return image url""" return self.image_url @admin.register(UserEmailOtp) @@ -43,4 +45,5 @@ class UserDeviceDetailsAdmin(admin.ModelAdmin): list_display = ['user', 'device_id'] def __str__(self): + """Return user email""" return self.user.email diff --git a/account/custom_middleware.py b/account/custom_middleware.py index 3bd5e60..7c4dc32 100644 --- a/account/custom_middleware.py +++ b/account/custom_middleware.py @@ -8,10 +8,10 @@ from account.utils import custom_error_response from account.models import UserDeviceDetails from base.messages import ERROR_CODE, SUCCESS_CODE -"""Custom middleware -when user login with +"""Custom middleware +when user login with multiple device simultaneously""" -class CustomMiddleware: +class CustomMiddleware(object): """Custom middleware""" def __init__(self, get_response): """response""" @@ -21,11 +21,11 @@ class CustomMiddleware: # Code to be executed before the view is called response = self.get_response(request) # Code to be executed after the view is called - device_id = request.META['HTTP_DEVICE_ID'] + device_id = request.META.get('HTTP_DEVICE_ID') if request.user.is_authenticated: """device details""" device_details = UserDeviceDetails.objects.filter(user=request.user, device_id=device_id).last() - if not device_details: + if device_id and not device_details: custom_error = custom_error_response(ERROR_CODE['2037'], response_status=status.HTTP_404_NOT_FOUND) response = Response(custom_error.data, status=status.HTTP_404_NOT_FOUND) # Set content type header to "application/json" diff --git a/base/messages.py b/base/messages.py index 02b0e34..e3399ed 100644 --- a/base/messages.py +++ b/base/messages.py @@ -58,8 +58,10 @@ ERROR_CODE = { "2032": "Failed to send email", "2033": "Missing required fields", "2034": "Junior is not associated", + # image size "2035": "Image should not be 0 kb", "2036": "Choose valid user", + # log in multiple device msg "2037": "You are already log in another device" } """Success message code""" diff --git a/guardian/urls.py b/guardian/urls.py index 14398f2..4a1c644 100644 --- a/guardian/urls.py +++ b/guardian/urls.py @@ -9,15 +9,15 @@ from rest_framework import routers """Define Router""" router = routers.SimpleRouter() -"""API End points with router -in this file -we define various api end point -that is covered in this guardian -section API:- like -sign-up, create guardian profile, -create-task, -all task list, top junior, -filter-task""" +# API End points with router +# in this file +# we define various api end point +# that is covered in this guardian +# section API:- like +# sign-up, create guardian profile, +# create-task, +# all task list, top junior, +# filter-task""" """Sign up API""" router.register('sign-up', SignupViewset, basename='sign-up') """Create guardian profile API""" From cfc36735d61dbd5377a74eb885d5331be015bd46 Mon Sep 17 00:00:00 2001 From: jain Date: Mon, 17 Jul 2023 11:58:04 +0530 Subject: [PATCH 11/14] sonar issues fixed --- account/custom_middleware.py | 10 ++++-- account/serializers.py | 32 +++++++++++++++++- account/urls.py | 22 +++++++++++- account/utils.py | 32 ++++++++++++++++-- base/constants.py | 36 +++++++++----------- guardian/urls.py | 16 ++++----- guardian/utils.py | 8 +++++ junior/models.py | 65 ++++++++++++++++++++++++------------ junior/urls.py | 24 ++++++++----- junior/utils.py | 16 ++++++--- 10 files changed, 190 insertions(+), 71 deletions(-) diff --git a/account/custom_middleware.py b/account/custom_middleware.py index 7c4dc32..7a06e43 100644 --- a/account/custom_middleware.py +++ b/account/custom_middleware.py @@ -8,9 +8,13 @@ from account.utils import custom_error_response from account.models import UserDeviceDetails from base.messages import ERROR_CODE, SUCCESS_CODE -"""Custom middleware -when user login with -multiple device simultaneously""" +# Custom middleware +# when user login with +# multiple device simultaneously +# It restricted login in +# multiple devices only +# user can login in single +# device at a time""" class CustomMiddleware(object): """Custom middleware""" def __init__(self, get_response): diff --git a/account/serializers.py b/account/serializers.py index bbde6a0..4583b6a 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -1,10 +1,20 @@ """Account serializer""" -"""Django Imoprt""" +"""Django Import""" import random from rest_framework import serializers from django.contrib.auth.models import User from rest_framework_simplejwt.tokens import RefreshToken """App import""" +# Import guardian's model, +# Import junior's model, +# Import account's model, +# Import constant from +# base package, +# Import messages from +# base package, +# Import some functions +# from utils file""" + from guardian.models import Guardian from junior.models import Junior from account.models import UserEmailOtp, DefaultTaskImages, UserDelete, UserNotification, UserPhoneOtp @@ -12,6 +22,25 @@ from base.constants import GUARDIAN, JUNIOR, SUPERUSER from base.messages import ERROR_CODE_REQUIRED, ERROR_CODE, SUCCESS_CODE, STATUS_CODE_ERROR from .utils import delete_user_account_condition_social, delete_user_account_condition +# In this serializer file +# define google login serializer +# update junior profile, +# update guardian profile, +# super admin serializer, +# reset password, +# forgot password, +# change password, +# basic junior serializer, +# basic guardian serializer, +# user delete account serializer, +# user notification serializer, +# update user notification serializer, +# default task's images serializer, +# upload default task's images serializer, +# email verification serializer, +# phone otp serializer + + class GoogleLoginSerializer(serializers.Serializer): """google login serializer""" access_token = serializers.CharField(max_length=5000, required=True) @@ -89,6 +118,7 @@ class ChangePasswordSerializer(serializers.Serializer): def create(self, validated_data): new_password = validated_data.pop('new_password') current_password = validated_data.pop('current_password') + """Check new password is different from current password""" if new_password == current_password: raise serializers.ValidationError({"details": ERROR_CODE['2026']}) user_details = User.objects.filter(email=self.context).last() diff --git a/account/urls.py b/account/urls.py index 9977658..ef3d026 100644 --- a/account/urls.py +++ b/account/urls.py @@ -3,7 +3,27 @@ from django.urls import path, include """Third party import""" from rest_framework import routers -"""Import view functions""" +# Import view functions +# UserLogin views, +# SendPhoneOtp views, +# UserPhoneVerification views, +# UserEmailVerification views, +# ReSendEmailOtp views, +# ForgotPasswordAPIView views, +# ResetPasswordAPIView views, +# ChangePasswordAPIView views, +# UpdateProfileImage views, +# GoogleLoginViewSet views, +# SigninWithApple views, +# ProfileAPIViewSet views, +# UploadImageAPIViewSet views, +# DefaultImageAPIViewSet views, +# DeleteUserProfileAPIViewSet views, +# UserNotificationAPIViewSet views, +# UpdateUserNotificationAPIViewSet views, +# SendSupportEmail views, +# LogoutAPIView views, +# AccessTokenAPIView views""" from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVerification, ReSendEmailOtp, ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage, GoogleLoginViewSet, SigninWithApple, ProfileAPIViewSet, UploadImageAPIViewSet, diff --git a/account/utils.py b/account/utils.py index b925b49..eeb6954 100644 --- a/account/utils.py +++ b/account/utils.py @@ -12,12 +12,37 @@ from calendar import timegm from uuid import uuid4 import secrets from rest_framework import serializers +# Django App Import +# Import models from junior App, +# Import models from guardian App, +# Import models from account App, +# Import messages from base package""" from junior.models import Junior from guardian.models import Guardian from account.models import UserDelete from base.messages import ERROR_CODE +# Define delete +# user account condition, +# Define delete +# user account +# condition for social +# login account, +# Update junior account, +# Update guardian account, +# Define custom email for otp verification, +# Define support email for user's query, +# Define custom success response, +# Define custom error response, +# Generate access token, +# refresh token by using jwt, +# Define function for generating +# guardian code, junior code, +# referral code, +# Define function for generating +# alphanumeric code + def delete_user_account_condition(user, user_type_data, user_type, user_tb, data, random_num): """delete user account""" if user_type == '1' and user_type_data == '1': @@ -28,10 +53,10 @@ def delete_user_account_condition(user, user_type_data, user_type, user_tb, data raise serializers.ValidationError({"details": ERROR_CODE['2030'], "code": "400", "status": "failed"}) user_tb.email = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower() user_tb.username = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower() - user_tb.password = 'None' d_email = user_tb.email o_mail = user.email user_tb.save() + """create object in user delete model""" instance = UserDelete.objects.create(user=user_tb, d_email=d_email, old_email=o_mail, is_active=True, reason=data) @@ -47,10 +72,10 @@ def delete_user_account_condition_social(user, user_type,user_tb, data, random_n raise serializers.ValidationError({"details": ERROR_CODE['2030'], "code": "400", "status": "failed"}) user_tb.email = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower() user_tb.username = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower() - user_tb.password = 'None' dummy_email = user_tb.email old_mail = user.email user_tb.save() + """create object in user delete model""" instance_data = UserDelete.objects.create(user=user_tb, d_email=dummy_email, old_email=old_mail, is_active=True, reason=data) @@ -72,6 +97,7 @@ def guardian_account_update(user_tb): guardian_data.is_verified = False guardian_data.save() jun_data = Junior.objects.filter(guardian_code__icontains=str(guardian_data.guardian_code)) + """Disassociate relation between guardian and junior""" for data in jun_data: data.guardian_code.remove(guardian_data.guardian_code) data.save() @@ -79,6 +105,7 @@ def send_otp_email(recipient_email, otp): """Send otp on email with template""" from_email = settings.EMAIL_FROM_ADDRESS recipient_list = [recipient_email] + """Send otp on email""" send_templated_mail( template_name='email_otp_verification.email', from_email=from_email, @@ -93,6 +120,7 @@ def send_support_email(name, sender, subject, message): """Send otp on email with template""" to_email = [settings.EMAIL_FROM_ADDRESS] from_email = settings.DEFAULT_ADDRESS + """Send support email to zod bank support team""" send_templated_mail( template_name='support_mail.email', from_email=from_email, diff --git a/base/constants.py b/base/constants.py index 6025e0b..648bdd8 100644 --- a/base/constants.py +++ b/base/constants.py @@ -6,31 +6,22 @@ import os # GOOGLE_URL used for interact with google server to verify user existence. #GOOGLE_URL = "https://www.googleapis.com/plus/v1/" +# Define Code prefix word +# for guardian code, +# junior code, +# referral code""" ZOD = 'ZOD' JUN = 'JUN' GRD = 'GRD' +# Define number variable +# from zero to +# twenty and +# some standard +# number""" NUMBER = { - 'point_zero': 0.0, - 'zero': 0, - 'one': 1, - 'two': 2, - 'three': 3, - 'four': 4, - 'five': 5, - 'six': 6, - 'seven': 7, - 'eight': 8, - 'nine': 9, - 'ten': 10, - 'eleven': 11, - 'twelve': 12, - 'thirteen': 13, - 'fourteen': 14, - 'fifteen': 15, - 'sixteen': 16, - 'seventeen': 17, - 'eighteen': 18, - 'nineteen': 19, + 'point_zero': 0.0, 'zero': 0, 'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6, 'seven': 7, + 'eight': 8, 'nine': 9, 'ten': 10, 'eleven': 11, 'twelve': 12, 'thirteen': 13, 'fourteen': 14, 'fifteen': 15, + 'sixteen': 16, 'seventeen': 17, 'eighteen': 18, 'nineteen': 19, 'twenty_four': 24, 'twenty_one': 21, 'twenty_two': 22, @@ -108,6 +99,9 @@ RELATIONSHIP = ( ('1', 'parent'), ('2', 'legal_guardian') ) +""" +Define task status +in a number""" PENDING = 1 IN_PROGRESS = 2 REJECTED = 3 diff --git a/guardian/urls.py b/guardian/urls.py index 4a1c644..71d3036 100644 --- a/guardian/urls.py +++ b/guardian/urls.py @@ -20,21 +20,21 @@ router = routers.SimpleRouter() # filter-task""" """Sign up API""" router.register('sign-up', SignupViewset, basename='sign-up') -"""Create guardian profile API""" +# Create guardian profile API""" router.register('create-guardian-profile', UpdateGuardianProfile, basename='update-guardian-profile') -"""Create Task API""" +# Create Task API""" router.register('create-task', CreateTaskAPIView, basename='create-task') -"""All Task list API""" +# All Task list API""" router.register('all-task-list', AllTaskListAPIView, basename='all-task-list') -"""Task list bases on the status API""" +# Task list bases on the status API""" router.register('task-list', TaskListAPIView, basename='task-list') -"""Leaderboard API""" +# Leaderboard API""" router.register('top-junior', TopJuniorListAPIView, basename='top-junior') -"""Search Task list on the bases of status, due date, and task title API""" +# Search Task list on the bases of status, due date, and task title API""" router.register('filter-task', SearchTaskListAPIView, basename='filter-task') -"""Approve junior API""" +# Approve junior API""" router.register('approve-junior', ApproveJuniorAPIView, basename='approve-junior') -"""Define Url pattern""" +# Define Url pattern""" urlpatterns = [ path('api/v1/', include(router.urls)), ] diff --git a/guardian/utils.py b/guardian/utils.py index f565e4b..c3f9f39 100644 --- a/guardian/utils.py +++ b/guardian/utils.py @@ -6,6 +6,14 @@ from django.conf import settings """Import tempfile""" import tempfile +# Define upload image on +# ali baba cloud +# firstly save image +# in temporary file +# then check bucket name +# then upload on ali baba +# bucket and reform the image url""" + def upload_image_to_alibaba(image, filename): """upload image on oss alibaba bucket""" # Save the image object to a temporary file diff --git a/junior/models.py b/junior/models.py index 381bbf4..41dddc8 100644 --- a/junior/models.py +++ b/junior/models.py @@ -10,45 +10,66 @@ from base.constants import GENDERS, SIGNUP_METHODS, RELATIONSHIP """Define User model""" User = get_user_model() # Create your models here. +# Define junior model with +# various fields like +# phone, country code, +# country name, +# gender, +# date of birth, +# profile image, +# relationship type of the guardian +# signup method, +# guardian code, +# junior code, +# referral code, +# referral code that used by the junior +# is invited junior +# profile is active or not +# profile is complete or not +# passcode +# junior is verified or not +"""Define junior points model""" +# points of the junior +# position of the junior class Junior(models.Model): """Junior model""" auth = models.ForeignKey(User, on_delete=models.CASCADE, related_name='junior_profile', verbose_name='Email') - """Contact details""" + # Contact details""" phone = models.CharField(max_length=31, null=True, blank=True, default=None) country_code = models.IntegerField(blank=True, null=True) - """country name of the guardian""" + # country name of the guardian""" country_name = models.CharField(max_length=100, null=True, blank=True, default=None) - """Personal info""" + # Personal info""" gender = models.CharField(max_length=10, choices=GENDERS, null=True, blank=True, default=None) - """Date of birth""" + # Date of birth""" dob = models.DateField(max_length=15, null=True, blank=True, default=None) - """Image of the junior""" + # Image of the junior""" image = models.URLField(null=True, blank=True, default=None) - """relationship""" + # relationship""" relationship = models.CharField(max_length=31, choices=RELATIONSHIP, null=True, blank=True, default='1') - """Sign up method""" + # Sign up method""" signup_method = models.CharField(max_length=31, choices=SIGNUP_METHODS, default='1') - """Codes""" + # Codes""" junior_code = models.CharField(max_length=10, null=True, blank=True, default=None) - """Guardian Codes""" + # Guardian Codes""" guardian_code = ArrayField(models.CharField(max_length=10, null=True, blank=True, default=None),null=True) - """Referral code""" + # Referral code""" referral_code = models.CharField(max_length=10, null=True, blank=True, default=None) - """Referral code that is used by junior while signup""" + # Referral code that is used by junior while signup""" referral_code_used = models.CharField(max_length=10, null=True, blank=True, default=None) - """invited junior""" + # invited junior""" is_invited = models.BooleanField(default=False) - """Profile activity""" + # Profile activity""" is_active = models.BooleanField(default=True) - """junior profile is complete or not""" + # junior profile is complete or not""" is_complete_profile = models.BooleanField(default=False) - """passcode of the junior profile""" + # passcode of the junior profile""" passcode = models.IntegerField(null=True, blank=True, default=None) - """junior is verified or not""" + # junior is verified or not""" is_verified = models.BooleanField(default=False) - """Profile created and updated time""" + # Profile created and updated time""" created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) @@ -56,7 +77,7 @@ class Junior(models.Model): """ Meta class """ db_table = 'junior' verbose_name = 'Junior' - """another name of the model""" + # another name of the model""" verbose_name_plural = 'Junior' def __str__(self): @@ -66,11 +87,11 @@ class Junior(models.Model): class JuniorPoints(models.Model): """Junior model""" junior = models.OneToOneField(Junior, on_delete=models.CASCADE, related_name='junior_points') - """Contact details""" + # Contact details""" total_task_points = models.IntegerField(blank=True, null=True, default=0) - """position of the junior""" + # position of the junior""" position = models.IntegerField(blank=True, null=True, default=99999) - """Profile created and updated time""" + # Profile created and updated time""" created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) @@ -78,7 +99,7 @@ class JuniorPoints(models.Model): """ Meta class """ db_table = 'junior_task_points' verbose_name = 'Junior Task Points' - """another name of the model""" + # another name of the model""" verbose_name_plural = 'Junior Task Points' def __str__(self): diff --git a/junior/urls.py b/junior/urls.py index 162f693..ecedb1a 100644 --- a/junior/urls.py +++ b/junior/urls.py @@ -8,21 +8,29 @@ from rest_framework import routers """Router""" router = routers.SimpleRouter() - +# API End points with router +# in this file +# we define various api end point +# that is covered in this guardian +# section API:- like +# Create junior profile API, validate junior profile, +# junior list, +# add junior list, invited junior, +# filter-junior, +# remove junior""" """API End points with router""" -"""Create junior profile API""" router.register('create-junior-profile', UpdateJuniorProfile, basename='profile-update') -"""validate guardian code API""" +# validate guardian code API""" router.register('validate-guardian-code', ValidateGuardianCode, basename='validate-guardian-code') -"""junior list API""" +# junior list API""" router.register('junior-list', JuniorListAPIView, basename='junior-list') -"""Add junior list API""" +# Add junior list API""" router.register('add-junior', AddJuniorAPIView, basename='add-junior') -"""Invited junior list API""" +# Invited junior list API""" router.register('invited-junior', InvitedJuniorAPIView, basename='invited-junior') -"""Filter junior list API""" +# Filter junior list API""" router.register('filter-junior', FilterJuniorAPIView, basename='filter-junior') -"""Define url pattern""" +# Define url pattern""" urlpatterns = [ path('api/v1/', include(router.urls)), path('api/v1/remove-junior/', RemoveJuniorAPIView.as_view()) diff --git a/junior/utils.py b/junior/utils.py index 41c393d..e1fb5df 100644 --- a/junior/utils.py +++ b/junior/utils.py @@ -4,14 +4,20 @@ from django.conf import settings """Third party Django app""" from templated_email import send_templated_mail - - +# junior notification +# email for sending email +# when guardian create junior profile +# guardian get email when junior send +# request for approving the profile and +# being part of the zod bank and access the platform +# define junior notification email +# junior approval email def junior_notification_email(recipient_email, full_name, email, password): """Notification email""" from_email = settings.EMAIL_FROM_ADDRESS - """recipient email""" + # recipient email""" recipient_list = [recipient_email] - """use send template mail for sending email""" + # use send template mail for sending email""" send_templated_mail( template_name='junior_notification_email.email', from_email=from_email, @@ -29,7 +35,7 @@ def junior_approval_mail(guardian, full_name): """junior approval mail""" from_email = settings.EMAIL_FROM_ADDRESS recipient_list = [guardian] - """use send tempolate mail for sending email""" + # use send template mail for sending email""" send_templated_mail( template_name='junior_approval_mail.email', from_email=from_email, From 1399b585e860da6dea3f4688b160c0abae7014d8 Mon Sep 17 00:00:00 2001 From: jain Date: Mon, 17 Jul 2023 16:07:06 +0530 Subject: [PATCH 12/14] sonar issues --- account/serializers.py | 22 +++++++----- account/utils.py | 5 +++ base/constants.py | 40 +++++----------------- base/messages.py | 9 +++-- guardian/models.py | 27 +++++++++++++++ guardian/serializers.py | 57 ++++++++++++++++++++++++++++--- guardian/urls.py | 4 ++- guardian/views.py | 75 +++++++++++++++++++++++++++++++++++++---- junior/views.py | 36 ++++++++++++++++++-- zod_bank/settings.py | 44 ++++++++++++++++-------- 10 files changed, 249 insertions(+), 70 deletions(-) diff --git a/account/serializers.py b/account/serializers.py index 4583b6a..3596c07 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -1,9 +1,10 @@ """Account serializer""" """Django Import""" -import random +# Import Refresh token of jwt from rest_framework import serializers from django.contrib.auth.models import User from rest_framework_simplejwt.tokens import RefreshToken +import secrets """App import""" # Import guardian's model, # Import junior's model, @@ -18,8 +19,8 @@ from rest_framework_simplejwt.tokens import RefreshToken from guardian.models import Guardian from junior.models import Junior from account.models import UserEmailOtp, DefaultTaskImages, UserDelete, UserNotification, UserPhoneOtp -from base.constants import GUARDIAN, JUNIOR, SUPERUSER -from base.messages import ERROR_CODE_REQUIRED, ERROR_CODE, SUCCESS_CODE, STATUS_CODE_ERROR +from base.constants import GUARDIAN, JUNIOR, SUPERUSER, NUMBER +from base.messages import ERROR_CODE, SUCCESS_CODE, STATUS_CODE_ERROR from .utils import delete_user_account_condition_social, delete_user_account_condition # In this serializer file @@ -90,6 +91,7 @@ class ResetPasswordSerializer(serializers.Serializer): def create(self, validated_data): verification_code = validated_data.pop('verification_code') password = validated_data.pop('password') + # fetch email otp object of the user user_opt_details = UserEmailOtp.objects.filter(otp=verification_code, is_verified=True).last() if user_opt_details: user_details = User.objects.filter(email=user_opt_details.email).last() @@ -112,6 +114,7 @@ class ChangePasswordSerializer(serializers.Serializer): def validate_current_password(self, value): user = self.context + # check old password if self.context.password not in ('', None) and user.check_password(value): return value raise serializers.ValidationError(ERROR_CODE['2015']) @@ -170,9 +173,9 @@ class GuardianSerializer(serializers.ModelSerializer): def get_user_type(self, obj): """user type""" email_verified = UserEmailOtp.objects.filter(email=obj.user.username).last() - if email_verified and email_verified.user_type != None: + if email_verified and email_verified.user_type is not None: return email_verified.user_type - return '2' + return str(NUMBER['two']) def get_auth(self, obj): """user email address""" @@ -217,7 +220,7 @@ class JuniorSerializer(serializers.ModelSerializer): email_verified = UserEmailOtp.objects.filter(email=obj.auth.username).last() if email_verified and email_verified.user_type is not None: return email_verified.user_type - return '1' + return str(NUMBER['one']) def get_auth(self, obj): return obj.auth.username @@ -251,6 +254,7 @@ class DefaultTaskImagesSerializer(serializers.ModelSerializer): model = DefaultTaskImages fields = ['id', 'task_name', 'image_url'] def create(self, validated_data): + # create default task object data = DefaultTaskImages.objects.create(**validated_data) return data @@ -273,10 +277,11 @@ class UserDeleteSerializer(serializers.ModelSerializer): data = validated_data.get('reason') passwd = self.context['password'] signup_method = self.context['signup_method'] - random_num = random.randint(0, 10000) + random_num = secrets.randbelow(10001) user_tb = User.objects.filter(id=user.id).last() user_type_datas = UserEmailOtp.objects.filter(email=user.email).last() - if user_tb and user_tb.check_password(passwd) and signup_method == '1': + # check password and sign up method + if user_tb and user_tb.check_password(passwd) and signup_method == str(NUMBER['one']): user_type_data = user_type_datas.user_type instance = delete_user_account_condition(user, user_type_data, user_type, user_tb, data, random_num) return instance @@ -305,6 +310,7 @@ class UpdateUserNotificationSerializer(serializers.ModelSerializer): def create(self, validated_data): instance = UserNotification.objects.filter(user=self.context).last() if instance: + # change notification status instance.push_notification = validated_data.get('push_notification',instance.push_notification) instance.email_notification = validated_data.get('email_notification', instance.email_notification) instance.sms_notification = validated_data.get('sms_notification', instance.sms_notification) diff --git a/account/utils.py b/account/utils.py index eeb6954..9aca671 100644 --- a/account/utils.py +++ b/account/utils.py @@ -10,6 +10,7 @@ import string from datetime import datetime from calendar import timegm from uuid import uuid4 +# Import secrets module for generating random number import secrets from rest_framework import serializers # Django App Import @@ -55,6 +56,7 @@ def delete_user_account_condition(user, user_type_data, user_type, user_tb, data user_tb.username = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower() d_email = user_tb.email o_mail = user.email + # update user email with dummy email user_tb.save() """create object in user delete model""" instance = UserDelete.objects.create(user=user_tb, d_email=d_email, old_email=o_mail, @@ -74,6 +76,7 @@ def delete_user_account_condition_social(user, user_type,user_tb, data, random_n user_tb.username = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower() dummy_email = user_tb.email old_mail = user.email + # update user email with dummy email user_tb.save() """create object in user delete model""" instance_data = UserDelete.objects.create(user=user_tb, d_email=dummy_email, old_email=old_mail, @@ -84,6 +87,7 @@ def junior_account_update(user_tb): """junior account delete""" junior_data = Junior.objects.filter(auth__email=user_tb.email).first() if junior_data: + # Update junior account junior_data.is_active = False junior_data.is_verified = False junior_data.guardian_code = '{}' @@ -93,6 +97,7 @@ def guardian_account_update(user_tb): """update guardian account after delete the user account""" guardian_data = Guardian.objects.filter(user__email=user_tb.email).first() if guardian_data: + # Update guardian account guardian_data.is_active = False guardian_data.is_verified = False guardian_data.save() diff --git a/base/constants.py b/base/constants.py index 648bdd8..d8ca8a8 100644 --- a/base/constants.py +++ b/base/constants.py @@ -21,31 +21,10 @@ GRD = 'GRD' NUMBER = { 'point_zero': 0.0, 'zero': 0, 'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6, 'seven': 7, 'eight': 8, 'nine': 9, 'ten': 10, 'eleven': 11, 'twelve': 12, 'thirteen': 13, 'fourteen': 14, 'fifteen': 15, - 'sixteen': 16, 'seventeen': 17, 'eighteen': 18, 'nineteen': 19, - 'twenty_four': 24, - 'twenty_one': 21, - 'twenty_two': 22, - 'twenty_five': 25, - 'thirty': 30, - 'thirty_five': 35, - 'thirty_six': 36, - 'forty': 40, - 'fifty': 50, - 'fifty_nine': 59, - 'sixty': 60, - 'seventy_five': 75, - 'eighty': 80, - 'ninty_five': 95, - 'ninty_six': 96, - 'ninety_nine': 99, - 'hundred': 100, - 'one_one_nine': 119, - 'one_twenty': 120, - 'four_zero_four': 404, - 'five_hundred': 500, - 'minus_one': -1, - 'point_three': 0.3, - 'point_seven': 0.7 + 'sixteen': 16, 'seventeen': 17, 'eighteen': 18, 'nineteen': 19, 'twenty': 20, + 'twenty_one': 21, 'twenty_two': 22,'twenty_three': 23, 'twenty_four': 24, 'twenty_five': 25, + 'thirty': 30, 'forty': 40, 'fifty': 50, 'sixty': 60, 'seventy': 70, 'eighty': 80, 'ninty': 90, + 'ninety_nine': 99, 'hundred': 100, } @@ -65,10 +44,6 @@ FILE_SIZE = 5 * 1024 * 1024 # String constant for configurable date for allocation lock period ALLOCATION_LOCK_DATE = 1 -sort_dict = { - '1': 'name', - '2': '-name' -} """user type""" USER_TYPE = ( ('1', 'junior'), @@ -80,7 +55,7 @@ GENDERS = ( ('1', 'Male'), ('2', 'Female') ) -"""Task status""" +# Task status""" TASK_STATUS = ( ('1', 'pending'), ('2', 'in-progress'), @@ -88,13 +63,13 @@ TASK_STATUS = ( ('4', 'requested'), ('5', 'completed') ) -"""sign up method""" +# sign up method SIGNUP_METHODS = ( ('1', 'manual'), ('2', 'google'), ('3', 'apple') ) -"""relationship""" +# relationship RELATIONSHIP = ( ('1', 'parent'), ('2', 'legal_guardian') @@ -110,6 +85,7 @@ COMPLETED = 5 TASK_POINTS = 5 # duplicate name used defined in constant PROJECT_NAME PROJECT_NAME = 'Zod Bank' +# define user type constant GUARDIAN = 'guardian' JUNIOR = 'junior' SUPERUSER = 'superuser' diff --git a/base/messages.py b/base/messages.py index e3399ed..8b65d2a 100644 --- a/base/messages.py +++ b/base/messages.py @@ -62,7 +62,8 @@ ERROR_CODE = { "2035": "Image should not be 0 kb", "2036": "Choose valid user", # log in multiple device msg - "2037": "You are already log in another device" + "2037": "You are already log in another device", + "2038": "Choose valid action for task" } """Success message code""" SUCCESS_CODE = { @@ -98,8 +99,10 @@ SUCCESS_CODE = { "3020": "Logged out successfully.", "3021": "Add junior successfully", "3022": "Remove junior successfully", - "3023": "Approved junior successfully", - "3024": "Reject junior request successfully" + "3023": "Junior is approved successfully", + "3024": "Junior request is rejected successfully", + "3025": "Task is approved successfully", + "3026": "Task is rejected successfully", } """status code error""" STATUS_CODE_ERROR = { diff --git a/guardian/models.py b/guardian/models.py index 5636a80..1746c44 100644 --- a/guardian/models.py +++ b/guardian/models.py @@ -8,6 +8,33 @@ from base.constants import GENDERS, TASK_STATUS, PENDING, TASK_POINTS, SIGNUP_ME from junior.models import Junior """Add user model""" User = get_user_model() + +# Create your models here. +# Define junior model with +# various fields like +# phone, country code, +# country name, +# gender, +# date of birth, +# profile image, +# signup method, +# guardian code, +# referral code, +# referral code that used by the guardian +# is invited guardian +# profile is active or not +# profile is complete or not +# passcode +# guardian is verified or not +"""Define junior task model""" +# define name of the Task +# task description +# points of the task +# default image of the task +# image uploaded by junior +# task status +# task approved or not + # Create your models here. class Guardian(models.Model): diff --git a/guardian/serializers.py b/guardian/serializers.py index 055d738..8bcd0cf 100644 --- a/guardian/serializers.py +++ b/guardian/serializers.py @@ -1,20 +1,41 @@ """Serializer of Guardian""" """Third party Django app""" import logging -import random from rest_framework import serializers +# Import Refresh token of jwt from rest_framework_simplejwt.tokens import RefreshToken from django.db import transaction from django.contrib.auth.models import User """Import Django app""" +# Import guardian's model, +# Import junior's model, +# Import account's model, +# Import constant from +# base package, +# Import messages from +# base package, +# Import some functions +# from utils file""" from .models import Guardian, JuniorTask from account.models import UserProfile, UserEmailOtp, UserNotification from account.utils import generate_code -from account.serializers import JuniorSerializer from junior.serializers import JuniorDetailSerializer from base.messages import ERROR_CODE, SUCCESS_CODE from base.constants import NUMBER, JUN, ZOD, GRD from junior.models import Junior, JuniorPoints + + +# In this serializer file +# define user serializer, +# create guardian serializer, +# task serializer, +# guardian serializer, +# task details serializer, +# top junior serializer, +# guardian profile serializer, +# approve junior serializer, +# approve task serializer, + class UserSerializer(serializers.ModelSerializer): """User serializer""" auth_token = serializers.SerializerMethodField('get_auth_token') @@ -38,10 +59,12 @@ class UserSerializer(serializers.ModelSerializer): """Create user profile""" user = User.objects.create_user(username=email, email=email, password=password) UserNotification.objects.create(user=user) - if user_type == '1': + if user_type == str(NUMBER['one']): + # create junior profile Junior.objects.create(auth=user, junior_code=generate_code(JUN, user.id), referral_code=generate_code(ZOD, user.id)) - if user_type == '2': + if user_type == str(NUMBER['two']): + # create guardian profile Guardian.objects.create(user=user, guardian_code=generate_code(GRD, user.id), referral_code=generate_code(ZOD, user.id)) return user @@ -56,6 +79,7 @@ class UserSerializer(serializers.ModelSerializer): "code": 400, "status":"failed", }) +# update guardian profile class CreateGuardianSerializer(serializers.ModelSerializer): """Create guardian serializer""" """Basic info""" @@ -65,9 +89,12 @@ class CreateGuardianSerializer(serializers.ModelSerializer): """Contact details""" phone = serializers.CharField(max_length=20, required=False) country_code = serializers.IntegerField(required=False) + # basic info family_name = serializers.CharField(max_length=100, required=False) dob = serializers.DateField(required=False) + # code info referral_code = serializers.CharField(max_length=100, required=False) + # image info image = serializers.URLField(required=False) class Meta(object): @@ -140,6 +167,7 @@ class TaskSerializer(serializers.ModelSerializer): def create(self, validated_data): """create default task image data""" validated_data['guardian'] = Guardian.objects.filter(user=self.context['user']).last() + # update image of the task images = self.context['image'] validated_data['default_image'] = images instance = JuniorTask.objects.create(**validated_data) @@ -227,6 +255,7 @@ class GuardianProfileSerializer(serializers.ModelSerializer): """total filled fields count""" total_field_list = [obj.user.first_name, obj.country_name, obj.gender, obj.dob, obj.image] + # count total complete field total_complete_field = [data for data in total_field_list if data != '' and data is not None] return len(total_complete_field) @@ -256,4 +285,24 @@ class ApproveJuniorSerializer(serializers.ModelSerializer): instance.save() return instance +class ApproveTaskSerializer(serializers.ModelSerializer): + """approve task serializer""" + class Meta(object): + """Meta info""" + model = JuniorTask + fields = ['id', 'task_status', 'is_approved'] + + def create(self, validated_data): + """update task status """ + instance = self.context['task_instance'] + if self.context['action'] == str(NUMBER['one']): + # approve the task + instance.task_status = str(NUMBER['five']) + instance.is_approved = True + else: + # reject the task + instance.task_status = str(NUMBER['three']) + instance.is_approved = False + instance.save() + return instance diff --git a/guardian/urls.py b/guardian/urls.py index 71d3036..b14aa77 100644 --- a/guardian/urls.py +++ b/guardian/urls.py @@ -2,7 +2,7 @@ """Django import""" from django.urls import path, include from .views import (SignupViewset, UpdateGuardianProfile, AllTaskListAPIView, CreateTaskAPIView, TaskListAPIView, - SearchTaskListAPIView, TopJuniorListAPIView, ApproveJuniorAPIView) + SearchTaskListAPIView, TopJuniorListAPIView, ApproveJuniorAPIView, ApproveTaskAPIView) """Third party import""" from rest_framework import routers @@ -34,6 +34,8 @@ router.register('top-junior', TopJuniorListAPIView, basename='top-junior') router.register('filter-task', SearchTaskListAPIView, basename='filter-task') # Approve junior API""" router.register('approve-junior', ApproveJuniorAPIView, basename='approve-junior') +# Approve junior API""" +router.register('approve-task', ApproveTaskAPIView, basename='approve-task') # Define Url pattern""" urlpatterns = [ path('api/v1/', include(router.urls)), diff --git a/guardian/views.py b/guardian/views.py index f35ca90..f53dc7d 100644 --- a/guardian/views.py +++ b/guardian/views.py @@ -5,14 +5,24 @@ from rest_framework import viewsets, status from rest_framework.pagination import PageNumberPagination from django.contrib.auth.models import User from django.utils import timezone -from PIL import Image -from datetime import datetime, timedelta """Import Django app""" + +# Import guardian's model, +# Import junior's model, +# Import account's model, +# Import constant from +# base package, +# Import messages from +# base package, +# Import some functions +# from utils file +# Import account's serializer +# Import account's task + from .serializers import (UserSerializer, CreateGuardianSerializer, TaskSerializer, TaskDetailsSerializer, - TopJuniorSerializer, ApproveJuniorSerializer) + TopJuniorSerializer, ApproveJuniorSerializer, ApproveTaskSerializer) from .models import Guardian, JuniorTask from junior.models import Junior, JuniorPoints -from junior.serializers import JuniorDetailSerializer from account.models import UserEmailOtp, UserNotification from .tasks import generate_otp from account.utils import send_otp_email @@ -20,7 +30,17 @@ from account.utils import custom_response, custom_error_response from base.messages import ERROR_CODE, SUCCESS_CODE from base.constants import NUMBER from .utils import upload_image_to_alibaba -from django.db.models import Sum + +""" Define APIs """ +# Define Signup API, +# update guardian profile, +# list of all task +# list of task according to the status of the task +# create task API +# search task by name of the task API +# top junior API, +# approve junior API +# approve task API # Create your views here. class SignupViewset(viewsets.ModelViewSet): """Signup view set""" @@ -35,6 +55,7 @@ class SignupViewset(viewsets.ModelViewSet): """Generate otp""" otp = generate_otp() expiry = timezone.now() + timezone.timedelta(days=1) + # create user email otp object UserEmailOtp.objects.create(email=request.data['email'], otp=otp, user_type=str(request.data['user_type']), expired_at=expiry) """Send email to the register user""" @@ -60,6 +81,7 @@ class UpdateGuardianProfile(viewsets.ViewSet): if image and image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) filename = f"images/{image.name}" + # upload image on ali baba image_url = upload_image_to_alibaba(image, filename) data = {"image":image_url} serializer = CreateGuardianSerializer(context={"user":request.user, @@ -83,6 +105,7 @@ class AllTaskListAPIView(viewsets.ModelViewSet): def list(self, request, *args, **kwargs): """Create guardian profile""" queryset = JuniorTask.objects.filter(guardian__user=request.user) + # use TaskDetailsSerializer serializer serializer = TaskDetailsSerializer(queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) @@ -102,7 +125,9 @@ class TaskListAPIView(viewsets.ModelViewSet): queryset = JuniorTask.objects.filter(guardian__user=request.user, task_status=status_value).order_by('due_date','created_at') paginator = self.pagination_class() + # use Pagination paginated_queryset = paginator.paginate_queryset(queryset, request) + # use TaskDetailsSerializer serializer serializer = TaskDetailsSerializer(paginated_queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) @@ -123,8 +148,10 @@ class CreateTaskAPIView(viewsets.ModelViewSet): image_url = upload_image_to_alibaba(image, filename) image_data = image_url data.pop('default_image') + # use TaskSerializer serializer serializer = TaskSerializer(context={"user":request.user, "image":image_data}, data=data) if serializer.is_valid(): + # save serializer serializer.save() return custom_response(SUCCESS_CODE['3018'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) @@ -139,6 +166,7 @@ class SearchTaskListAPIView(viewsets.ModelViewSet): def get_queryset(self): """Get the queryset for the view""" title = self.request.GET.get('title') + # fetch junior query junior_queryset = JuniorTask.objects.filter(guardian__user=self.request.user, task_name__icontains=title)\ .order_by('due_date', 'created_at') return junior_queryset @@ -149,7 +177,7 @@ class SearchTaskListAPIView(viewsets.ModelViewSet): paginator = self.pagination_class() paginated_queryset = paginator.paginate_queryset(queryset, request) - + # use TaskSerializer serializer serializer = TaskDetailsSerializer(paginated_queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) @@ -186,18 +214,53 @@ class ApproveJuniorAPIView(viewsets.ViewSet): def get_queryset(self): """Get the queryset for the view""" guardian = Guardian.objects.filter(user__email=self.request.user).last() + # fetch junior query junior_queryset = Junior.objects.filter(id=self.request.data.get('junior_id')).last() return guardian, junior_queryset def create(self, request, *args, **kwargs): """ junior list""" queryset = self.get_queryset() + # action 1 is use for approve and 2 for reject if request.data['action'] == '1': + # use ApproveJuniorSerializer serializer serializer = ApproveJuniorSerializer(context={"guardian_code": queryset[0].guardian_code, "junior": queryset[1], "action": request.data['action']}, data=request.data) if serializer.is_valid(): + # save serializer serializer.save() return custom_response(SUCCESS_CODE['3023'], serializer.data, response_status=status.HTTP_200_OK) else: return custom_response(SUCCESS_CODE['3024'], response_status=status.HTTP_200_OK) + +class ApproveTaskAPIView(viewsets.ViewSet): + """approve junior by guardian""" + serializer_class = ApproveTaskSerializer + permission_classes = [IsAuthenticated] + + def get_queryset(self): + """Get the queryset for the view""" + guardian = Guardian.objects.filter(user__email=self.request.user).last() + task_queryset = JuniorTask.objects.filter(id=self.request.data.get('task_id'), + guardian=guardian, + junior=self.request.data.get('junior_id')).last() + return guardian, task_queryset + + def create(self, request, *args, **kwargs): + """ junior list""" + # action 1 is use for approve and 2 for reject + queryset = self.get_queryset() + # use ApproveJuniorSerializer serializer + serializer = ApproveTaskSerializer(context={"guardian_code": queryset[0].guardian_code, + "task_instance": queryset[1], + "action": str(request.data['action'])}, + data=request.data) + if str(request.data['action']) == str(NUMBER['one']) and serializer.is_valid(): + serializer.save() + return custom_response(SUCCESS_CODE['3025'], response_status=status.HTTP_200_OK) + elif str(request.data['action']) == str(NUMBER['two']) and serializer.is_valid(): + serializer.save() + return custom_response(SUCCESS_CODE['3026'], response_status=status.HTTP_200_OK) + else: + return custom_response(ERROR_CODE['2038'], response_status=status.HTTP_400_BAD_REQUEST) diff --git a/junior/views.py b/junior/views.py index 5766c82..d77727b 100644 --- a/junior/views.py +++ b/junior/views.py @@ -2,9 +2,19 @@ from rest_framework import viewsets, status, generics,views from rest_framework.permissions import IsAuthenticated from rest_framework.pagination import PageNumberPagination -from rest_framework.response import Response -from PIL import Image """Django app import""" + +# Import guardian's model, +# Import junior's model, +# Import account's model, +# Import constant from +# base package, +# Import messages from +# base package, +# Import some functions +# from utils file +# Import account's serializer +# Import account's task from junior.models import Junior from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer,\ RemoveJuniorSerializer) @@ -13,6 +23,17 @@ from base.messages import ERROR_CODE, SUCCESS_CODE from base.constants import NUMBER from account.utils import custom_response, custom_error_response from guardian.utils import upload_image_to_alibaba + +""" Define APIs """ +# Define validate guardian code API, +# update junior profile, +# list of all assosicated junior +# Add junior API +# invite junior API +# search junior API +# remove junior API, +# approve junior API + # Create your views here. class UpdateJuniorProfile(viewsets.ViewSet): """Update junior profile""" @@ -29,6 +50,7 @@ class UpdateJuniorProfile(viewsets.ViewSet): if image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) filename = f"images/{image.name}" + # upload image on ali baba image_url = upload_image_to_alibaba(image, filename) request_data = {"image": image_url} serializer = CreateJuniorSerializer(context={"user":request.user, "image":image_url, @@ -51,6 +73,7 @@ class ValidateGuardianCode(viewsets.ViewSet): """check guardian code""" guardian_code = self.request.GET.get('guardian_code').split(',') for code in guardian_code: + # fetch guardian object guardian_data = Guardian.objects.filter(guardian_code=code).exists() if guardian_data: return custom_response(SUCCESS_CODE['3013'], response_status=status.HTTP_200_OK) @@ -68,6 +91,7 @@ class JuniorListAPIView(viewsets.ModelViewSet): """ junior list""" guardian_data = Guardian.objects.filter(user__email=request.user).last() queryset = Junior.objects.filter(guardian_code__icontains=str(guardian_data.guardian_code)) + # use JuniorDetailListSerializer serializer serializer = JuniorDetailListSerializer(queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) @@ -80,8 +104,10 @@ class AddJuniorAPIView(viewsets.ModelViewSet): """ junior list""" info = {'user': request.user, 'email': request.data['email'], 'first_name': request.data['first_name'], 'last_name': request.data['last_name']} + # use AddJuniorSerializer serializer serializer = AddJuniorSerializer(data=request.data, context=info) if serializer.is_valid(): + # save serializer serializer.save() return custom_response(SUCCESS_CODE['3021'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.error, response_status=status.HTTP_400_BAD_REQUEST) @@ -105,6 +131,7 @@ class InvitedJuniorAPIView(viewsets.ModelViewSet): queryset = self.get_queryset() paginator = self.pagination_class() paginated_queryset = paginator.paginate_queryset(queryset, request) + # use JuniorDetailListSerializer serializer serializer = JuniorDetailListSerializer(paginated_queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) @@ -128,7 +155,9 @@ class FilterJuniorAPIView(viewsets.ModelViewSet): """Create guardian profile""" queryset = self.get_queryset() paginator = self.pagination_class() + # use Pagination paginated_queryset = paginator.paginate_queryset(queryset, request) + # use JuniorDetailListSerializer serializer serializer = JuniorDetailListSerializer(paginated_queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) @@ -142,11 +171,14 @@ class RemoveJuniorAPIView(views.APIView): def put(self, request, format=None): junior_id = self.request.GET.get('id') guardian = Guardian.objects.filter(user__email=self.request.user).last() + # fetch junior query junior_queryset = Junior.objects.filter(id=junior_id, guardian_code__icontains=str(guardian.guardian_code), is_invited=True).last() if junior_queryset: + # use RemoveJuniorSerializer serializer serializer = RemoveJuniorSerializer(junior_queryset, data=request.data, partial=True) if serializer.is_valid(): + # save serializer serializer.save() return custom_response(SUCCESS_CODE['3022'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) diff --git a/zod_bank/settings.py b/zod_bank/settings.py index b052a4f..84191b0 100644 --- a/zod_bank/settings.py +++ b/zod_bank/settings.py @@ -9,13 +9,14 @@ https://docs.djangoproject.com/en/3.0/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/3.0/ref/settings/ """ - +# Django Import import os from dotenv import load_dotenv from datetime import timedelta load_dotenv() # OR, the same with increased verbosity: load_dotenv(verbose=True) +# env path env_path = os.path.join(os.path.abspath(os.path.join('.env', os.pardir)), '.env') load_dotenv(dotenv_path=env_path) @@ -34,32 +35,36 @@ SECRET_KEY = '-pb+8w#)6qsh+w&tr+q$tholf7=54v%05e^9!lneiqqgtddg6q' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True +# allow all host ALLOWED_HOSTS = ['*'] # Application definition INSTALLED_APPS = [ + # Add your installed Django apps here 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + # Add Django rest frame work apps here 'django_extensions', 'storages', 'drf_yasg', 'corsheaders', 'django.contrib.postgres', 'rest_framework', + # Add your custom apps here. 'django_ses', 'account', 'junior', - 'guardian', - # 'social_django' + 'guardian' ] - +# define middle ware here MIDDLEWARE = [ + # Add your middleware classes here. 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', @@ -70,8 +75,10 @@ MIDDLEWARE = [ 'account.custom_middleware.CustomMiddleware' ] +# define root ROOT_URLCONF = 'zod_bank.urls' +# define templates TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', @@ -88,7 +95,9 @@ TEMPLATES = [ }, ] +# define wsgi WSGI_APPLICATION = 'zod_bank.wsgi.application' +# define rest frame work REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ # 'rest_framework.authentication.SessionAuthentication', @@ -97,6 +106,7 @@ REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 5, } +# define jwt token SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(hours=2, minutes=59, seconds=59, microseconds=999999), 'REFRESH_TOKEN_LIFETIME': timedelta(hours=71, minutes=59, seconds=59, microseconds=999999), @@ -113,7 +123,7 @@ DATABASES = { 'PORT':os.getenv('DB_PORT'), } } - +# define swagger setting SWAGGER_SETTINGS = { "exclude_namespaces": [], "api_version": '0.1', @@ -140,6 +150,7 @@ SWAGGER_SETTINGS = { # Password validation # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators +# password validation AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', @@ -159,20 +170,23 @@ AUTH_PASSWORD_VALIDATORS = [ # Internationalization # https://docs.djangoproject.com/en/3.0/topics/i18n/ +# language code LANGUAGE_CODE = 'en-us' - +# time zone TIME_ZONE = 'UTC' - +# define I18N USE_I18N = True - +# define L10N USE_L10N = True - +# define TZ USE_TZ = True # cors header settings SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +# cors allow setting CORS_ORIGIN_ALLOW_ALL = True +# cors allow method CORS_ALLOW_METHODS = ( 'DELETE', 'GET', @@ -181,7 +195,7 @@ CORS_ALLOW_METHODS = ( 'POST', 'PUT', ) - +# cors allow header CORS_ALLOW_HEADERS = ( 'accept', 'accept-encoding', @@ -197,11 +211,12 @@ CORS_ALLOW_HEADERS = ( """Static files (CSS, JavaScript, Images) https://docs.djangoproject.com/en/3.0/howto/static-files/""" - +# google client id GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID') +# google client secret key GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET') - +# email settings EMAIL_BACKEND="django.core.mail.backends.smtp.EmailBackend" EMAIL_HOST="smtp.sendgrid.net" EMAIL_PORT="587" @@ -211,14 +226,15 @@ EMAIL_HOST_PASSWORD="SG.HAMnFRvaSMWeVLatqr4seg.Y9fQb-ckK9gyXLoMKdUE8eCh5lrel36Tm EMAIL_FROM_ADDRESS="support@zodbank.com" DEFAULT_ADDRESS="zodbank@yopmail.com" - +# ali baba cloud settings ALIYUN_OSS_ACCESS_KEY_ID = os.getenv('ALIYUN_OSS_ACCESS_KEY_ID') ALIYUN_OSS_ACCESS_KEY_SECRET = os.getenv('ALIYUN_OSS_ACCESS_KEY_SECRET') ALIYUN_OSS_BUCKET_NAME = os.getenv('ALIYUN_OSS_BUCKET_NAME') ALIYUN_OSS_ENDPOINT = os.getenv('ALIYUN_OSS_ENDPOINT') ALIYUN_OSS_REGION = os.getenv('ALIYUN_OSS_REGION') - +# define static url STATIC_URL = 'static/' +# define static root STATIC_ROOT = 'static' From 6d6d21137fec028c6656e8fa1a3a37a3a49ef2b4 Mon Sep 17 00:00:00 2001 From: jain Date: Mon, 17 Jul 2023 17:00:33 +0530 Subject: [PATCH 13/14] sonar issues --- account/serializers.py | 17 +++++++++++++++-- account/views.py | 2 +- base/messages.py | 2 ++ guardian/tasks.py | 5 +++-- guardian/views.py | 4 ++++ 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/account/serializers.py b/account/serializers.py index 3596c07..11944e6 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -140,15 +140,28 @@ class ForgotPasswordSerializer(serializers.Serializer): class SuperUserSerializer(serializers.ModelSerializer): """Super admin serializer""" user_type = serializers.SerializerMethodField('get_user_type') + auth_token = serializers.SerializerMethodField('get_auth_token') + refresh_token = serializers.SerializerMethodField('get_refresh_token') + + def get_auth_token(self, obj): + refresh = RefreshToken.for_user(obj.auth) + access_token = str(refresh.access_token) + return access_token + + def get_refresh_token(self, obj): + refresh = RefreshToken.for_user(obj.user) + refresh_token = str(refresh) + return refresh_token def get_user_type(self, obj): """user type""" - return SUPERUSER + return str(NUMBER['three']) class Meta(object): """Meta info""" model = User - fields = ['id', 'username', 'email', 'first_name', 'last_name', 'is_active', 'user_type'] + fields = ['id', 'auth_token', 'refresh_token', 'username', 'email', 'first_name', + 'last_name', 'is_active', 'user_type'] class GuardianSerializer(serializers.ModelSerializer): diff --git a/account/views.py b/account/views.py index b6fc821..c11e955 100644 --- a/account/views.py +++ b/account/views.py @@ -214,7 +214,7 @@ class ForgotPasswordAPIView(views.APIView): User.objects.get(email=email) except User.DoesNotExist: return custom_error_response(ERROR_CODE['2004'], response_status=status.HTTP_404_NOT_FOUND) - verification_code = ''.join([str(random.randrange(9)) for _ in range(6)]) + verification_code = generate_otp() # Send the verification code to the user's email from_email = settings.EMAIL_FROM_ADDRESS recipient_list = [email] diff --git a/base/messages.py b/base/messages.py index 8b65d2a..82d471a 100644 --- a/base/messages.py +++ b/base/messages.py @@ -47,6 +47,7 @@ ERROR_CODE = { "2021": "Already register", "2022": "Invalid Guardian code", "2023": "Invalid user", + # email not verified "2024": "Email not verified", "2025": "Invalid input. Expected a list of strings.", "2026": "New password should not same as old password", @@ -54,6 +55,7 @@ ERROR_CODE = { "2028": "You are not authorized person to sign up on this platform", "2029": "Validity of otp verification is expired", "2030": "Use correct user type and token", + # invalid password "2031": "Invalid password", "2032": "Failed to send email", "2033": "Missing required fields", diff --git a/guardian/tasks.py b/guardian/tasks.py index 7a5dd90..9cf39b3 100644 --- a/guardian/tasks.py +++ b/guardian/tasks.py @@ -1,6 +1,7 @@ """task files""" """Django import""" -import random +import secrets def generate_otp(): """generate random otp""" - return ''.join([str(random.randrange(9)) for _ in range(6)]) + digits = "0123456789" + return "".join(secrets.choice(digits) for _ in range(6)) diff --git a/guardian/views.py b/guardian/views.py index f53dc7d..1d1808e 100644 --- a/guardian/views.py +++ b/guardian/views.py @@ -176,6 +176,7 @@ class SearchTaskListAPIView(viewsets.ModelViewSet): queryset = self.get_queryset() paginator = self.pagination_class() + # use pagination paginated_queryset = paginator.paginate_queryset(queryset, request) # use TaskSerializer serializer serializer = TaskDetailsSerializer(paginated_queryset, many=True) @@ -242,6 +243,7 @@ class ApproveTaskAPIView(viewsets.ViewSet): def get_queryset(self): """Get the queryset for the view""" guardian = Guardian.objects.filter(user__email=self.request.user).last() + # task query task_queryset = JuniorTask.objects.filter(id=self.request.data.get('task_id'), guardian=guardian, junior=self.request.data.get('junior_id')).last() @@ -257,9 +259,11 @@ class ApproveTaskAPIView(viewsets.ViewSet): "action": str(request.data['action'])}, data=request.data) if str(request.data['action']) == str(NUMBER['one']) and serializer.is_valid(): + # save serializer serializer.save() return custom_response(SUCCESS_CODE['3025'], response_status=status.HTTP_200_OK) elif str(request.data['action']) == str(NUMBER['two']) and serializer.is_valid(): + # save serializer serializer.save() return custom_response(SUCCESS_CODE['3026'], response_status=status.HTTP_200_OK) else: From 4779749b0c85c111e54e44eff1aaba1e749554a3 Mon Sep 17 00:00:00 2001 From: jain Date: Mon, 17 Jul 2023 17:05:45 +0530 Subject: [PATCH 14/14] success msg --- account/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account/views.py b/account/views.py index c11e955..015d505 100644 --- a/account/views.py +++ b/account/views.py @@ -321,7 +321,7 @@ class UserLogin(viewsets.ViewSet): return custom_response(ERROR_CODE['2024'], {"email_otp": otp, "is_email_verified": is_verified}, response_status=status.HTTP_200_OK) data.update({"is_email_verified": is_verified}) - return custom_response(None, data, response_status=status.HTTP_200_OK) + return custom_response(SUCCESS_CODE['3003'], data, response_status=status.HTTP_200_OK) @action(methods=['post'], detail=False) def admin_login(self, request):