From 02f4916e4916d18abdcfb41db1d6614b88592d4e Mon Sep 17 00:00:00 2001 From: Bavisetti Narayan <72156168+NarayanBavisetti@users.noreply.github.com> Date: Wed, 1 Nov 2023 14:30:45 +0530 Subject: [PATCH] chore: workspace members and project members endpoint (#2560) * fix: removed members endpoint * fix: changed project permisson class for project member * fix: permission changed in workspace and project * fix: added project filter in members --- apiserver/plane/api/urls/project.py | 16 +-- apiserver/plane/api/urls/workspace.py | 6 - apiserver/plane/api/views/__init__.py | 3 - apiserver/plane/api/views/project.py | 159 ++++++++++++------------- apiserver/plane/api/views/workspace.py | 35 +++--- 5 files changed, 99 insertions(+), 120 deletions(-) diff --git a/apiserver/plane/api/urls/project.py b/apiserver/plane/api/urls/project.py index b2a3fbd60..2d9e513df 100644 --- a/apiserver/plane/api/urls/project.py +++ b/apiserver/plane/api/urls/project.py @@ -4,17 +4,15 @@ from plane.api.views import ( ProjectViewSet, InviteProjectEndpoint, ProjectMemberViewSet, - ProjectMemberEndpoint, ProjectMemberInvitationsViewset, ProjectMemberUserEndpoint, - AddMemberToProjectEndpoint, ProjectJoinEndpoint, AddTeamToProjectEndpoint, ProjectUserViewsEndpoint, ProjectIdentifierEndpoint, ProjectFavoritesViewSet, LeaveProjectEndpoint, - ProjectPublicCoverImagesEndpoint + ProjectPublicCoverImagesEndpoint, ) @@ -53,7 +51,7 @@ urlpatterns = [ ), path( "workspaces//projects//members/", - ProjectMemberViewSet.as_view({"get": "list"}), + ProjectMemberViewSet.as_view({"get": "list", "post": "create"}), name="project-member", ), path( @@ -67,16 +65,6 @@ urlpatterns = [ ), name="project-member", ), - path( - "workspaces//projects//project-members/", - ProjectMemberEndpoint.as_view(), - name="project-member", - ), - path( - "workspaces//projects//members/add/", - AddMemberToProjectEndpoint.as_view(), - name="project", - ), path( "workspaces//projects/join/", ProjectJoinEndpoint.as_view(), diff --git a/apiserver/plane/api/urls/workspace.py b/apiserver/plane/api/urls/workspace.py index 7cfc8f27a..f26730833 100644 --- a/apiserver/plane/api/urls/workspace.py +++ b/apiserver/plane/api/urls/workspace.py @@ -5,7 +5,6 @@ from plane.api.views import ( WorkSpaceViewSet, InviteWorkspaceEndpoint, WorkSpaceMemberViewSet, - WorkspaceMembersEndpoint, WorkspaceInvitationsViewset, WorkspaceMemberUserEndpoint, WorkspaceMemberUserViewsEndpoint, @@ -86,11 +85,6 @@ urlpatterns = [ ), name="workspace-member", ), - path( - "workspaces//workspace-members/", - WorkspaceMembersEndpoint.as_view(), - name="workspace-members", - ), path( "workspaces//teams/", TeamMemberViewSet.as_view( diff --git a/apiserver/plane/api/views/__init__.py b/apiserver/plane/api/views/__init__.py index e17550050..df6de7a82 100644 --- a/apiserver/plane/api/views/__init__.py +++ b/apiserver/plane/api/views/__init__.py @@ -7,14 +7,12 @@ from .project import ( ProjectMemberInvitationsViewset, ProjectMemberInviteDetailViewSet, ProjectIdentifierEndpoint, - AddMemberToProjectEndpoint, ProjectJoinEndpoint, ProjectUserViewsEndpoint, ProjectMemberUserEndpoint, ProjectFavoritesViewSet, ProjectDeployBoardViewSet, ProjectDeployBoardPublicSettingsEndpoint, - ProjectMemberEndpoint, WorkspaceProjectDeployBoardEndpoint, LeaveProjectEndpoint, ProjectPublicCoverImagesEndpoint, @@ -53,7 +51,6 @@ from .workspace import ( WorkspaceUserProfileEndpoint, WorkspaceUserProfileIssuesEndpoint, WorkspaceLabelsEndpoint, - WorkspaceMembersEndpoint, LeaveWorkspaceEndpoint, ) from .state import StateViewSet diff --git a/apiserver/plane/api/views/project.py b/apiserver/plane/api/views/project.py index 632a5bf53..6ce847f9d 100644 --- a/apiserver/plane/api/views/project.py +++ b/apiserver/plane/api/views/project.py @@ -482,6 +482,83 @@ class ProjectMemberViewSet(BaseViewSet): .select_related("workspace", "workspace__owner") ) + def create(self, request, slug, project_id): + members = request.data.get("members", []) + + # get the project + project = Project.objects.get(pk=project_id, workspace__slug=slug) + + if not len(members): + return Response( + {"error": "Atleast one member is required"}, + status=status.HTTP_400_BAD_REQUEST, + ) + bulk_project_members = [] + bulk_issue_props = [] + + project_members = ( + ProjectMember.objects.filter( + workspace__slug=slug, + member_id__in=[member.get("member_id") for member in members], + ) + .values("member_id", "sort_order") + .order_by("sort_order") + ) + + for member in members: + sort_order = [ + project_member.get("sort_order") + for project_member in project_members + if str(project_member.get("member_id")) == str(member.get("member_id")) + ] + bulk_project_members.append( + ProjectMember( + member_id=member.get("member_id"), + role=member.get("role", 10), + project_id=project_id, + workspace_id=project.workspace_id, + sort_order=sort_order[0] - 10000 if len(sort_order) else 65535, + ) + ) + bulk_issue_props.append( + IssueProperty( + user_id=member.get("member_id"), + project_id=project_id, + workspace_id=project.workspace_id, + ) + ) + + project_members = ProjectMember.objects.bulk_create( + bulk_project_members, + batch_size=10, + ignore_conflicts=True, + ) + + _ = IssueProperty.objects.bulk_create( + bulk_issue_props, batch_size=10, ignore_conflicts=True + ) + + serializer = ProjectMemberSerializer(project_members, many=True) + + return Response(serializer.data, status=status.HTTP_201_CREATED) + + def list(self, request, slug, project_id): + project_member = ProjectMember.objects.get( + member=request.user, workspace__slug=slug, project_id=project_id + ) + + project_members = ProjectMember.objects.filter( + project_id=project_id, + workspace__slug=slug, + member__is_bot=False, + ).select_related("project", "member", "workspace") + + if project_member.role > 10: + serializer = ProjectMemberAdminSerializer(project_members, many=True) + else: + serializer = ProjectMemberSerializer(project_members, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + def partial_update(self, request, slug, project_id, pk): project_member = ProjectMember.objects.get( pk=pk, workspace__slug=slug, project_id=project_id @@ -567,73 +644,6 @@ class ProjectMemberViewSet(BaseViewSet): return Response(status=status.HTTP_204_NO_CONTENT) -class AddMemberToProjectEndpoint(BaseAPIView): - permission_classes = [ - ProjectBasePermission, - ] - - def post(self, request, slug, project_id): - members = request.data.get("members", []) - - # get the project - project = Project.objects.get(pk=project_id, workspace__slug=slug) - - if not len(members): - return Response( - {"error": "Atleast one member is required"}, - status=status.HTTP_400_BAD_REQUEST, - ) - bulk_project_members = [] - bulk_issue_props = [] - - project_members = ( - ProjectMember.objects.filter( - workspace__slug=slug, - member_id__in=[member.get("member_id") for member in members], - ) - .values("member_id", "sort_order") - .order_by("sort_order") - ) - - for member in members: - sort_order = [ - project_member.get("sort_order") - for project_member in project_members - if str(project_member.get("member_id")) - == str(member.get("member_id")) - ] - bulk_project_members.append( - ProjectMember( - member_id=member.get("member_id"), - role=member.get("role", 10), - project_id=project_id, - workspace_id=project.workspace_id, - sort_order=sort_order[0] - 10000 if len(sort_order) else 65535, - ) - ) - bulk_issue_props.append( - IssueProperty( - user_id=member.get("member_id"), - project_id=project_id, - workspace_id=project.workspace_id, - ) - ) - - project_members = ProjectMember.objects.bulk_create( - bulk_project_members, - batch_size=10, - ignore_conflicts=True, - ) - - _ = IssueProperty.objects.bulk_create( - bulk_issue_props, batch_size=10, ignore_conflicts=True - ) - - serializer = ProjectMemberSerializer(project_members, many=True) - - return Response(serializer.data, status=status.HTTP_201_CREATED) - - class AddTeamToProjectEndpoint(BaseAPIView): permission_classes = [ ProjectBasePermission, @@ -933,21 +943,6 @@ class ProjectDeployBoardViewSet(BaseViewSet): return Response(serializer.data, status=status.HTTP_200_OK) -class ProjectMemberEndpoint(BaseAPIView): - permission_classes = [ - ProjectEntityPermission, - ] - - def get(self, request, slug, project_id): - project_members = ProjectMember.objects.filter( - project_id=project_id, - workspace__slug=slug, - member__is_bot=False, - ).select_related("project", "member", "workspace") - serializer = ProjectMemberSerializer(project_members, many=True) - return Response(serializer.data, status=status.HTTP_200_OK) - - class ProjectDeployBoardPublicSettingsEndpoint(BaseAPIView): permission_classes = [ AllowAny, diff --git a/apiserver/plane/api/views/workspace.py b/apiserver/plane/api/views/workspace.py index 165a96179..ff555a711 100644 --- a/apiserver/plane/api/views/workspace.py +++ b/apiserver/plane/api/views/workspace.py @@ -472,7 +472,7 @@ class WorkSpaceMemberViewSet(BaseViewSet): model = WorkspaceMember permission_classes = [ - WorkSpaceAdminPermission, + WorkspaceEntityPermission, ] search_fields = [ @@ -489,6 +489,25 @@ class WorkSpaceMemberViewSet(BaseViewSet): .select_related("member") ) + def list(self, request, slug): + workspace_member = WorkspaceMember.objects.get( + member=request.user, workspace__slug=slug + ) + + workspace_members = WorkspaceMember.objects.filter( + workspace__slug=slug, + member__is_bot=False, + ).select_related("workspace", "member") + + if workspace_member.role > 10: + serializer = WorkspaceMemberAdminSerializer(workspace_members, many=True) + else: + serializer = WorkSpaceMemberSerializer( + workspace_members, + many=True, + ) + return Response(serializer.data, status=status.HTTP_200_OK) + def partial_update(self, request, slug, pk): workspace_member = WorkspaceMember.objects.get(pk=pk, workspace__slug=slug) if request.user.id == workspace_member.member_id: @@ -1252,20 +1271,6 @@ class WorkspaceLabelsEndpoint(BaseAPIView): return Response(labels, status=status.HTTP_200_OK) -class WorkspaceMembersEndpoint(BaseAPIView): - permission_classes = [ - WorkspaceEntityPermission, - ] - - def get(self, request, slug): - workspace_members = WorkspaceMember.objects.filter( - workspace__slug=slug, - member__is_bot=False, - ).select_related("workspace", "member") - serialzier = WorkSpaceMemberSerializer(workspace_members, many=True) - return Response(serialzier.data, status=status.HTTP_200_OK) - - class LeaveWorkspaceEndpoint(BaseAPIView): permission_classes = [ WorkspaceEntityPermission,