mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
[WEB - 898] fix: external webhooks (#4119)
* fix: project webhooks * fix: issue and issue comment webhooks * dev: remove module and cycle issue webhooks * fix: linting errors
This commit is contained in:
parent
57f2445bb8
commit
2c8c139c62
@ -79,7 +79,7 @@ class IssueSerializer(BaseSerializer):
|
|||||||
parsed_str = html.tostring(parsed, encoding="unicode")
|
parsed_str = html.tostring(parsed, encoding="unicode")
|
||||||
data["description_html"] = parsed_str
|
data["description_html"] = parsed_str
|
||||||
|
|
||||||
except Exception as e:
|
except Exception:
|
||||||
raise serializers.ValidationError("Invalid HTML passed")
|
raise serializers.ValidationError("Invalid HTML passed")
|
||||||
|
|
||||||
# Validate assignees are from project
|
# Validate assignees are from project
|
||||||
@ -366,7 +366,7 @@ class IssueCommentSerializer(BaseSerializer):
|
|||||||
parsed_str = html.tostring(parsed, encoding="unicode")
|
parsed_str = html.tostring(parsed, encoding="unicode")
|
||||||
data["comment_html"] = parsed_str
|
data["comment_html"] = parsed_str
|
||||||
|
|
||||||
except Exception as e:
|
except Exception:
|
||||||
raise serializers.ValidationError("Invalid HTML passed")
|
raise serializers.ValidationError("Invalid HTML passed")
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# Module imports
|
# Module imports
|
||||||
from plane.db.models import User
|
from plane.db.models import User
|
||||||
|
|
||||||
from .base import BaseSerializer
|
from .base import BaseSerializer
|
||||||
|
|
||||||
|
|
||||||
@ -12,5 +13,6 @@ class UserLiteSerializer(BaseSerializer):
|
|||||||
"last_name",
|
"last_name",
|
||||||
"avatar",
|
"avatar",
|
||||||
"display_name",
|
"display_name",
|
||||||
|
"email",
|
||||||
]
|
]
|
||||||
read_only_fields = fields
|
read_only_fields = fields
|
||||||
|
@ -12,7 +12,7 @@ urlpatterns = [
|
|||||||
name="project",
|
name="project",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"workspaces/<str:slug>/projects/<uuid:project_id>/",
|
"workspaces/<str:slug>/projects/<uuid:pk>/",
|
||||||
ProjectAPIEndpoint.as_view(),
|
ProjectAPIEndpoint.as_view(),
|
||||||
name="project",
|
name="project",
|
||||||
),
|
),
|
||||||
|
@ -7,6 +7,7 @@ import zoneinfo
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
|
from django.urls import resolve
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
@ -165,7 +166,12 @@ class BaseAPIView(TimezoneMixin, APIView, BasePaginator):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def project_id(self):
|
def project_id(self):
|
||||||
return self.kwargs.get("project_id", None)
|
project_id = self.kwargs.get("project_id", None)
|
||||||
|
if project_id:
|
||||||
|
return project_id
|
||||||
|
|
||||||
|
if resolve(self.request.path_info).url_name == "project":
|
||||||
|
return self.kwargs.get("pk", None)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fields(self):
|
def fields(self):
|
||||||
|
@ -308,8 +308,6 @@ class IssueAPIEndpoint(WebhookMixin, BaseAPIView):
|
|||||||
actor_id=str(request.user.id),
|
actor_id=str(request.user.id),
|
||||||
issue_id=str(pk),
|
issue_id=str(pk),
|
||||||
project_id=str(project_id),
|
project_id=str(project_id),
|
||||||
external_id__isnull=False,
|
|
||||||
external_source__isnull=False,
|
|
||||||
current_instance=current_instance,
|
current_instance=current_instance,
|
||||||
epoch=int(timezone.now().timestamp()),
|
epoch=int(timezone.now().timestamp()),
|
||||||
)
|
)
|
||||||
|
@ -1,27 +1,29 @@
|
|||||||
# Django imports
|
# Django imports
|
||||||
from django.utils import timezone
|
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
from django.db.models import Exists, OuterRef, Q, F, Func, Subquery, Prefetch
|
from django.db.models import Exists, F, Func, OuterRef, Prefetch, Q, Subquery
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
# Third party imports
|
# Third party imports
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.serializers import ValidationError
|
from rest_framework.serializers import ValidationError
|
||||||
|
|
||||||
|
from plane.api.serializers import ProjectSerializer
|
||||||
|
from plane.app.permissions import ProjectBasePermission
|
||||||
|
|
||||||
# Module imports
|
# Module imports
|
||||||
from plane.db.models import (
|
from plane.db.models import (
|
||||||
Workspace,
|
|
||||||
Project,
|
|
||||||
ProjectMember,
|
|
||||||
ProjectDeployBoard,
|
|
||||||
State,
|
|
||||||
Cycle,
|
Cycle,
|
||||||
Module,
|
|
||||||
IssueProperty,
|
|
||||||
Inbox,
|
Inbox,
|
||||||
|
IssueProperty,
|
||||||
|
Module,
|
||||||
|
Project,
|
||||||
|
ProjectDeployBoard,
|
||||||
|
ProjectMember,
|
||||||
|
State,
|
||||||
|
Workspace,
|
||||||
)
|
)
|
||||||
from plane.app.permissions import ProjectBasePermission
|
|
||||||
from plane.api.serializers import ProjectSerializer
|
|
||||||
from .base import BaseAPIView, WebhookMixin
|
from .base import BaseAPIView, WebhookMixin
|
||||||
|
|
||||||
|
|
||||||
@ -103,8 +105,8 @@ class ProjectAPIEndpoint(WebhookMixin, BaseAPIView):
|
|||||||
.distinct()
|
.distinct()
|
||||||
)
|
)
|
||||||
|
|
||||||
def get(self, request, slug, project_id=None):
|
def get(self, request, slug, pk=None):
|
||||||
if project_id is None:
|
if pk is None:
|
||||||
sort_order_query = ProjectMember.objects.filter(
|
sort_order_query = ProjectMember.objects.filter(
|
||||||
member=request.user,
|
member=request.user,
|
||||||
project_id=OuterRef("pk"),
|
project_id=OuterRef("pk"),
|
||||||
@ -135,7 +137,7 @@ class ProjectAPIEndpoint(WebhookMixin, BaseAPIView):
|
|||||||
expand=self.expand,
|
expand=self.expand,
|
||||||
).data,
|
).data,
|
||||||
)
|
)
|
||||||
project = self.get_queryset().get(workspace__slug=slug, pk=project_id)
|
project = self.get_queryset().get(workspace__slug=slug, pk=pk)
|
||||||
serializer = ProjectSerializer(
|
serializer = ProjectSerializer(
|
||||||
project,
|
project,
|
||||||
fields=self.fields,
|
fields=self.fields,
|
||||||
@ -259,10 +261,10 @@ class ProjectAPIEndpoint(WebhookMixin, BaseAPIView):
|
|||||||
status=status.HTTP_410_GONE,
|
status=status.HTTP_410_GONE,
|
||||||
)
|
)
|
||||||
|
|
||||||
def patch(self, request, slug, project_id=None):
|
def patch(self, request, slug, pk):
|
||||||
try:
|
try:
|
||||||
workspace = Workspace.objects.get(slug=slug)
|
workspace = Workspace.objects.get(slug=slug)
|
||||||
project = Project.objects.get(pk=project_id)
|
project = Project.objects.get(pk=pk)
|
||||||
|
|
||||||
if project.archived_at:
|
if project.archived_at:
|
||||||
return Response(
|
return Response(
|
||||||
@ -291,7 +293,7 @@ class ProjectAPIEndpoint(WebhookMixin, BaseAPIView):
|
|||||||
name="Triage",
|
name="Triage",
|
||||||
group="backlog",
|
group="backlog",
|
||||||
description="Default state for managing all Inbox Issues",
|
description="Default state for managing all Inbox Issues",
|
||||||
project_id=project_id,
|
project_id=pk,
|
||||||
color="#ff7700",
|
color="#ff7700",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -322,8 +324,8 @@ class ProjectAPIEndpoint(WebhookMixin, BaseAPIView):
|
|||||||
status=status.HTTP_410_GONE,
|
status=status.HTTP_410_GONE,
|
||||||
)
|
)
|
||||||
|
|
||||||
def delete(self, request, slug, project_id):
|
def delete(self, request, slug, pk):
|
||||||
project = Project.objects.get(pk=project_id, workspace__slug=slug)
|
project = Project.objects.get(pk=pk, workspace__slug=slug)
|
||||||
project.delete()
|
project.delete()
|
||||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# Third Party imports
|
# Third Party imports
|
||||||
from rest_framework.permissions import BasePermission, SAFE_METHODS
|
from rest_framework.permissions import SAFE_METHODS, BasePermission
|
||||||
|
|
||||||
# Module import
|
# Module import
|
||||||
from plane.db.models import WorkspaceMember, ProjectMember
|
from plane.db.models import ProjectMember, WorkspaceMember
|
||||||
|
|
||||||
# Permission Mappings
|
# Permission Mappings
|
||||||
Admin = 20
|
Admin = 20
|
||||||
|
@ -202,16 +202,7 @@ def send_webhook(event, payload, kw, action, slug, bulk, current_site):
|
|||||||
if webhooks:
|
if webhooks:
|
||||||
if action in ["POST", "PATCH"]:
|
if action in ["POST", "PATCH"]:
|
||||||
if bulk and event in ["cycle_issue", "module_issue"]:
|
if bulk and event in ["cycle_issue", "module_issue"]:
|
||||||
event_data = IssueExpandSerializer(
|
return
|
||||||
Issue.objects.filter(
|
|
||||||
pk__in=[
|
|
||||||
str(event.get("issue")) for event in payload
|
|
||||||
]
|
|
||||||
).prefetch_related("issue_cycle", "issue_module"),
|
|
||||||
many=True,
|
|
||||||
).data
|
|
||||||
event = "issue"
|
|
||||||
action = "PATCH"
|
|
||||||
else:
|
else:
|
||||||
event_data = [
|
event_data = [
|
||||||
get_model_data(
|
get_model_data(
|
||||||
@ -219,7 +210,7 @@ def send_webhook(event, payload, kw, action, slug, bulk, current_site):
|
|||||||
event_id=(
|
event_id=(
|
||||||
payload.get("id")
|
payload.get("id")
|
||||||
if isinstance(payload, dict)
|
if isinstance(payload, dict)
|
||||||
else None
|
else kw.get("pk")
|
||||||
),
|
),
|
||||||
many=False,
|
many=False,
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user