Пример #1
0
 def bulk_create(self, request, **kwargs):
     serializer = serializers.UserStoriesBulkSerializer(data=request.DATA)
     if serializer.is_valid():
         data = serializer.data
         project = Project.objects.get(id=data["project_id"])
         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")
             or project.default_us_status_id,
             callback=self.post_save,
             precall=self.pre_save)
         user_stories_serialized = self.serializer_class(user_stories,
                                                         many=True)
         return response.Ok(user_stories_serialized.data)
     return response.BadRequest(serializer.errors)
Пример #2
0
    def undelete_comment(self, request, pk):
        obj = self.get_object()
        comment_id = request.QUERY_PARAMS.get('id', None)
        comment = services.get_history_queryset_by_model_instance(obj).filter(
            id=comment_id).first()

        self.check_permissions(request, 'undelete_comment', comment)

        if comment is None:
            return response.NotFound()

        if not comment.delete_comment_date and not comment.delete_comment_user:
            return response.BadRequest({"error": _("Comment not deleted")})

        comment.delete_comment_date = None
        comment.delete_comment_user = None
        comment.save()
        return response.Ok()
Пример #3
0
    def bulk_update_milestone(self, request, **kwargs):
        serializer = serializers.UpdateMilestoneBulkSerializer(
            data=request.DATA)
        if not serializer.is_valid():
            return response.BadRequest(serializer.errors)

        data = serializer.data
        project = get_object_or_404(Project, pk=data["project_id"])
        milestone = get_object_or_404(Milestone, pk=data["milestone_id"])

        self.check_permissions(request, "bulk_update_milestone", project)

        services.update_userstories_milestone_in_bulk(data["bulk_stories"],
                                                      milestone)
        services.snapshot_userstories_in_bulk(data["bulk_stories"],
                                              request.user)

        return response.NoContent()
Пример #4
0
    def bulk_update_milestone(self, request, **kwargs):
        validator = validators.UpdateMilestoneBulkValidator(data=request.DATA)
        if not validator.is_valid():
            return response.BadRequest(validator.errors)

        data = validator.data
        project = get_object_or_error(Project,
                                      request.user,
                                      pk=data["project_id"])
        milestone = get_object_or_error(Milestone,
                                        request.user,
                                        pk=data["milestone_id"])

        self.check_permissions(request, "bulk_update_milestone", project)

        ret = services.update_issues_milestone_in_bulk(data["bulk_issues"],
                                                       milestone)

        return response.Ok(ret)
Пример #5
0
    def bulk_create(self, request, **kwargs):
        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)
            if project.blocked_code is not None:
                raise exc.Blocked(_("Blocked element"))

            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, precall=self.pre_save)
            issues_serialized = self.get_serializer_class()(issues, many=True)

            return response.Ok(data=issues_serialized.data)

        return response.BadRequest(serializer.errors)
Пример #6
0
    def edit_tag(self, request, pk=None):
        project = self.get_object()
        self.check_permissions(request, "edit_tag", project)
        self._raise_if_blocked(project)

        validator = validators.EditTagTagValidator(data=request.DATA,
                                                   project=project)
        if not validator.is_valid():
            return response.BadRequest(validator.errors)

        data = validator.data
        services.edit_tag(
            project,
            data.get("from_tag"),
            to_tag=data.get("to_tag", None),
            color=data.get("color", None),
        )

        return response.Ok()
Пример #7
0
    def delete_comment(self, request, pk):
        obj = self.get_object()
        history_entry_id = request.QUERY_PARAMS.get('id', None)
        history_entry = services.get_history_queryset_by_model_instance(obj).filter(id=history_entry_id).first()
        if history_entry is None:
            return response.NotFound()

        self.check_permissions(request, 'delete_comment', history_entry)

        if history_entry is None:
            return response.NotFound()

        if history_entry.delete_comment_date or history_entry.delete_comment_user:
            return response.BadRequest({"error": _("Comment already deleted")})

        history_entry.delete_comment_date = timezone.now()
        history_entry.delete_comment_user = {"pk": request.user.pk, "name": request.user.get_full_name()}
        history_entry.save()
        return response.Ok()
Пример #8
0
    def move_issues_to_sprint(self, request, pk=None, **kwargs):
        milestone = get_object_or_404(models.Milestone, pk=pk)

        self.check_permissions(request, "move_related_items", milestone)

        validator = IssuesUpdateMilestoneValidator(data=request.DATA)
        if not validator.is_valid():
            return response.BadRequest(validator.errors)

        data = validator.data
        project = get_object_or_404(Project, pk=data["project_id"])
        milestone_result = get_object_or_404(models.Milestone, pk=data["milestone_id"])

        if data["bulk_issues"]:
            self.check_permissions(request, "move_issues_to_sprint", project)
            services.update_issues_milestone_in_bulk(data["bulk_issues"], milestone_result)
            services.snapshot_issues_in_bulk(data["bulk_issues"], request.user)

        return response.NoContent()
Пример #9
0
    def _bulk_update_order(self, order_field, request, **kwargs):
        serializer = serializers.UpdateTasksOrderBulkSerializer(
            data=request.DATA)
        if not serializer.is_valid():
            return response.BadRequest(serializer.errors)

        data = serializer.data
        project = get_object_or_404(Project, pk=data["project_id"])

        self.check_permissions(request, "bulk_update_order", project)
        if project.blocked_code is not None:
            raise exc.Blocked(_("Blocked element"))

        services.update_tasks_order_in_bulk(data["bulk_tasks"],
                                            project=project,
                                            field=order_field)
        services.snapshot_tasks_in_bulk(data["bulk_tasks"], request.user)

        return response.NoContent()
Пример #10
0
    def bulk_create(self, request, **kwargs):
        validator = validators.UserStoriesBulkValidator(data=request.DATA)
        if validator.is_valid():
            data = validator.data
            project = Project.objects.get(id=data["project_id"])
            self.check_permissions(request, 'bulk_create', project)
            if project.blocked_code is not None:
                raise exc.Blocked(_("Blocked element"))

            user_stories = services.create_userstories_in_bulk(
                data["bulk_stories"], project=project, owner=request.user,
                status_id=data.get("status_id") or project.default_us_status_id,
                callback=self.post_save, precall=self.pre_save)

            user_stories = self.get_queryset().filter(id__in=[i.id for i in user_stories])
            user_stories_serialized = self.get_serializer_class()(user_stories, many=True)

            return response.Ok(user_stories_serialized.data)
        return response.BadRequest(validator.errors)
Пример #11
0
    def _bulk_update_order(self, order_field, request, **kwargs):
        validator = validators.UpdateTasksOrderBulkValidator(data=request.DATA)
        if not validator.is_valid():
            return response.BadRequest(validator.errors)

        data = validator.data
        project = get_object_or_error(Project,
                                      request.user,
                                      pk=data["project_id"])

        self.check_permissions(request, "bulk_update_order", project)
        if project.blocked_code is not None:
            raise exc.Blocked(_("Blocked element"))

        user_story = None
        user_story_id = data.get("user_story_id", None)
        if user_story_id is not None:
            user_story = get_object_or_error(UserStory,
                                             request.user,
                                             pk=user_story_id)

        status = None
        status_id = data.get("status_id", None)
        if status_id is not None:
            status = get_object_or_error(TaskStatus,
                                         request.user,
                                         pk=status_id)

        milestone = None
        milestone_id = data.get("milestone_id", None)
        if milestone_id is not None:
            milestone = get_object_or_error(Milestone,
                                            request.user,
                                            pk=milestone_id)

        ret = services.update_tasks_order_in_bulk(data["bulk_tasks"],
                                                  order_field,
                                                  project,
                                                  user_story=user_story,
                                                  status=status,
                                                  milestone=milestone)
        return response.Ok(ret)
Пример #12
0
    def create(self, request, **kwargs):
        self.check_permissions(request, "create", None)

        data = copy.deepcopy(request.DATA)
        data.update({"full_name": request.user.get_full_name(),
                     "email": request.user.email})

        serializer = self.serializer_class(data=data)
        if not serializer.is_valid():
            return response.BadRequest(serializer.errors)

        self.object = serializer.save(force_insert=True)

        extra = {
            "HTTP_HOST":  request.META.get("HTTP_HOST", None),
            "HTTP_REFERER": request.META.get("HTTP_REFERER", None),
            "HTTP_USER_AGENT": request.META.get("HTTP_USER_AGENT", None),
        }
        services.send_feedback(self.object, extra, reply_to=[request.user.email])

        return response.Ok(serializer.data)
Пример #13
0
    def change_password_from_recovery(self, request, pk=None):
        """
        Change password with token (from password recovery step).
        """

        self.check_permissions(request, "change_password_from_recovery", None)

        validator = validators.RecoveryValidator(data=request.DATA, many=False)
        if not validator.is_valid():
            return response.BadRequest(validator.errors)

        try:
            user = models.User.objects.get(token=validator.data["token"])
        except models.User.DoesNotExist:
            raise exc.WrongArguments(_("Token is invalid"))

        user.set_password(validator.data["password"])
        user.token = None
        user.save(update_fields=["password", "token"])

        return response.NoContent()
Пример #14
0
    def bulk_create(self, request, **kwargs):
        serializer = serializers.TasksBulkSerializer(data=request.DATA)
        if serializer.is_valid():
            data = serializer.data
            project = Project.objects.get(id=data["project_id"])
            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")
                or project.default_task_status_id,
                project=project,
                owner=request.user,
                callback=self.post_save,
                precall=self.pre_save)
            tasks_serialized = self.get_serializer_class()(tasks, many=True)

            return response.Ok(tasks_serialized.data)

        return response.BadRequest(serializer.errors)
Пример #15
0
    def update(self, request, *args, **kwargs):
        self.object = self.get_object_or_none()
        project_id = request.DATA.get('project', None)
        if project_id and self.object and self.object.project.id != project_id:
            try:
                new_project = Project.objects.get(pk=project_id)
                self.check_permissions(request, "destroy", self.object)
                self.check_permissions(request, "create", new_project)

                status_id = request.DATA.get('status', None)
                if status_id is not None:
                    try:
                        old_status = self.object.project.epic_statuses.get(pk=status_id)
                        new_status = new_project.epic_statuses.get(slug=old_status.slug)
                        request.DATA['status'] = new_status.id
                    except EpicStatus.DoesNotExist:
                        request.DATA['status'] = new_project.default_epic_status.id

            except Project.DoesNotExist:
                return response.BadRequest(_("The project doesn't exist"))

        return super().update(request, *args, **kwargs)
Пример #16
0
    def undelete_comment(self, request, pk):
        obj = self.get_object()
        history_entry_id = request.QUERY_PARAMS.get("id", None)
        history_entry = (
            services.get_history_queryset_by_model_instance(obj).filter(
                id=history_entry_id).first())
        if history_entry is None:
            return response.NotFound()

        self.check_permissions(request, "undelete_comment", history_entry)

        if history_entry is None:
            return response.NotFound()

        if (not history_entry.delete_comment_date
                and not history_entry.delete_comment_user):
            return response.BadRequest({"error": _("Comment not deleted")})

        history_entry.delete_comment_date = None
        history_entry.delete_comment_user = None
        history_entry.save()
        return response.Ok()
Пример #17
0
    def update(self, request, *args, **kwargs):
        self.object = self.get_object_or_none()
        project_id = request.DATA.get('project', None)
        # print("##############################################################")
        request.obj = self.object
        # slack.send_slack_notification(request, obj)

        if project_id and self.object and self.object.project.id != project_id:
            try:
                new_project = Project.objects.get(pk=project_id)
                self.check_permissions(request, "destroy", self.object)
                self.check_permissions(request, "create", new_project)

                milestone_id = request.DATA.get('milestone', None)
                if milestone_id is not None and new_project.milestones.filter(
                        pk=milestone_id).count() == 0:
                    request.DATA['milestone'] = None

                us_id = request.DATA.get('user_story', None)
                if us_id is not None and new_project.user_stories.filter(
                        pk=us_id).count() == 0:
                    request.DATA['user_story'] = None

                status_id = request.DATA.get('status', None)
                if status_id is not None:
                    try:
                        old_status = self.object.project.task_statuses.get(
                            pk=status_id)
                        new_status = new_project.task_statuses.get(
                            slug=old_status.slug)
                        request.DATA['status'] = new_status.id
                    except TaskStatus.DoesNotExist:
                        request.DATA[
                            'status'] = new_project.default_task_status.id

            except Project.DoesNotExist:
                return response.BadRequest(_("The project doesn't exist"))

        return super().update(request, *args, **kwargs)
Пример #18
0
    def _bulk_update_order(self, order_field, request, **kwargs):
        serializer = serializers.UpdateUserStoriesOrderBulkSerializer(data=request.DATA)
        if not serializer.is_valid():
            return response.BadRequest(serializer.errors)

        data = serializer.data
        project = get_object_or_404(Project, pk=data["project_id"])

        self.check_permissions(request, "bulk_update_order", project)
        services.update_userstories_order_in_bulk(data["bulk_stories"],
                                                  project=project,
                                                  field=order_field)
        services.snapshot_userstories_in_bulk(data["bulk_stories"], request.user)

        if order_field in ["sprint_order", "backlog_order"]:
            # NOTE: This is useful according to issue #2851 to update sprints column in
            #       the browser client when move USs from the backlog to an sprint, from
            #       an sprint to the backlog or between sprints.
            has_closed_milestones = project.milestones.filter(closed=True).exists()
            self.headers["Taiga-Info-Has-Closed-Milestones"] = has_closed_milestones

        return response.NoContent()
Пример #19
0
    def duplicate(self, request, pk=None):
        project = self.get_object()
        self.check_permissions(request, "duplicate", project)
        if project.blocked_code is not None:
            raise exc.Blocked(_("Blocked element"))

        validator = validators.DuplicateProjectValidator(data=request.DATA)
        if not validator.is_valid():
            return response.BadRequest(validator.errors)

        data = validator.data
        new_name = data.get("name", "")
        new_description = data.get("description", "")
        new_owner = self.request.user
        new_is_private = data.get('is_private', False)
        new_members = data.get("users", [])

        # Validate if the project can be imported
        (enough_slots, error_message,
         total_members) = services.check_if_project_can_be_duplicate(
             project=project,
             new_owner=new_owner,
             new_is_private=new_is_private,
             new_user_id_members=[m["id"] for m in new_members])
        if not enough_slots:
            raise exc.NotEnoughSlotsForProject(new_is_private, total_members,
                                               error_message)

        new_project = services.duplicate_project(project=project,
                                                 name=new_name,
                                                 description=new_description,
                                                 owner=new_owner,
                                                 is_private=new_is_private,
                                                 users=new_members)
        new_project = get_object_or_error(self.get_queryset(),
                                          request.user,
                                          id=new_project.id)
        serializer = self.get_serializer(new_project)
        return response.Created(serializer.data)
Пример #20
0
    def bulk_create(self, request, **kwargs):
        validator = validators.TasksBulkValidator(data=request.DATA)
        if not validator.is_valid():
            return response.BadRequest(validator.errors)

        data = validator.data
        project = Project.objects.get(id=data["project_id"])
        self.check_permissions(request, 'bulk_create', project)
        if project.blocked_code is not None:
            raise exc.Blocked(_("Blocked element"))

        tasks = services.create_tasks_in_bulk(
            data["bulk_tasks"], milestone_id=data["milestone_id"], user_story_id=data["us_id"],
            status_id=data.get("status_id") or project.default_task_status_id,
            project=project, owner=request.user, callback=self.post_save, precall=self.pre_save)

        tasks = self.get_queryset().filter(id__in=[i.id for i in tasks])
        for task in tasks:
            self.persist_history_snapshot(obj=task)

        tasks_serialized = self.get_serializer_class()(tasks, many=True)

        return response.Ok(tasks_serialized.data)
Пример #21
0
    def update(self, request, *args, **kwargs):
        self.object = self.get_object_or_none()
        project_id = request.DATA.get("project", None)

        if project_id and self.object and self.object.project.id != project_id:
            try:
                new_project = Project.objects.get(pk=project_id)
                self.check_permissions(request, "destroy", self.object)
                self.check_permissions(request, "create", new_project)

                milestone_id = request.DATA.get("milestone", None)
                if (
                    milestone_id is not None
                    and new_project.milestones.filter(pk=milestone_id).count() == 0
                ):
                    request.DATA["milestone"] = None

                us_id = request.DATA.get("user_story", None)
                if (
                    us_id is not None
                    and new_project.user_stories.filter(pk=us_id).count() == 0
                ):
                    request.DATA["user_story"] = None

                status_id = request.DATA.get("status", None)
                if status_id is not None:
                    try:
                        old_status = self.object.project.task_statuses.get(pk=status_id)
                        new_status = new_project.task_statuses.get(slug=old_status.slug)
                        request.DATA["status"] = new_status.id
                    except TaskStatus.DoesNotExist:
                        request.DATA["status"] = new_project.default_task_status.id

            except Project.DoesNotExist:
                return response.BadRequest(_("The project doesn't exist"))

        return super().update(request, *args, **kwargs)
Пример #22
0
    def update(self, request, *args, **kwargs):
        self.object = self.get_object_or_none()
        project_id = request.DATA.get('project', None)

        if project_id and self.object and self.object.project.id != project_id:
            try:
                new_project = Project.objects.get(pk=project_id)
                self.check_permissions(request, "destroy", self.object)
                self.check_permissions(request, "create", new_project)

                sprint_id = request.DATA.get('milestone', None)
                if sprint_id is not None and new_project.milestones.filter(
                        pk=sprint_id).count() == 0:
                    request.DATA['milestone'] = None

                status_id = request.DATA.get('status', None)
                if status_id is not None:
                    try:
                        old_status = self.object.project.us_statuses.get(
                            pk=status_id)
                        new_status = new_project.us_statuses.get(
                            slug=old_status.slug)
                        request.DATA['status'] = new_status.id
                    except UserStoryStatus.DoesNotExist:
                        request.DATA[
                            'status'] = new_project.default_us_status.id
            except Project.DoesNotExist:
                return response.BadRequest(_("The project doesn't exist"))

        if self.object and self.object.project_id:
            self._max_order = models.UserStory.objects.filter(
                project_id=self.object.project_id,
                status_id=request.DATA.get('status', None)).aggregate(
                    Max('kanban_order'))['kanban_order__max']

        return super().update(request, *args, **kwargs)
Пример #23
0
    def update(self, request, *args, **kwargs):
        self.object = self.get_object_or_none()

        # If you move the US to another project...
        project_id = request.DATA.get('project', None)
        if project_id and self.object and self.object.project.id != project_id:
            try:
                new_project = Project.objects.get(pk=project_id)
                self.check_permissions(request, "destroy", self.object)
                self.check_permissions(request, "create", new_project)

                sprint_id = request.DATA.get('milestone', None)
                if sprint_id is not None and new_project.milestones.filter(
                        pk=sprint_id).count() == 0:
                    request.DATA['milestone'] = None

                swimlane_id = request.DATA.get('swimlane', None)
                if swimlane_id is not None and new_project.swimlanes.filter(
                        pk=swimlane_id).count() == 0:
                    request.DATA['swimlane'] = None

                status_id = request.DATA.get('status', None)
                if status_id is not None:
                    try:
                        old_status = self.object.project.us_statuses.get(
                            pk=status_id)
                        new_status = new_project.us_statuses.get(
                            slug=old_status.slug)
                        request.DATA['status'] = new_status.id
                    except UserStoryStatus.DoesNotExist:
                        request.DATA[
                            'status'] = new_project.default_us_status_id
            except Project.DoesNotExist:
                return response.BadRequest(_("The project doesn't exist"))

        return super().update(request, *args, **kwargs)
Пример #24
0
    def update(self, request, *args, **kwargs):
        self.object = self.get_object_or_none()
        project_id = request.DATA.get('project', None)
        if project_id and self.object and self.object.project.id != project_id:
            try:
                new_project = Project.objects.get(pk=project_id)
                self.check_permissions(request, "destroy", self.object)
                self.check_permissions(request, "create", new_project)

                sprint_id = request.DATA.get('milestone', None)
                if sprint_id is not None and new_project.milestones.filter(
                        pk=sprint_id).count() == 0:
                    request.DATA['milestone'] = None

                status_id = request.DATA.get('status', None)
                if status_id is not None:
                    try:
                        old_status = self.object.project.issue_statuses.get(
                            pk=status_id)
                        new_status = new_project.issue_statuses.get(
                            slug=old_status.slug)
                        request.DATA['status'] = new_status.id
                    except IssueStatus.DoesNotExist:
                        request.DATA[
                            'status'] = new_project.default_issue_status.id

                priority_id = request.DATA.get('priority', None)
                if priority_id is not None:
                    try:
                        old_priority = self.object.project.priorities.get(
                            pk=priority_id)
                        new_priority = new_project.priorities.get(
                            name=old_priority.name)
                        request.DATA['priority'] = new_priority.id
                    except Priority.DoesNotExist:
                        request.DATA[
                            'priority'] = new_project.default_priority.id

                severity_id = request.DATA.get('severity', None)
                if severity_id is not None:
                    try:
                        old_severity = self.object.project.severities.get(
                            pk=severity_id)
                        new_severity = new_project.severities.get(
                            name=old_severity.name)
                        request.DATA['severity'] = new_severity.id
                    except Severity.DoesNotExist:
                        request.DATA[
                            'severity'] = new_project.default_severity.id

                type_id = request.DATA.get('type', None)
                if type_id is not None:
                    try:
                        old_type = self.object.project.issue_types.get(
                            pk=type_id)
                        new_type = new_project.issue_types.get(
                            name=old_type.name)
                        request.DATA['type'] = new_type.id
                    except IssueType.DoesNotExist:
                        request.DATA[
                            'type'] = new_project.default_issue_type.id

            except Project.DoesNotExist:
                return response.BadRequest(_("The project doesn't exist"))

        return super().update(request, *args, **kwargs)
Пример #25
0
    def load_dump(self, request):
        throttle = throttling.ImportDumpModeRateThrottle()

        if not throttle.allow_request(request, self):
            self.throttled(request, throttle.wait())

        self.check_permissions(request, "load_dump", None)

        dump = request.FILES.get('dump', None)

        if not dump:
            raise exc.WrongArguments(_("Needed dump file"))

        reader = codecs.getreader("utf-8")

        try:
            dump = json.load(reader(dump))
        except Exception:
            raise exc.WrongArguments(_("Invalid dump format"))

        slug = dump.get('slug', None)
        if slug is not None and Project.objects.filter(slug=slug).exists():
            del dump['slug']

        user = request.user
        dump['owner'] = user.email

        # Validate if the project can be imported
        is_private = dump.get("is_private", False)
        total_memberships = len([
            m for m in dump.get("memberships", [])
            if m.get("email", None) != dump["owner"]
        ])
        total_memberships = total_memberships + 1  # 1 is the owner
        (enough_slots, error_message
         ) = users_services.has_available_slot_for_import_new_project(
             user, is_private, total_memberships)
        if not enough_slots:
            raise exc.NotEnoughSlotsForProject(is_private, total_memberships,
                                               error_message)

        # Async mode
        if settings.CELERY_ENABLED:
            task = tasks.load_project_dump.delay(user, dump)
            return response.Accepted({"import_id": task.id})

        # Sync mode
        try:
            project = services.store_project_from_dict(dump, request.user)
        except err.TaigaImportError as e:
            # On Error
            ## remove project
            if e.project:
                e.project.delete_related_content()
                e.project.delete()

            return response.BadRequest({
                "error": e.message,
                "details": e.errors
            })
        else:
            # On Success
            response_data = ProjectSerializer(project).data
            return response.Created(response_data)