I'm newbie in Django I have a trouble with this: I've already make API for 'request-reset-email', 'password-reset' and 'password-reset-complete' Here are the code: file: urls.py
from django.urls import path
from .views import *
from django.contrib.auth import views as auth_view
from rest_framework_simplejwt.views import (
TokenObtainSlidingView,
TokenRefreshSlidingView,
)
urlpatterns=[
path('register/', RegisterView.as_view(), name="register"),
path('login/', LoginAPIView.as_view(), name="login"),
path('email-verify/', VerifyEmail.as_view(), name="email-verify"),
path('token/refresh/', TokenRefreshSlidingView.as_view(), name='token_refresh'),
path('request-reset-email/',RequestPasswordResetEmail.as_view(), name='request-reset-email'),
path('password-reset/<uidb64>/<token>/',PasswordTokenCheckAPIView.as_view(),name='password-reset'),
path('password-reset-complete/',SetNewPasswordAPIView.as_view(),name='password-reset-complete')
]
file Views.py:
from django.shortcuts import render
from rest_framework import exceptions, generics, serializers
from rest_framework.response import Response
from rest_framework import status
from .models import *
from .serializers import *
from rest_framework_simplejwt.tokens import RefreshToken
from .utils import *
from django.contrib.sites.shortcuts import get_current_site
from django.urls import reverse
import jwt
from django.conf import settings
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
# Create your views here.
class RegisterView(generics.GenericAPIView):
queryset = User.objects.all()
serializer_class=RegisterSerializer
def post(self, request):
user = request.data
serializer = self.serializer_class(data=user)
serializer.is_valid(raise_exception=True)
serializer.save()
user_data = serializer.data
user= User.objects.get(email=user_data['email'])
token=RefreshToken.for_user(user).access_token
current_site=get_current_site(request).domain
realtivelink = reverse('email-verify')
absurl='http://'+current_site+realtivelink+"?token="+ str(token)
email_body='Hi '+ user.email+ ' Use link below to verify your email \n' + absurl
data={'email_body':email_body,'to_email':user.email,'email_subject':'Verify your email'}
Util.send_email(data)
return Response(user_data,status= status.HTTP_201_CREATED)
class VerifyEmail(generics.GenericAPIView):
def get(self,request):
token= request.GET.get('token')
try:
payload=jwt.decode(token,settings.SECRET_KEY,algorithms='HS256')
user=User.objects.get(id=payload['user_id'])
if not user.is_verified:
user.is_verified=True
user.save()
return Response({'email':'Successfully activated'},status= status.HTTP_200_OK)
except jwt.ExpiredSignatureError as indentifier:
return Response({'email':'Activation expired'},status= status.HTTP_400_BAD_REQUEST)
except jwt.exceptions.DecodeError as indentifier:
return Response({'email':'Invalid token'},status= status.HTTP_400_BAD_REQUEST)
class LoginAPIView(generics.GenericAPIView):
queryset = User.objects.all()
serializer_class = LoginSerializers
def post(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
return Response(serializer.data,status=status.HTTP_200_OK )
class RequestPasswordResetEmail(generics.GenericAPIView):
queryset = User.objects.all()
serializer_class=ResetPasswordViaEmailSerializer
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
realtivelink = reverse('password-reset',kwargs={'uidb64':uidb64,'token':token})
absurl='http://'+current_site+realtivelink
email_body='Hi, \nUse link below to reset your password \n' + absurl
data={'email_body':email_body,'to_email':user.email,'email_subject':'Reset your password'}
Util.send_email(data)
return Response({'successfully':'check your email to reset your password'},status=status.HTTP_200_OK)
class PasswordTokenCheckAPIView(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):
return Response({'error':'token is not valid, please check the new one'},status=status.HTTP_401_UNAUTHORIZED)
return Response({'sucess':True, 'message':'Credential Valid','uidb64':uidb64, 'token':token},status=status.HTTP_200_OK)
except DjangoUnicodeDecodeError as indentifier:
return Response({'error':'token is not valid, please check the new one'},status=status.HTTP_401_UNAUTHORIZED)
class SetNewPasswordAPIView(generics.GenericAPIView):
queryset = User.objects.all()
serializer_class=ResetPassWordSerializer
def patch(self, request):
serializer=self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
return Response({'sucess':True, 'message':'Password is reset successfully'},status=status.HTTP_200_OK)
APIs've already worked. But I want to make the "PasswordTokenCheckAPIView" have a templete for user to enter the new password and confirm it. So, could you please to give me some way to do this? I've tried to use django.contrib.auth.PasswordResetConfirmView, it appears the template when I click the link I received in mail, but when I confirm change password, there is error
from django.urls import path
from .views import *
from django.contrib.auth import views as auth_view
from rest_framework_simplejwt.views import (
TokenObtainSlidingView,
TokenRefreshSlidingView,
)
urlpatterns=[
path('register/', RegisterView.as_view(), name="register"),
path('login/', LoginAPIView.as_view(), name="login"),
path('email-verify/', VerifyEmail.as_view(), name="email-verify"),
path('token/refresh/', TokenRefreshSlidingView.as_view(), name='token_refresh'),
path('request-reset-email/',RequestPasswordResetEmail.as_view(), name='request-reset-email'),
path('password-reset/<uidb64>/<token>/',auth_view.PasswordResetConfirmView.as_view(),name='password-reset'),
path('password_reset_complete/',auth_view.PasswordResetCompleteView.as_view(),name='password-reset-complete')
]
Thank you very much!