from typing import Any from django.db.models.base import Model as Model from django.db.models.query import QuerySet from django.views import generic import logging from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import Q from django.http import JsonResponse from django.shortcuts import render, redirect, get_object_or_404 from django.urls import reverse_lazy from module_iam import iam_constant from module_project.mixins import DatatablesMixin from django_datatables_view.base_datatable_view import BaseDatatableView from module_project.mixins import ActionMixin from .forms import ( CustomAuthenticationForm, IAmPrincipalForm, IAmPrincipalGroupRoleLinkForm, IAmPrincipalRoleAppResourceActionLinkForm, IAmPrincipalGroupLinkForm, ProfileEditForm ) from .models import ( IAmPrincipal, IAmPrincipalType, IAmAppResourceActionLink, IAmPrincipalGroup, IAmRole, ) from module_project import constants logger = logging.getLogger(__name__) # Create your views here. class DashboardView(generic.TemplateView): page_name = 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 PrincipalGroupLinkView(LoginRequiredMixin, generic.TemplateView): page_name = 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 PrincipalGroupLinkAdminListJsonView(BaseDatatableView): model = IAmPrincipal columns = ["id", "first_name", "email", "principal_type__name", "is_active"], order_columns = ["id", "first_name", "email"] def get_initial_queryset(self): deleted_flag = self.request.GET.get('deleted_flag', False) return self.model.objects.filter(deleted=deleted_flag).exclude(principal_type__name=iam_constant.PRINCIPAL_TYPE_USER) class PrincipalGroupView(LoginRequiredMixin, generic.TemplateView): page_name = 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 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 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 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 def generate_role_data(self, queryset): roles_data = [] for obj in queryset: roles = [{'name': role.name} for role in obj.role.all()] print(f"role data is this {roles}") roles_data.append({ 'id': obj.id, 'name': obj.name, 'active': str(obj.active), 'roles': roles }) return roles_data def get_context_data(self, *args, **kwargs): roles = self.filter_queryset(self.get_initial_queryset()) role_data = self.generate_role_data(roles) context = super().get_context_data(*args, **kwargs) context['recordsTotal'] = len(role_data) context['recordsFiltered'] = len(role_data) context['data'] = role_data context['result'] = 'ok' return context class PrincipalGroupCreateOrUpdateView(LoginRequiredMixin, generic.View): page_name = 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 AppRoleView(LoginRequiredMixin, generic.TemplateView): page_name = 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 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 def generate_resource_data(self, roles): role_data = [] for role in roles: role_info = { "id": role.id, "name": role.name, "active": str(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, *args, **kwargs): roles = self.filter_queryset(self.get_initial_queryset()) role_data = self.generate_resource_data(roles) context = super().get_context_data(*args, **kwargs) context['recordsTotal'] = len(role_data) context['recordsFiltered'] = len(role_data) context['data'] = role_data context['result'] = 'ok' return context class AppRoleCreateOrUpdateView(LoginRequiredMixin, generic.View): page_name = 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 PrincipalProfileView(LoginRequiredMixin, generic.TemplateView): page_name = 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(generic.View): page_name = 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)