diff --git a/taiga/projects/issues/api.py b/taiga/projects/issues/api.py index f68aa71f..e0fc00da 100644 --- a/taiga/projects/issues/api.py +++ b/taiga/projects/issues/api.py @@ -22,7 +22,7 @@ from django.http import Http404 from rest_framework.response import Response from rest_framework import status -from taiga.base import filters +from taiga.base import filters, response from taiga.base import exceptions as exc from taiga.base.decorators import detail_route, list_route from taiga.base.api import ModelCrudViewSet, ModelListViewSet @@ -155,25 +155,21 @@ class IssueViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMixin, @list_route(methods=["POST"]) def bulk_create(self, request, **kwargs): - bulk_issues = request.DATA.get('bulkIssues', None) - if bulk_issues is None: - raise exc.BadRequest(_('bulkIssues parameter is mandatory')) + serializer = serializers.IssuesBulkSerializer(data=request.DATA) + if serializer.is_valid(): + data = serializer.data + project = Project.objects.get(pk=data["project_id"]) + self.check_permissions(request, 'bulk_create', project) + issues = services.create_issues_in_bulk( + data["bulk_issues"], project=project, owner=request.user, + status=project.default_issue_status, severity=project.default_severity, + priority=project.default_priority, type=project.default_issue_type, + callback=self.post_save) + issues_serialized = self.serializer_class(issues, many=True) - project_id = request.DATA.get('projectId', None) - if project_id is None: - raise exc.BadRequest(_('projectId parameter is mandatory')) + return response.Ok(data=issues_serialized.data) - project = get_object_or_404(Project, id=project_id) - - self.check_permissions(request, 'bulk_create', project) - - issues = services.create_issues_in_bulk( - bulk_issues, callback=self.post_save, project=project, owner=request.user, - status=project.default_issue_status, severity=project.default_severity, - priority=project.default_priority, type=project.default_issue_type) - - issues_serialized = self.serializer_class(issues, many=True) - return Response(data=issues_serialized.data) + return response.BadRequest(serializer.errors) @detail_route(methods=['post']) def upvote(self, request, pk=None): diff --git a/taiga/projects/issues/serializers.py b/taiga/projects/issues/serializers.py index b069c0f9..13055010 100644 --- a/taiga/projects/issues/serializers.py +++ b/taiga/projects/issues/serializers.py @@ -16,8 +16,9 @@ from rest_framework import serializers -from taiga.base.serializers import PickleField, NeighborsSerializerMixin +from taiga.base.serializers import Serializer, PickleField, NeighborsSerializerMixin from taiga.mdrender.service import render as mdrender +from taiga.projects.validators import ProjectExistsValidator from . import models @@ -62,3 +63,8 @@ class NeighborIssueSerializer(serializers.ModelSerializer): model = models.Issue fields = ("id", "ref", "subject") depth = 0 + + +class IssuesBulkSerializer(ProjectExistsValidator, Serializer): + project_id = serializers.IntegerField() + bulk_issues = serializers.CharField() diff --git a/taiga/projects/tasks/api.py b/taiga/projects/tasks/api.py index 6d1ea7b3..c67cb15f 100644 --- a/taiga/projects/tasks/api.py +++ b/taiga/projects/tasks/api.py @@ -69,7 +69,7 @@ class TaskViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMixin, self.check_permissions(request, 'bulk_create', project) tasks = services.create_tasks_in_bulk( data["bulk_tasks"], milestone_id=data["sprint_id"], user_story_id=data["us_id"], - status_id=data.get("status_id", project.default_task_status_id), + status_id=data.get("status_id") or project.default_task_status_id, project=project, owner=request.user, callback=self.post_save) tasks_serialized = self.serializer_class(tasks, many=True) diff --git a/taiga/projects/userstories/api.py b/taiga/projects/userstories/api.py index b9ae9f5d..effa0ec5 100644 --- a/taiga/projects/userstories/api.py +++ b/taiga/projects/userstories/api.py @@ -72,7 +72,7 @@ class UserStoryViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMi self.check_permissions(request, 'bulk_create', project) user_stories = services.create_userstories_in_bulk( data["bulk_stories"], project=project, owner=request.user, - status_id=data.get("status_id", project.default_us_status_id), + status_id=data.get("status_id") or project.default_us_status_id, callback=self.post_save) user_stories_serialized = self.serializer_class(user_stories, many=True) return response.Ok(user_stories_serialized.data) diff --git a/tests/integration/resources_permissions/test_issues_resources.py b/tests/integration/resources_permissions/test_issues_resources.py index 4395766b..b5de0869 100644 --- a/tests/integration/resources_permissions/test_issues_resources.py +++ b/tests/integration/resources_permissions/test_issues_resources.py @@ -295,15 +295,15 @@ def test_issue_bulk_create(client, data): ] - bulk_data = json.dumps({"bulkIssues": "test1\ntest2", "projectId": data.public_issue.project.pk}) + bulk_data = json.dumps({"bulk_issues": "test1\ntest2", "project_id": data.public_issue.project.pk}) results = helper_test_http_method(client, 'post', url, bulk_data, users) assert results == [401, 200, 200, 200, 200] - bulk_data = json.dumps({"bulkIssues": "test1\ntest2", "projectId": data.private_issue1.project.pk}) + bulk_data = json.dumps({"bulk_issues": "test1\ntest2", "project_id": data.private_issue1.project.pk}) results = helper_test_http_method(client, 'post', url, bulk_data, users) assert results == [401, 200, 200, 200, 200] - bulk_data = json.dumps({"bulkIssues": "test1\ntest2", "projectId": data.private_issue2.project.pk}) + bulk_data = json.dumps({"bulk_issues": "test1\ntest2", "project_id": data.private_issue2.project.pk}) results = helper_test_http_method(client, 'post', url, bulk_data, users) assert results == [401, 403, 403, 200, 200] diff --git a/tests/integration/test_issues.py b/tests/integration/test_issues.py index 3cc2b64c..5339a3f9 100644 --- a/tests/integration/test_issues.py +++ b/tests/integration/test_issues.py @@ -47,8 +47,8 @@ def test_api_create_issues_in_bulk(client): project = f.create_project() url = reverse("issues-bulk-create") - data = {"bulkIssues": "Issue #1\nIssue #2", - "projectId": project.id} + data = {"bulk_issues": "Issue #1\nIssue #2", + "project_id": project.id} client.login(project.owner) response = client.json.post(url, data)