import requests 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.permissions import AllowAny 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 UpdatePageAccessViewSet(BaseViewSet, SoftDeleteMixin, viewsets.ModelViewSet): queryset = Page.objects.all() serializer_class = PageSerializer permission_classes = [AllowAny] def list(self, request, *args, **kwargs): queryset = self.queryset.all() page_serializer = self.get_serializer(queryset, many=True) return Response(page_serializer.data) @transaction.atomic def create(self, request, *args, **kwargs): """ sync update page & access on development version with production """ url = 'https://api.tdam.rasadyar.com/auth/api/v1/update_access/' # get data page & permissions data from development req = requests.get(url) response = req.json() url = 'https://api.dam.rasadyar.com/auth/api/v1/update_access/update_page_access/' updated_response = requests.post(url=url, json=response) return Response(updated_response.json()) @action(methods=['post'], detail=False, url_name='update_page_access', url_path='update_page_access') def update_page_access(self, request, *args, **kwargs): """ Sync page & permissions in development with production """ # if page or permission exists in production, don't create just update for page in request.data: page_obj = Page.objects.filter(code=page['code']) permissions = page.pop('permissions') # remove permissions from data if not page_obj.exists(): page_obj = Page.objects.create(**page) else: page_obj.update_or_create( code=page['code'], name=page['name'], is_active=page['is_active'], ) # get page object page_obj = page_obj.first() for permission in permissions: permission.pop('page') # remove page from data perm = Permissions.objects.filter(page=page_obj, name=permission['name']) if perm.exists(): perm.update_or_create( name=permission['name'], description=permission['description'], category=permission['category'], page=page_obj, is_active=permission['is_active'], modify_state=permission['modify_state'], ) else: Permissions.objects.create( **permission, page_id=page.id, ) return Response(request.data) 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): """ all permissions """ if 'modify_state' in request.GET.keys(): param = self.request.query_params.get('modify_state') # noqa if param == 'true': self.queryset = self.get_queryset().filter(modify_state=True).order_by('-modify_date') elif param == 'false': self.queryset = self.get_queryset().filter(modify_state=False).order_by('-modify_date') else: self.queryset = self.get_queryset().filter().order_by('-modify_date') else: self.queryset = self.queryset.order_by('-modify_date') queryset = self.filter_queryset(self.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) 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() print(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)