Add initial project import api
parent
a5865a1cec
commit
fdb0a327c1
|
@ -287,6 +287,9 @@ class APIView(View):
|
||||||
request.user
|
request.user
|
||||||
|
|
||||||
def check_permissions(self, request, action, obj=None):
|
def check_permissions(self, request, action, obj=None):
|
||||||
|
if action is None:
|
||||||
|
self.permission_denied(request)
|
||||||
|
|
||||||
for permission in self.get_permissions():
|
for permission in self.get_permissions():
|
||||||
if not permission.check_permissions(action=action, obj=obj):
|
if not permission.check_permissions(action=action, obj=obj):
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import status
|
||||||
|
|
||||||
|
from taiga.base.api.mixins import CreateModelMixin
|
||||||
|
from taiga.base.api.viewsets import GenericViewSet
|
||||||
|
from taiga.base.decorators import detail_route
|
||||||
|
from taiga.projects.models import Project
|
||||||
|
|
||||||
|
from . import serializers
|
||||||
|
from . import service
|
||||||
|
from . import permissions
|
||||||
|
|
||||||
|
from django.db.models import signals
|
||||||
|
|
||||||
|
def __disconnect_signals():
|
||||||
|
signals.pre_save.receivers = []
|
||||||
|
signals.post_save.receivers = []
|
||||||
|
|
||||||
|
class ProjectImporterViewSet(CreateModelMixin, GenericViewSet):
|
||||||
|
model = Project
|
||||||
|
permission_classes = (permissions.ImportPermission, )
|
||||||
|
|
||||||
|
def create(self, request, *args, **kwargs):
|
||||||
|
self.check_permissions(request, 'import_project', None)
|
||||||
|
|
||||||
|
data = request.DATA
|
||||||
|
project_serialized = service.store_project(data)
|
||||||
|
|
||||||
|
if project_serialized:
|
||||||
|
service.store_choices(project_serialized.object, data, "points", project_serialized.object.points, serializers.PointsExportSerializer, "default_points")
|
||||||
|
service.store_choices(project_serialized.object, data, "issue_types", project_serialized.object.issue_types, serializers.IssueTypeExportSerializer, "default_issue_type")
|
||||||
|
service.store_choices(project_serialized.object, data, "issue_statuses", project_serialized.object.issue_statuses, serializers.IssueStatusExportSerializer, "default_issue_status")
|
||||||
|
service.store_choices(project_serialized.object, data, "us_statuses", project_serialized.object.us_statuses, serializers.UserStoryStatusExportSerializer, "default_us_status")
|
||||||
|
service.store_choices(project_serialized.object, data, "task_statuses", project_serialized.object.task_statuses, serializers.TaskStatusExportSerializer, "default_task_status")
|
||||||
|
service.store_choices(project_serialized.object, data, "priorities", project_serialized.object.priorities, serializers.PriorityExportSerializer, "default_priority")
|
||||||
|
service.store_choices(project_serialized.object, data, "severities", project_serialized.object.severities, serializers.SeverityExportSerializer, "default_severity")
|
||||||
|
service.store_default_choices(project_serialized.object, data)
|
||||||
|
service.store_roles(project_serialized.object, data)
|
||||||
|
service.store_memberships(project_serialized.object, data)
|
||||||
|
headers = self.get_success_headers(project_serialized.data)
|
||||||
|
return Response(project_serialized.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||||
|
|
||||||
|
return Response(service.get_errors(), status=status.HTTP_400_BAD_REQUEST)
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
||||||
|
# Copyright (C) 2014 Jesús Espino <jespinog@gmail.com>
|
||||||
|
# Copyright (C) 2014 David Barragán <bameda@dbarragan.com>
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from taiga.base.api.permissions import (TaigaResourcePermission,
|
||||||
|
IsProjectOwner, IsAuthenticated)
|
||||||
|
|
||||||
|
|
||||||
|
class ImportPermission(TaigaResourcePermission):
|
||||||
|
import_project_perms = IsAuthenticated()
|
||||||
|
import_item_perms = IsProjectOwner()
|
|
@ -1,18 +1,40 @@
|
||||||
from . import serializers
|
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
||||||
from taiga.projects.models import Project
|
# Copyright (C) 2014 Jesús Espino <jespinog@gmail.com>
|
||||||
|
# Copyright (C) 2014 David Barragán <bameda@dbarragan.com>
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from django.db.models import signals
|
from django.db.models import signals
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
|
||||||
|
from taiga.projects.models import Project
|
||||||
|
|
||||||
|
from . import serializers
|
||||||
|
|
||||||
|
_errors_log = []
|
||||||
|
|
||||||
|
def get_errors():
|
||||||
|
_errors = _errors_log.copy()
|
||||||
|
_errors_log.clear()
|
||||||
|
return _errors
|
||||||
|
|
||||||
|
def add_errors(errors):
|
||||||
|
_errors_log.append(errors)
|
||||||
|
|
||||||
def project_to_dict(project):
|
def project_to_dict(project):
|
||||||
return serializers.ProjectExportSerializer(project).data
|
return serializers.ProjectExportSerializer(project).data
|
||||||
|
|
||||||
def dict_to_project(data, owner=None):
|
|
||||||
signals.pre_save.receivers = []
|
|
||||||
signals.post_save.receivers = []
|
|
||||||
signals.pre_delete.receivers = []
|
|
||||||
signals.post_delete.receivers = []
|
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def store_project(data):
|
def store_project(data):
|
||||||
project_data = {}
|
project_data = {}
|
||||||
|
@ -29,10 +51,13 @@ def dict_to_project(data, owner=None):
|
||||||
project_data[key] = value
|
project_data[key] = value
|
||||||
|
|
||||||
serialized = serializers.ProjectExportSerializer(data=project_data)
|
serialized = serializers.ProjectExportSerializer(data=project_data)
|
||||||
serialized.is_valid()
|
if serialized.is_valid():
|
||||||
serialized.object._importing = True
|
serialized.object._importing = True
|
||||||
serialized.object.save()
|
serialized.object.save()
|
||||||
return serialized.object
|
return serialized
|
||||||
|
else:
|
||||||
|
add_errors(serialized.errors)
|
||||||
|
return None
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def store_choices(project, data, field, relation, serializer, default_field):
|
def store_choices(project, data, field, relation, serializer, default_field):
|
||||||
|
@ -174,23 +199,30 @@ def dict_to_project(data, owner=None):
|
||||||
for attachment in issue['attachments']:
|
for attachment in issue['attachments']:
|
||||||
store_attachment(project, serialized.object, attachment)
|
store_attachment(project, serialized.object, attachment)
|
||||||
|
|
||||||
|
|
||||||
|
def dict_to_project(data, owner=None):
|
||||||
|
signals.pre_save.receivers = []
|
||||||
|
signals.post_save.receivers = []
|
||||||
|
signals.pre_delete.receivers = []
|
||||||
|
signals.post_delete.receivers = []
|
||||||
|
|
||||||
if owner:
|
if owner:
|
||||||
data['owner'] = owner
|
data['owner'] = owner
|
||||||
|
|
||||||
project = store_project(data)
|
project_serialized = store_project(data)
|
||||||
store_choices(project, data, "points", project.points, serializers.PointsExportSerializer, "default_points")
|
store_choices(project_serialized.object, data, "points", project_serialized.object.points, serializers.PointsExportSerializer, "default_points")
|
||||||
store_choices(project, data, "issue_types", project.issue_types, serializers.IssueTypeExportSerializer, "default_issue_type")
|
store_choices(project_serialized.object, data, "issue_types", project_serialized.object.issue_types, serializers.IssueTypeExportSerializer, "default_issue_type")
|
||||||
store_choices(project, data, "issue_statuses", project.issue_statuses, serializers.IssueStatusExportSerializer, "default_issue_status")
|
store_choices(project_serialized.object, data, "issue_statuses", project_serialized.object.issue_statuses, serializers.IssueStatusExportSerializer, "default_issue_status")
|
||||||
store_choices(project, data, "us_statuses", project.us_statuses, serializers.UserStoryStatusExportSerializer, "default_us_status")
|
store_choices(project_serialized.object, data, "us_statuses", project_serialized.object.us_statuses, serializers.UserStoryStatusExportSerializer, "default_us_status")
|
||||||
store_choices(project, data, "task_statuses", project.task_statuses, serializers.TaskStatusExportSerializer, "default_task_status")
|
store_choices(project_serialized.object, data, "task_statuses", project_serialized.object.task_statuses, serializers.TaskStatusExportSerializer, "default_task_status")
|
||||||
store_choices(project, data, "priorities", project.priorities, serializers.PriorityExportSerializer, "default_priority")
|
store_choices(project_serialized.object, data, "priorities", project_serialized.object.priorities, serializers.PriorityExportSerializer, "default_priority")
|
||||||
store_choices(project, data, "severities", project.severities, serializers.SeverityExportSerializer, "default_severity")
|
store_choices(project_serialized.object, data, "severities", project_serialized.object.severities, serializers.SeverityExportSerializer, "default_severity")
|
||||||
store_default_choices(project, data)
|
store_default_choices(project_serialized.object, data)
|
||||||
store_roles(project, data)
|
store_roles(project_serialized.object, data)
|
||||||
store_memberships(project, data)
|
store_memberships(project_serialized.object, data)
|
||||||
store_milestones(project, data)
|
store_milestones(project_serialized.object, data)
|
||||||
store_wiki_pages(project, data)
|
store_wiki_pages(project_serialized.object, data)
|
||||||
store_wiki_links(project, data)
|
store_wiki_links(project_serialized.object, data)
|
||||||
|
|
||||||
store_user_stories(project, data)
|
store_user_stories(project_serialized.object, data)
|
||||||
store_issues(project, data)
|
store_issues(project_serialized.object, data)
|
||||||
|
|
|
@ -44,6 +44,12 @@ from taiga.searches.api import SearchViewSet
|
||||||
router.register(r"search", SearchViewSet, base_name="search")
|
router.register(r"search", SearchViewSet, base_name="search")
|
||||||
|
|
||||||
|
|
||||||
|
# Importer
|
||||||
|
from taiga.export_import.api import ProjectImporterViewSet
|
||||||
|
|
||||||
|
router.register(r"importer", ProjectImporterViewSet, base_name="importer")
|
||||||
|
|
||||||
|
|
||||||
# Projects & Types
|
# Projects & Types
|
||||||
from taiga.projects.api import RolesViewSet
|
from taiga.projects.api import RolesViewSet
|
||||||
from taiga.projects.api import ProjectViewSet
|
from taiga.projects.api import ProjectViewSet
|
||||||
|
@ -58,6 +64,7 @@ from taiga.projects.api import PriorityViewSet
|
||||||
from taiga.projects.api import SeverityViewSet
|
from taiga.projects.api import SeverityViewSet
|
||||||
from taiga.projects.api import ProjectTemplateViewSet
|
from taiga.projects.api import ProjectTemplateViewSet
|
||||||
|
|
||||||
|
|
||||||
router.register(r"roles", RolesViewSet, base_name="roles")
|
router.register(r"roles", RolesViewSet, base_name="roles")
|
||||||
router.register(r"projects", ProjectViewSet, base_name="projects")
|
router.register(r"projects", ProjectViewSet, base_name="projects")
|
||||||
router.register(r"project-templates", ProjectTemplateViewSet, base_name="project-templates")
|
router.register(r"project-templates", ProjectTemplateViewSet, base_name="project-templates")
|
||||||
|
@ -71,7 +78,6 @@ router.register(r"issue-types", IssueTypeViewSet, base_name="issue-types")
|
||||||
router.register(r"priorities", PriorityViewSet, base_name="priorities")
|
router.register(r"priorities", PriorityViewSet, base_name="priorities")
|
||||||
router.register(r"severities",SeverityViewSet , base_name="severities")
|
router.register(r"severities",SeverityViewSet , base_name="severities")
|
||||||
|
|
||||||
|
|
||||||
# Attachments
|
# Attachments
|
||||||
from taiga.projects.attachments.api import UserStoryAttachmentViewSet
|
from taiga.projects.attachments.api import UserStoryAttachmentViewSet
|
||||||
from taiga.projects.attachments.api import IssueAttachmentViewSet
|
from taiga.projects.attachments.api import IssueAttachmentViewSet
|
||||||
|
|
Loading…
Reference in New Issue