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
2 changes: 0 additions & 2 deletions apiserver/plane/app/serializers/draft.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,9 @@ class Meta:

class DraftIssueDetailSerializer(DraftIssueSerializer):
description_html = serializers.CharField()
description_binary = serializers.CharField()

class Meta(DraftIssueSerializer.Meta):
fields = DraftIssueSerializer.Meta.fields + [
"description_html",
"description_binary",
]
read_only_fields = fields
20 changes: 0 additions & 20 deletions apiserver/plane/app/serializers/issue.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# Python imports
import base64

# Django imports
from django.utils import timezone
from django.core.validators import URLValidator
Expand Down Expand Up @@ -735,31 +732,14 @@ class Meta:
read_only_fields = fields


class Base64BinaryField(serializers.CharField):
def to_representation(self, value):
# Encode the binary data to base64 string for JSON response
if value:
return base64.b64encode(value).decode("utf-8")
return None

def to_internal_value(self, data):
# Decode the base64 string to binary data when saving
try:
return base64.b64decode(data)
except (TypeError, ValueError):
raise serializers.ValidationError("Invalid base64-encoded data")


class IssueDetailSerializer(IssueSerializer):
description_html = serializers.CharField()
description_binary = Base64BinaryField()
is_subscribed = serializers.BooleanField(read_only=True)

class Meta(IssueSerializer.Meta):
fields = IssueSerializer.Meta.fields + [
"description_html",
"is_subscribed",
"description_binary",
]
read_only_fields = fields

Expand Down
1 change: 0 additions & 1 deletion apiserver/plane/app/serializers/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ class Meta:

class WorkspaceMemberMeSerializer(BaseSerializer):
draft_issue_count = serializers.IntegerField(read_only=True)

class Meta:
model = WorkspaceMember
fields = "__all__"
Expand Down
10 changes: 0 additions & 10 deletions apiserver/plane/app/urls/intake.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,4 @@
),
name="inbox-issue",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/inbox-issues/<uuid:pk>/description/",
IntakeIssueViewSet.as_view(
{
"get": "retrieve_description",
"post": "update_description",
}
),
name="inbox-issue-description",
),
]
19 changes: 0 additions & 19 deletions apiserver/plane/app/urls/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,6 @@
),
name="project-issue",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:pk>/description/",
IssueViewSet.as_view(
{
"get": "retrieve_description",
"post": "update_description",
}
),
name="project-issue-description",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-labels/",
LabelViewSet.as_view(
Expand Down Expand Up @@ -298,15 +288,6 @@
),
name="project-issue-archive-unarchive",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/archived-issues/<uuid:pk>/description/",
IssueArchiveViewSet.as_view(
{
"get": "retrieve_description",
}
),
name="archive-issue-description",
),
## End Issue Archives
## Issue Relation
path(
Expand Down
10 changes: 0 additions & 10 deletions apiserver/plane/app/urls/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,16 +276,6 @@
),
name="workspace-drafts-issues",
),
path(
"workspaces/<str:slug>/draft-issues/<uuid:pk>/description/",
WorkspaceDraftIssueViewSet.as_view(
{
"get": "retrieve_description",
"post": "update_description",
}
),
name="workspace-drafts-issues",
),
path(
"workspaces/<str:slug>/draft-to-issue/<uuid:draft_id>/",
WorkspaceDraftIssueViewSet.as_view({"post": "create_draft_to_issue"}),
Expand Down
86 changes: 2 additions & 84 deletions apiserver/plane/app/views/intake/base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Python imports
import json
import requests
import base64

# Django import
from django.utils import timezone
Expand All @@ -11,9 +9,6 @@
from django.contrib.postgres.fields import ArrayField
from django.db.models import Value, UUIDField
from django.db.models.functions import Coalesce
from django.http import StreamingHttpResponse
from django.conf import settings


# Third party imports
from rest_framework import status
Expand Down Expand Up @@ -45,6 +40,7 @@


class IntakeViewSet(BaseViewSet):

serializer_class = IntakeSerializer
model = Intake

Expand Down Expand Up @@ -93,6 +89,7 @@ def destroy(self, request, slug, project_id, pk):


class IntakeIssueViewSet(BaseViewSet):

serializer_class = IntakeIssueSerializer
model = IntakeIssue

Expand Down Expand Up @@ -643,82 +640,3 @@ def destroy(self, request, slug, project_id, pk):

intake_issue.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def retrieve_description(self, request, slug, project_id, pk):
issue = Issue.objects.filter(
pk=pk, workspace__slug=slug, project_id=project_id
).first()
if issue is None:
return Response(
{"error": "Issue not found"},
status=404,
)
binary_data = issue.description_binary

def stream_data():
if binary_data:
yield binary_data
else:
yield b""

response = StreamingHttpResponse(
stream_data(), content_type="application/octet-stream"
)
response["Content-Disposition"] = (
'attachment; filename="issue_description.bin"'
)
return response

@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def update_description(self, request, slug, project_id, pk):
issue = Issue.objects.get(
workspace__slug=slug, project_id=project_id, pk=pk
)
base64_description = issue.description_binary
# convert to base64 string
if base64_description:
base64_description = base64.b64encode(base64_description).decode(
"utf-8"
)
data = {
"original_document": base64_description,
"updates": request.data.get("description_binary"),
}
base_url = f"{settings.LIVE_BASE_URL}/resolve-document-conflicts/"
try:
response = requests.post(base_url, json=data, headers=None)
except requests.RequestException:
return Response(
{"error": "Failed to connect to the external service"},
status=status.HTTP_502_BAD_GATEWAY,
)

if response.status_code == 200:
issue.description = response.json().get(
"description", issue.description
)
issue.description_html = response.json().get("description_html")
response_description_binary = response.json().get(
"description_binary"
)
issue.description_binary = base64.b64decode(
response_description_binary
)
issue.save()

def stream_data():
if issue.description_binary:
yield issue.description_binary
else:
yield b""

response = StreamingHttpResponse(
stream_data(), content_type="application/octet-stream"
)
response["Content-Disposition"] = (
'attachment; filename="issue_description.bin"'
)
return response

return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
30 changes: 1 addition & 29 deletions apiserver/plane/app/views/issue/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.views.decorators.gzip import gzip_page
from django.http import StreamingHttpResponse


# Third Party imports
from rest_framework import status
Expand All @@ -29,7 +27,7 @@
IssueLink,
IssueSubscriber,
IssueReaction,
CycleIssue,
CycleIssue
)
from plane.utils.grouper import (
issue_group_values,
Expand Down Expand Up @@ -329,32 +327,6 @@ def unarchive(self, request, slug, project_id, pk=None):

return Response(status=status.HTTP_204_NO_CONTENT)

@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def retrieve_description(self, request, slug, project_id, pk):
issue = Issue.objects.filter(
pk=pk, workspace__slug=slug, project_id=project_id
).first()
if issue is None:
return Response(
{"error": "Issue not found"},
status=404,
)
binary_data = issue.description_binary

def stream_data():
if binary_data:
yield binary_data
else:
yield b""

response = StreamingHttpResponse(
stream_data(), content_type="application/octet-stream"
)
response["Content-Disposition"] = (
'attachment; filename="issue_description.bin"'
)
return response


class BulkArchiveIssuesEndpoint(BaseAPIView):
permission_classes = [
Expand Down
82 changes: 0 additions & 82 deletions apiserver/plane/app/views/issue/base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Python imports
import json
import requests
import base64

# Django imports
from django.contrib.postgres.aggregates import ArrayAgg
Expand All @@ -22,10 +20,8 @@
)
from django.db.models.functions import Coalesce
from django.utils import timezone
from django.http import StreamingHttpResponse
from django.utils.decorators import method_decorator
from django.views.decorators.gzip import gzip_page
from django.conf import settings

# Third Party imports
from rest_framework import status
Expand Down Expand Up @@ -729,84 +725,6 @@ def destroy(self, request, slug, project_id, pk=None):
)
return Response(status=status.HTTP_204_NO_CONTENT)

@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def retrieve_description(self, request, slug, project_id, pk):
issue = Issue.issue_objects.filter(
pk=pk, workspace__slug=slug, project_id=project_id
).first()
if issue is None:
return Response(
{"error": "Issue not found"},
status=404,
)
binary_data = issue.description_binary

def stream_data():
if binary_data:
yield binary_data
else:
yield b""

response = StreamingHttpResponse(
stream_data(), content_type="application/octet-stream"
)
response["Content-Disposition"] = (
'attachment; filename="issue_description.bin"'
)
return response

def update_description(self, request, slug, project_id, pk):
issue = Issue.issue_objects.get(
workspace__slug=slug, project_id=project_id, pk=pk
)
base64_description = issue.description_binary
# convert to base64 string
if base64_description:
base64_description = base64.b64encode(base64_description).decode(
"utf-8"
)
data = {
"original_document": base64_description,
"updates": request.data.get("description_binary"),
}
base_url = f"{settings.LIVE_BASE_URL}/resolve-document-conflicts/"
try:
response = requests.post(base_url, json=data, headers=None)
except requests.RequestException:
return Response(
{"error": "Failed to connect to the external service"},
status=status.HTTP_502_BAD_GATEWAY,
)

if response.status_code == 200:
issue.description = response.json().get(
"description", issue.description
)
issue.description_html = response.json().get("description_html")
response_description_binary = response.json().get(
"description_binary"
)
issue.description_binary = base64.b64decode(
response_description_binary
)
issue.save()

def stream_data():
if issue.description_binary:
yield issue.description_binary
else:
yield b""

response = StreamingHttpResponse(
stream_data(), content_type="application/octet-stream"
)
response["Content-Disposition"] = (
'attachment; filename="issue_description.bin"'
)
return response

return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class IssueUserDisplayPropertyEndpoint(BaseAPIView):
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
Expand Down
Loading