Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions apiserver/plane/api/views/cycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
Project,
IssueAttachment,
IssueLink,
ProjectMember,
)
from plane.utils.analytics_plot import burndown_plot

Expand Down Expand Up @@ -363,14 +364,28 @@ def patch(self, request, slug, project_id, pk):
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

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(
CycleIssue.objects.filter(
cycle_id=self.kwargs.get("pk")
).values_list("issue", flat=True)
)
cycle = Cycle.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk
)

issue_activity.delay(
type="cycle.activity.deleted",
Expand Down
35 changes: 16 additions & 19 deletions apiserver/plane/api/views/inbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,29 +390,26 @@ def delete(self, request, slug, project_id, issue_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
if inbox_issue.status in [-2, -1, 0, 2]:
# Delete the issue also
Issue.objects.filter(
issue = Issue.objects.filter(
workspace__slug=slug, project_id=project_id, pk=issue_id
Comment on lines +396 to 397
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure the issue exists before proceeding with deletion.

Add a check to ensure the issue exists before proceeding with the deletion logic to avoid potential errors.

+ issue = Issue.objects.filter(
+     workspace__slug=slug, project_id=project_id, pk=issue_id
+ ).first()
+ if not issue:
+     return Response(
+         {"error": "Issue not found"},
+         status=status.HTTP_404_NOT_FOUND,
+     )
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
issue = Issue.objects.filter(
workspace__slug=slug, project_id=project_id, pk=issue_id
issue = Issue.objects.filter(
workspace__slug=slug, project_id=project_id, pk=issue_id
).first()
if not issue:
return Response(
{"error": "Issue not found"},
status=status.HTTP_404_NOT_FOUND,
)

).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()
return Response(status=status.HTTP_204_NO_CONTENT)
20 changes: 18 additions & 2 deletions apiserver/plane/api/views/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,11 +310,14 @@ def post(self, request, slug, project_id):

serializer.save()
# 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.save(update_fields=["created_at"])


# Track the issue
issue_activity.delay(
type="issue.activity.created",
Expand Down Expand Up @@ -386,6 +389,19 @@ def delete(self, request, slug, project_id, pk=None):
issue = Issue.objects.get(
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(
IssueSerializer(issue).data, cls=DjangoJSONEncoder
)
Expand Down
15 changes: 15 additions & 0 deletions apiserver/plane/api/views/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
ModuleIssue,
ModuleLink,
Project,
ProjectMember,
)

from .base import BaseAPIView
Expand Down Expand Up @@ -265,6 +266,20 @@ def delete(self, request, slug, project_id, pk):
module = Module.objects.get(
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(
ModuleIssue.objects.filter(module_id=pk).values_list(
"issue", flat=True
Expand Down
21 changes: 18 additions & 3 deletions apiserver/plane/app/views/cycle/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
Label,
User,
Project,
ProjectMember,
)
from plane.utils.analytics_plot import burndown_plot

Expand Down Expand Up @@ -1039,14 +1040,28 @@ def retrieve(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
)
Comment on lines +1043 to +1045
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure proper exception handling for Cycle.objects.get.

Using get without exception handling can raise Cycle.DoesNotExist if the cycle is not found. It's better to handle this exception.

-  cycle = Cycle.objects.get(
+  try:
+      cycle = Cycle.objects.get(
+          workspace__slug=slug, project_id=project_id, pk=pk
+      )
+  except Cycle.DoesNotExist:
+      return Response(
+          {"error": "Cycle not found"},
+          status=status.HTTP_404_NOT_FOUND,
+      )
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cycle = Cycle.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk
)
try:
cycle = Cycle.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk
)
except Cycle.DoesNotExist:
return Response(
{"error": "Cycle not found"},
status=status.HTTP_404_NOT_FOUND,
)

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(
CycleIssue.objects.filter(
cycle_id=self.kwargs.get("pk")
).values_list("issue", flat=True)
)
cycle = Cycle.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk
)

issue_activity.delay(
type="cycle.activity.deleted",
Expand Down
33 changes: 16 additions & 17 deletions apiserver/plane/app/views/inbox/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,28 +553,27 @@ def destroy(self, request, slug, project_id, issue_id):
project_id=project_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
if inbox_issue.status in [-2, -1, 0, 2]:
# Delete the issue also
Issue.objects.filter(
issue = Issue.objects.filter(
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()
return Response(status=status.HTTP_204_NO_CONTENT)
28 changes: 28 additions & 0 deletions apiserver/plane/app/views/issue/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
IssueReaction,
IssueSubscriber,
Project,
ProjectMember,
)
from plane.utils.grouper import (
issue_group_values,
Expand Down Expand Up @@ -549,6 +550,20 @@ def destroy(self, request, slug, project_id, pk=None):
issue = Issue.objects.get(
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_activity.delay(
type="issue.activity.deleted",
Expand Down Expand Up @@ -602,6 +617,19 @@ class BulkDeleteIssuesEndpoint(BaseAPIView):
]

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", [])

if not len(issue_ids):
Expand Down
14 changes: 14 additions & 0 deletions apiserver/plane/app/views/issue/draft.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
IssueReaction,
IssueSubscriber,
Project,
ProjectMember,
)
from plane.utils.grouper import (
issue_group_values,
Expand Down Expand Up @@ -380,6 +381,19 @@ def destroy(self, request, slug, project_id, pk=None):
issue = Issue.objects.get(
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_activity.delay(
type="issue_draft.activity.deleted",
Expand Down
16 changes: 16 additions & 0 deletions apiserver/plane/app/views/module/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
ModuleLink,
ModuleUserProperties,
Project,
ProjectMember,
)
from plane.utils.analytics_plot import burndown_plot
from plane.utils.user_timezone_converter import user_timezone_converter
Expand Down Expand Up @@ -737,6 +738,21 @@ def destroy(self, request, slug, project_id, pk):
module = Module.objects.get(
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(
ModuleIssue.objects.filter(module_id=pk).values_list(
"issue", flat=True
Expand Down
14 changes: 14 additions & 0 deletions apiserver/plane/app/views/page/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,20 @@ def destroy(self, request, slug, project_id, pk):
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
if (
ProjectMember.objects.filter(
Expand Down
Loading