from django.db import transaction from django.db.models import Count from rest_framework import filters from rest_framework import status from rest_framework import viewsets from rest_framework.decorators import action from rest_framework.exceptions import APIException from rest_framework.response import Response from apps.authorization.api.v1.serializers import ( RoleSerializer, PermissionSerializer, UserRelationSerializer, PageSerializer ) from apps.authorization.exception import AdminRoleDeleteException from apps.authorization.models import ( Role, Permissions, UserRelations, Page ) from apps.core.api import BaseViewSet from apps.core.exceptions import ConflictException from apps.core.mixins.search_mixin import DynamicSearchMixin from apps.core.mixins.soft_delete_mixin import SoftDeleteMixin from common.helpers import get_organization_by_user class RoleViewSet(BaseViewSet, SoftDeleteMixin, viewsets.ModelViewSet): """ Crud Operations For User Roles """ queryset = Role.objects.all() serializer_class = RoleSerializer filter_backends = [filters.SearchFilter] search_fields = ['role_name', 'type__name'] def list(self, request, *args, **kwargs): """ all roles """ role = self.paginate_queryset(self.get_queryset().order_by('-modify_date')) if role is not None: # noqa serializer = self.get_serializer(role, many=True) return self.get_paginated_response(serializer.data) def destroy(self, request, pk=None, *args, **kwargs): """ soft delete of role except Admin """ role = self.get_object() if role.type.key == 'ADM': raise AdminRoleDeleteException() role.soft_delete() return Response(status=status.HTTP_200_OK) class PageViewSet(SoftDeleteMixin, viewsets.ModelViewSet): """ add website pages to system to set permission on it """ queryset = Page.objects.all() serializer_class = PageSerializer filter_backends = [filters.SearchFilter] search_fields = ['name', 'code'] def list(self, request, *args, **kwargs): """ all pages """ page = self.paginate_queryset(self.filter_queryset(self.queryset.order_by('-modify_date'))) if page is not None: # noqa serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) @action( methods=['delete'], detail=True, url_name='delete', url_path='delete', name='delete' ) @transaction.atomic def delete(self, request, pk=None): """ Full delete of page & permissions of page object """ try: page = self.queryset.get(id=pk) permissions = Permissions.objects.filter(page=page) permissions.delete() page.delete() return Response(status=status.HTTP_200_OK) except APIException as e: return Response(e, status=status.HTTP_204_NO_CONTENT) class PermissionViewSet(SoftDeleteMixin, viewsets.ModelViewSet): """ Crud Operations for Permissions """ queryset = Permissions.objects.all() serializer_class = PermissionSerializer filter_backends = [filters.SearchFilter] search_fields = ['page__name', 'name'] def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset().order_by('-modify_date')) # noqa page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True) return Response(serializer.data) def create(self, request, *args, **kwargs): if self.queryset.filter(name=request.data['name'], page_id=request.data['page']).exists(): raise ConflictException('a permission with this page exists.') serializer = self.serializer_class(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_200_OK) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @action( methods=['get'], detail=False, url_name='connectionless_permissions', url_path='connectionless_permissions', name='connectionless_permissions' ) @transaction.atomic def connectionless_permissions(self, request, *args, **kwargs): """ get all permissions that are not assigned to any user relation """ permissions = Permissions.objects.annotate( user_relation_num=Count('userrelations'), # noqa role_num=Count('role'), ).filter(user_relation_num=0, role_num=0) # noqa page = self.paginate_queryset(self.filter_queryset(permissions)) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(permissions, many=True) return Response(serializer.data) class UserRelationViewSet(BaseViewSet, SoftDeleteMixin, viewsets.ModelViewSet, DynamicSearchMixin): """ Crud Operations for User Relations """ queryset = UserRelations.objects.select_related('organization', 'role', 'user') serializer_class = UserRelationSerializer filter_backends = [filters.SearchFilter] search_fields = [ 'user__username', 'user__mobile', 'user__phone', 'user__first_name', 'user__last_name', 'user__national_code', 'user__province__name', 'user__city__name', 'user__unit_name', 'user__unit_national_id', ] def list(self, request, *args, **kwargs): role_param = self.request.query_params.get('role') # noqa org = get_organization_by_user(request.user) queryset = self.get_queryset( visibility_by_org_scope=True ) if org.free_visibility_by_scope else self.get_queryset() if role_param != '': queryset = queryset.filter(role_id=int(role_param)) else: queryset = queryset.order_by('-create_date') queryset = self.filter_queryset(queryset) # noqa page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True) return Response(serializer.data)