From 45ee8d9ae769b184703e8ccf264399c25d42aa79 Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Fri, 1 Sep 2023 11:19:14 +0530 Subject: [PATCH 1/3] feat: leave project and workspace endpoint --- apiserver/plane/api/urls.py | 16 +++++++ apiserver/plane/api/views/__init__.py | 2 + apiserver/plane/api/views/project.py | 64 ++++++++++++++++++++------ apiserver/plane/api/views/workspace.py | 41 +++++++++++++++++ 4 files changed, 108 insertions(+), 15 deletions(-) diff --git a/apiserver/plane/api/urls.py b/apiserver/plane/api/urls.py index 1fb2b8e905c..57f62764dea 100644 --- a/apiserver/plane/api/urls.py +++ b/apiserver/plane/api/urls.py @@ -51,6 +51,7 @@ WorkspaceUserProfileEndpoint, WorkspaceUserProfileIssuesEndpoint, WorkspaceLabelsEndpoint, + LeaveWorkspaceEndpoint, ## End Workspaces # File Assets FileAssetEndpoint, @@ -68,6 +69,7 @@ UserProjectInvitationsViewset, ProjectIdentifierEndpoint, ProjectFavoritesViewSet, + LeaveProjectEndpoint, ## End Projects # Issues IssueViewSet, @@ -441,6 +443,11 @@ WorkspaceLabelsEndpoint.as_view(), name="workspace-labels", ), + path( + "workspaces//members/leave/", + LeaveWorkspaceEndpoint.as_view(), + name="workspace-labels", + ), ## End Workspaces ## # Projects path( @@ -554,6 +561,15 @@ ), name="project", ), + path( + "workspaces//projects//members/leave/", + LeaveProjectEndpoint.as_view( + { + "delete": "destroy", + } + ), + name="project", + ), # End Projects # States path( diff --git a/apiserver/plane/api/views/__init__.py b/apiserver/plane/api/views/__init__.py index b697741ae2a..71647bfea8f 100644 --- a/apiserver/plane/api/views/__init__.py +++ b/apiserver/plane/api/views/__init__.py @@ -16,6 +16,7 @@ ProjectDeployBoardPublicSettingsEndpoint, ProjectMemberEndpoint, WorkspaceProjectDeployBoardEndpoint, + LeaveProjectEndpoint, ) from .user import ( UserEndpoint, @@ -52,6 +53,7 @@ WorkspaceUserProfileIssuesEndpoint, WorkspaceLabelsEndpoint, WorkspaceMembersEndpoint, + LeaveWorkspaceEndpoint, ) from .state import StateViewSet from .view import IssueViewViewSet, ViewIssuesEndpoint, IssueViewFavoriteViewSet diff --git a/apiserver/plane/api/views/project.py b/apiserver/plane/api/views/project.py index 97b06fce581..ec4f63540c1 100644 --- a/apiserver/plane/api/views/project.py +++ b/apiserver/plane/api/views/project.py @@ -11,14 +11,8 @@ OuterRef, Func, F, - Max, - CharField, Func, Subquery, - Prefetch, - When, - Case, - Value, ) from django.core.validators import validate_email from django.conf import settings @@ -47,6 +41,7 @@ ProjectBasePermission, ProjectEntityPermission, ProjectMemberPermission, + ProjectLitePermission, ) from plane.db.models import ( @@ -71,16 +66,9 @@ ModuleMember, Inbox, ProjectDeployBoard, - Issue, - IssueReaction, - IssueLink, - IssueAttachment, - Label, ) from plane.bgtasks.project_invitation_task import project_invitation -from plane.utils.grouper import group_results -from plane.utils.issue_filters import issue_filters class ProjectViewSet(BaseViewSet): @@ -1144,8 +1132,9 @@ def get(self, request, slug, project_id): class WorkspaceProjectDeployBoardEndpoint(BaseAPIView): - - permission_classes = [AllowAny,] + permission_classes = [ + AllowAny, + ] def get(self, request, slug): try: @@ -1176,3 +1165,48 @@ def get(self, request, slug): {"error": "Something went wrong please try again later"}, status=status.HTTP_400_BAD_REQUEST, ) + + +class LeaveProjectEndpoint(BaseAPIView): + permission_classes = [ + ProjectLitePermission, + ] + + def delete(self, request, slug, project_id): + try: + project_member = ProjectMember.objects.get( + workspace__slug=slug, + member=request.user, + project_id=project_id, + ) + + # Only Admin case + if ( + project_member.role == 20 + and ProjectMember.objects.filter( + workspace__slug=slug, + role=20, + project_id=project_id, + ).count() + == 1 + ): + return Response( + { + "error": "You cannot leave the project since you are the only admin of the project you should delete the project" + }, + status=status.HTTP_400, + ) + # Delete the member from workspace + project_member.delete() + return Response(status=status.HTTP_204_NO_CONTENT) + except ProjectMember.DoesNotExist: + return Response( + {"error": "Workspace member does not exists"}, + status=status.HTTP_400_BAD_REQUEST, + ) + except Exception as e: + capture_exception(e) + return Response( + {"error": "Something went wrong please try again later"}, + status=status.HTTP_400_BAD_REQUEST, + ) diff --git a/apiserver/plane/api/views/workspace.py b/apiserver/plane/api/views/workspace.py index cbf62548fb6..8464fc8f7ee 100644 --- a/apiserver/plane/api/views/workspace.py +++ b/apiserver/plane/api/views/workspace.py @@ -1473,3 +1473,44 @@ def get(self, request, slug): {"error": "Something went wrong please try again later"}, status=status.HTTP_400_BAD_REQUEST, ) + + +class LeaveWorkspaceEndpoint(BaseAPIView): + permission_classes = [ + WorkspaceEntityPermission, + ] + + def delete(self, request, slug): + try: + workspace_member = WorkspaceMember.objects.get( + workspace__slug=slug, member=request.user + ) + + # Only Admin case + if ( + workspace_member.role == 20 + and WorkspaceMember.objects.filter( + workspace__slug=slug, role=20 + ).count() + == 1 + ): + return Response( + { + "error": "You cannot leave the workspace since you are the only admin of the workspace you should delete the workspace" + }, + status=status.HTTP_400, + ) + # Delete the member from workspace + workspace_member.delete() + return Response(status=status.HTTP_204_NO_CONTENT) + except WorkspaceMember.DoesNotExist: + return Response( + {"error": "Workspace member does not exists"}, + status=status.HTTP_400_BAD_REQUEST, + ) + except Exception as e: + capture_exception(e) + return Response( + {"error": "Something went wrong please try again later"}, + status=status.HTTP_400_BAD_REQUEST, + ) From e1a97eb9036175f93eea2697a541ab23b43573d5 Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Fri, 1 Sep 2023 11:35:35 +0530 Subject: [PATCH 2/3] fix: argument error --- apiserver/plane/api/urls.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/apiserver/plane/api/urls.py b/apiserver/plane/api/urls.py index 57f62764dea..558b7f059d8 100644 --- a/apiserver/plane/api/urls.py +++ b/apiserver/plane/api/urls.py @@ -563,11 +563,7 @@ ), path( "workspaces//projects//members/leave/", - LeaveProjectEndpoint.as_view( - { - "delete": "destroy", - } - ), + LeaveProjectEndpoint.as_view(), name="project", ), # End Projects From 66111d650294bea3178ce8398554577603c27f90 Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Fri, 1 Sep 2023 15:31:47 +0530 Subject: [PATCH 3/3] dev: update endpoint status --- apiserver/plane/api/views/project.py | 4 ++-- apiserver/plane/api/views/workspace.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apiserver/plane/api/views/project.py b/apiserver/plane/api/views/project.py index ec4f63540c1..a83bbca25d4 100644 --- a/apiserver/plane/api/views/project.py +++ b/apiserver/plane/api/views/project.py @@ -617,7 +617,7 @@ def destroy(self, request, slug, project_id, pk): return Response(status=status.HTTP_204_NO_CONTENT) except ProjectMember.DoesNotExist: return Response( - {"error": "Project Member does not exist"}, status=status.HTTP_400 + {"error": "Project Member does not exist"}, status=status.HTTP_400_BAD_REQUEST ) except Exception as e: capture_exception(e) @@ -1194,7 +1194,7 @@ def delete(self, request, slug, project_id): { "error": "You cannot leave the project since you are the only admin of the project you should delete the project" }, - status=status.HTTP_400, + status=status.HTTP_400_BAD_REQUEST, ) # Delete the member from workspace project_member.delete() diff --git a/apiserver/plane/api/views/workspace.py b/apiserver/plane/api/views/workspace.py index 8464fc8f7ee..ce425185e6e 100644 --- a/apiserver/plane/api/views/workspace.py +++ b/apiserver/plane/api/views/workspace.py @@ -1498,7 +1498,7 @@ def delete(self, request, slug): { "error": "You cannot leave the workspace since you are the only admin of the workspace you should delete the workspace" }, - status=status.HTTP_400, + status=status.HTTP_400_BAD_REQUEST, ) # Delete the member from workspace workspace_member.delete()