From 9e60f34fb2644a1abf3af9837820aae21dc2f4f2 Mon Sep 17 00:00:00 2001 From: Bavisetti Narayan <72156168+NarayanBavisetti@users.noreply.github.com> Date: Fri, 15 Dec 2023 18:01:16 +0530 Subject: [PATCH] feat: workspace and project members endpoint (#3092) --- apiserver/plane/app/serializers/__init__.py | 1 + apiserver/plane/app/serializers/project.py | 5 +++ apiserver/plane/app/serializers/workspace.py | 4 +- apiserver/plane/app/urls/workspace.py | 6 +++ apiserver/plane/app/views/__init__.py | 1 + apiserver/plane/app/views/project.py | 14 ++---- apiserver/plane/app/views/workspace.py | 45 +++++++++++++++++++- 7 files changed, 62 insertions(+), 14 deletions(-) diff --git a/apiserver/plane/app/serializers/__init__.py b/apiserver/plane/app/serializers/__init__.py index c406453b7..c1f8f71b6 100644 --- a/apiserver/plane/app/serializers/__init__.py +++ b/apiserver/plane/app/serializers/__init__.py @@ -31,6 +31,7 @@ from .project import ( ProjectDeployBoardSerializer, ProjectMemberAdminSerializer, ProjectPublicMemberSerializer, + ProjectMemberRoleSerializer, ) from .state import StateSerializer, StateLiteSerializer from .view import GlobalViewSerializer, IssueViewSerializer, IssueViewFavoriteSerializer diff --git a/apiserver/plane/app/serializers/project.py b/apiserver/plane/app/serializers/project.py index aef715e33..b3122962b 100644 --- a/apiserver/plane/app/serializers/project.py +++ b/apiserver/plane/app/serializers/project.py @@ -159,6 +159,11 @@ class ProjectMemberAdminSerializer(BaseSerializer): model = ProjectMember fields = "__all__" +class ProjectMemberRoleSerializer(DynamicBaseSerializer): + + class Meta: + model = ProjectMember + fields = ("id", "role", "member", "project") class ProjectMemberInviteSerializer(BaseSerializer): project = ProjectLiteSerializer(read_only=True) diff --git a/apiserver/plane/app/serializers/workspace.py b/apiserver/plane/app/serializers/workspace.py index d6f0894a5..78e14a25c 100644 --- a/apiserver/plane/app/serializers/workspace.py +++ b/apiserver/plane/app/serializers/workspace.py @@ -62,7 +62,7 @@ class WorkspaceLiteSerializer(BaseSerializer): -class WorkSpaceMemberSerializer(BaseSerializer): +class WorkSpaceMemberSerializer(DynamicBaseSerializer): member = UserLiteSerializer(read_only=True) workspace = WorkspaceLiteSerializer(read_only=True) @@ -78,7 +78,7 @@ class WorkspaceMemberMeSerializer(BaseSerializer): fields = "__all__" -class WorkspaceMemberAdminSerializer(BaseSerializer): +class WorkspaceMemberAdminSerializer(DynamicBaseSerializer): member = UserAdminLiteSerializer(read_only=True) workspace = WorkspaceLiteSerializer(read_only=True) diff --git a/apiserver/plane/app/urls/workspace.py b/apiserver/plane/app/urls/workspace.py index 2c3638842..b400ff701 100644 --- a/apiserver/plane/app/urls/workspace.py +++ b/apiserver/plane/app/urls/workspace.py @@ -18,6 +18,7 @@ from plane.app.views import ( WorkspaceUserProfileEndpoint, WorkspaceUserProfileIssuesEndpoint, WorkspaceLabelsEndpoint, + WorkspaceProjectMemberEndpoint, ) @@ -92,6 +93,11 @@ urlpatterns = [ WorkSpaceMemberViewSet.as_view({"get": "list"}), name="workspace-member", ), + path( + "workspaces//project-members/", + WorkspaceProjectMemberEndpoint.as_view(), + name="workspace-member-roles", + ), path( "workspaces//members//", WorkSpaceMemberViewSet.as_view( diff --git a/apiserver/plane/app/views/__init__.py b/apiserver/plane/app/views/__init__.py index c122dce9f..5939f7ab4 100644 --- a/apiserver/plane/app/views/__init__.py +++ b/apiserver/plane/app/views/__init__.py @@ -45,6 +45,7 @@ from .workspace import ( WorkspaceUserProfileEndpoint, WorkspaceUserProfileIssuesEndpoint, WorkspaceLabelsEndpoint, + WorkspaceProjectMemberEndpoint ) from .state import StateViewSet from .view import ( diff --git a/apiserver/plane/app/views/project.py b/apiserver/plane/app/views/project.py index aa98615fd..c5caac666 100644 --- a/apiserver/plane/app/views/project.py +++ b/apiserver/plane/app/views/project.py @@ -36,6 +36,7 @@ from plane.app.serializers import ( ProjectFavoriteSerializer, ProjectDeployBoardSerializer, ProjectMemberAdminSerializer, + ProjectMemberRoleSerializer, ) from plane.app.permissions import ( @@ -710,13 +711,7 @@ class ProjectMemberViewSet(BaseViewSet): 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, - is_active=True, - ) - + # Get the list of project members for the project project_members = ProjectMember.objects.filter( project_id=project_id, workspace__slug=slug, @@ -724,10 +719,7 @@ class ProjectMemberViewSet(BaseViewSet): is_active=True, ).select_related("project", "member", "workspace") - if project_member.role > 10: - serializer = ProjectMemberAdminSerializer(project_members, many=True) - else: - serializer = ProjectMemberSerializer(project_members, many=True) + serializer = ProjectMemberRoleSerializer(project_members, fields=("id", "member", "role"), many=True) return Response(serializer.data, status=status.HTTP_200_OK) def partial_update(self, request, slug, project_id, pk): diff --git a/apiserver/plane/app/views/workspace.py b/apiserver/plane/app/views/workspace.py index cf002af63..8d778a850 100644 --- a/apiserver/plane/app/views/workspace.py +++ b/apiserver/plane/app/views/workspace.py @@ -44,6 +44,7 @@ from plane.app.serializers import ( IssueLiteSerializer, WorkspaceMemberAdminSerializer, WorkspaceMemberMeSerializer, + ProjectMemberRoleSerializer, ) from plane.app.views.base import BaseAPIView from . import BaseViewSet @@ -543,10 +544,15 @@ class WorkSpaceMemberViewSet(BaseViewSet): workspace_members = self.get_queryset() if workspace_member.role > 10: - serializer = WorkspaceMemberAdminSerializer(workspace_members, many=True) + serializer = WorkspaceMemberAdminSerializer( + workspace_members, + fields=("id", "member", "role"), + many=True, + ) else: serializer = WorkSpaceMemberSerializer( workspace_members, + fields=("id", "member", "role"), many=True, ) return Response(serializer.data, status=status.HTTP_200_OK) @@ -711,6 +717,43 @@ class WorkSpaceMemberViewSet(BaseViewSet): return Response(status=status.HTTP_204_NO_CONTENT) +class WorkspaceProjectMemberEndpoint(BaseAPIView): + serializer_class = ProjectMemberRoleSerializer + model = ProjectMember + + permission_classes = [ + WorkspaceEntityPermission, + ] + + def get(self, request, slug): + # Fetch all project IDs where the user is involved + project_ids = ProjectMember.objects.filter( + member=request.user, + member__is_bot=False, + is_active=True, + ).values_list('project_id', flat=True).distinct() + + # Get all the project members in which the user is involved + project_members = ProjectMember.objects.filter( + workspace__slug=slug, + member__is_bot=False, + project_id__in=project_ids, + is_active=True, + ).select_related("project", "member", "workspace") + project_members = ProjectMemberRoleSerializer(project_members, many=True).data + + project_members_dict = dict() + + # Construct a dictionary with project_id as key and project_members as value + for project_member in project_members: + project_id = project_member.pop("project") + if str(project_id) not in project_members_dict: + project_members_dict[str(project_id)] = [] + project_members_dict[str(project_id)].append(project_member) + + return Response(project_members_dict, status=status.HTTP_200_OK) + + class TeamMemberViewSet(BaseViewSet): serializer_class = TeamSerializer model = Team