Files
goodtimes/accounts/views.py
2024-04-10 12:57:44 +05:30

679 lines
24 KiB
Python

import logging
from django.db.models import Count, Q
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.core.exceptions import ValidationError
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse_lazy
from django.views import generic
from django.db import models, transaction, IntegrityError
from django.utils import timezone
from accounts import permission
from goodtimes import constants
from . import resource_action
from .forms import (
CustomAuthenticationForm,
IAmPrincipalForm,
IAmPrincipalGroupRoleLinkForm,
IAmPrincipalResourceLinkForm,
IAmPrincipalRoleAppResourceActionLinkForm,
IAmPrincipalGroupLinkForm,
ProfileEditForm,
)
from .models import (
IAmPrincipal,
IAmPrincipalType,
IAmAppResourceActionLink,
IAmPrincipalGroup,
IAmRole,
)
logger = logging.getLogger(__name__)
class AdminLoginView(generic.View):
form_class = CustomAuthenticationForm
template_name = "accounts/authentication/login.html"
success_url = reverse_lazy("dashboard:main_dashboard")
error_url = reverse_lazy("accounts:login")
success_message = constants.LOGIN_SUCCESS
error_message = "Login failed, Invalid email or 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)
if not form.is_valid():
error_message = form.errors.get("__all__") or ["Invalid email or password."]
messages.error(
request, error_message[0]
) # Display the form-level error or fallback message
return redirect(self.error_url)
# Uncomment this block if you implement the first-time login logic
# if not user.last_login:
# messages.info(request, "Welcome! Since this is your first login, please change your password.")
# return redirect(reverse_lazy('accounts:change_password'))
login(request, form.user)
return redirect(self.success_url)
class AdminLogoutView(LogoutView):
next_page = reverse_lazy("accounts:login")
class CustomPasswordResetView(PasswordResetView):
form_class = PasswordResetForm
template_name = "accounts/authentication/password_reset_form.html"
email_template_name = "accounts/authentication/password_reset_email_template.html"
success_url = reverse_lazy("accounts:password_reset_done")
class CustomPasswordResetDoneView(PasswordResetDoneView):
template_name = "accounts/authentication/password_reset_done.html"
class CustomPasswordResetConfirmView(PasswordResetConfirmView):
template_name = "accounts/authentication/password_reset_confirm.html"
success_url = reverse_lazy("accounts:password_reset_complete")
class CustomPasswordResetCompleteView(PasswordResetCompleteView):
template_name = "accounts/authentication/password_reset_complete.html"
# class PrinicpalCreateView(generic.View):
# model = IAmPrincipal
# form_class = RegistrationForm
# template_name = "registration/form.html"
# title = "Add Sub admin"
# success_message = constants.RECORD_CREATED
# error_message = constants.ERROR_OCCURR
# success_url = reverse_lazy("accounts:register")
# def get_context_data(self, **kwargs):
# context = {"title": self.title, "operation": "Add"}
# context.update(kwargs)
# return context
# def get(self, *args, **kwargs):
# form = self.form_class()
# context = self.get_context_data(form=form)
# return render(self.request, self.template_name, context=context)
# def post(self, *args, **kwargs):
# form = self.form_class(self.request.POST)
# if not form.is_valid():
# messages.error(self.request, self.error_message)
# context = self.get_context_data(form=form)
# return render(self.request, self.template_name, context=context)
# form.save()
# messages.success(self.request, self.success_message)
# return redirect(self.success_url)
# template_name = "registration/password_reset_complete.html"
class AdminDashboard(generic.View):
template_name = "dashboard/index.html"
def get(self, request):
return render(request, self.template_name)
"""I Am Principal"""
class PrincipalListView(LoginRequiredMixin, generic.ListView):
page_name = resource_action.RESOURCE_IAM_PRINCIPAL
# resource = resource_action.RESOURCE_IAM_PRINCIPAL
# action = resource_action.ACTION_READ
model = IAmPrincipal
template_name = "accounts/iam_module/iam_principal_list.html"
context_object_name = "data_obj"
def get_queryset(self):
return (
super()
.get_queryset()
.select_related("principal_type", "principal_source")
.exclude(
models.Q(
principal_type__name=resource_action.PRINCIPAL_TYPE_EVENT_MANAGER
)
| models.Q(
principal_type__name=resource_action.PRINCIPAL_TYPE_EVENT_USER
)
| models.Q(
principal_type__name=resource_action.PRINCIPAL_TYPE_FREE_USER
)
)
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
import datetime
class PrincipalCreateOrUpdateView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_PRINCIPAL
model = IAmPrincipal
form_class = IAmPrincipalForm
template_name = "accounts/iam_module/iam_principal_add.html"
success_url = reverse_lazy("accounts:principal_list")
success_message = "Saved Successfully"
error_message = "An error occurred while saving the data."
def get_object(self):
pk = self.kwargs.get("pk")
return get_object_or_404(self.model, pk=pk) if pk else None
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Edit" if self.object else "Add",
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
@transaction.atomic
def post(self, request, *args, **kwargs):
print(request.POST)
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object)
try:
if form.is_valid():
principal = form.save(commit=False)
# Check if it's a new object (create action) or an existing one (update action)
if not principal.pk: # pk is None for new objects
principal.created_by = request.user
principal.modified_by = request.user
principal.modified_on = timezone.now()
# Save the object
principal.save()
messages.success(request, "Form submitted successfully")
return redirect(self.success_url)
except Exception as e:
self.error_message = constants.ERROR_OCCURR.format(str(e))
print(self.error_message)
messages.error(request, self.error_message)
context = self.get_context_data(form=form)
return render(request, template_name=self.template_name, context=context)
class PrincipalResourcePermissionEditView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_PRINCIPAL
resource = resource_action.RESOURCE_IAM_PRINCIPAL_GROUP
model = IAmPrincipal
template_name = "accounts/iam_module/iam_principal_resource_permission_edit.html"
form_class = IAmPrincipalResourceLinkForm
success_url = reverse_lazy("accounts:principal_group_link_list")
success_message = "Record Updated Successfully"
error_message = "An error occurred while saving the data"
def get_object(self):
pk = self.kwargs.get("pk")
return get_object_or_404(self.model, pk=pk) if pk else None
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Edit",
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object)
if not form.is_valid():
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(request, self.success_message)
return redirect(self.success_url)
"""Principal Group Link"""
class PrincipalGroupLinkListView(LoginRequiredMixin, generic.ListView):
page_name = resource_action.RESOURCE_IAM_PRINCIPAL_GROUP
model = IAmPrincipal
template_name = "accounts/iam_module/iam_principal_group_link_list.html"
context_object_name = "data_obj"
def get_queryset(self):
return (
super()
.get_queryset()
.select_related("principal_type", "principal_source")
.prefetch_related("principal_group")
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
context["admin_principal"] = self.get_queryset().filter(
principal_type__name=resource_action.PRINCIPAL_TYPE_ADMIN, is_active=True
)
context["subadmin_principal"] = self.get_queryset().filter(
principal_type__name=resource_action.PRINCIPAL_TYPE_SUBADMIN, is_active=True
)
print(context["subadmin_principal"])
return context
class PrincipalGroupLinkEditView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_PRINCIPAL_GROUP
model = IAmPrincipal
template_name = "accounts/iam_module/iam_principal_group_link_edit.html"
form_class = IAmPrincipalGroupLinkForm
success_url = reverse_lazy("accounts:principal_group_link_list")
success_message = "Record Updated Successfully"
error_message = "An error occurred while saving the data"
def get_object(self):
pk = self.kwargs.get("pk")
return get_object_or_404(self.model, pk=pk) if pk else None
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Edit",
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object)
if not form.is_valid():
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(request, self.success_message)
return redirect(self.success_url)
"""Principal Group"""
class PrincipalGroupListView(LoginRequiredMixin, generic.ListView):
page_name = resource_action.RESOURCE_IAM_GROUP
model = IAmPrincipalGroup
template_name = "accounts/iam_module/iam_group_list.html"
context_object_name = "data_obj"
def get_queryset(self):
return super().get_queryset().prefetch_related("role").filter(deleted=False)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
class PrincipalGroupCreateOrUpdateView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_GROUP
page_title = "Principal Group"
model = IAmPrincipalGroup
template_name = "accounts/iam_module/iam_group_add.html"
form_class = IAmPrincipalGroupRoleLinkForm
success_url = reverse_lazy("accounts:principal_group_list")
error_message = "An error occurred while saving the data."
def get_success_message(self):
self.success_message = (
constants.RECORD_CREATED if not self.object else constants.RECORD_UPDATED
)
return self.success_message
def get_object(self):
pk = self.kwargs.get("pk")
return get_object_or_404(self.model, pk=pk) if pk else None
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Add" if not self.object else "Edit",
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object)
if not form.is_valid():
print(form.errors)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(self.request, self.get_success_message())
return redirect(self.success_url)
class PrincipalGroupDeleteView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_GROUP
model = IAmPrincipalGroup
success_url = reverse_lazy("accounts:principal_group_list")
success_message = constants.RECORD_DELETED
error_message = constants.RECORD_NOT_FOUND
def get(self, request, pk):
try:
type_obj = self.model.objects.get(id=pk)
principal = IAmPrincipal.objects.filter(principal_group=type_obj).exists()
if principal:
messages.success(
request,
"You can't delete this record as it's assigned to principals.",
)
else:
type_obj.deleted = True
type_obj.save()
messages.success(request, self.success_message)
except self.model.DoesNotExist:
messages.success(request, self.error_message)
return redirect(self.success_url)
""" Role"""
class AppRoleListView(LoginRequiredMixin, generic.ListView):
page_name = resource_action.RESOURCE_IAM_ROLE
model = IAmRole
template_name = "accounts/iam_module/iam_role_list.html"
context_object_name = "data_obj"
def get_queryset(self):
return (
super()
.get_queryset()
.prefetch_related(
"app_resource_action",
"app_resource_action__app_resource",
"app_resource_action__app_action",
)
.filter(deleted=False)
)
def generate_role_data(self):
roles = self.get_queryset()
role_data = []
for role in roles:
role_info = {
"id": role.id,
"name": role.name,
"active": role.active,
"resources": {},
}
for link in role.app_resource_action.all():
resource = link.app_resource.name
action = link.app_action.name
if resource in role_info["resources"]:
role_info["resources"][resource].append(action)
else:
role_info["resources"][resource] = [action]
role_data.append(role_info)
return role_data
def get_context_data(self, **kwargs):
context = {"page_name": self.page_name, "roles": self.generate_role_data()}
context.update(kwargs)
return context
class AppRoleCreateOrUpdateView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_ROLE
model = IAmRole
template_name = "accounts/iam_module/iam_role_add.html"
form_class = IAmPrincipalRoleAppResourceActionLinkForm
success_url = reverse_lazy("accounts:role_list")
success_message = "Saved Successfully"
error_message = "An error occurred while saving the data."
def get_success_message(self):
self.success_message = (
f"Record {'Created' if not self.object else 'Updated'} Successfully"
)
return self.success_message
def get_object(self):
pk = self.kwargs.get("pk")
return get_object_or_404(self.model, pk=pk) if pk else None
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Add" if not self.object else "Edit",
"app_resource_action": IAmAppResourceActionLink.objects.generate_app_resource_action_data(),
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
try:
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
except Exception as e:
messages.error(request, str(e))
return redirect(self.success_url)
def post(self, request, *args, **kwargs):
try:
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object)
if not form.is_valid():
print(form.errors)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(self.request, self.get_success_message())
return redirect(self.success_url)
except Exception as e:
messages.error(self.request, str(e))
return redirect(self.success_url)
class AppRoleDeleteView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_ROLE
model = IAmRole
success_url = reverse_lazy("accounts:role_list")
success_message = constants.RECORD_DELETED
error_message = constants.RECORD_NOT_FOUND
def get(self, request, pk):
try:
type_obj = self.model.objects.get(id=pk)
principal = IAmPrincipalGroup.objects.filter(role=type_obj).exists()
if principal:
messages.success(
request, "You can't delete this record as it's assigned to groups."
)
else:
type_obj.deleted = True
type_obj.save()
messages.success(request, self.success_message)
except self.model.DoesNotExist:
messages.success(request, self.error_message)
return redirect(self.success_url)
"""Customer"""
class CustomerListView(LoginRequiredMixin, generic.ListView):
page_name = resource_action.RESOURCE_MANAGE_CUSTOMER
resource = resource_action.RESOURCE_MANAGE_CUSTOMER
action = resource_action.ACTION_READ
model = IAmPrincipal
template_name = "accounts/customer/customer_list.html"
context_object_name = "data_objs"
def get_queryset(self):
queryset = (
super()
.get_queryset()
.select_related("principal_type", "principal_source")
.filter(
models.Q(
principal_type__name=resource_action.PRINCIPAL_TYPE_EVENT_MANAGER
)
| models.Q(
principal_type__name=resource_action.PRINCIPAL_TYPE_EVENT_USER
)
| models.Q(
principal_type__name=resource_action.PRINCIPAL_TYPE_FREE_USER
),
)
)
# Annotate the queryset with the count of referrals for each principal
queryset = queryset.annotate(
referral_count=Count(
"referrals_by_referrer",
filter=Q(
referrals_by_referrer__is_completed=True
), # Assuming you only want to count completed referrals
distinct=True, # Ensures referrals are not double-counted if there are multiple conditions or joins
)
)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
class DatatableListView(LoginRequiredMixin, generic.ListView):
pass
class PrincipalProfileView(LoginRequiredMixin, generic.ListView):
page_name = resource_action.RESOURCE_MANAGE_DASHBOARD
model = IAmPrincipal
template_name = "accounts/iam_module/profile_details.html"
context_object_name = "data_obj"
def get_queryset(self):
return (
super()
.get_queryset()
.select_related("principal_type", "principal_source")
.get(id=self.request.user.id)
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
class PrincipalProfileEditView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_MANAGE_DASHBOARD
model = IAmPrincipal
template_name = "accounts/iam_module/profile_details_edit.html"
form_class = ProfileEditForm
success_url = reverse_lazy("accounts:profile_details")
success_message = "Saved Successfully"
error_message = "An error occurred while saving the data."
def get_success_message(self):
self.success_message = (
f"Record {'Created' if not self.object else 'Updated'} Successfully"
)
return self.success_message
def get_object(self):
return self.request.user
def get_context_data(self, **kwargs):
context = {
# "page_name": self.page_name,
"operation": "Edit",
"page_name": self.page_name,
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
# try:
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
# except Exception as e:
# print("error in project ", str)
# messages.error(request, str(e))
# return redirect(self.success_url)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(request.POST, request.FILES, instance=self.object)
if not form.is_valid():
print(form.errors)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(self.request, self.get_success_message())
return redirect(self.success_url)