[WEB-2043] chore: updated permissions for delete operation (#5231)

* chore: added permission for delete operation

* chore: added permission for external apis

* chore: condition changes

* chore: minor changes
This commit is contained in:
Bavisetti Narayan 2024-07-26 16:42:51 +05:30 committed by GitHub
parent dfcba4dfc1
commit 2c609670c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 197 additions and 52 deletions

View file

@ -34,6 +34,7 @@ from plane.db.models import (
Project, Project,
IssueAttachment, IssueAttachment,
IssueLink, IssueLink,
ProjectMember,
) )
from plane.utils.analytics_plot import burndown_plot from plane.utils.analytics_plot import burndown_plot
@ -363,14 +364,28 @@ class CycleAPIEndpoint(BaseAPIView):
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, slug, project_id, pk): def delete(self, request, slug, project_id, pk):
cycle = Cycle.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk
)
if cycle.owned_by_id != request.user.id and (
not ProjectMember.objects.filter(
workspace__slug=slug,
member=request.user,
role=20,
project_id=project_id,
is_active=True,
).exists()
):
return Response(
{"error": "Only admin or creator can delete the cycle"},
status=status.HTTP_403_FORBIDDEN,
)
cycle_issues = list( cycle_issues = list(
CycleIssue.objects.filter( CycleIssue.objects.filter(
cycle_id=self.kwargs.get("pk") cycle_id=self.kwargs.get("pk")
).values_list("issue", flat=True) ).values_list("issue", flat=True)
) )
cycle = Cycle.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk
)
issue_activity.delay( issue_activity.delay(
type="cycle.activity.deleted", type="cycle.activity.deleted",

View file

@ -390,29 +390,26 @@ class InboxIssueAPIEndpoint(BaseAPIView):
inbox_id=inbox.id, inbox_id=inbox.id,
) )
# Get the project member
project_member = ProjectMember.objects.get(
workspace__slug=slug,
project_id=project_id,
member=request.user,
is_active=True,
)
# Check the inbox issue created
if project_member.role <= 10 and str(inbox_issue.created_by_id) != str(
request.user.id
):
return Response(
{"error": "You cannot delete inbox issue"},
status=status.HTTP_400_BAD_REQUEST,
)
# Check the issue status # Check the issue status
if inbox_issue.status in [-2, -1, 0, 2]: if inbox_issue.status in [-2, -1, 0, 2]:
# Delete the issue also # Delete the issue also
Issue.objects.filter( issue = Issue.objects.filter(
workspace__slug=slug, project_id=project_id, pk=issue_id workspace__slug=slug, project_id=project_id, pk=issue_id
).delete() ).first()
if issue.created_by_id != request.user.id and (
not ProjectMember.objects.filter(
workspace__slug=slug,
member=request.user,
role=20,
project_id=project_id,
is_active=True,
).exists()
):
return Response(
{"error": "Only admin or creator can delete the issue"},
status=status.HTTP_403_FORBIDDEN,
)
issue.delete()
inbox_issue.delete() inbox_issue.delete()
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)

View file

@ -310,11 +310,14 @@ class IssueAPIEndpoint(BaseAPIView):
serializer.save() serializer.save()
# Refetch the issue # Refetch the issue
issue = Issue.objects.filter(workspace__slug=slug, project_id=project_id, pk=serializer.data["id"]).first() issue = Issue.objects.filter(
workspace__slug=slug,
project_id=project_id,
pk=serializer.data["id"],
).first()
issue.created_at = request.data.get("created_at") issue.created_at = request.data.get("created_at")
issue.save(update_fields=["created_at"]) issue.save(update_fields=["created_at"])
# Track the issue # Track the issue
issue_activity.delay( issue_activity.delay(
type="issue.activity.created", type="issue.activity.created",
@ -386,6 +389,19 @@ class IssueAPIEndpoint(BaseAPIView):
issue = Issue.objects.get( issue = Issue.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk workspace__slug=slug, project_id=project_id, pk=pk
) )
if issue.created_by_id != request.user.id and (
not ProjectMember.objects.filter(
workspace__slug=slug,
member=request.user,
role=20,
project_id=project_id,
is_active=True,
).exists()
):
return Response(
{"error": "Only admin or creator can delete the issue"},
status=status.HTTP_403_FORBIDDEN,
)
current_instance = json.dumps( current_instance = json.dumps(
IssueSerializer(issue).data, cls=DjangoJSONEncoder IssueSerializer(issue).data, cls=DjangoJSONEncoder
) )

View file

@ -27,6 +27,7 @@ from plane.db.models import (
ModuleIssue, ModuleIssue,
ModuleLink, ModuleLink,
Project, Project,
ProjectMember,
) )
from .base import BaseAPIView from .base import BaseAPIView
@ -265,6 +266,20 @@ class ModuleAPIEndpoint(BaseAPIView):
module = Module.objects.get( module = Module.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk workspace__slug=slug, project_id=project_id, pk=pk
) )
if module.created_by_id != request.user.id and (
not ProjectMember.objects.filter(
workspace__slug=slug,
member=request.user,
role=20,
project_id=project_id,
is_active=True,
).exists()
):
return Response(
{"error": "Only admin or creator can delete the module"},
status=status.HTTP_403_FORBIDDEN,
)
module_issues = list( module_issues = list(
ModuleIssue.objects.filter(module_id=pk).values_list( ModuleIssue.objects.filter(module_id=pk).values_list(
"issue", flat=True "issue", flat=True

View file

@ -47,6 +47,7 @@ from plane.db.models import (
Label, Label,
User, User,
Project, Project,
ProjectMember,
) )
from plane.utils.analytics_plot import burndown_plot from plane.utils.analytics_plot import burndown_plot
@ -1039,14 +1040,28 @@ class CycleViewSet(BaseViewSet):
) )
def destroy(self, request, slug, project_id, pk): def destroy(self, request, slug, project_id, pk):
cycle = Cycle.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk
)
if cycle.owned_by_id != request.user.id and not (
ProjectMember.objects.filter(
workspace__slug=slug,
member=request.user,
role=20,
project_id=project_id,
is_active=True,
).exists()
):
return Response(
{"error": "Only admin or owner can delete the cycle"},
status=status.HTTP_403_FORBIDDEN,
)
cycle_issues = list( cycle_issues = list(
CycleIssue.objects.filter( CycleIssue.objects.filter(
cycle_id=self.kwargs.get("pk") cycle_id=self.kwargs.get("pk")
).values_list("issue", flat=True) ).values_list("issue", flat=True)
) )
cycle = Cycle.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk
)
issue_activity.delay( issue_activity.delay(
type="cycle.activity.deleted", type="cycle.activity.deleted",

View file

@ -553,28 +553,27 @@ class InboxIssueViewSet(BaseViewSet):
project_id=project_id, project_id=project_id,
inbox_id=inbox_id, inbox_id=inbox_id,
) )
# Get the project member
project_member = ProjectMember.objects.get(
workspace__slug=slug,
project_id=project_id,
member=request.user,
is_active=True,
)
if project_member.role <= 10 and str(inbox_issue.created_by_id) != str(
request.user.id
):
return Response(
{"error": "You cannot delete inbox issue"},
status=status.HTTP_400_BAD_REQUEST,
)
# Check the issue status # Check the issue status
if inbox_issue.status in [-2, -1, 0, 2]: if inbox_issue.status in [-2, -1, 0, 2]:
# Delete the issue also # Delete the issue also
Issue.objects.filter( issue = Issue.objects.filter(
workspace__slug=slug, project_id=project_id, pk=issue_id workspace__slug=slug, project_id=project_id, pk=issue_id
).delete() ).first()
if issue.created_by_id != request.user.id and (
not ProjectMember.objects.filter(
workspace__slug=slug,
member=request.user,
role=20,
project_id=project_id,
is_active=True,
).exists()
):
return Response(
{"error": "Only admin or creator can delete the issue"},
status=status.HTTP_403_FORBIDDEN,
)
issue.delete()
inbox_issue.delete() inbox_issue.delete()
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)

View file

@ -44,6 +44,7 @@ from plane.db.models import (
IssueReaction, IssueReaction,
IssueSubscriber, IssueSubscriber,
Project, Project,
ProjectMember,
) )
from plane.utils.grouper import ( from plane.utils.grouper import (
issue_group_values, issue_group_values,
@ -549,6 +550,20 @@ class IssueViewSet(BaseViewSet):
issue = Issue.objects.get( issue = Issue.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk workspace__slug=slug, project_id=project_id, pk=pk
) )
if issue.created_by_id != request.user.id and (
not ProjectMember.objects.filter(
workspace__slug=slug,
member=request.user,
role=20,
project_id=project_id,
is_active=True,
).exists()
):
return Response(
{"error": "Only admin or creator can delete the issue"},
status=status.HTTP_403_FORBIDDEN,
)
issue.delete() issue.delete()
issue_activity.delay( issue_activity.delay(
type="issue.activity.deleted", type="issue.activity.deleted",
@ -602,6 +617,19 @@ class BulkDeleteIssuesEndpoint(BaseAPIView):
] ]
def delete(self, request, slug, project_id): def delete(self, request, slug, project_id):
if ProjectMember.objects.filter(
workspace__slug=slug,
member=request.user,
role=20,
project_id=project_id,
is_active=True,
).exists():
return Response(
{"error": "Only admin can perform this action"},
status=status.HTTP_403_FORBIDDEN,
)
issue_ids = request.data.get("issue_ids", []) issue_ids = request.data.get("issue_ids", [])
if not len(issue_ids): if not len(issue_ids):

View file

@ -40,6 +40,7 @@ from plane.db.models import (
IssueReaction, IssueReaction,
IssueSubscriber, IssueSubscriber,
Project, Project,
ProjectMember,
) )
from plane.utils.grouper import ( from plane.utils.grouper import (
issue_group_values, issue_group_values,
@ -380,6 +381,19 @@ class IssueDraftViewSet(BaseViewSet):
issue = Issue.objects.get( issue = Issue.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk workspace__slug=slug, project_id=project_id, pk=pk
) )
if issue.created_by_id != request.user.id and (
not ProjectMember.objects.filter(
workspace__slug=slug,
member=request.user,
role=20,
project_id=project_id,
is_active=True,
).exists()
):
return Response(
{"error": "Only admin or creator can delete the issue"},
status=status.HTTP_403_FORBIDDEN,
)
issue.delete() issue.delete()
issue_activity.delay( issue_activity.delay(
type="issue_draft.activity.deleted", type="issue_draft.activity.deleted",

View file

@ -48,6 +48,7 @@ from plane.db.models import (
ModuleLink, ModuleLink,
ModuleUserProperties, ModuleUserProperties,
Project, Project,
ProjectMember,
) )
from plane.utils.analytics_plot import burndown_plot from plane.utils.analytics_plot import burndown_plot
from plane.utils.user_timezone_converter import user_timezone_converter from plane.utils.user_timezone_converter import user_timezone_converter
@ -737,6 +738,21 @@ class ModuleViewSet(BaseViewSet):
module = Module.objects.get( module = Module.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk workspace__slug=slug, project_id=project_id, pk=pk
) )
if module.created_by_id != request.user.id and (
not ProjectMember.objects.filter(
workspace__slug=slug,
member=request.user,
role=20,
project_id=project_id,
is_active=True,
).exists()
):
return Response(
{"error": "Only admin or creator can delete the module"},
status=status.HTTP_403_FORBIDDEN,
)
module_issues = list( module_issues = list(
ModuleIssue.objects.filter(module_id=pk).values_list( ModuleIssue.objects.filter(module_id=pk).values_list(
"issue", flat=True "issue", flat=True

View file

@ -333,6 +333,20 @@ class PageViewSet(BaseViewSet):
pk=pk, workspace__slug=slug, projects__id=project_id pk=pk, workspace__slug=slug, projects__id=project_id
) )
if not page.owned_by_id != request.user.id and not (
ProjectMember.objects.filter(
workspace__slug=slug,
member=request.user,
role=20,
project_id=project_id,
is_active=True,
).exists()
):
return Response(
{"error": "Only admin or owner can delete the page"},
status=status.HTTP_403_FORBIDDEN,
)
# only the owner and admin can delete the page # only the owner and admin can delete the page
if ( if (
ProjectMember.objects.filter( ProjectMember.objects.filter(

View file

@ -116,6 +116,20 @@ class WorkspaceViewViewSet(BaseViewSet):
pk=pk, pk=pk,
workspace__slug=slug, workspace__slug=slug,
) )
if not (
WorkspaceMember.objects.filter(
workspace__slug=slug,
member=request.user,
role=20,
is_active=True,
).exists()
and workspace_view.owned_by_id != request.user.id
):
return Response(
{"error": "You do not have permission to delete this view"},
status=status.HTTP_403_FORBIDDEN,
)
workspace_member = WorkspaceMember.objects.filter( workspace_member = WorkspaceMember.objects.filter(
workspace__slug=slug, workspace__slug=slug,
member=request.user, member=request.user,
@ -412,14 +426,16 @@ class IssueViewViewSet(BaseViewSet):
project_id=project_id, project_id=project_id,
workspace__slug=slug, workspace__slug=slug,
) )
project_member = ProjectMember.objects.filter( if (
ProjectMember.objects.filter(
workspace__slug=slug, workspace__slug=slug,
project_id=project_id, project_id=project_id,
member=request.user, member=request.user,
role=20, role=20,
is_active=True, is_active=True,
) ).exists()
if project_member.exists() or project_view.owned_by == request.user: or project_view.owned_by_id == request.user.id
):
project_view.delete() project_view.delete()
else: else:
return Response( return Response(