Files
digest_app/module_iam/views.py
2024-05-15 11:11:27 +05:30

602 lines
23 KiB
Python

import logging
from datetime import datetime
from typing import Any
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db import transaction
from django.db.models import Q
from django.db.models.base import Model as Model
from django.db.models.query import QuerySet
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse_lazy
from django.views import generic
from django_datatables_view.base_datatable_view import BaseDatatableView
from module_iam import iam_constant, permission
from module_project import constants
from module_project.mixins import ActionMixin
from module_project.utils import JsonResponseUtil
from .forms import (CustomAuthenticationForm, IAmPrincipalForm, IAmPrincipalResourceLinkForm,
IAmPrincipalGroupLinkForm, IAmPrincipalGroupRoleLinkForm,
IAmPrincipalRoleAppResourceActionLinkForm, ProfileEditForm)
from .models import (IAmAppResourceActionLink, IAmPrincipal, IAmPrincipalGroup,
IAmPrincipalType, IAmRole)
logger = logging.getLogger(__name__)
# Create your views here.
class DashboardView(LoginRequiredMixin, generic.TemplateView):
page_name = iam_constant.RESOURCE_MANAGE_DASHBOARD
resource = iam_constant.RESOURCE_MANAGE_DASHBOARD
template_name = "base_structure/layout/dashboard.html"
def get_user_count(self):
obj = IAmPrincipal.objects.all()
# Count active users
active_user_count = obj.filter(is_active=True).count()
# Count total users
total_user_count = obj.count()
return active_user_count, total_user_count
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
active_user_count, total_user_count = self.get_user_count()
context["active_user_count"] = active_user_count
context["total_user_count"] = total_user_count
context["page_name"] = self.page_name
return context
class PrincipalCreateOrUpdateView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.View):
page_name = iam_constant.RESOURCE_IAM_PRINCIPAL
resource = iam_constant.RESOURCE_IAM_PRINCIPAL
model = IAmPrincipal
form_class = IAmPrincipalForm
template_name = "module_iam/iam_principal_add.html"
success_url = reverse_lazy("module_iam:principal_group_link")
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 = datetime.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 PrincipalArchiveListJsonView(BaseDatatableView):
model = IAmPrincipal
columns = ["id", "first_name", "email", "is_active"]
order_columns = ["id", "first_name", "email", "is_active"]
def get_initial_queryset(self):
deleted_flag = self.request.GET.get("deleted_flag", False)
return self.model.objects.filter(
deleted=deleted_flag,
principal_type__name__in=(
iam_constant.PRINCIPAL_TYPE_ADMIN,
iam_constant.PRINCIPAL_TYPE_SUBADMIN,
),
)
def render_column(self, row, column):
if column == "principal_type_name":
return row.principal_type.name if row.principal_type else None
return super().render_column(row, column)
def filter_queryset(self, qs):
search_value = self.request.GET.get("search[value]", None)
if search_value:
qs = qs.filter(
Q(id__icontains=search_value)
| Q(first_name__icontains=search_value)
| Q(email__icontains=search_value)
)
return qs
class PrincipalResourcePermissionEditView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.View):
page_name = iam_constant.RESOURCE_IAM_PRINCIPAL
resource = iam_constant.RESOURCE_IAM_PRINCIPAL_GROUP
model = IAmPrincipal
template_name = "module_iam/iam_principal_resource_permission_edit.html"
form_class = IAmPrincipalResourceLinkForm
success_url = reverse_lazy("module_iam:principal_group_link")
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)
class PrincipalGroupLinkView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.TemplateView):
page_name = iam_constant.RESOURCE_IAM_PRINCIPAL_GROUP
resource = iam_constant.RESOURCE_IAM_PRINCIPAL_GROUP
model = IAmPrincipal
template_name = "module_iam/iam_principal_group_link.html"
def get_context_data(self, **kwargs) -> dict[str, Any]:
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
class PrincipalArchiveView(PrincipalGroupLinkView):
page_name = iam_constant.RESOURCE_IAM_PRINCIPAL
resource = iam_constant.RESOURCE_IAM_PRINCIPAL
action = None
template_name = "module_iam/iam_principal_archive.html"
class PrincipalGroupLinkAdminListJsonView(BaseDatatableView):
model = IAmPrincipal
columns = ["id", "first_name", "email", "is_active"]
order_columns = ["id", "first_name", "email", "is_active"]
def get_initial_queryset(self):
deleted_flag = self.request.GET.get("deleted_flag", False)
return self.model.objects.filter(
deleted=deleted_flag, principal_type__name=iam_constant.PRINCIPAL_TYPE_ADMIN
)
def render_column(self, row, column):
if column == "principal_type_name":
return row.principal_type.name if row.principal_type else None
return super().render_column(row, column)
def filter_queryset(self, qs):
search_value = self.request.GET.get("search[value]", None)
if search_value:
qs = qs.filter(
Q(id__icontains=search_value)
| Q(first_name__icontains=search_value)
| Q(email__icontains=search_value)
)
return qs
class PrincipalGroupLinkSubAdminListJsonView(permission.ResourcePermissionRequiredMixin, BaseDatatableView):
model = IAmPrincipal
columns = ["id", "first_name", "email", "is_active"]
order_columns = ["id", "first_name", "email", "is_active"]
def get_initial_queryset(self):
deleted_flag = self.request.GET.get("deleted_flag", False)
return self.model.objects.filter(
deleted=deleted_flag,
principal_type__name=iam_constant.PRINCIPAL_TYPE_SUBADMIN,
)
def render_column(self, row, column):
if column == "principal_type_name":
return row.principal_type.name if row.principal_type else None
if column == "permission":
return [{"name": resource.name} for resource in row.principal_resource.all()]
return super().render_column(row, column)
def filter_queryset(self, qs):
search_value = self.request.GET.get("search[value]", None)
if search_value:
qs = qs.filter(
Q(id__icontains=search_value)
| Q(first_name__icontains=search_value)
| Q(email__icontains=search_value)
)
return qs
class PrincipalGroupLinkEditView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.View):
page_name = iam_constant.RESOURCE_IAM_PRINCIPAL_GROUP
resource = iam_constant.RESOURCE_IAM_PRINCIPAL_GROUP
model = IAmPrincipal
template_name = "module_iam/iam_principal_group_link_edit.html"
form_class = IAmPrincipalGroupLinkForm
success_url = reverse_lazy("module_iam:principal_group_link")
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)
class PrincipalGroupLinkActionView(generic.View):
model = IAmPrincipal
def post(self, request, *args, **kwargs):
if self.model is None:
raise NotImplementedError(
"Subclasses of BaseActionView must define a 'model' attribute."
)
action = request.POST.get("action") # 'archive', 'active', or 'unarchive'
ids = request.POST.getlist("ids[]") # List of IDs to perform action on
active = request.POST.get("active")
print(f"arhive action {action} and id is {ids} and active data is {active}")
if action == "archive":
# Update 'deleted' field to True for the selected users
self.model.objects.filter(id__in=ids).update(deleted=True, is_active=False)
message = "Record archived successfully."
elif action == "active":
# Update 'active' field to True for the selected users
self.model.objects.filter(id__in=ids).update(is_active=active.capitalize())
message = "Record updated successfully."
elif action == "unarchive":
# Update 'deleted' field to False for the selected users
self.model.objects.filter(id__in=ids).update(deleted=False)
message = "Record unarchived successfully."
else:
return JsonResponseUtil.error(message="Invalid Action")
return JsonResponseUtil.success(message=message)
class PrincipalGroupView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.TemplateView):
page_name = iam_constant.RESOURCE_IAM_GROUP
resource = iam_constant.RESOURCE_IAM_GROUP
model = IAmPrincipalGroup
template_name = "module_iam/iam_group.html"
def get_context_data(self, **kwargs) -> dict[str, Any]:
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
class PrincipalGroupListJsonView(BaseDatatableView):
model = IAmPrincipalGroup
columns = ["id", "name", "active"]
order_columns = ["id", "name", "active"]
def get_initial_queryset(self):
deleted_flag = self.request.GET.get("deleted_flag", False)
return self.model.objects.filter(deleted=deleted_flag)
def render_column(self, row, column):
if column == "roles":
return [{"name": role.name} for role in row.role.all()]
return super().render_column(row, column)
def filter_queryset(self, qs):
search_value = self.request.GET.get("search[value]", None)
if search_value:
qs = qs.filter(
Q(id__icontains=search_value) | Q(name__icontains=search_value)
)
return qs
class PrincipalGroupCreateOrUpdateView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.View):
page_name = iam_constant.RESOURCE_IAM_GROUP
resource = iam_constant.RESOURCE_IAM_GROUP
page_title = "Principal Group"
model = IAmPrincipalGroup
template_name = "module_iam/iam_group_add.html"
form_class = IAmPrincipalGroupRoleLinkForm
success_url = reverse_lazy("module_iam:principal_group")
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 PrincipalGroupActionView(ActionMixin):
model = IAmPrincipalGroup
class PrincipalGroupArchiveView(PrincipalGroupView):
template_name = "module_iam/iam_group_archive_list.html"
class AppRoleView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.TemplateView):
page_name = iam_constant.RESOURCE_IAM_ROLE
resource = iam_constant.RESOURCE_IAM_ROLE
model = IAmRole
template_name = "module_iam/iam_role.html"
def get_context_data(self, **kwargs) -> dict[str, Any]:
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
class AppRoleListJsonView(BaseDatatableView):
model = IAmRole
columns = ["id", "name", "active", "resources"]
order_columns = ["id", "name"]
def get_initial_queryset(self):
deleted_flag = self.request.GET.get("deleted_flag", False)
return (
super(AppRoleListJsonView, self)
.get_initial_queryset()
.prefetch_related(
"app_resource_action",
"app_resource_action__app_resource",
"app_resource_action__app_action",
)
.filter(deleted=deleted_flag)
)
def render_column(self, row, column):
if column == "resources":
resources = {}
# Loop through all the app_resource_action links for the current ro
for link in row.app_resource_action.all():
resource = link.app_resource.name
action = link.app_action.name
# If the resource is already in the dictionary, append the action to the list of actions
if resource in resources:
resources[resource].append(action)
# Otherwise, add the resource to the dictionary with a list containing the action
else:
resources[resource] = [action]
return resources
return super().render_column(row, column)
def filter_queryset(self, qs):
search_value = self.request.GET.get("search[value]", None)
if search_value:
qs = qs.filter(
Q(id__icontains=search_value)
| Q(name__icontains=search_value)
| Q(app_resource_action__app_resource__name__icontains=search_value)
| Q(app_resource_action__app_action__name__icontains=search_value)
)
return qs
class AppRoleCreateOrUpdateView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.View):
page_name = iam_constant.RESOURCE_IAM_ROLE
resource = iam_constant.RESOURCE_IAM_ROLE
model = IAmRole
template_name = "module_iam/iam_role_add.html"
form_class = IAmPrincipalRoleAppResourceActionLinkForm
success_url = reverse_lazy("module_iam:role")
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 AppRoleActionView(LoginRequiredMixin, ActionMixin):
model = IAmRole
class AppRoleArchiveView(AppRoleView):
template_name = "module_iam/iam_role_archive.html"
class PrincipalProfileView( LoginRequiredMixin, generic.TemplateView):
page_name = iam_constant.RESOURCE_MANAGE_DASHBOARD
resource = iam_constant.RESOURCE_MANAGE_DASHBOARD
model = IAmPrincipal
template_name = "module_iam/profile_details.html"
def get_object(self, queryset=None):
user = self.request.user.id
return get_object_or_404(
self.model.objects.select_related("principal_type", "principal_source"),
pk=user,
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
context["data_obj"] = self.get_object()
return context
class PrincipalProfileEditView(LoginRequiredMixin, generic.View):
page_name = iam_constant.RESOURCE_MANAGE_DASHBOARD
resource = iam_constant.RESOURCE_MANAGE_DASHBOARD
model = IAmPrincipal
template_name = "module_iam/profile_details_edit.html"
form_class = ProfileEditForm
success_url = reverse_lazy("module_iam: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)
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)