[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:
Nikhil 2024-04-08 14:59:50 +05:30 committed by GitHub
parent 57f2445bb8
commit 2c8c139c62
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 37 additions and 38 deletions

View File

@ -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

View File

@ -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

View File

@ -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",
), ),

View File

@ -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):

View File

@ -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()),
) )

View File

@ -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)

View File

@ -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

View File

@ -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,
) )