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_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")) user_story = None user_story_id = data.get("user_story_id", None) if user_story_id is not None: user_story = get_object_or_404(UserStory, pk=user_story_id) status = None status_id = data.get("status_id", None) if status_id is not None: status = get_object_or_404(TaskStatus, pk=status_id) milestone = None milestone_id = data.get("milestone_id", None) if milestone_id is not None: milestone = get_object_or_404(Milestone, 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 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_404(Project, pk=data["project_id"]) milestone = get_object_or_404(Milestone, 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 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 # Validate if the project can be imported is_private = data.get('is_private', False) total_memberships = len(data.get("users", [])) + 1 (enough_slots, error_message) = users_services.has_available_slot_for_new_project( self.request.user, is_private, total_memberships) if not enough_slots: raise exc.NotEnoughSlotsForProject(is_private, total_memberships, error_message) new_project = services.duplicate_project( project=project, owner=request.user, name=data["name"], description=data["description"], is_private=data["is_private"], users=data["users"]) new_project = get_object_or_404(self.get_queryset(), id=new_project.id) serializer = self.get_serializer(new_project) return response.Created(serializer.data)
def by_slug(self, request): slug = request.QUERY_PARAMS.get("slug", None) project_id = request.QUERY_PARAMS.get("project", None) wiki_page = get_object_or_404(models.WikiPage, slug=slug, project_id=project_id) return self.retrieve(request, pk=wiki_page.pk)
def bulk_create(self, request, **kwargs): validator = validators.CreateRelatedUserStoriesBulkValidator( data=request.DATA) if not validator.is_valid(): return response.BadRequest(validator.errors) data = validator.data epic = get_object_or_404(models.Epic, id=kwargs["epic"]) project = Project.objects.get(pk=data.get('project_id')) self.check_permissions(request, 'bulk_create', project) if project.blocked_code is not None: raise exc.Blocked(_("Blocked element")) related_userstories = services.create_related_userstories_in_bulk( data["bulk_userstories"], epic, project=project, owner=request.user) for related_userstory in related_userstories: self.persist_history_snapshot(obj=related_userstory) self.persist_history_snapshot(obj=related_userstory.user_story) related_uss_serialized = self.get_serializer_class()( epic.relateduserstory_set.all(), many=True) return response.Ok(related_uss_serialized.data)
def list(self, request, *args, **kwargs): resource_id = kwargs.get("resource_id", None) resource = get_object_or_404(self.resource_model, pk=resource_id) self.check_permissions(request, 'list', resource) return super().list(request, *args, **kwargs)
def voted(self, request, *args, **kwargs): for_user = get_object_or_404(models.User, **kwargs) from_user = request.user self.check_permissions(request, 'liked', for_user) filters = { "type": request.GET.get("type", None), "q": request.GET.get("q", None), } self.object_list = services.get_voted_list(for_user, from_user, **filters) page = self.paginate_queryset(self.object_list) elements = page.object_list if page is not None else self.object_list extra_args = { "user_watching": services.get_watched_content_for_user(request.user), "user_votes": services.get_voted_content_for_user(request.user), } response_data = [ serializers.VotedObjectSerializer(into_namedtuple(elem), **extra_args).data for elem in elements ] return response.Ok(response_data)
def retrieve(self, request, pk, *args, **kwargs): throttle = throttling.ImportDumpModeRateThrottle() if not throttle.allow_request(request, self): self.throttled(request, throttle.wait()) project = get_object_or_404(self.get_queryset(), pk=pk) self.check_permissions(request, 'export_project', project) dump_format = request.QUERY_PARAMS.get("dump_format", "plain") if settings.CELERY_ENABLED: task = tasks.dump_project.delay(request.user, project, dump_format) tasks.delete_project_dump.apply_async( (project.pk, project.slug, task.id, dump_format), countdown=settings.EXPORTS_TTL) return response.Accepted({"export_id": task.id}) if dump_format == "gzip": path = "exports/{}/{}-{}.json.gz".format(project.pk, project.slug, uuid.uuid4().hex) with default_storage.open(path, mode="wb") as outfile: services.render_project(project, gzip.GzipFile(fileobj=outfile)) else: path = "exports/{}/{}-{}.json".format(project.pk, project.slug, uuid.uuid4().hex) with default_storage.open(path, mode="wb") as outfile: services.render_project(project, outfile) response_data = {"url": default_storage.url(path)} return response.Ok(response_data)
def filters_data(self, request, *args, **kwargs): project_id = request.QUERY_PARAMS.get("project", None) project = get_object_or_404(Project, id=project_id) filter_backends = self.get_filter_backends() statuses_filter_backends = (f for f in filter_backends if f != filters.StatusesFilter) assigned_to_filter_backends = (f for f in filter_backends if f != filters.AssignedToFilter) owners_filter_backends = (f for f in filter_backends if f != filters.OwnersFilter) roles_filter_backends = (f for f in filter_backends if f != filters.RoleFilter) tags_filter_backends = (f for f in filter_backends if f != filters.TagsFilter) queryset = self.get_queryset() querysets = { "statuses": self.filter_queryset(queryset, filter_backends=statuses_filter_backends), "assigned_to": self.filter_queryset(queryset, filter_backends=assigned_to_filter_backends), "owners": self.filter_queryset(queryset, filter_backends=owners_filter_backends), "tags": self.filter_queryset(queryset, filter_backends=tags_filter_backends), "roles": self.filter_queryset(queryset, filter_backends=roles_filter_backends), } return response.Ok(services.get_tasks_filters_data(project, querysets))
def filter_queryset(self, request, queryset, view): project_id = None project = None qs = queryset.filter(is_active=True) if "project" in request.QUERY_PARAMS: try: project_id = int(request.QUERY_PARAMS["project"]) except: logger.error( "Filtering project diferent value than an integer: {}". format(request.QUERY_PARAMS["project"])) raise exc.BadRequest(_("'project' must be an integer value.")) if project_id: Project = apps.get_model('projects', 'Project') project = get_object_or_404(Project, pk=project_id) if request.user.is_authenticated() and request.user.is_superuser: qs = qs elif request.user.is_authenticated(): Membership = apps.get_model('projects', 'Membership') memberships_qs = Membership.objects.filter(user=request.user) if project_id: memberships_qs = memberships_qs.filter(project_id=project_id) memberships_qs = memberships_qs.filter( Q(role__permissions__contains=[self.permission]) | Q(is_admin=True)) projects_list = [ membership.project_id for membership in memberships_qs ] if project: is_member = project.id in projects_list has_project_public_view_permission = "view_project" in project.public_permissions if not is_member and not has_project_public_view_permission: qs = qs.none() q = Q(memberships__project_id__in=projects_list) | Q( id=request.user.id) # If there is no selected project we want access to users from public projects if not project: q = q | Q(memberships__project__public_permissions__contains=[ self.permission ]) qs = qs.filter(q) else: if project and "view_project" not in project.anon_permissions: qs = qs.none() qs = qs.filter(memberships__project__anon_permissions__contains=[ self.permission ]) return qs.distinct()
def patch(self, request, *args, **kwargs): self.check_permissions(request) resource_id = kwargs.get("resource_id", None) resource = get_object_or_404(self.resource_model, pk=resource_id) resource.read = timezone.now() resource.save() return response.Ok({})
def authorize_token(application_id: int, user: object, state: str) -> object: ApplicationToken = apps.get_model("external_apps", "ApplicationToken") Application = apps.get_model("external_apps", "Application") application = get_object_or_404(Application, id=application_id) token, _ = ApplicationToken.objects.get_or_create(user=user, application=application) token.update_auth_code() token.state = state token.save() return token
def csv(self, request): uuid = request.QUERY_PARAMS.get("uuid", None) if uuid is None: return response.NotFound() project = get_object_or_404(Project, issues_csv_uuid=uuid) queryset = project.issues.all().order_by('ref') data = services.issues_to_csv(project, queryset) csv_response = HttpResponse(data.getvalue(), content_type='application/csv; charset=utf-8') csv_response['Content-Disposition'] = 'attachment; filename="issues.csv"' return csv_response
def pre_delete(self, obj): move_to = self.request.QUERY_PARAMS.get('moveTo', None) if move_to: membership_model = apps.get_model("projects", "Membership") role_dest = get_object_or_404(self.model, project=obj.project, id=move_to) qs = membership_model.objects.filter(project_id=obj.project.pk, role=obj) qs.update(role=role_dest) super().pre_delete(obj)
def remove_logo(self, request, *args, **kwargs): """ Remove the logo of a project. """ self.object = get_object_or_404(self.get_queryset(), **kwargs) self.check_permissions(request, "remove_logo", self.object) self.pre_conditions_on_save(self.object) self.object.logo = None self.object.save(update_fields=["logo"]) serializer = self.get_serializer(self.object) return response.Ok(serializer.data)
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 stats(self, request, pk=None): milestone = get_object_or_404(models.Milestone, pk=pk) self.check_permissions(request, "stats", milestone) total_points = milestone.total_points milestone_stats = { 'name': milestone.name, 'estimated_start': milestone.estimated_start, 'estimated_finish': milestone.estimated_finish, 'total_points': total_points, 'completed_points': milestone.closed_points.values(), 'total_userstories': milestone.cached_user_stories.count(), 'completed_userstories': milestone.cached_user_stories.filter(is_closed=True).count(), 'total_tasks': milestone.tasks.count(), 'completed_tasks': milestone.tasks.filter(status__is_closed=True).count(), 'iocaine_doses': milestone.tasks.filter(is_iocaine=True).count(), 'days': [] } current_date = milestone.estimated_start sumTotalPoints = sum(total_points.values()) optimal_points = sumTotalPoints milestone_days = (milestone.estimated_finish - milestone.estimated_start).days optimal_points_per_day = sumTotalPoints / milestone_days if milestone_days else 0 while current_date <= milestone.estimated_finish: milestone_stats['days'].append({ 'day': current_date, 'name': current_date.day, 'open_points': sumTotalPoints - milestone.total_closed_points_by_date(current_date), 'optimal_points': optimal_points, }) current_date = current_date + datetime.timedelta(days=1) optimal_points -= optimal_points_per_day return response.Ok(milestone_stats)
def retrieve(self, request, *args, **kwargs): pk = kwargs.get("pk", None) resource_id = kwargs.get("resource_id", None) resource = get_object_or_404(self.resource_model, pk=resource_id) self.check_permissions(request, 'retrieve', resource) try: self.object = services.get_fans(resource).get(pk=pk) except ObjectDoesNotExist: # or User.DoesNotExist return response.NotFound() serializer = self.get_serializer(self.object) return response.Ok(serializer.data)
def validate(self, request, pk=None): application_id = request.DATA.get("application", None) auth_code = request.DATA.get("auth_code", None) state = request.DATA.get("state", None) application_token = get_object_or_404(models.ApplicationToken, application__id=application_id, auth_code=auth_code, state=state) application_token.generate_token() application_token.save() access_token_data = serializers.AccessTokenSerializer( application_token).data return response.Ok(access_token_data)
def render(self, request, **kwargs): content = request.DATA.get("content", None) project_id = request.DATA.get("project_id", None) if not content: raise exc.WrongArguments( {"content": _("'content' parameter is mandatory")}) if not project_id: raise exc.WrongArguments( {"project_id": _("'project_id' parameter is mandatory")}) project = get_object_or_404(Project, pk=project_id) self.check_permissions(request, "render", project) data = mdrender(project, content) return response.Ok({"data": data})
def contacts(self, request, *args, **kwargs): user = get_object_or_404(models.User, **kwargs) self.check_permissions(request, 'contacts', user) self.object_list = user_filters.ContactsFilterBackend( ).filter_queryset( user, request, self.get_queryset(), self).extra(select={ "complete_user_name": "concat(full_name, username)" }).order_by("complete_user_name") page = self.paginate_queryset(self.object_list) if page is not None: serializer = self.serializer_class(page.object_list, many=True) else: serializer = self.serializer_class(self.object_list, many=True) return response.Ok(serializer.data)
def bulk_update_order(self, request, **kwargs): bulk_data = request.DATA.get(self.bulk_update_param, None) if bulk_data is None: raise exc.BadRequest(_("'{param}' parameter is mandatory".format(param=self.bulk_update_param))) project_id = request.DATA.get('project', None) if project_id is None: raise exc.BadRequest(_("'project' parameter is mandatory")) project = get_object_or_404(Project, id=project_id) self.check_permissions(request, 'bulk_update_order', project) if project.blocked_code is not None: raise exc.Blocked(_("Blocked element")) self.__class__.bulk_update_order_action(project, request.user, bulk_data) return response.NoContent(data=None)
def token(self, request, *args, **kwargs): if self.request.user.is_anonymous(): raise exc.NotAuthenticated(_("Authentication required")) application = get_object_or_404(models.Application, **kwargs) self.check_permissions(request, 'token', request.user) try: application_token = models.ApplicationToken.objects.get( user=request.user, application=application) application_token.update_auth_code() application_token.state = request.GET.get("state", None) application_token.save() except models.ApplicationToken.DoesNotExist: application_token = models.ApplicationToken( user=request.user, application=application) auth_code_data = serializers.ApplicationTokenSerializer( application_token).data return response.Ok(auth_code_data)
def retrieve(self, request, *args, **kwargs): qs = self.get_queryset() if self.action == "by_slug": self.lookup_field = "slug" # If we retrieve the project by slug we want to filter by user the # permissions and return 404 in case the user don't have access flt = filters.get_filter_expression_can_view_projects( self.request.user) qs = qs.filter(flt) self.object = get_object_or_404(qs, **kwargs) self.check_permissions(request, 'retrieve', self.object) if self.object is None: raise Http404 serializer = self.get_serializer(self.object) return response.Ok(serializer.data)
def get_serializer_class(self): use_admin_serializer = False if self.action == "create": use_admin_serializer = True if self.action == "retrieve": use_admin_serializer = permissions_services.is_project_admin( self.request.user, self.object.project) project_id = self.request.QUERY_PARAMS.get("project", None) if self.action == "list" and project_id is not None: project = get_object_or_404(models.Project, pk=project_id) use_admin_serializer = permissions_services.is_project_admin( self.request.user, project) if use_admin_serializer: return self.admin_serializer_class else: return self.serializer_class
def destroy(self, request, *args, **kwargs): move_to = self.request.QUERY_PARAMS.get('moveTo', None) if move_to is None: return super().destroy(request, *args, **kwargs) obj = self.get_object_or_none() move_item = get_object_or_404(self.model, id=move_to) self.check_permissions(request, 'destroy', obj) qs = self.move_on_destroy_related_class.objects.filter( **{self.move_on_destroy_related_field: obj}) qs.update(**{self.move_on_destroy_related_field: move_item}) if getattr(obj.project, self.move_on_destroy_project_default_field) == obj: setattr(obj.project, self.move_on_destroy_project_default_field, move_item) obj.project.save() return super().destroy(request, *args, **kwargs)
def duplicate_project(project, **new_project_extra_args): owner = new_project_extra_args.get("owner") users = new_project_extra_args.pop("users") disconnect_projects_signals() Project = apps.get_model("projects", "Project") new_project = Project.objects.create(**new_project_extra_args) connect_projects_signals() permissions_services.set_base_permissions_for_project(new_project) # Cloning the structure from the old project using templates Template = apps.get_model("projects", "ProjectTemplate") template = Template() template.load_data_from_project(project) template.apply_to_project(new_project) new_project.creation_template = project.creation_template new_project.save() # Creating the membership for the new owner Membership = apps.get_model("projects", "Membership") Membership.objects.create( user=owner, is_admin=True, role=new_project.roles.get(slug=template.default_owner_role), project=new_project) # Creating the extra memberships for user in users: project_memberships = project.memberships.exclude(user_id=owner.id) membership = get_object_or_404(project_memberships, user_id=user["id"]) Membership.objects.create( user=membership.user, is_admin=membership.is_admin, role=new_project.roles.get(slug=membership.role.slug), project=new_project) # Take initial snapshot for the project take_snapshot(new_project, user=owner) return new_project
def watched(self, request, *args, **kwargs): for_user = get_object_or_404(models.User, **kwargs) from_user = request.user self.check_permissions(request, 'watched', for_user) filters = { "type": request.GET.get("type", None), "q": request.GET.get("q", None), } self.object_list = services.get_watched_list(for_user, from_user, **filters) page = self.paginate_queryset(self.object_list) elements = page.object_list if page is not None else self.object_list extra_args_liked = { "user_watching": services.get_watched_content_for_user(request.user), "user_likes": services.get_liked_content_for_user(request.user), } extra_args_voted = { "user_watching": services.get_watched_content_for_user(request.user), "user_votes": services.get_voted_content_for_user(request.user), } response_data = [] for elem in elements: if elem["type"] == "project": # projects are liked objects response_data.append( serializers.LikedObjectSerializer(into_namedtuple(elem), **extra_args_liked).data) else: # stories, tasks and issues are voted objects response_data.append( serializers.VotedObjectSerializer(into_namedtuple(elem), **extra_args_voted).data) return response.Ok(response_data)
def change_logo(self, request, *args, **kwargs): """ Change logo to this project. """ self.object = get_object_or_404(self.get_queryset(), **kwargs) self.check_permissions(request, "change_logo", self.object) logo = request.FILES.get('logo', None) if not logo: raise exc.WrongArguments(_("Incomplete arguments")) try: pil_image(logo) except Exception: raise exc.WrongArguments(_("Invalid image format")) self.pre_conditions_on_save(self.object) self.object.logo = logo self.object.save(update_fields=["logo"]) serializer = self.get_serializer(self.object) return response.Ok(serializer.data)
def _get_project(self, project_id): project_model = apps.get_model("projects", "Project") return get_object_or_404(project_model, pk=project_id)