fix: iamprincipal

This commit is contained in:
bobbyvish
2024-04-02 19:23:52 +05:30
parent 6892bd6675
commit 9e66760fae
13 changed files with 234 additions and 80 deletions

View File

@@ -27,6 +27,8 @@ from .iam_constant import (
RESOURCE_IAM_ROLE,
)
from .models import IAmPrincipal
def iam_constants_context(request):
return {
'iam_constants_context': {
@@ -57,4 +59,15 @@ def iam_constants_context(request):
'RESOURCE_IAM_GROUP': RESOURCE_IAM_GROUP,
'RESOURCE_IAM_ROLE': RESOURCE_IAM_ROLE,
}
}
def resource_permissions(request):
if request.user.is_authenticated:
resource_permissions = IAmPrincipal.objects.filter(id=request.user.id).values_list('principal_resource__name', flat=True)
else:
resource_permissions = []
return {
'resource_permissions': resource_permissions,
}

86
module_iam/permission.py Normal file
View File

@@ -0,0 +1,86 @@
from functools import wraps
from django.core.exceptions import PermissionDenied
from . import models
from django.db.models import Q
# import logging
# logger = logging.getLogger(__name__)
# class CustomPermissionRequiredMixin:
# resource = None
# action = None
# def has_custom_permission(self, user, resource, action):
# if not self.resource or not self.action:
# raise AttributeError("Resource and action attributes must be defined in the view")
# # if not request.user.is_authenticated:
# # return self.handle_no_permission()
# if user.is_superuser: # will chagne to principal type for admin
# return True
# permission_query = Q(
# principal_group__role__app_resource_action__app_resource__name=resource,
# principal_group__role__app_resource_action__app_action__name=action
# )
# return models.IAmPrincipal.objects.filter(permission_query, id=user.id).exists()
# def dispatch(self, request, *args, **kwargs):
# if not self.has_custom_permission(request.user, self.resource, self.action):
# # logger.warning(f"Permission denied for user {request.user} accessing {self.resource}:{self.action}")
# raise PermissionDenied("You do not have permission to access this resource.")
# return super().dispatch(request, *args, **kwargs)
# @classmethod
# def as_decorator(cls, resource, action):
# def decorator(view_func):
# @wraps(view_func)
# def _wrapped_view(request, *args, **kwargs):
# instance = cls()
# instance.resource = resource
# instance.action = action
# if not instance.has_custom_permission(request.user, instance.resource, instance.action):
# raise PermissionDenied("You do not have permission to access this resource.")
# return view_func(request, *args, **kwargs)
# return _wrapped_view
# return decorator
class ResourcePermissionRequiredMixin:
resource = None
def has_resource_permission(self, user, resource):
# if not self.resource or resource:
# raise AttributeError("Resource attributes must be defined in the view")
# if not request.user.is_authenticated:
# return self.handle_no_permission()
if user.is_superuser: # will chagne to principal type for admin
return True
permission_query = Q(
principal_resource__name=resource,
)
return models.IAmPrincipal.objects.filter(permission_query, id=user.id).exists()
def dispatch(self, request, *args, **kwargs):
if not self.has_resource_permission(request.user, self.resource):
# logger.warning(f"Permission denied for user {request.user} accessing {self.resource}:{self.action}")
raise PermissionDenied("You do not have permission to access this resource.")
return super().dispatch(request, *args, **kwargs)
@classmethod
def as_decorator(cls, resource):
def decorator(view_func):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
instance = cls()
instance.resource = resource
if not instance.has_resource_permission(request.user, instance.resource):
raise PermissionDenied("You do not have permission to access this resource.")
return view_func(request, *args, **kwargs)
return _wrapped_view
return decorator

View File

@@ -0,0 +1,27 @@
from django import template
from module_iam.permission import ResourcePermissionRequiredMixin
register = template.Library()
@register.filter(name='has_resource_permission')
def has_resource_permission(user, resource):
"""
Check if a user has a specific resource and action permission.
Args:
user (User): The user to check for permission.
resource_action (str): The resource and action string (e.g., "resource_name.action_name").
Returns:
bool: True if the user has the specified permission, False otherwise.
Example usage in a template:
{% if user|has_resource_permission:"article" %}
<!-- Render content for users with permission -->
{% else %}
<!-- Render content for users without permission -->
{% endif %}
"""
# resource, action = resource_action.split(".")
return ResourcePermissionRequiredMixin().has_resource_permission(user, resource)

View File

@@ -14,12 +14,12 @@ 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
from module_iam import iam_constant, permission
from module_project import constants
from module_project.mixins import ActionMixin, DatatablesMixin
from module_project.utils import JsonResponseUtil
from .forms import (CustomAuthenticationForm, IAmPrincipalForm,IAmPrincipalResourceLinkForm,
from .forms import (CustomAuthenticationForm, IAmPrincipalForm, IAmPrincipalResourceLinkForm,
IAmPrincipalGroupLinkForm, IAmPrincipalGroupRoleLinkForm,
IAmPrincipalRoleAppResourceActionLinkForm, ProfileEditForm)
from .models import (IAmAppResourceActionLink, IAmPrincipal, IAmPrincipalGroup,
@@ -30,8 +30,9 @@ logger = logging.getLogger(__name__)
# Create your views here.
class DashboardView(generic.TemplateView):
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):
@@ -51,8 +52,9 @@ class DashboardView(generic.TemplateView):
return context
class PrincipalCreateOrUpdateView(LoginRequiredMixin, generic.View):
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"
@@ -137,10 +139,9 @@ class PrincipalArchiveListJsonView(BaseDatatableView):
)
return qs
class PrincipalResourcePermissionEditView(LoginRequiredMixin, generic.View):
page_name = iam_constant.RESOURCE_IAM_PRINCIPAL_GROUP
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
@@ -177,8 +178,9 @@ class PrincipalResourcePermissionEditView(LoginRequiredMixin, generic.View):
return redirect(self.success_url)
class PrincipalGroupLinkView(LoginRequiredMixin, generic.TemplateView):
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"
@@ -189,7 +191,7 @@ class PrincipalGroupLinkView(LoginRequiredMixin, generic.TemplateView):
class PrincipalArchiveView(PrincipalGroupLinkView):
page_name = iam_constant.RESOURCE_IAM_PRINCIPAL
resource = None
resource = iam_constant.RESOURCE_IAM_PRINCIPAL
action = None
template_name = "module_iam/iam_principal_archive.html"
@@ -221,7 +223,7 @@ class PrincipalGroupLinkAdminListJsonView(BaseDatatableView):
return qs
class PrincipalGroupLinkSubAdminListJsonView(BaseDatatableView):
class PrincipalGroupLinkSubAdminListJsonView(permission.ResourcePermissionRequiredMixin, BaseDatatableView):
model = IAmPrincipal
columns = ["id", "first_name", "email", "is_active"]
order_columns = ["id", "first_name", "email", "is_active"]
@@ -251,8 +253,9 @@ class PrincipalGroupLinkSubAdminListJsonView(BaseDatatableView):
return qs
class PrincipalGroupLinkEditView(LoginRequiredMixin, generic.View):
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
@@ -321,8 +324,9 @@ class PrincipalGroupLinkActionView(generic.View):
return JsonResponseUtil.success(message=message)
class PrincipalGroupView(LoginRequiredMixin, generic.TemplateView):
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"
@@ -355,8 +359,9 @@ class PrincipalGroupListJsonView(BaseDatatableView):
return qs
class PrincipalGroupCreateOrUpdateView(LoginRequiredMixin, generic.View):
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"
@@ -407,8 +412,9 @@ class PrincipalGroupActionView(ActionMixin):
class PrincipalGroupArchiveView(PrincipalGroupView):
template_name = "module_iam/iam_group_archive_list.html"
class AppRoleView(LoginRequiredMixin, generic.TemplateView):
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"
@@ -464,8 +470,9 @@ class AppRoleListJsonView(BaseDatatableView):
return qs
class AppRoleCreateOrUpdateView(LoginRequiredMixin, generic.View):
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
@@ -526,8 +533,9 @@ class AppRoleArchiveView(AppRoleView):
template_name = "module_iam/iam_role_archive.html"
class PrincipalProfileView(LoginRequiredMixin, generic.TemplateView):
class PrincipalProfileView(permission.ResourcePermissionRequiredMixin, 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"
@@ -545,8 +553,9 @@ class PrincipalProfileView(LoginRequiredMixin, generic.TemplateView):
return context
class PrincipalProfileEditView(generic.View):
class PrincipalProfileEditView(permission.ResourcePermissionRequiredMixin, 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