diff --git a/zod_bank/account/serializers.py b/zod_bank/account/serializers.py index 03b1012..f70f084 100644 --- a/zod_bank/account/serializers.py +++ b/zod_bank/account/serializers.py @@ -13,6 +13,38 @@ from rest_framework.decorators import action from django.contrib.auth import authenticate, login from rest_framework_simplejwt.tokens import RefreshToken +class ResetPasswordSerializer(serializers.Serializer): + """Reset Password after verification""" + verification_code = serializers.CharField(max_length=10) + password = serializers.CharField(required=True) + class Meta(object): + """Meta info""" + model = User + + def create(self, validated_data): + verification_code = validated_data.pop('verification_code') + password = validated_data.pop('password') + print("verification_code===>",verification_code) + print("password===>", password) + user_opt_details = UserEmailOtp.objects.filter(otp=verification_code, is_verified=True).last() + print("user_opt_details===>",user_opt_details) + if user_opt_details: + print("qqqqqqqqqq") + user_details = User.objects.filter(email=user_opt_details.email).last() + if user_details: + print("333333333==>",user_details.password) + user_details.set_password(password) + user_details.save() + return {'password':password} + return user_opt_details + + + + +class ForgotPasswordSerializer(serializers.Serializer): + """Forget password serializer""" + email = serializers.EmailField() + class SuperUserSerializer(serializers.ModelSerializer): user_type = serializers.SerializerMethodField('get_user_type') diff --git a/zod_bank/account/templates/templated_email/email_base.email b/zod_bank/account/templates/templated_email/email_base.email new file mode 100644 index 0000000..5721e28 --- /dev/null +++ b/zod_bank/account/templates/templated_email/email_base.email @@ -0,0 +1,54 @@ + +{% block subject %}DinDin{% endblock %} +{% load static %} + +{% block html %} + + + + + Zod Bank | OTP + + + + + + + + + + +
+ + + + + {% block plain %} + {% endblock %} + + + +
+
+

-

+

Cheers!

+

Zod Bank Team

+
+
+ + + +{% endblock %} diff --git a/zod_bank/account/templates/templated_email/email_otp_verification.email b/zod_bank/account/templates/templated_email/email_otp_verification.email new file mode 100644 index 0000000..8b3c693 --- /dev/null +++ b/zod_bank/account/templates/templated_email/email_otp_verification.email @@ -0,0 +1,23 @@ +{% extends "templated_email/email_base.email" %} + +{% block subject %} + OTP Verification +{% endblock %} + +{% block plain %} + + +

+ Hi User, +

+ + + + +

+ You are receiving this email for email verification. Please use {{ otp }} as the verification code for your email address & username. + +

+ + +{% endblock %} diff --git a/zod_bank/account/templates/templated_email/email_reset_verification.email b/zod_bank/account/templates/templated_email/email_reset_verification.email new file mode 100644 index 0000000..0138d99 --- /dev/null +++ b/zod_bank/account/templates/templated_email/email_reset_verification.email @@ -0,0 +1,23 @@ +{% extends "templated_email/email_base.email" %} + +{% block subject %} + Reset Password Verification +{% endblock %} + +{% block plain %} + + +

+ Hi User, +

+ + + + +

+ You are receiving this email for reset password verification. Please use {{ verification_code }} as the verification code. + +

+ + +{% endblock %} diff --git a/zod_bank/account/urls.py b/zod_bank/account/urls.py index 1350cea..0b3ddb5 100644 --- a/zod_bank/account/urls.py +++ b/zod_bank/account/urls.py @@ -4,7 +4,8 @@ from django.urls import path, include from rest_framework.decorators import api_view """Third party import""" from rest_framework import routers -from .views import UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVerification, ReSendEmailOtp +from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVerification, ReSendEmailOtp, + ForgotPasswordAPIView, ResetPasswordAPIView) """Router""" router = routers.SimpleRouter() @@ -15,6 +16,9 @@ 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') router.register('resend-email-otp', ReSendEmailOtp, basename='resend-email-otp') + urlpatterns = [ path('api/v1/', include(router.urls)), + path('api/v1/forgot-password/', ForgotPasswordAPIView.as_view()), + path('api/v1/reset-password/', ResetPasswordAPIView.as_view()) ] diff --git a/zod_bank/account/utils.py b/zod_bank/account/utils.py index c6ffe7f..2d86106 100644 --- a/zod_bank/account/utils.py +++ b/zod_bank/account/utils.py @@ -3,12 +3,19 @@ from django.conf import settings import random from rest_framework import viewsets, status from rest_framework.response import Response + +from templated_email import send_templated_mail def send_otp_email(recipient_email, otp): - subject = 'One-Time Password' - message = f'Your OTP is: {otp}' - from_email = settings.DEFAULT_FROM_EMAIL + from_email = settings.EMAIL_HOST_USER recipient_list = [recipient_email] - send_mail(subject, message, from_email, recipient_list) + send_templated_mail( + template_name='email_otp_verification.email', + from_email=from_email, + recipient_list=recipient_list, + context={ + 'otp': otp + } + ) return otp def custom_response(detail, data=None, response_status=status.HTTP_200_OK): diff --git a/zod_bank/account/views.py b/zod_bank/account/views.py index 352b834..321b200 100644 --- a/zod_bank/account/views.py +++ b/zod_bank/account/views.py @@ -1,12 +1,13 @@ -from rest_framework import viewsets, status +from rest_framework import viewsets, status, views from rest_framework.decorators import action -from rest_framework.response import Response +import random from django.contrib.auth import authenticate, login from guardian.models import Guardian from junior.models import Junior from account.models import UserProfile, UserPhoneOtp, UserEmailOtp from django.contrib.auth.models import User -from .serializers import SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer +from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer, + ForgotPasswordSerializer, ResetPasswordSerializer) from django.views.decorators.csrf import csrf_exempt from rest_framework_simplejwt.serializers import TokenObtainPairSerializer from rest_framework_simplejwt.views import TokenObtainPairView @@ -15,6 +16,49 @@ from base.messages import ERROR_CODE, SUCCESS_CODE from guardian.tasks import generate_otp 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 templated_email import send_templated_mail +import secrets + +class ResetPasswordAPIView(views.APIView): + def post(self, request): + print("request.data====>",request.data) + serializer = ResetPasswordSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return custom_response(SUCCESS_CODE['3006'], response_status=status.HTTP_200_OK) + return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) + +class ForgotPasswordAPIView(views.APIView): + def post(self, request): + serializer = ForgotPasswordSerializer(data=request.data) + if serializer.is_valid(): + email = serializer.validated_data['email'] + try: + 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)]) + # Send the verification code to the user's email + subject = 'Password Reset Verification Code' + message = f'Your verification code is: {verification_code}' + from_email = 'infozodbank@gmail.com' + recipient_list = [email] + send_templated_mail( + template_name='email_reset_verification.email', + from_email=from_email, + recipient_list=recipient_list, + context={ + 'verification_code': verification_code + } + ) + UserEmailOtp.objects.create(email=email, otp=verification_code) + return custom_response(SUCCESS_CODE['3015'], {'verification_code': verification_code}, + response_status=status.HTTP_200_OK) + return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) + class SendPhoneOtp(viewsets.ModelViewSet): """Send otp on phone""" def create(self, request, *args, **kwargs): diff --git a/zod_bank/base/messages.py b/zod_bank/base/messages.py index 718d6be..953d761 100644 --- a/zod_bank/base/messages.py +++ b/zod_bank/base/messages.py @@ -27,7 +27,7 @@ ERROR_CODE = { "2001": "Your account has not been verified. Please check your email and verify it.", "2002": "Invalid login credentials.", "2003": "An account already exists with this email address.", - "2004": "User doesn't exist.", + "2004": "User not found.", "2005": "Your account has been activated.", "2006": "Your account is not activated.", "2007": "Your account already activated.", @@ -73,7 +73,8 @@ SUCCESS_CODE = { "3011": "Email OTP Verified successfully", "3012": "Phone OTP Verified successfully", "3013": "Valid Guardian code", - "3014": "Password has been updated successfully." + "3014": "Password has been updated successfully.", + "3015": "Verification code sent on your email." } STATUS_CODE_ERROR = { diff --git a/zod_bank/guardian/views.py b/zod_bank/guardian/views.py index f43e4c8..2b40702 100644 --- a/zod_bank/guardian/views.py +++ b/zod_bank/guardian/views.py @@ -17,6 +17,7 @@ from .tasks import generate_otp from account.utils import send_otp_email from account.utils import custom_response, custom_error_response from base.messages import ERROR_CODE, SUCCESS_CODE + class SignupViewset(viewsets.ModelViewSet): serializer_class = UserSerializer @@ -26,7 +27,7 @@ class SignupViewset(viewsets.ModelViewSet): serializer.save() otp = generate_otp() UserEmailOtp.objects.create(email=request.data['email'], otp=otp) - # send_otp_email(request.data['email'], otp) + send_otp_email(request.data['email'], otp) return custom_response(SUCCESS_CODE['3001'], {"email_otp": otp}, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) diff --git a/zod_bank/zod_bank/settings.py b/zod_bank/zod_bank/settings.py index 0c8da76..9e47b30 100644 --- a/zod_bank/zod_bank/settings.py +++ b/zod_bank/zod_bank/settings.py @@ -171,6 +171,32 @@ CORS_ALLOW_HEADERS = ( # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.0/howto/static-files/ +# +# MAIL_MAILER='smtp' +# MAIL_HOST='smtp.gmail.com' +# MAIL_PORT=587 +# mail_username='infozodbank@gmail.com' +# MAIL_PASSWORD='ghwdmznwwslvchga' +# MAIL_ENCRYPTION='tls' +# mail_from_address='infozodbank@gmail.com' +# MAIL_FROM_NAME="${APP_NAME}" + +# MAIL_MAILER='smtp' +# MAIL_HOST='smtp.gmail.com' +# MAIL_PORT=587 +# mail_username='ankita.jain@kiwitech.com' +# MAIL_PASSWORD='jaijain0912@' +# MAIL_ENCRYPTION='tls' +# mail_from_address='infozodbank@gmail.com' +# MAIL_FROM_NAME="${APP_NAME}" + +# Email settings +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_HOST = 'smtp.gmail.com' +EMAIL_PORT = 587 +EMAIL_USE_TLS = True +EMAIL_HOST_USER = 'infozodbank@gmail.com' +EMAIL_HOST_PASSWORD = 'ghwdmznwwslvchga' # Replace with your Gmail email password or App password STATIC_URL = '/static/'