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