first commit
This commit is contained in:
0
module_auth/__init__.py
Normal file
0
module_auth/__init__.py
Normal file
3
module_auth/admin.py
Normal file
3
module_auth/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
103
module_auth/api/serializers.py
Normal file
103
module_auth/api/serializers.py
Normal file
@@ -0,0 +1,103 @@
|
||||
from django.contrib.auth.hashers import make_password
|
||||
from rest_framework import serializers
|
||||
from module_iam.models import IAmPrincipal
|
||||
from module_project import constants
|
||||
from django.contrib.auth import authenticate
|
||||
|
||||
# class BasePasswordSerializer(serializers.Serializer):
|
||||
# confirm_password = serializers.CharField(write_only=True, required=True)
|
||||
|
||||
# def validate(self, attrs):
|
||||
# password = attrs.get("password")
|
||||
# confirm_password = attrs.pop("confirm_password")
|
||||
# if password != confirm_password:
|
||||
# raise serializers.ValidationError({'password': constants.PASSWORD_NOT_MATCH})
|
||||
# return super().validate(attrs)
|
||||
|
||||
# def update(self, instance, validate_data):
|
||||
# new_password = validate_data.get("password")
|
||||
# if new_password:
|
||||
# instance.password = make_password(new_password)
|
||||
# instance.save()
|
||||
# return instance
|
||||
|
||||
class RegistrationSerializer(serializers.ModelSerializer):
|
||||
password = serializers.CharField(write_only=True, required=True)
|
||||
confirm_password = serializers.CharField(write_only=True, required=True)
|
||||
|
||||
class Meta:
|
||||
model = IAmPrincipal
|
||||
fields = [
|
||||
"first_name",
|
||||
"email",
|
||||
"phone_no",
|
||||
"password",
|
||||
"confirm_password",
|
||||
"player_id",
|
||||
]
|
||||
|
||||
def validate(self, attrs):
|
||||
email = attrs.get("email")
|
||||
phone_no = attrs.get("phone_no")
|
||||
password = attrs.get("password")
|
||||
confirm_password = attrs.get("confirm_password")
|
||||
|
||||
if password != confirm_password:
|
||||
raise serializers.ValidationError({'password': constants.PASSWORD_NOT_MATCH})
|
||||
|
||||
obj = self.Meta.model.objects.filter(email=email).first()
|
||||
|
||||
if obj:
|
||||
raise serializers.ValidationError({"email": constants.EMAIL_EXISTS})
|
||||
|
||||
return attrs
|
||||
|
||||
def create(self, validated_data):
|
||||
del validated_data['confirm_password']
|
||||
validated_data["username"] = validated_data["email"]
|
||||
validated_data["password"] = make_password(validated_data["password"])
|
||||
principal = self.Meta.model.objects.create(**validated_data)
|
||||
return principal
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
# update prinicpal instance fiedls based on the validation data
|
||||
instance.first_name = validated_data.get("first_name", instance.first_name)
|
||||
instance.email = validated_data.get("email", instance.email)
|
||||
instance.username = validated_data.get("email", instance.email)
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
|
||||
class LoginSerializer(serializers.Serializer):
|
||||
email = serializers.EmailField(write_only=True, required=True)
|
||||
password = serializers.CharField(write_only=True, required=True)
|
||||
player_id = serializers.CharField(write_only=True, required=True)
|
||||
|
||||
class OtpVerificationSerializer(serializers.Serializer):
|
||||
email = serializers.EmailField(write_only=True, required=True)
|
||||
otp = serializers.IntegerField(write_only=True, required=True)
|
||||
|
||||
class PasswordResetSerializer(serializers.ModelSerializer):
|
||||
password = serializers.CharField(write_only=True, required=True)
|
||||
confirm_password = serializers.CharField(write_only=True, required=True)
|
||||
|
||||
class Meta:
|
||||
model = IAmPrincipal
|
||||
fields = [
|
||||
"password",
|
||||
"confirm_password"
|
||||
]
|
||||
|
||||
def validate(self, attrs):
|
||||
password = attrs.get("password")
|
||||
confirm_password = attrs.get("confirm_password")
|
||||
if password != confirm_password:
|
||||
raise serializers.ValidationError({'password': constants.PASSWORD_NOT_MATCH})
|
||||
return super().validate(attrs)
|
||||
|
||||
def update(self, instance, validate_data):
|
||||
new_password = validate_data.get("password")
|
||||
if new_password:
|
||||
instance.password = make_password(new_password)
|
||||
instance.save()
|
||||
return instance
|
||||
16
module_auth/api/urls.py
Normal file
16
module_auth/api/urls.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from django.urls import path
|
||||
from . import views
|
||||
from rest_framework_simplejwt.views import TokenRefreshView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
|
||||
path("signup/", views.RegistrationView.as_view()),
|
||||
path("login/", views.LoginView.as_view()),
|
||||
|
||||
path("request-otp/", views.OtpRequestView.as_view()),
|
||||
path("verify-otp/", views.OTPVerificationView.as_view()),
|
||||
path("forget-password/", views.ForgetPasswordView.as_view()),
|
||||
|
||||
# path("profile/", views.Profile)
|
||||
]
|
||||
183
module_auth/api/utils.py
Normal file
183
module_auth/api/utils.py
Normal file
@@ -0,0 +1,183 @@
|
||||
from typing import Optional
|
||||
from module_project import constants
|
||||
from module_project.utils import ApiResponse
|
||||
from module_iam.models import IAmPrincipal, IAmPrincipalOtp
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
from django.core.exceptions import ValidationError
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def generate_token_and_user_data(principal):
|
||||
"""
|
||||
Generate a token and user data based on an 'IAmPrincipal' object.
|
||||
|
||||
Args:
|
||||
principal (IAmPrincipal): The user object.
|
||||
|
||||
Returns:
|
||||
dict: A dictionary containing token data and user information.
|
||||
"""
|
||||
refresh = RefreshToken.for_user(principal)
|
||||
data = {
|
||||
"access": str(refresh.access_token),
|
||||
"refresh": str(refresh),
|
||||
"first_name": principal.first_name,
|
||||
"phone_no": str(principal.phone_no),
|
||||
"complete": principal.register_complete,
|
||||
}
|
||||
return data
|
||||
|
||||
class AuthService:
|
||||
"""
|
||||
Provides authentication services for IAmPrincipal users.
|
||||
"""
|
||||
|
||||
def __init__(self, principal_model, otp_model=None):
|
||||
self.principal_model = principal_model
|
||||
self.otp_model = otp_model
|
||||
|
||||
def authenticate(self, principal_id: str, otp: Optional[str] = None, password: Optional[str] = None) -> None:
|
||||
"""
|
||||
Authenticates a principal using OTP and/or password.
|
||||
|
||||
Raises:
|
||||
AuthenticationError: If authentication fails.
|
||||
"""
|
||||
try:
|
||||
principal = self.get_principal(principal_id)
|
||||
self.validate_principal_status(principal)
|
||||
self.validate_credentials_provided(otp, password)
|
||||
|
||||
if otp:
|
||||
self.authenticate_with_otp(principal, otp)
|
||||
else:
|
||||
self.authenticate_with_password(principal, password)
|
||||
except ValidationError as e:
|
||||
raise e
|
||||
except Exception as e:
|
||||
logger.error(f"Authentication failed for principal {principal_id}: {str(e)}")
|
||||
raise ValidationError("Authentication failed") from e
|
||||
|
||||
def get_principal(self, principal_id: str) -> IAmPrincipal:
|
||||
"""Retrieves a principal instance by ID."""
|
||||
try:
|
||||
return self.principal_model.objects.get(pk=principal_id)
|
||||
except self.principal_model.DoesNotExist:
|
||||
raise ValidationError("Invalid principal ID")
|
||||
|
||||
def get_principal_by_email(self, email: str):
|
||||
"""Retrieves a principal instance by email."""
|
||||
try:
|
||||
return self.principal_model.objects.get(email=email)
|
||||
except self.principal_model.DoesNotExist:
|
||||
raise ValidationError(constants.EMAIL_NOT_REGISTERED)
|
||||
|
||||
def validate_principal_status(self, principal: IAmPrincipal) -> None:
|
||||
"""Validates that the principal is active."""
|
||||
if not principal.is_active:
|
||||
raise ValidationError(constants.ACCOUNT_DEACTIVATED)
|
||||
|
||||
def validate_credentials_provided(self, otp: Optional[str], password: Optional[str]) -> None:
|
||||
"""Ensures that at least one of OTP or password is provided."""
|
||||
if otp is None and password is None:
|
||||
raise ValidationError(constants.OTP_OR_PASSWORD_REQUIRED)
|
||||
|
||||
def authenticate_with_otp(self, principal: IAmPrincipal, otp: str) -> None:
|
||||
"""Authenticates using OTP."""
|
||||
if self.otp_model is None:
|
||||
raise ValidationError("OTP authentication is not supported")
|
||||
|
||||
otp_instance = self.otp_model.objects.filter(principal=principal, otp_code=otp).last()
|
||||
if not otp_instance:
|
||||
raise ValidationError(constants.OTP_INVALID)
|
||||
|
||||
if otp_instance.is_expired():
|
||||
raise ValidationError(constants.OTP_EXPIRED)
|
||||
|
||||
otp_instance.is_used = True
|
||||
otp_instance.save()
|
||||
|
||||
def authenticate_with_password(self, principal: IAmPrincipal, password: str) -> None:
|
||||
"""Authenticates using password."""
|
||||
if not principal.check_password(password):
|
||||
raise ValidationError(constants.INVALID_PASSWORD)
|
||||
|
||||
|
||||
def authticate_with_otp_and_passsword(principal: IAmPrincipal, otp=None, password=None):
|
||||
"""
|
||||
Authenticate a principal using OTP and/or Password.
|
||||
|
||||
Parameters:
|
||||
- principal (User): The principal object to authenticate.
|
||||
- otp (str, optional): One-Time Password (OTP). Default is None.
|
||||
- password (str, optional): User's password. Default is None.
|
||||
|
||||
Returns:
|
||||
None: Successful authentication.
|
||||
Response: Error response if authentication fails.
|
||||
|
||||
Example:
|
||||
```
|
||||
principal = User.objects.get(phone_no='8987546598')
|
||||
otp = request.data.get("otp")
|
||||
password = request.data.get("password")
|
||||
|
||||
result = authenticate_with_otp_and_password(principal, otp, password)
|
||||
if isinstance(result, Response):
|
||||
return result # Authentication failed, return error response
|
||||
else:
|
||||
# Authentication successful, proceed with authorized actions.
|
||||
```
|
||||
"""
|
||||
|
||||
if not principal.is_active:
|
||||
return ApiResponse.error(
|
||||
message=constants.ACCOUNT_DEACTIVATED, errors=constants.ACCOUNT_DEACTIVATED
|
||||
)
|
||||
|
||||
# Ensure that either OTP or password is provided
|
||||
if otp is None and password is None:
|
||||
return ApiResponse.error(
|
||||
message=constants.OTP_OR_PASSWORD_REQUIRED, errors=constants.OTP_OR_PASSWORD_REQUIRED
|
||||
)
|
||||
|
||||
if otp:
|
||||
otp_instance = IAmPrincipalOtp.objects.filter(
|
||||
principal=principal, otp_code=otp
|
||||
).last()
|
||||
|
||||
if not otp_instance:
|
||||
return ApiResponse.error(
|
||||
message=constants.OTP_INVALID, errors=constants.OTP_INVALID
|
||||
)
|
||||
|
||||
if otp_instance.is_expired():
|
||||
return ApiResponse.error(
|
||||
message=constants.OTP_EXPIRED, errors=constants.OTP_EXPIRED
|
||||
)
|
||||
|
||||
otp_instance.is_used = True
|
||||
otp_instance.save()
|
||||
|
||||
elif password:
|
||||
print(password)
|
||||
if not principal.check_password(password):
|
||||
return ApiResponse.error(
|
||||
message=constants.INVALID_PASSWORD, errors=constants.INVALID_PASSWORD
|
||||
)
|
||||
print("after passsowrd", password)
|
||||
|
||||
return None
|
||||
|
||||
def get_principal_by_email(email: str):
|
||||
try:
|
||||
principal = IAmPrincipal.objects.get(email=email)
|
||||
return principal
|
||||
except IAmPrincipal.DoesNotExist:
|
||||
error_response = {
|
||||
"message": constants.EMAIL_NOT_REGISTERED,
|
||||
"errors": constants.EMAIL_NOT_REGISTERED,
|
||||
}
|
||||
return ApiResponse.error(**error_response)
|
||||
217
module_auth/api/views.py
Normal file
217
module_auth/api/views.py
Normal file
@@ -0,0 +1,217 @@
|
||||
import datetime
|
||||
from rest_framework import status
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||||
from module_project import constants
|
||||
from module_project.service import SMSService, EmailService
|
||||
from module_project.utils import ApiResponse
|
||||
from .utils import AuthService
|
||||
from module_iam.models import IAmPrincipal, IAmPrincipalOtp
|
||||
from .serializers import RegistrationSerializer, LoginSerializer, OtpVerificationSerializer, PasswordResetSerializer
|
||||
from django.conf import settings
|
||||
from rest_framework.response import Response
|
||||
|
||||
from .utils import (
|
||||
generate_token_and_user_data, get_principal_by_email, authticate_with_otp_and_passsword
|
||||
)
|
||||
|
||||
|
||||
class RegistrationView(APIView):
|
||||
authentication_classes = []
|
||||
permission_classes = []
|
||||
model = IAmPrincipal
|
||||
serializer_class = RegistrationSerializer
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
print(f"request data is {request.data}")
|
||||
if not serializer.is_valid():
|
||||
error_response = {
|
||||
"status": status.HTTP_403_FORBIDDEN,
|
||||
"message": constants.REGISTRATION_FAIL,
|
||||
"errors": serializer.errors,
|
||||
}
|
||||
return ApiResponse.error(**error_response)
|
||||
|
||||
try:
|
||||
instance = serializer.save()
|
||||
principal = instance
|
||||
token_data = generate_token_and_user_data(principal)
|
||||
except Exception as e:
|
||||
return ApiResponse.error(
|
||||
status=status.HTTP_403_FORBIDDEN, message=str(e), errors=str(e)
|
||||
)
|
||||
|
||||
return ApiResponse.success(message=constants.REGISTRATION_SUCCESS, data=token_data)
|
||||
|
||||
|
||||
class LoginView(APIView):
|
||||
authentication_classes = []
|
||||
permission_classes = []
|
||||
model = IAmPrincipal
|
||||
serializer_class = LoginSerializer
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if not serializer.is_valid():
|
||||
error_response = {
|
||||
"status": status.HTTP_403_FORBIDDEN,
|
||||
"message": constants.LOGIN_FAIL,
|
||||
"errors": serializer.errors,
|
||||
}
|
||||
return ApiResponse.error(**error_response)
|
||||
|
||||
email = request.data.get("email")
|
||||
otp = request.data.get("otp")
|
||||
password = request.data.get("password")
|
||||
player_id = request.data.get("player_id")
|
||||
|
||||
principal = get_principal_by_email(email=email)
|
||||
|
||||
if isinstance(principal, Response):
|
||||
return principal
|
||||
|
||||
validation_result = authticate_with_otp_and_passsword(
|
||||
principal, otp=otp, password=password
|
||||
)
|
||||
print("pasword instance ", validation_result)
|
||||
|
||||
if isinstance(validation_result, Response):
|
||||
print("Errror reponse")
|
||||
return validation_result # Return the error response if validation fails
|
||||
|
||||
|
||||
# auth_service = AuthService(principal_model=IAmPrincipal)
|
||||
|
||||
# try:
|
||||
# principal = self.model.objects.get(email=email)
|
||||
# except Exception as e:
|
||||
# error_response = {
|
||||
# "status": status.HTTP_403_FORBIDDEN,
|
||||
# "message": constants.INVALID_EMAIL_PASSWORD,
|
||||
# "errors": constants.INVALID_EMAIL_PASSWORD,
|
||||
# }
|
||||
# return ApiResponse.error(**error_response)
|
||||
|
||||
# try:
|
||||
# auth_service.authenticate(principal_id=principal.id, password=password)
|
||||
# except Exception as e:
|
||||
# error_response = {
|
||||
# "status": status.HTTP_403_FORBIDDEN,
|
||||
# "message": e,
|
||||
# "errors": e,
|
||||
# }
|
||||
# return ApiResponse.error(**error_response)
|
||||
|
||||
try:
|
||||
principal.player_id = player_id
|
||||
principal.last_login = datetime.datetime.now()
|
||||
principal.save()
|
||||
except Exception as e:
|
||||
error_response = {
|
||||
"status": status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
"message": constants.INTERNAL_SERVER_ERROR,
|
||||
"errors": str(e),
|
||||
}
|
||||
return ApiResponse.error(**error_response)
|
||||
|
||||
token_data = generate_token_and_user_data(principal)
|
||||
return ApiResponse.success(message=constants.LOGIN_SUCCESS, data=token_data)
|
||||
|
||||
|
||||
class OtpRequestView(APIView):
|
||||
authentication_classes = []
|
||||
permission_classes = []
|
||||
|
||||
def post(self, request):
|
||||
if "email" not in request.data:
|
||||
return ApiResponse.error(message=constants.EMAIL_REQUIRED, errors=constants.EMAIL_REQUIRED)
|
||||
print(f"email auth username: {settings.EMAIL_HOST_USER}")
|
||||
email = request.data.get("email")
|
||||
|
||||
principal = get_principal_by_email(email=email)
|
||||
|
||||
if isinstance(principal, Response):
|
||||
return principal
|
||||
|
||||
try:
|
||||
# auth_service = AuthService(IAmPrincipal)
|
||||
# principal = auth_service.get_principal_by_email(request.data.get("email"))
|
||||
|
||||
otp_code = SMSService().create_otp(principal=principal, otp_purpose="Forget password")
|
||||
|
||||
except Exception as e:
|
||||
return ApiResponse.error(message=str(e), errors=str(e))
|
||||
|
||||
email_service = EmailService(
|
||||
subject="Forget Password",
|
||||
to=principal.email,
|
||||
from_email=settings.EMAIL_HOST_USER
|
||||
)
|
||||
|
||||
# Send the email
|
||||
try:
|
||||
email_service.load_template("module_auth/email_template.html", context={"code": otp_code} )
|
||||
email_service.send()
|
||||
except Exception as e:
|
||||
return ApiResponse.error(message=f"Error sending email: {str(e)}", errors=str(e))
|
||||
|
||||
return ApiResponse.success(message=constants.SUCCESS)
|
||||
|
||||
class OTPVerificationView(APIView):
|
||||
authentication_classes = []
|
||||
permission_classes = []
|
||||
serializer_class = OtpVerificationSerializer
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if not serializer.is_valid():
|
||||
error_response = {
|
||||
"status": status.HTTP_403_FORBIDDEN,
|
||||
"message": constants.VALIDATION_ERROR,
|
||||
"errors": serializer.errors,
|
||||
}
|
||||
return ApiResponse.error(**error_response)
|
||||
|
||||
email = serializer.validated_data.get("email")
|
||||
otp = serializer.validated_data.get("otp")
|
||||
|
||||
principal = get_principal_by_email(email=email)
|
||||
|
||||
if isinstance(principal, Response):
|
||||
return principal
|
||||
|
||||
validation_result = authticate_with_otp_and_passsword(
|
||||
principal, otp=otp
|
||||
)
|
||||
print("pasword instance ", validation_result)
|
||||
|
||||
if isinstance(validation_result, Response):
|
||||
print("Errror reponse")
|
||||
return validation_result # Return the error response if validation fails
|
||||
|
||||
token_data = generate_token_and_user_data(principal)
|
||||
return ApiResponse.success(message=constants.SUCCESS, data=token_data)
|
||||
|
||||
class ForgetPasswordView(APIView):
|
||||
authentication_classes = [JWTAuthentication]
|
||||
permission_classes = [IsAuthenticated]
|
||||
serializer_class = PasswordResetSerializer
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.serializer_class(request.user, data=request.data)
|
||||
if not serializer.is_valid():
|
||||
error_response = {
|
||||
"status": status.HTTP_403_FORBIDDEN,
|
||||
"message": constants.VALIDATION_ERROR,
|
||||
"errors": serializer.errors,
|
||||
}
|
||||
return ApiResponse.error(**error_response)
|
||||
|
||||
try:
|
||||
serializer.save()
|
||||
except Exception as e:
|
||||
return ApiResponse.error(message=str(e), errors=str(e))
|
||||
|
||||
return ApiResponse.success(message=constants.SUCCESS)
|
||||
6
module_auth/apps.py
Normal file
6
module_auth/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ModuleAuthConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'module_auth'
|
||||
15
module_auth/forms.py
Normal file
15
module_auth/forms.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from django import forms
|
||||
from django.core import validators
|
||||
from module_project import constants
|
||||
|
||||
class LoginForm(forms.Form):
|
||||
email = forms.EmailField(
|
||||
max_length=254,
|
||||
widget=forms.TextInput(attrs={"autofocus": True}),
|
||||
label="Email",
|
||||
)
|
||||
password = forms.CharField(
|
||||
label="Password",
|
||||
strip=False,
|
||||
widget=forms.PasswordInput()
|
||||
)
|
||||
0
module_auth/migrations/__init__.py
Normal file
0
module_auth/migrations/__init__.py
Normal file
3
module_auth/models.py
Normal file
3
module_auth/models.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
3
module_auth/tests.py
Normal file
3
module_auth/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
17
module_auth/urls.py
Normal file
17
module_auth/urls.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
app_name = "module_auth"
|
||||
|
||||
urlpatterns = [
|
||||
path('login/', views.AdminLoginView.as_view(), name="login"),
|
||||
path('logout/', views.AdminLogoutView.as_view(), name="logout"),
|
||||
path('password-reset/', views.CustomPasswordResetView.as_view(), name='password_reset'),
|
||||
path('password-reset/done/', views.CustomPasswordResetDoneView.as_view(), name='password_reset_done'),
|
||||
path('password-reset-confirm/<uidb64>/<token>/', views.CustomPasswordResetConfirmView.as_view(), name='password_reset_confirm'),
|
||||
path('password-reset-complete/', views.CustomPasswordResetCompleteView.as_view(), name='password_reset_complete'),
|
||||
path('users/', views.UserDashView.as_view(), name='users'),
|
||||
path('users/list/', views.UserListJson.as_view(), name='users_list'),
|
||||
path('user/view/<int:id>/', views.UserRecordView.as_view(), name='user_view'),
|
||||
|
||||
]
|
||||
203
module_auth/views.py
Normal file
203
module_auth/views.py
Normal file
@@ -0,0 +1,203 @@
|
||||
import logging
|
||||
|
||||
from django.db.models import Q, Prefetch
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from django.contrib.auth.views import LogoutView
|
||||
from django.contrib.auth.forms import PasswordResetForm
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.views import (
|
||||
LoginView,
|
||||
PasswordResetCompleteView,
|
||||
PasswordResetConfirmView,
|
||||
PasswordResetDoneView,
|
||||
PasswordResetView,
|
||||
)
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.urls import reverse_lazy
|
||||
from django.views import generic
|
||||
from .forms import LoginForm
|
||||
from module_iam.models import IAmPrincipal
|
||||
from module_activity.models import PrincipalHealthData, Intolerance, Symptoms, PastTreatment, ChronicCondition
|
||||
from django_datatables_view.base_datatable_view import BaseDatatableView
|
||||
|
||||
from module_project import constants
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class AdminLoginView(generic.View):
|
||||
template_name = "module_auth/login.html"
|
||||
form_class = LoginForm
|
||||
success_url = reverse_lazy("module_iam:dashboard")
|
||||
error_url = reverse_lazy("module_auth:login")
|
||||
success_message = constants.LOGIN_SUCCESS
|
||||
error_message = constants.INVALID_EMAIL_PASSWORD
|
||||
|
||||
def get(self, request):
|
||||
form = self.form_class()
|
||||
|
||||
return render(request, self.template_name, context={"form": form})
|
||||
|
||||
def post(self, request):
|
||||
form = self.form_class(data=request.POST)
|
||||
context = {"form": form}
|
||||
if not form.is_valid():
|
||||
messages.error(request, constants.INVALID_EMAIL_PASSWORD)
|
||||
return render(request, self.template_name, context=context)
|
||||
|
||||
email = form.cleaned_data['email']
|
||||
password = form.cleaned_data['password']
|
||||
|
||||
user = authenticate(request, email=email, password=password)
|
||||
if user is None:
|
||||
messages.error(request, constants.INVALID_EMAIL_PASSWORD)
|
||||
return render(request, self.template_name, context=context)
|
||||
|
||||
login(request, user)
|
||||
logging.info(f"User {user.email} logged in.")
|
||||
|
||||
return redirect(self.success_url)
|
||||
|
||||
|
||||
class AdminLogoutView(LogoutView):
|
||||
next_page = reverse_lazy("module_auth:login")
|
||||
|
||||
class CustomPasswordResetView(PasswordResetView):
|
||||
form_class = PasswordResetForm
|
||||
template_name = "module_auth/password_reset_form.html"
|
||||
email_template_name = "module_auth/password_reset_email_template.html"
|
||||
success_url = reverse_lazy("module_auth:password_reset_done")
|
||||
|
||||
|
||||
class CustomPasswordResetDoneView(PasswordResetDoneView):
|
||||
template_name = "module_auth/password_reset_done.html"
|
||||
|
||||
|
||||
class UserDashView(LoginRequiredMixin, generic.TemplateView):
|
||||
page_name = None
|
||||
resource = None
|
||||
action = None
|
||||
template_name = "module_auth/users_list.html"
|
||||
model = IAmPrincipal
|
||||
context_objext_name = "obj"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["page_name"] = self.page_name
|
||||
return context
|
||||
|
||||
|
||||
class UserListJson(BaseDatatableView):
|
||||
model = IAmPrincipal
|
||||
columns = ["id", "first_name", "email", "phone_no", "date_of_birth", "is_active"]
|
||||
order_columns = ["id", "first_name", "email", "phone_no", "date_of_birth", "is_active"]
|
||||
|
||||
def filter_queryset(self, qs):
|
||||
print(f"request is {self.request.GET}")
|
||||
search_value = self.request.GET.get("search[value]", None)
|
||||
if search_value:
|
||||
# print(f"isdiget {search_value.isdigit()}")
|
||||
# if search_value.isdigit():
|
||||
# qs = qs.filter(Q(id=search_value))
|
||||
|
||||
qs = qs.filter(
|
||||
Q(id__icontains=search_value)
|
||||
| Q(first_name__icontains=search_value)
|
||||
| Q(email__icontains=search_value)
|
||||
| Q(date_of_birth__icontains=search_value)
|
||||
| Q(phone_no__icontains=search_value)
|
||||
)
|
||||
|
||||
for column in self.columns:
|
||||
search_value = self.request.GET.get(f'columns[{self.columns.index(column)}][search][value]', None)
|
||||
if search_value:
|
||||
qs = qs.filter(**{f"{column}__icontains": search_value})
|
||||
|
||||
return qs
|
||||
|
||||
|
||||
class UserRecordView(LoginRequiredMixin, generic.View):
|
||||
page_name = None
|
||||
resource = None
|
||||
action = None
|
||||
model = IAmPrincipal
|
||||
template_name = "module_auth/user_view.html"
|
||||
|
||||
def get(self, request, id):
|
||||
# Retrieve the IAmPrincipal instance
|
||||
principal_instance = get_object_or_404(IAmPrincipal, id=id)
|
||||
|
||||
# Prefetch related Intolerance objects for the principal
|
||||
intolerance_prefetch = Prefetch(
|
||||
"intolerance_principal",
|
||||
queryset=Intolerance.objects.filter(principal=principal_instance),
|
||||
to_attr="intolerance_data",
|
||||
)
|
||||
|
||||
symptom_prefetch = Prefetch(
|
||||
"symptoms_principal",
|
||||
queryset=Symptoms.objects.filter(principal=principal_instance),
|
||||
to_attr="symptoms_data",
|
||||
)
|
||||
|
||||
pasttreatment_prefetch = Prefetch(
|
||||
"pasttreatment_principal",
|
||||
queryset=PastTreatment.objects.filter(principal=principal_instance),
|
||||
to_attr="pasttreatment_data",
|
||||
)
|
||||
|
||||
chronic_prefetch = Prefetch(
|
||||
"chronic_principal",
|
||||
queryset=ChronicCondition.objects.filter(principal=principal_instance),
|
||||
to_attr="chronic_data",
|
||||
)
|
||||
|
||||
# Now fetch the principal instance with prefetches
|
||||
obj = IAmPrincipal.objects.prefetch_related(
|
||||
intolerance_prefetch,
|
||||
symptom_prefetch,
|
||||
pasttreatment_prefetch,
|
||||
chronic_prefetch
|
||||
).get(id=id)
|
||||
|
||||
print(f"prefetch datatas")
|
||||
for data in obj.chronic_data:
|
||||
print(f"data is {data.name, data.duration}")
|
||||
|
||||
# Render the template with the principal instance and related data
|
||||
return render(request, self.template_name, {'obj': obj})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class CustomPasswordResetConfirmView(PasswordResetConfirmView):
|
||||
template_name = "module_auth/password_reset_confirm.html"
|
||||
success_url = reverse_lazy("module_auth:password_reset_complete")
|
||||
|
||||
|
||||
class CustomPasswordResetCompleteView(PasswordResetCompleteView):
|
||||
template_name = "module_auth/password_reset_complete.html"
|
||||
Reference in New Issue
Block a user