Forgot Password Django |
follow these steps for forgot password
1. The user enters register email
2. if the email exists we send a link on that email
3. User will click on the link and enter a new password
4. hit post request by the end of the user using uidb64, token and new password
5. We validate and verify and send successful change password message in response
6. that it's, you follow these, I hope you enjoy it.
In Serializers.py
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils.encoding import ( smart_str, force_str, smart_bytes,
DjangoUnicodeDecodeError ) from django.utils.http import (urlsafe_base64_decode,
urlsafe_base64_encode ) from rest_framework import exceptions
# Forgot Password
class ResetPasswordRequestSerializer(serializers.Serializer):
email = serializers.EmailField(min_length=2)
class Meta:
fields = ['email']
class SetNewPasswordSerializer(serializers.Serializer):
password = serializers.CharField(
min_length=6, max_length=68, write_only=True)
token = serializers.CharField(min_length=1, write_only=True)
uidb64 = serializers.CharField(min_length=1, write_only=True)
class Meta:
fields = ['password', 'token', 'uidb64']
def validate(self, attrs):
try:
password = attrs.get('password')
token = attrs.get('token')
uidb64 = attrs.get('uidb64')
id = force_str(urlsafe_base64_decode(uidb64))
user = User.objects.get(id=id)
if not PasswordResetTokenGenerator().check_token(user, token):
raise exceptions.AuthenticationFailed(
'The reset link is invalid', 401)
user.set_password(password)
user.save()
return user
except Exception as e:
raise exceptions.AuthenticationFailed(
'The reset link is invalid', 401)
return super().validate(attrs)
DjangoUnicodeDecodeError ) from django.utils.http import (urlsafe_base64_decode,
urlsafe_base64_encode ) from rest_framework import exceptions
# Forgot Password
class ResetPasswordRequestSerializer(serializers.Serializer):
email = serializers.EmailField(min_length=2)
class Meta:
fields = ['email']
class SetNewPasswordSerializer(serializers.Serializer):
password = serializers.CharField(
min_length=6, max_length=68, write_only=True)
token = serializers.CharField(min_length=1, write_only=True)
uidb64 = serializers.CharField(min_length=1, write_only=True)
class Meta:
fields = ['password', 'token', 'uidb64']
def validate(self, attrs):
try:
password = attrs.get('password')
token = attrs.get('token')
uidb64 = attrs.get('uidb64')
id = force_str(urlsafe_base64_decode(uidb64))
user = User.objects.get(id=id)
if not PasswordResetTokenGenerator().check_token(user, token):
raise exceptions.AuthenticationFailed(
'The reset link is invalid', 401)
user.set_password(password)
user.save()
return user
except Exception as e:
raise exceptions.AuthenticationFailed(
'The reset link is invalid', 401)
return super().validate(attrs)
Views.py
# Reset Password
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils.encoding import smart_str, force_str, smart_bytes, DjangoUnicodeDecodeError
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
from django.contrib.sites.shortcuts import get_current_site
from django.urls import reverse
from modules.core.utils import Util
# Forgot Password
class RequestPasswordResetEmailView(generics.GenericAPIView):
serializer_class = serializers.ResetPasswordRequestSerializer
def post(self, request):
serializer = self.serializer_class(data=request.data)
email = request.data['email']
if User.objects.filter(email=email).exists():
user = User.objects.get(email=email)
uidb64 = urlsafe_base64_encode(smart_bytes(user.id))
token = PasswordResetTokenGenerator().make_token(user)
current_site = get_current_site(
request=request).domain
relative_link = reverse(
'password-reset-confirm', kwargs= {'uidb64':uidb64, 'token': token})
absurl = 'http://' + current_site + relative_link
email_body = 'Hello \n Use link below to reset your password \n' + absurl
data = {'email_body': email_body,
'to_email':user.email,
'to_email':user.email,
'email_subject': 'Reset your password'}
Util.send_email(data)
return Response({'success': 'We have sent you a link to reset your password on email'})
class PasswordTokenCheckAPI(generics.GenericAPIView):
def get(self, request, uidb64, token):
try:
id = smart_str(urlsafe_base64_decode(uidb64))
user = User.objects.get(id=id)
if not PasswordResetTokenGenerator().check_token(
user,token):
user,token):
return Response({'error': 'Token is not valid, Please Request a new One'})
return Response({'success': True, 'message': 'Credentials Valid',
'uidb64': uidb64,
'token': token})
'uidb64': uidb64,
'token': token})
except DjangoUnicodeDecodeError as e:
if not PasswordResetTokenGenerator():
return Response({'error': 'Token is not valid, Please Request a new One'})
class SetNewPasswordView(generics.GenericAPIView):
serializer_class = serializers.SetNewPasswordSerializer
def patch(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
return Response({
'sucess': True,
'message': 'Password Reset Success'
})
Urls.py
path('request-reset-email/', views.RequestPasswordResetEmailView.as_view(), name='request-reset-email'),
path('password-reset/<uidb64>/<token>/', views.PasswordTokenCheckAPI.as_view(),
name='password-reset-confirm'),
path('password-reset-complete/', views.SetNewPasswordView.as_view(), name='password-reset-complete'),
path('password-reset/<uidb64>/<token>/', views.PasswordTokenCheckAPI.as_view(),
name='password-reset-confirm'),
path('password-reset-complete/', views.SetNewPasswordView.as_view(),
name='password-reset-complete'),
Send Email
from django.core.mail import EmailMessage
class Util:
@staticmethod
def send_email(data):
email = EmailMessage(
subject=data['email_subject'], body=data['email_body'],
from_email='tech@tecgslate.com',
to=[data['to_email']]
)
email.send()
0 Comments