Skip to content
Open
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
47 changes: 28 additions & 19 deletions apps/api/plane/api/views/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,25 +236,34 @@ def get(self, request, slug, project_identifier=None, issue_identifier=None):
Retrieve a specific work item using workspace slug, project identifier, and issue identifier.
This endpoint provides workspace-level access to work items.
"""
if issue_identifier and project_identifier:
# The `<project_identifier>-<issue_identifier>` route also matches UUIDs;
# sequence_id is an integer, so anything else can't be a work item here.
if not issue_identifier.isdecimal():
return Response({"error": "Work item not found"}, status=status.HTTP_404_NOT_FOUND)
issue = Issue.issue_objects.annotate(
sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
).get(
workspace__slug=slug,
project__identifier=project_identifier,
sequence_id=issue_identifier,
)
return Response(
IssueSerializer(issue, fields=self.fields, expand=self.expand).data,
status=status.HTTP_200_OK,
)
# The route splits `<project_identifier>-<issue_identifier>` on the last
# hyphen, so a UUID there leaves a non-numeric identifier to filter on.
sequence_id = None
if project_identifier and issue_identifier:
try:
# isdecimal() rejects the superscript digits isdigit() allows;
# int() rejects decimal strings longer than 4300 characters.
sequence_id = int(issue_identifier) if issue_identifier.isdecimal() else None
except ValueError:
sequence_id = None

if sequence_id is None:
return Response({"error": "Work item not found"}, status=status.HTTP_404_NOT_FOUND)

issue = Issue.issue_objects.annotate(
sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
).get(
workspace__slug=slug,
project__identifier=project_identifier,
sequence_id=sequence_id,
)
return Response(
IssueSerializer(issue, fields=self.fields, expand=self.expand).data,
status=status.HTTP_200_OK,
)


class IssueListCreateAPIEndpoint(BaseAPIView):
Expand Down
Loading