From 198452430f996d22eba0499d0b1c6fa65e1d82ca Mon Sep 17 00:00:00 2001 From: Bavisetti Narayan <72156168+NarayanBavisetti@users.noreply.github.com> Date: Thu, 20 Jun 2024 16:04:46 +0530 Subject: [PATCH] [WEB-1674] chore: views access control (#4885) * chore: access control changes in views * chore: view serializer change --- apiserver/plane/app/serializers/view.py | 8 +--- apiserver/plane/app/views/view/base.py | 57 +++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/apiserver/plane/app/serializers/view.py b/apiserver/plane/app/serializers/view.py index 32fba7d0c..6b08ae80b 100644 --- a/apiserver/plane/app/serializers/view.py +++ b/apiserver/plane/app/serializers/view.py @@ -3,18 +3,12 @@ from rest_framework import serializers # Module imports from .base import DynamicBaseSerializer -from .workspace import WorkspaceLiteSerializer -from .project import ProjectLiteSerializer from plane.db.models import IssueView from plane.utils.issue_filters import issue_filters class IssueViewSerializer(DynamicBaseSerializer): is_favorite = serializers.BooleanField(read_only=True) - project_detail = ProjectLiteSerializer(source="project", read_only=True) - workspace_detail = WorkspaceLiteSerializer( - source="workspace", read_only=True - ) class Meta: model = IssueView @@ -24,6 +18,8 @@ class IssueViewSerializer(DynamicBaseSerializer): "project", "query", "owned_by", + "access", + "is_locked", ] def create(self, validated_data): diff --git a/apiserver/plane/app/views/view/base.py b/apiserver/plane/app/views/view/base.py index 8e9f5b284..fc44866fc 100644 --- a/apiserver/plane/app/views/view/base.py +++ b/apiserver/plane/app/views/view/base.py @@ -69,11 +69,40 @@ class WorkspaceViewViewSet(BaseViewSet): .get_queryset() .filter(workspace__slug=self.kwargs.get("slug")) .filter(project__isnull=True) + .filter(Q(owned_by=self.request.user) | Q(access=1)) .select_related("workspace") .order_by(self.request.GET.get("order_by", "-created_at")) .distinct() ) + def partial_update(self, request, slug, pk): + workspace_view = IssueView.objects.get( + pk=pk, + workspace__slug=slug, + ) + + if workspace_view.is_locked: + return Response( + {"error": "view is locked"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + # Only update the view if owner is updating + if workspace_view.owned_by_id != request.user.id: + return Response( + {"error": "Only the owner of the view can update the view"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + serializer = IssueViewSerializer( + workspace_view, data=request.data, partial=True + ) + + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + class WorkspaceViewIssuesViewSet(BaseViewSet): permission_classes = [ @@ -294,6 +323,7 @@ class IssueViewViewSet(BaseViewSet): project__project_projectmember__is_active=True, project__archived_at__isnull=True, ) + .filter(Q(owned_by=self.request.user) | Q(access=1)) .select_related("project") .select_related("workspace") .annotate(is_favorite=Exists(subquery)) @@ -313,6 +343,33 @@ class IssueViewViewSet(BaseViewSet): ).data return Response(views, status=status.HTTP_200_OK) + def partial_update(self, request, slug, project_id, pk): + issue_view = IssueView.objects.get( + pk=pk, workspace__slug=slug, project_id=project_id + ) + + if issue_view.is_locked: + return Response( + {"error": "view is locked"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + # Only update the view if owner is updating + if issue_view.owned_by_id != request.user.id: + return Response( + {"error": "Only the owner of the view can update the view"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + serializer = IssueViewSerializer( + issue_view, data=request.data, partial=True + ) + + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + class IssueViewFavoriteViewSet(BaseViewSet): model = UserFavorite