From e86d2ba743289c3755688049aa3a1d54d9e98095 Mon Sep 17 00:00:00 2001 From: Nikhil <118773738+pablohashescobar@users.noreply.github.com> Date: Wed, 21 Feb 2024 19:51:25 +0530 Subject: [PATCH] [WEB - 485] chore: external apis validation (#3737) * dev: add integrity validation for states * dev: add validation for issue comment with same external id and external source --- apiserver/plane/api/views/issue.py | 50 +++++++++++++++++++ apiserver/plane/api/views/state.py | 78 +++++++++++++++++------------- 2 files changed, 95 insertions(+), 33 deletions(-) diff --git a/apiserver/plane/api/views/issue.py b/apiserver/plane/api/views/issue.py index a759b15f6..50269fe07 100644 --- a/apiserver/plane/api/views/issue.py +++ b/apiserver/plane/api/views/issue.py @@ -647,6 +647,33 @@ class IssueCommentAPIEndpoint(WebhookMixin, BaseAPIView): ) def post(self, request, slug, project_id, issue_id): + + # Validation check if the issue already exists + if ( + request.data.get("external_id") + and request.data.get("external_source") + and IssueComment.objects.filter( + project_id=project_id, + workspace__slug=slug, + external_source=request.data.get("external_source"), + external_id=request.data.get("external_id"), + ).exists() + ): + issue_comment = IssueComment.objects.filter( + workspace__slug=slug, + project_id=project_id, + external_id=request.data.get("external_id"), + external_source=request.data.get("external_source"), + ).first() + return Response( + { + "error": "Issue Comment with the same external id and external source already exists", + "id": str(issue_comment.id), + }, + status=status.HTTP_409_CONFLICT, + ) + + serializer = IssueCommentSerializer(data=request.data) if serializer.is_valid(): serializer.save( @@ -680,6 +707,29 @@ class IssueCommentAPIEndpoint(WebhookMixin, BaseAPIView): IssueCommentSerializer(issue_comment).data, cls=DjangoJSONEncoder, ) + + # Validation check if the issue already exists + if ( + str(request.data.get("external_id")) + and (issue_comment.external_id != str(request.data.get("external_id"))) + and Issue.objects.filter( + project_id=project_id, + workspace__slug=slug, + external_source=request.data.get( + "external_source", issue_comment.external_source + ), + external_id=request.data.get("external_id"), + ).exists() + ): + return Response( + { + "error": "Issue Comment with the same external id and external source already exists", + "id": str(issue_comment.id), + }, + status=status.HTTP_409_CONFLICT, + ) + + serializer = IssueCommentSerializer( issue_comment, data=request.data, partial=True ) diff --git a/apiserver/plane/api/views/state.py b/apiserver/plane/api/views/state.py index 0a262a071..dedc15ccd 100644 --- a/apiserver/plane/api/views/state.py +++ b/apiserver/plane/api/views/state.py @@ -1,7 +1,5 @@ -# Python imports -from itertools import groupby - # Django imports +from django.db import IntegrityError from django.db.models import Q # Third party imports @@ -34,37 +32,51 @@ class StateAPIEndpoint(BaseAPIView): ) def post(self, request, slug, project_id): - serializer = StateSerializer( - data=request.data, context={"project_id": project_id} - ) - if serializer.is_valid(): - if ( - request.data.get("external_id") - and request.data.get("external_source") - and State.objects.filter( - project_id=project_id, - workspace__slug=slug, - external_source=request.data.get("external_source"), - external_id=request.data.get("external_id"), - ).exists() - ): - state = State.objects.filter( - workspace__slug=slug, - project_id=project_id, - external_id=request.data.get("external_id"), - external_source=request.data.get("external_source"), - ).first() - return Response( - { - "error": "State with the same external id and external source already exists", - "id": str(state.id), - }, - status=status.HTTP_409_CONFLICT, - ) + try: + serializer = StateSerializer( + data=request.data, context={"project_id": project_id} + ) + if serializer.is_valid(): + if ( + request.data.get("external_id") + and request.data.get("external_source") + and State.objects.filter( + project_id=project_id, + workspace__slug=slug, + external_source=request.data.get("external_source"), + external_id=request.data.get("external_id"), + ).exists() + ): + state = State.objects.filter( + workspace__slug=slug, + project_id=project_id, + external_id=request.data.get("external_id"), + external_source=request.data.get("external_source"), + ).first() + return Response( + { + "error": "State with the same external id and external source already exists", + "id": str(state.id), + }, + status=status.HTTP_409_CONFLICT, + ) - serializer.save(project_id=project_id) - return Response(serializer.data, status=status.HTTP_200_OK) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + serializer.save(project_id=project_id) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + except IntegrityError as e: + state = State.objects.filter( + workspace__slug=slug, + project_id=project_id, + name=request.data.get("name"), + ).first() + return Response( + { + "error": "State with the same name already exists in the project", + "id": str(state.id), + }, + status=status.HTTP_409_CONFLICT, + ) def get(self, request, slug, project_id, state_id=None): if state_id: