diff --git a/apiserver/plane/api/permissions/__init__.py b/apiserver/plane/api/permissions/__init__.py index 91b3aea35..8b15a9373 100644 --- a/apiserver/plane/api/permissions/__init__.py +++ b/apiserver/plane/api/permissions/__init__.py @@ -1,2 +1,2 @@ -from .workspace import WorkSpaceBasePermission, WorkSpaceAdminPermission, WorkspaceEntityPermission +from .workspace import WorkSpaceBasePermission, WorkSpaceAdminPermission, WorkspaceEntityPermission, WorkspaceViewerPermission from .project import ProjectBasePermission, ProjectEntityPermission, ProjectMemberPermission, ProjectLitePermission diff --git a/apiserver/plane/api/permissions/workspace.py b/apiserver/plane/api/permissions/workspace.py index 7fccc455e..d01b545ee 100644 --- a/apiserver/plane/api/permissions/workspace.py +++ b/apiserver/plane/api/permissions/workspace.py @@ -61,3 +61,13 @@ class WorkspaceEntityPermission(BasePermission): return WorkspaceMember.objects.filter( member=request.user, workspace__slug=view.workspace_slug ).exists() + + +class WorkspaceViewerPermission(BasePermission): + def has_permission(self, request, view): + if request.user.is_anonymous: + return False + + return WorkspaceMember.objects.filter( + member=request.user, workspace__slug=view.workspace_slug, role__gte=10 + ).exists() diff --git a/apiserver/plane/api/views/workspace.py b/apiserver/plane/api/views/workspace.py index a9822aa0b..10428b53d 100644 --- a/apiserver/plane/api/views/workspace.py +++ b/apiserver/plane/api/views/workspace.py @@ -73,12 +73,14 @@ from plane.db.models import ( IssueSubscriber, Project, Label, + WorkspaceMember, CycleIssue, ) from plane.api.permissions import ( WorkSpaceBasePermission, WorkSpaceAdminPermission, WorkspaceEntityPermission, + WorkspaceViewerPermission, ) from plane.bgtasks.workspace_invitation_task import workspace_invitation from plane.utils.issue_filters import issue_filters @@ -1209,64 +1211,64 @@ class WorkspaceUserActivityEndpoint(BaseAPIView): class WorkspaceUserProfileEndpoint(BaseAPIView): - permission_classes = [ - WorkspaceEntityPermission, - ] def get(self, request, slug, user_id): try: user_data = User.objects.get(pk=user_id) - projects = ( - Project.objects.filter( - workspace__slug=slug, - project_projectmember__member=request.user, - ) - .annotate( - created_issues=Count( - "project_issue", filter=Q(project_issue__created_by_id=user_id) + requesting_workspace_member = WorkspaceMember.objects.get(workspace__slug=slug, member=request.user) + projects = [] + if requesting_workspace_member.role >= 10: + projects = ( + Project.objects.filter( + workspace__slug=slug, + project_projectmember__member=request.user, + ) + .annotate( + created_issues=Count( + "project_issue", filter=Q(project_issue__created_by_id=user_id) + ) + ) + .annotate( + assigned_issues=Count( + "project_issue", + filter=Q(project_issue__assignees__in=[user_id]), + ) + ) + .annotate( + completed_issues=Count( + "project_issue", + filter=Q( + project_issue__completed_at__isnull=False, + project_issue__assignees__in=[user_id], + ), + ) + ) + .annotate( + pending_issues=Count( + "project_issue", + filter=Q( + project_issue__state__group__in=[ + "backlog", + "unstarted", + "started", + ], + project_issue__assignees__in=[user_id], + ), + ) + ) + .values( + "id", + "name", + "identifier", + "emoji", + "icon_prop", + "created_issues", + "assigned_issues", + "completed_issues", + "pending_issues", ) ) - .annotate( - assigned_issues=Count( - "project_issue", - filter=Q(project_issue__assignees__in=[user_id]), - ) - ) - .annotate( - completed_issues=Count( - "project_issue", - filter=Q( - project_issue__completed_at__isnull=False, - project_issue__assignees__in=[user_id], - ), - ) - ) - .annotate( - pending_issues=Count( - "project_issue", - filter=Q( - project_issue__state__group__in=[ - "backlog", - "unstarted", - "started", - ], - project_issue__assignees__in=[user_id], - ), - ) - ) - .values( - "id", - "name", - "identifier", - "emoji", - "icon_prop", - "created_issues", - "assigned_issues", - "completed_issues", - "pending_issues", - ) - ) return Response( { @@ -1283,6 +1285,8 @@ class WorkspaceUserProfileEndpoint(BaseAPIView): }, status=status.HTTP_200_OK, ) + except WorkspaceMember.DoesNotExist: + return Response({"error": "Forbidden"}, status=status.HTTP_403_FORBIDDEN) except Exception as e: capture_exception(e) return Response( @@ -1293,7 +1297,7 @@ class WorkspaceUserProfileEndpoint(BaseAPIView): class WorkspaceUserProfileIssuesEndpoint(BaseAPIView): permission_classes = [ - WorkspaceEntityPermission, + WorkspaceViewerPermission, ] def get(self, request, slug, user_id): @@ -1412,7 +1416,7 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView): class WorkspaceLabelsEndpoint(BaseAPIView): permission_classes = [ - WorkspaceEntityPermission, + WorkspaceViewerPermission, ] def get(self, request, slug):