From e26c506cf975bb9692ee05d30d2bec0223a1a02a Mon Sep 17 00:00:00 2001 From: Sangeetha Date: Thu, 18 Sep 2025 20:11:35 +0530 Subject: [PATCH] [WEB-4899] fix: workspace admin cannot delete intake and cycle (#7807) * fix: permission check on viewset * chore: check workspace admin * chore: initiative is_workspace_admin before if condition * chore: project member check * fix: if conditions * chore: add condition for guests to only edit description and name * fix: use ROLE enum instead of magic numbers * chore: remove if condition --- apps/api/plane/app/views/cycle/base.py | 13 --------- apps/api/plane/app/views/intake/base.py | 39 ++++++++++++++++++------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/apps/api/plane/app/views/cycle/base.py b/apps/api/plane/app/views/cycle/base.py index bcce69bf85..cb07d76c42 100644 --- a/apps/api/plane/app/views/cycle/base.py +++ b/apps/api/plane/app/views/cycle/base.py @@ -504,19 +504,6 @@ class CycleViewSet(BaseViewSet): @allow_permission([ROLE.ADMIN], creator=True, model=Cycle) def destroy(self, request, slug, project_id, pk): cycle = Cycle.objects.get(workspace__slug=slug, project_id=project_id, pk=pk) - if cycle.owned_by_id != request.user.id and not ( - ProjectMember.objects.filter( - workspace__slug=slug, - member=request.user, - role=20, - project_id=project_id, - is_active=True, - ).exists() - ): - return Response( - {"error": "Only admin or owner can delete the cycle"}, - status=status.HTTP_403_FORBIDDEN, - ) cycle_issues = list( CycleIssue.objects.filter(cycle_id=self.kwargs.get("pk")).values_list( diff --git a/apps/api/plane/app/views/intake/base.py b/apps/api/plane/app/views/intake/base.py index 1ca9e39705..a55b40a7ca 100644 --- a/apps/api/plane/app/views/intake/base.py +++ b/apps/api/plane/app/views/intake/base.py @@ -28,6 +28,7 @@ from plane.db.models import ( ProjectMember, CycleIssue, IssueDescriptionVersion, + WorkspaceMember, ) from plane.app.serializers import ( IssueCreateSerializer, @@ -348,17 +349,32 @@ class IntakeIssueViewSet(BaseViewSet): project_id=project_id, intake_id=intake_id, ) - # Get the project member - project_member = ProjectMember.objects.get( + + project_member = ProjectMember.objects.filter( workspace__slug=slug, project_id=project_id, member=request.user, is_active=True, - ) + ).first() + + is_workspace_admin = WorkspaceMember.objects.filter( + workspace__slug=slug, + is_active=True, + member=request.user, + role=ROLE.ADMIN.value, + ).exists() + + if not project_member and not is_workspace_admin: + return Response( + {"error": "Only admin or creator can update the intake work items"}, + status=status.HTTP_403_FORBIDDEN, + ) + # Only project members admins and created_by users can access this endpoint - if project_member.role <= 5 and str(intake_issue.created_by_id) != str( - request.user.id - ): + if ( + (project_member and project_member.role <= ROLE.GUEST.value) + and not is_workspace_admin + ) and str(intake_issue.created_by_id) != str(request.user.id): return Response( {"error": "You cannot edit intake issues"}, status=status.HTTP_400_BAD_REQUEST, @@ -391,8 +407,8 @@ class IntakeIssueViewSet(BaseViewSet): Value([], output_field=ArrayField(UUIDField())), ), ).get(pk=intake_issue.issue_id, workspace__slug=slug, project_id=project_id) - # Only allow guests to edit name and description - if project_member.role <= 5: + + if project_member and project_member.role <= ROLE.GUEST.value: issue_data = { "name": issue_data.get("name", issue.name), "description_html": issue_data.get( @@ -400,6 +416,7 @@ class IntakeIssueViewSet(BaseViewSet): ), "description": issue_data.get("description", issue.description), } + current_instance = json.dumps( IssueDetailSerializer(issue).data, cls=DjangoJSONEncoder ) @@ -436,8 +453,10 @@ class IntakeIssueViewSet(BaseViewSet): issue_serializer.errors, status=status.HTTP_400_BAD_REQUEST ) - # Only project admins and members can edit intake issue attributes - if project_member.role > 15: + # Only project admins can edit intake issue attributes + if ( + project_member and project_member.role > ROLE.MEMBER.value + ) or is_workspace_admin: serializer = IntakeIssueSerializer( intake_issue, data=request.data, partial=True )