base setup
This commit is contained in:
273
at_django_boilerplate/accounts/api/v1.py
Executable file
273
at_django_boilerplate/accounts/api/v1.py
Executable file
@@ -0,0 +1,273 @@
|
||||
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from rest_framework.authtoken.models import Token
|
||||
from django.contrib.auth import authenticate
|
||||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
||||
from rest_framework.authentication import TokenAuthentication
|
||||
|
||||
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
|
||||
|
||||
from django.contrib.auth.tokens import default_token_generator
|
||||
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from rest_framework.authtoken.models import Token
|
||||
from django.contrib.auth import authenticate
|
||||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
||||
from rest_framework.authentication import TokenAuthentication
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
from django.core.mail import send_mail
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.html import strip_tags
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import password_validation
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from at_django_boilerplate.accounts.models import CustomUser
|
||||
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LoginApiView(APIView):
|
||||
permission_classes = [AllowAny] # This makes the endpoint open to all users
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
# Get the username and password from the request data
|
||||
username = request.data.get('username')
|
||||
password = request.data.get('password')
|
||||
|
||||
if not username or not password:
|
||||
return Response({"message": "Both username and password are required."}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
# Authenticate the user
|
||||
user = authenticate(username=username, password=password)
|
||||
if user is not None:
|
||||
# User is authenticated, generate token
|
||||
token, created = Token.objects.get_or_create(user=user)
|
||||
# You can retrieve the user's role or permission-based data here
|
||||
if user.is_superuser:
|
||||
role = "admin"
|
||||
elif user.get_manager():
|
||||
role = "manager"
|
||||
elif user.get_technician():
|
||||
role = "technician"
|
||||
else:
|
||||
role = "customer"
|
||||
|
||||
return Response({
|
||||
"token": token.key,
|
||||
"role": role,
|
||||
"userId": user.id,
|
||||
"username": f"{user.first_name} {user.last_name}",
|
||||
"profile_photo": user.profile_photo.url if user.profile_photo.url else None,
|
||||
"message": "Login successful"
|
||||
}, status=status.HTTP_200_OK)
|
||||
|
||||
# Invalid credentials
|
||||
return Response({"message": "Invalid username or password."}, status=status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
|
||||
class ValidatePasswordAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
authentication_classes = [TokenAuthentication]
|
||||
def post(self, request):
|
||||
password = request.data.get('password')
|
||||
if not password:
|
||||
return Response({"success": False, "message": "Password is required."}, status=400)
|
||||
user = request.user
|
||||
if user.check_password(password):
|
||||
return Response({"success": True, "message": "Password is valid."}, status=200)
|
||||
return Response({"success": False, "message": "Password is incorrect."}, status=400)
|
||||
|
||||
|
||||
class ResetPasswordAPIView(APIView):
|
||||
def post(self, request):
|
||||
# Get the email from the request data
|
||||
email = request.data.get('email')
|
||||
|
||||
# Ensure the email is provided
|
||||
if not email:
|
||||
return Response({"success": False, "message": "Email address is required."}, status=400)
|
||||
|
||||
try:
|
||||
# Check if the user exists in the database
|
||||
user = CustomUser.objects.get(email=email)
|
||||
except CustomUser.DoesNotExist:
|
||||
return Response({"success": False, "message": "User with this email does not exist."}, status=404)
|
||||
|
||||
# Send the password reset email
|
||||
if self.send_reset_email(request, user, email):
|
||||
return Response({"success": True, "message": "Please check your email to reset your password."}, status=200)
|
||||
else:
|
||||
return Response({"success": False, "message": "Failed to send email. Please try again later."}, status=500)
|
||||
|
||||
|
||||
def send_reset_email(self, request, user, email):
|
||||
# Generate a password reset token
|
||||
token = default_token_generator.make_token(user)
|
||||
|
||||
# Convert user.pk (integer) to string and then encode it to base64
|
||||
uid = urlsafe_base64_encode(str(user.pk).encode('utf-8')) # Encode user ID to base64 string
|
||||
|
||||
# Prepare the context for the email template
|
||||
context = {
|
||||
'user': user,
|
||||
'reset_link': f"http://localhost:3000/reset-password/{uid}/{token}/" # Update the URL if needed (to your front-end)
|
||||
}
|
||||
|
||||
# Render the HTML email template with the context
|
||||
html_message = render_to_string('email_template.html', context)
|
||||
|
||||
# Subject of the email
|
||||
subject = "Password Reset Request"
|
||||
|
||||
# Strip HTML tags for the plain-text version of the email
|
||||
message = strip_tags(html_message)
|
||||
|
||||
# From email and recipient list
|
||||
from_email = settings.DEFAULT_FROM_EMAIL
|
||||
recipient_list = [email]
|
||||
|
||||
try:
|
||||
# Send the email
|
||||
send_mail(subject, message, from_email, recipient_list, html_message=html_message)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error sending email: {str(e)}")
|
||||
return False
|
||||
|
||||
class ResetPasswordConfirmAPIView(APIView):
|
||||
def get(self, request, uidb64, token):
|
||||
try:
|
||||
# Decode the user ID from base64
|
||||
uid = urlsafe_base64_decode(uidb64).decode('utf-8')
|
||||
user = CustomUser.objects.get(pk=uid)
|
||||
|
||||
# Check if the token is valid
|
||||
if default_token_generator.check_token(user, token):
|
||||
return Response(
|
||||
{"success": True, "message": "Token is valid."},
|
||||
status=status.HTTP_200_OK
|
||||
)
|
||||
else:
|
||||
return Response(
|
||||
{"success": False, "message": "Invalid or expired token."},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
except (TypeError, ValueError, OverflowError, CustomUser.DoesNotExist):
|
||||
return Response(
|
||||
{"success": False, "message": "Invalid or expired token."},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
def post(self, request, uidb64, token):
|
||||
password = request.data.get('password')
|
||||
|
||||
if not password:
|
||||
return Response(
|
||||
{"success": False, "message": "Password is required."},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
try:
|
||||
# Decode the user ID from base64
|
||||
uid = urlsafe_base64_decode(uidb64).decode('utf-8')
|
||||
user = CustomUser.objects.get(pk=uid)
|
||||
except (TypeError, ValueError, OverflowError, CustomUser.DoesNotExist):
|
||||
return Response(
|
||||
{"success": False, "message": "Invalid user ID."},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
try:
|
||||
password_validation.validate_password(password=password)
|
||||
except ValidationError as e:
|
||||
return Response(
|
||||
{"success": False, "message": str(e)},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
# Validate the token
|
||||
if default_token_generator.check_token(user, token):
|
||||
# Set and save the new password
|
||||
user.set_password(password)
|
||||
user.save()
|
||||
return Response(
|
||||
{"success": True, "message": "Password has been reset successfully."},
|
||||
status=status.HTTP_200_OK
|
||||
)
|
||||
else:
|
||||
return Response(
|
||||
{"success": False, "message": "Invalid or expired token."},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
|
||||
class UserProfileView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
authentication_classes = [TokenAuthentication]
|
||||
|
||||
def get(self, request):
|
||||
user = request.user
|
||||
|
||||
if user.is_superuser:
|
||||
print('Is Superuser')
|
||||
users = CustomUser.objects.all()
|
||||
data = [
|
||||
{
|
||||
'id': u.id,
|
||||
'email': u.email,
|
||||
'first_name': u.first_name,
|
||||
'last_name': u.last_name,
|
||||
}
|
||||
for u in users
|
||||
]
|
||||
|
||||
elif user.is_manager: # Manager user only sees their own utility's data
|
||||
utility = user.get_utility() # Get Utility
|
||||
users = utility.accounts_in_utility.all()
|
||||
|
||||
data = [{
|
||||
'id': user.id,
|
||||
'email': user.email,
|
||||
'first_name': user.first_name,
|
||||
'last_name': user.last_name,
|
||||
'utility': str(utility)
|
||||
}
|
||||
for u in users
|
||||
]
|
||||
|
||||
elif user.is_technician:
|
||||
utility = user.get_utility() # Get Utility
|
||||
users = utility.accounts_in_utility.all()
|
||||
|
||||
data = [{
|
||||
'id': u.id,
|
||||
'email': u.email,
|
||||
'first_name': u.first_name,
|
||||
'last_name': u.last_name,
|
||||
'utility': str(utility)
|
||||
}
|
||||
for u in users if not u.is_manager and not u.is_superuser
|
||||
]
|
||||
|
||||
elif user.is_customer:
|
||||
utility = user.get_utility() # Get Utility
|
||||
data = [{
|
||||
'id': user.id,
|
||||
'email': user.email,
|
||||
'first_name': user.first_name,
|
||||
'last_name': user.last_name,
|
||||
'utility': str(utility)
|
||||
}]
|
||||
|
||||
else:
|
||||
data = None
|
||||
|
||||
return Response(data, status=status.HTTP_200_OK)
|
||||
Reference in New Issue
Block a user