From d2498f82ad3862ef76e06fa16bae69135a89cb64 Mon Sep 17 00:00:00 2001 From: jain Date: Fri, 30 Jun 2023 21:25:43 +0530 Subject: [PATCH] jira-5 google login and apple login --- account/serializers.py | 21 +++++----- account/urls.py | 7 ++-- account/utils.py | 57 ++++++++++++++++++++++++++- account/views.py | 88 +++++++++++++++++++++++++++--------------- zod_bank/settings.py | 20 +++++----- 5 files changed, 139 insertions(+), 54 deletions(-) diff --git a/account/serializers.py b/account/serializers.py index e7a9e33..f25510d 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -13,7 +13,7 @@ from rest_framework.decorators import action from django.contrib.auth import authenticate, login from rest_framework_simplejwt.tokens import RefreshToken from guardian.utils import upload_image_to_alibaba - +from .utils import get_token class GoogleSignInSerializer(serializers.Serializer): """Google login Serializer""" email = serializers.EmailField() @@ -139,11 +139,13 @@ 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 + return get_token()['access'] + def get_refresh_token(self, obj): + return get_token()['refresh'] + def get_user_type(self, obj): """user type""" @@ -164,7 +166,7 @@ class GuardianSerializer(serializers.ModelSerializer): class Meta(object): """Meta info""" model = Guardian - fields = ['auth_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'family_name', 'gender', 'dob', + fields = ['auth_token', 'refresh_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'family_name', 'gender', 'dob', 'referral_code', 'is_active', 'is_complete_profile', 'passcode', 'created_at', 'updated_at', 'user_type'] @@ -176,11 +178,12 @@ 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 + return get_token()['access'] + def get_refresh_token(self, obj): + return get_token()['refresh'] def get_user_type(self, obj): return JUNIOR @@ -197,7 +200,7 @@ class JuniorSerializer(serializers.ModelSerializer): class Meta(object): """Meta info""" model = Junior - fields = ['auth_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob', + fields = ['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', 'updated_at', 'user_type'] diff --git a/account/urls.py b/account/urls.py index 010398a..e0e1c6c 100644 --- a/account/urls.py +++ b/account/urls.py @@ -6,14 +6,14 @@ from rest_framework.decorators import api_view from rest_framework import routers from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVerification, ReSendEmailOtp, ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage, - GoogleLoginViewSet1) + GoogleLoginViewSet, SigninWithApple) """Router""" router = routers.SimpleRouter() """API End points with router""" router.register('user', UserLogin, basename='user') router.register('admin', UserLogin, basename='admin') -router.register('google-login', GoogleLoginViewSet1, basename='admin') +router.register('google-login', GoogleLoginViewSet, basename='admin') router.register('send-phone-otp', SendPhoneOtp, basename='send-phone-otp') router.register('user-phone-verification', UserPhoneVerification, basename='user-phone-verification') router.register('user-email-verification', UserEmailVerification, basename='user-email-verification') @@ -23,5 +23,6 @@ urlpatterns = [ path('api/v1/forgot-password/', ForgotPasswordAPIView.as_view()), path('api/v1/reset-password/', ResetPasswordAPIView.as_view()), path('api/v1/change-password/', ChangePasswordAPIView.as_view()), - path('api/v1/update-profile-image/', UpdateProfileImage.as_view()) + path('api/v1/update-profile-image/', UpdateProfileImage.as_view()), + path('api/v1/apple-login/', SigninWithApple.as_view(), name='signup_with_apple'), ] diff --git a/account/utils.py b/account/utils.py index bfc2399..0848c03 100644 --- a/account/utils.py +++ b/account/utils.py @@ -3,8 +3,13 @@ from django.conf import settings from rest_framework import viewsets, status from rest_framework.response import Response - from templated_email import send_templated_mail +import jwt +from datetime import datetime +from calendar import timegm +from uuid import uuid4 +import secrets + def send_otp_email(recipient_email, otp): from_email = settings.EMAIL_FROM_ADDRESS recipient_list = [recipient_email] @@ -36,3 +41,53 @@ def custom_error_response(detail, response_status): if not detail: detail = {} return Response({"error": detail, "status": "failed", "code": response_status}) + + +def get_user_data(attrs): + """ + used to decode token + """ + user_data = jwt.decode(jwt=attrs['token'], options={'verify_signature': False}, + algorithms=['RS256']) + return user_data + + +def generate_jwt_token(token_type: str, now_time: int, data: dict = dict): + """ + used to generate jwt token + """ + if type(data) == type: + data = {} + data.update({ + 'token_type': token_type, + 'iss': 'your_site_url', + 'iat': timegm(datetime.utcnow().utctimetuple()), + 'jti': uuid4().hex + }) + TOKEN_TYPE = ["access", "refresh"] + if token_type == TOKEN_TYPE[1]: + exp = now_time + settings.SIMPLE_JWT['REFRESH_TOKEN_LIFETIME'] + else: + exp = now_time + settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME'] + + data.update({ + "exp": timegm(exp.utctimetuple()) + }) + + + signing_key = secrets.token_hex(32) + + return jwt.encode(payload=data, key=signing_key, + algorithm='HS256') + + +def get_token(data: dict = dict): + """ create access and refresh token """ + now_time = datetime.utcnow() + access = generate_jwt_token('access', now_time, data) + refresh = generate_jwt_token('refresh', now_time, data) + + return { + 'access': access, + 'refresh': refresh + } \ No newline at end of file diff --git a/account/views.py b/account/views.py index 93cf17f..106dfce 100644 --- a/account/views.py +++ b/account/views.py @@ -2,6 +2,7 @@ from rest_framework import viewsets, status, views from rest_framework.decorators import action import random import logging +import jwt from django.contrib.auth import authenticate, login from guardian.models import Guardian from junior.models import Junior @@ -13,22 +14,17 @@ from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSeriali from rest_framework_simplejwt.tokens import RefreshToken from base.messages import ERROR_CODE, SUCCESS_CODE from guardian.tasks import generate_otp -from django.conf import settings from account.utils import send_otp_email from account.utils import custom_response, custom_error_response -from django.core.mail import EmailMessage -from django.core.mail import send_mail -from rest_framework.response import Response 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 from rest_framework.response import Response import requests from django.conf import settings -# from apps.accounts.utility import get_token +from .utils import get_token class GoogleLoginMixin: @@ -65,9 +61,18 @@ class GoogleLoginMixin: # Check if the user exists in your database or create a new user # ... - if User.objects.filter(email__iexact=email).exists(): + user_data = User.objects.filter(email__iexact=email) + if user_data.exists(): print("00000000000") - return custom_response(SUCCESS_CODE['3003'], response_status=status.HTTP_200_OK) + if str(user_type) == '1': + junior_query = Junior.objects.filter(auth=user_data.last()).last() + serializer = JuniorSerializer(junior_query) + if str(user_type) == '2': + guardian_query = Guardian.objects.filter(user=user_data.last()).last() + print("guardian_query==>",guardian_query,'====>',type(guardian_query)) + serializer = GuardianSerializer(guardian_query) + return custom_response(SUCCESS_CODE['3003'], serializer.data, + response_status=status.HTTP_200_OK) if not User.objects.filter(email__iexact=email).exists(): print("999999999999999") @@ -80,9 +85,11 @@ class GoogleLoginMixin: # Return a JSON response with the user's email and name - return Response({'token': "get_token()", 'name': name, 'email': email, 'profile_picture': profile_picture}) + return custom_response(SUCCESS_CODE['3003'], {'auth_token': get_token(), 'name': name, 'email': email, + 'profile_picture': profile_picture, "user_type":user_type}, + response_status=status.HTTP_200_OK) -class GoogleLoginViewSet1(GoogleLoginMixin, viewsets.GenericViewSet): +class GoogleLoginViewSet(GoogleLoginMixin, viewsets.GenericViewSet): serializer_class = GoogleLoginSerializer1 def create(self, request): @@ -91,27 +98,46 @@ class GoogleLoginViewSet1(GoogleLoginMixin, viewsets.GenericViewSet): print("88888888888888888888888888") return self.google_login(request) -# class GoogleLoginAPIViewset(viewsets.ModelViewSet): -# """Google Login""" -# serializer_class = GoogleSignInSerializer -# -# def create(self, request, *args, **kwargs): -# """ -# Override default behaviour of create method -# """ -# provider_type = [] -# serializer = self.get_serializer(data=request.data) -# if serializer.is_valid(raise_exception=True): -# # provider = self.get_provider_view(request.data.get('provider')) -# # if User is not authenticated then send error message -# # if not provider.is_authenticated(request): -# # return custom_error_response({}, status.HTTP_400_BAD_REQUEST) -# -# user = serializer.save() -# if User.objects.filter(email__iexact=user.email).exists(): -# print("ppppppppppppp") -# return custom_response(SUCCESS_CODE["3003"], response_status=status.HTTP_200_OK) -# return custom_response(ERROR_CODE["2002"], response_status=status.HTTP_400_BAD_REQUEST) +class SigninWithApple(views.APIView): + """This API is for sign in with Apple for app.""" + def post(self, request): + token = request.data.get("identityToken") + user_type = request.data.get("user_type") + if not token: + return Response({"message": "data should contain `identityToken`"}) + decoded_data = jwt.decode(token, options={"verify_signature": False}) + print("decoded_data===>",decoded_data) + user_data = {"email": decoded_data.get('email'),"username": decoded_data.get('email'), + "first_name": request.data.get("fullName").get("givenName"),"is_active": True, + "last_name": request.data.get("fullName").get("familyName"),} + if user_data['email'] and not user_data['first_name']: + user_data['first_name'] = user_data['email'].split("@")[0] + user_data['last_name'] = user_data['email'].split("@")[0] + if decoded_data.get("email"): + try: + user = User.objects.get(email=decoded_data.get("email")) + if str(user_type) == '1': + junior_query = Junior.objects.filter(auth=user).last() + print("junior_query==>", junior_query, '====>', type(junior_query)) + serializer = JuniorSerializer(junior_query) + if str(user_type) == '2': + guardian_query = Guardian.objects.filter(user=user).last() + print("guardian_query==>", guardian_query, '====>', type(guardian_query)) + serializer = GuardianSerializer(guardian_query) + return custom_response(SUCCESS_CODE['3003'], serializer.data, + response_status=status.HTTP_200_OK) + + except User.DoesNotExist: + user = User.objects.create(**user_data) + if str(user_type) == '1': + junior_query = Junior.objects.create(auth=user, is_verified=True, is_active=True) + serializer = JuniorSerializer(junior_query) + if str(user_type) == '2': + guardian_query = Guardian.objects.create(user=user, is_verified=True, is_active=True) + serializer = GuardianSerializer(guardian_query) + return custom_response(SUCCESS_CODE['3003'], serializer.data, + response_status=status.HTTP_200_OK) + class UpdateProfileImage(views.APIView): permission_classes = [IsAuthenticated] diff --git a/zod_bank/settings.py b/zod_bank/settings.py index 27d33b6..fc88b1c 100644 --- a/zod_bank/settings.py +++ b/zod_bank/settings.py @@ -96,7 +96,7 @@ REST_FRAMEWORK = { ] } SIMPLE_JWT = { - 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15), + 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=50), 'REFRESH_TOKEN_LIFETIME': timedelta(days=7), } # Database @@ -172,15 +172,15 @@ CORS_ALLOW_HEADERS = ( """Static files (CSS, JavaScript, Images) https://docs.djangoproject.com/en/3.0/howto/static-files/""" -AUTHENTICATION_BACKENDS = [ - 'social_core.backends.google.GoogleOAuth2', - 'django.contrib.auth.backends.ModelBackend', -] - -LOGIN_URL = 'login' -LOGIN_REDIRECT_URL = 'home' -LOGOUT_URL = 'logout' -LOGOUT_REDIRECT_URL = 'login' +# AUTHENTICATION_BACKENDS = [ +# 'social_core.backends.google.GoogleOAuth2', +# 'django.contrib.auth.backends.ModelBackend', +# ] +# +# LOGIN_URL = 'login' +# LOGIN_REDIRECT_URL = 'home' +# LOGOUT_URL = 'logout' +# LOGOUT_REDIRECT_URL = 'login' # SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '' # SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = ''