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
This commit is contained in:
Bavisetti Narayan 2023-11-01 14:30:45 +05:30 committed by GitHub
parent 1be82814fc
commit 02f4916e49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 99 additions and 120 deletions

View File

@ -4,17 +4,15 @@ from plane.api.views import (
ProjectViewSet, ProjectViewSet,
InviteProjectEndpoint, InviteProjectEndpoint,
ProjectMemberViewSet, ProjectMemberViewSet,
ProjectMemberEndpoint,
ProjectMemberInvitationsViewset, ProjectMemberInvitationsViewset,
ProjectMemberUserEndpoint, ProjectMemberUserEndpoint,
AddMemberToProjectEndpoint,
ProjectJoinEndpoint, ProjectJoinEndpoint,
AddTeamToProjectEndpoint, AddTeamToProjectEndpoint,
ProjectUserViewsEndpoint, ProjectUserViewsEndpoint,
ProjectIdentifierEndpoint, ProjectIdentifierEndpoint,
ProjectFavoritesViewSet, ProjectFavoritesViewSet,
LeaveProjectEndpoint, LeaveProjectEndpoint,
ProjectPublicCoverImagesEndpoint ProjectPublicCoverImagesEndpoint,
) )
@ -53,7 +51,7 @@ urlpatterns = [
), ),
path( path(
"workspaces/<str:slug>/projects/<uuid:project_id>/members/", "workspaces/<str:slug>/projects/<uuid:project_id>/members/",
ProjectMemberViewSet.as_view({"get": "list"}), ProjectMemberViewSet.as_view({"get": "list", "post": "create"}),
name="project-member", name="project-member",
), ),
path( path(
@ -67,16 +65,6 @@ urlpatterns = [
), ),
name="project-member", name="project-member",
), ),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/project-members/",
ProjectMemberEndpoint.as_view(),
name="project-member",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/members/add/",
AddMemberToProjectEndpoint.as_view(),
name="project",
),
path( path(
"workspaces/<str:slug>/projects/join/", "workspaces/<str:slug>/projects/join/",
ProjectJoinEndpoint.as_view(), ProjectJoinEndpoint.as_view(),

View File

@ -5,7 +5,6 @@ from plane.api.views import (
WorkSpaceViewSet, WorkSpaceViewSet,
InviteWorkspaceEndpoint, InviteWorkspaceEndpoint,
WorkSpaceMemberViewSet, WorkSpaceMemberViewSet,
WorkspaceMembersEndpoint,
WorkspaceInvitationsViewset, WorkspaceInvitationsViewset,
WorkspaceMemberUserEndpoint, WorkspaceMemberUserEndpoint,
WorkspaceMemberUserViewsEndpoint, WorkspaceMemberUserViewsEndpoint,
@ -86,11 +85,6 @@ urlpatterns = [
), ),
name="workspace-member", name="workspace-member",
), ),
path(
"workspaces/<str:slug>/workspace-members/",
WorkspaceMembersEndpoint.as_view(),
name="workspace-members",
),
path( path(
"workspaces/<str:slug>/teams/", "workspaces/<str:slug>/teams/",
TeamMemberViewSet.as_view( TeamMemberViewSet.as_view(

View File

@ -7,14 +7,12 @@ from .project import (
ProjectMemberInvitationsViewset, ProjectMemberInvitationsViewset,
ProjectMemberInviteDetailViewSet, ProjectMemberInviteDetailViewSet,
ProjectIdentifierEndpoint, ProjectIdentifierEndpoint,
AddMemberToProjectEndpoint,
ProjectJoinEndpoint, ProjectJoinEndpoint,
ProjectUserViewsEndpoint, ProjectUserViewsEndpoint,
ProjectMemberUserEndpoint, ProjectMemberUserEndpoint,
ProjectFavoritesViewSet, ProjectFavoritesViewSet,
ProjectDeployBoardViewSet, ProjectDeployBoardViewSet,
ProjectDeployBoardPublicSettingsEndpoint, ProjectDeployBoardPublicSettingsEndpoint,
ProjectMemberEndpoint,
WorkspaceProjectDeployBoardEndpoint, WorkspaceProjectDeployBoardEndpoint,
LeaveProjectEndpoint, LeaveProjectEndpoint,
ProjectPublicCoverImagesEndpoint, ProjectPublicCoverImagesEndpoint,
@ -53,7 +51,6 @@ from .workspace import (
WorkspaceUserProfileEndpoint, WorkspaceUserProfileEndpoint,
WorkspaceUserProfileIssuesEndpoint, WorkspaceUserProfileIssuesEndpoint,
WorkspaceLabelsEndpoint, WorkspaceLabelsEndpoint,
WorkspaceMembersEndpoint,
LeaveWorkspaceEndpoint, LeaveWorkspaceEndpoint,
) )
from .state import StateViewSet from .state import StateViewSet

View File

@ -482,6 +482,83 @@ class ProjectMemberViewSet(BaseViewSet):
.select_related("workspace", "workspace__owner") .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): def partial_update(self, request, slug, project_id, pk):
project_member = ProjectMember.objects.get( project_member = ProjectMember.objects.get(
pk=pk, workspace__slug=slug, project_id=project_id pk=pk, workspace__slug=slug, project_id=project_id
@ -567,73 +644,6 @@ class ProjectMemberViewSet(BaseViewSet):
return Response(status=status.HTTP_204_NO_CONTENT) 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): class AddTeamToProjectEndpoint(BaseAPIView):
permission_classes = [ permission_classes = [
ProjectBasePermission, ProjectBasePermission,
@ -933,21 +943,6 @@ class ProjectDeployBoardViewSet(BaseViewSet):
return Response(serializer.data, status=status.HTTP_200_OK) 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): class ProjectDeployBoardPublicSettingsEndpoint(BaseAPIView):
permission_classes = [ permission_classes = [
AllowAny, AllowAny,

View File

@ -472,7 +472,7 @@ class WorkSpaceMemberViewSet(BaseViewSet):
model = WorkspaceMember model = WorkspaceMember
permission_classes = [ permission_classes = [
WorkSpaceAdminPermission, WorkspaceEntityPermission,
] ]
search_fields = [ search_fields = [
@ -489,6 +489,25 @@ class WorkSpaceMemberViewSet(BaseViewSet):
.select_related("member") .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): def partial_update(self, request, slug, pk):
workspace_member = WorkspaceMember.objects.get(pk=pk, workspace__slug=slug) workspace_member = WorkspaceMember.objects.get(pk=pk, workspace__slug=slug)
if request.user.id == workspace_member.member_id: if request.user.id == workspace_member.member_id:
@ -1252,20 +1271,6 @@ class WorkspaceLabelsEndpoint(BaseAPIView):
return Response(labels, status=status.HTTP_200_OK) 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): class LeaveWorkspaceEndpoint(BaseAPIView):
permission_classes = [ permission_classes = [
WorkspaceEntityPermission, WorkspaceEntityPermission,