micro_service_placeholder/microService/api/ForgetPassword/view.py

90 lines
3.6 KiB
Python

# api/ForgetPassword/view.py
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.encoding import force_bytes, force_str
from django.core.mail import EmailMessage
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from django.contrib.auth.models import User
from rest_framework.permissions import AllowAny
from rest_framework import serializers
from django.conf import settings
from django.core.cache import cache
import uuid
class PasswordResetRequestView(APIView):
permission_classes = [AllowAny] # Allows access to any user, authenticated or not
def post(self, request):
email = request.data.get('email')
user = User.objects.filter(email=email).first()
if user:
token = default_token_generator.make_token(user)
uid = urlsafe_base64_encode(force_bytes(user.pk))
# Create a temporary token and store it in cache
temp_token = str(uuid.uuid4())
cache.set(temp_token, {'uid': uid, 'token': token}, timeout=3600) # Expires in 1 hour
reset_link = f"{settings.BASE_URL}/auth/pass-reset/{temp_token}/"
subject = "Password Reset Request"
message = (
f"Hi {user.username},<br><br>"
f"You requested a password reset. Click the link below to reset your password:<br>"
f'<a href="{reset_link}">Reset Password</a><br><br>'
"If you did not request this, please ignore this email.<br><br>"
"Thank you."
)
email_message = EmailMessage(subject, message, to=[user.email])
email_message.content_subtype = "html"
email_message.send()
return Response(
{"detail": "A password reset link has been sent successfully."},
status=status.HTTP_200_OK
)
else:
return Response(
{"detail": "No account found with this email address."},
status=status.HTTP_400_BAD_REQUEST
)
class PasswordResetConfirmSerializer(serializers.Serializer):
new_password = serializers.CharField(write_only=True)
class PasswordResetConfirmView(APIView):
permission_classes = [AllowAny]
def post(self, request, temp_token):
# Get the actual uid and token from cache
data = cache.get(temp_token)
if not data:
return Response({"detail": "Invalid or expired link"}, status=status.HTTP_400_BAD_REQUEST)
uidb64 = data['uid']
token = data['token']
serializer = PasswordResetConfirmSerializer(data=request.data)
if serializer.is_valid():
new_password = serializer.validated_data['new_password']
try:
uid = force_str(urlsafe_base64_decode(uidb64))
user = User.objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
return Response({"detail": "Invalid link"}, status=status.HTTP_400_BAD_REQUEST)
if default_token_generator.check_token(user, token):
user.set_password(new_password)
user.save()
cache.delete(temp_token) # Clean up the token after use
return Response({"detail": "Password has been reset successfully."}, status=status.HTTP_200_OK)
else:
return Response({"detail": "Invalid or expired token"}, status=status.HTTP_400_BAD_REQUEST)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)