Esempio n. 1
0
    def post(self, request, project_slug):
        project = get_object_or_404(Project, slug=project_slug)

        if not AdminPermission.is_admin(request.user, project):
            return HttpResponseForbidden()

        version_slug = request.POST.get('version_slug')
        version = get_object_or_404(
            Version,
            project=project,
            slug=version_slug,
        )

        update_docs_task, build = trigger_build(
            project=project,
            version=version,
        )
        if (update_docs_task, build) == (None, None):
            # Build was skipped
            messages.add_message(
                request,
                messages.WARNING,
                "This project is currently disabled and can't trigger new builds.",
            )
            return HttpResponseRedirect(
                reverse('builds_project_list', args=[project.slug]),
            )

        return HttpResponseRedirect(
            reverse('builds_detail', args=[project.slug, build.pk]),
        )
    def test_project_admins_can_delete_subprojects_that_they_are_not_admin_of(self):
        self.project.users.add(self.user)
        self.assertFalse(AdminPermission.is_admin(self.user, self.subproject))

        response = self.client.post(
            '/dashboard/my-mainproject/subprojects/my-subproject/delete/')
        self.assertEqual(response.status_code, 302)
        self.assertTrue(self.subproject not in [r.child for r in self.project.subprojects.all()])
Esempio n. 3
0
    def test_project_admins_can_delete_subprojects_that_they_are_not_admin_of(
        self, ):
        self.project.users.add(self.user)
        self.assertFalse(AdminPermission.is_admin(self.user, self.subproject))

        response = self.client.post(
            '/dashboard/my-mainproject/subprojects/my-subproject/delete/', )
        self.assertEqual(response.status_code, 302)
        self.assertTrue(
            self.subproject
            not in [r.child for r in self.project.subprojects.all()], )
Esempio n. 4
0
def project_versions(request, project_slug):
    """
    Project version list view.

    Shows the available versions and lets the user choose which ones to build.
    """
    max_inactive_versions = 100

    project = get_object_or_404(
        Project.objects.protected(request.user),
        slug=project_slug,
    )

    versions = Version.internal.public(
        user=request.user,
        project=project,
        only_active=False,
    )
    active_versions = versions.filter(active=True)

    # Limit inactive versions in case a project has a large number of branches or tags
    # Filter inactive versions based on the query string
    inactive_versions = versions.filter(active=False)
    version_filter = request.GET.get('version_filter', '')
    if version_filter:
        inactive_versions = inactive_versions.filter(
            verbose_name__icontains=version_filter)
    total_inactive_versions_count = inactive_versions.count()
    inactive_versions = inactive_versions[:max_inactive_versions]

    # If there's a wiped query string, check the string against the versions
    # list and display a success message. Deleting directories doesn't know how
    # to fail.  :)
    wiped = request.GET.get('wipe', '')
    wiped_version = versions.filter(slug=wiped)
    if wiped and wiped_version.exists():
        messages.success(request, 'Version wiped: ' + wiped)

    # Optimize project permission checks
    prefetch_related_objects([project], 'users')

    return render(
        request,
        'projects/project_version_list.html',
        {
            'inactive_versions': inactive_versions,
            'active_versions': active_versions,
            'project': project,
            'is_project_admin': AdminPermission.is_admin(
                request.user, project),
            'max_inactive_versions': max_inactive_versions,
            'total_inactive_versions_count': total_inactive_versions_count,
        },
    )
Esempio n. 5
0
    def post(self, request, project_slug):
        project = get_object_or_404(Project, slug=project_slug)

        if not AdminPermission.is_admin(request.user, project):
            return HttpResponseForbidden()

        version_slug = request.POST.get('version_slug')
        version = get_object_or_404(
            Version,
            project=project,
            slug=version_slug,
        )

        trigger_build(project=project, version=version)
        return HttpResponseRedirect(reverse('builds_project_list', args=[project.slug]))
Esempio n. 6
0
    def post(self, request, project_slug):
        project = get_object_or_404(Project, slug=project_slug)

        if not AdminPermission.is_admin(request.user, project):
            return HttpResponseForbidden()

        version_slug = request.POST.get('version_slug')
        version = get_object_or_404(
            Version,
            project=project,
            slug=version_slug,
        )

        _, build = trigger_build(project=project, version=version)
        return HttpResponseRedirect(
            reverse('builds_detail', args=[project.slug, build.pk]), )
Esempio n. 7
0
    def clean_subproject(self):
        """Normalize subproject field

        Does lookup on against :py:class:`Project` to ensure matching project
        exists. Return the :py:class:`Project` object instead.
        """
        subproject_name = self.cleaned_data['subproject']
        subproject_qs = Project.objects.filter(slug=subproject_name)
        if not subproject_qs.exists():
            raise forms.ValidationError(
                (_("Project %(name)s does not exist") % {
                    'name': subproject_name
                }))
        subproject = subproject_qs.first()
        if not AdminPermission.is_admin(self.user, subproject):
            raise forms.ValidationError(
                _('You need to be admin of {name} in order to add it as '
                  'a subproject.'.format(name=subproject_name)))
        return subproject
Esempio n. 8
0
    def post(self, request, project_slug, build_pk):
        project = get_object_or_404(Project, slug=project_slug)
        build = get_object_or_404(Build, pk=build_pk)

        if not AdminPermission.is_admin(request.user, project):
            return HttpResponseForbidden()

        # NOTE: `terminate=True` is required for the child to attend our call
        # immediately when it's running the build. Otherwise, it finishes the
        # task. However, to revoke a task that has not started yet, we don't
        # need it.
        if build.state == BUILD_STATE_TRIGGERED:
            # Since the task won't be executed at all, we need to update the
            # Build object here.
            terminate = False
            build.state = BUILD_STATE_FINISHED
            build.success = False
            build.error = BuildCancelled.message
            build.length = 0
            build.save()
        else:
            # In this case, we left the update of the Build object to the task
            # itself to be executed in the `on_failure` handler.
            terminate = True

        log.warning(
            'Canceling build.',
            project_slug=project.slug,
            version_slug=build.version.slug,
            build_id=build.pk,
            build_task_id=build.task_id,
            terminate=terminate,
        )
        app.control.revoke(build.task_id,
                           signal=signal.SIGINT,
                           terminate=terminate)

        return HttpResponseRedirect(
            reverse('builds_detail', args=[project.slug, build.pk]), )
Esempio n. 9
0
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        project = self.get_project()

        # Get filtered and sorted versions
        versions = self._get_versions(project)
        if settings.RTD_EXT_THEME_ENABLED:
            filter = ProjectVersionListFilterSet(
                self.request.GET,
                queryset=versions,
            )
            context['filter'] = filter
            versions = filter.qs
        context['versions'] = versions

        protocol = 'http'
        if self.request.is_secure():
            protocol = 'https'

        version_slug = project.get_default_version()

        context['badge_url'] = ProjectBadgeView.get_badge_url(
            project.slug,
            version_slug,
            protocol=protocol,
        )
        context['site_url'] = '{url}?badge={version}'.format(
            url=project.get_docs_url(version_slug),
            version=version_slug,
        )

        context['is_project_admin'] = AdminPermission.is_admin(
            self.request.user,
            project,
        )

        return context
Esempio n. 10
0
def is_admin(user, project):
    return AdminPermission.is_admin(user, project)
Esempio n. 11
0
 def has_object_permission(self, request, view, obj):
     if request.method in permissions.SAFE_METHODS:
         return True  # TODO: Similar logic to #1084
     return AdminPermission.is_admin(request.user, obj.node.project)
Esempio n. 12
0
 def has_object_permission(self, request, view, obj):
     if request.method in permissions.SAFE_METHODS:
         return True  # TODO: Similar logic to #1084
     return AdminPermission.is_admin(request.user, obj.node.project)
Esempio n. 13
0
    def post(self, request, project_slug):
        commit_to_retrigger = None
        project = get_object_or_404(Project, slug=project_slug)

        if not AdminPermission.is_admin(request.user, project):
            return HttpResponseForbidden()

        version_slug = request.POST.get('version_slug')
        build_pk = request.POST.get('build_pk')

        if build_pk:
            # Filter over external versions only when re-triggering a specific build
            version = get_object_or_404(
                Version.external.public(self.request.user),
                slug=version_slug,
                project=project,
            )

            build_to_retrigger = get_object_or_404(
                Build.objects.all(),
                pk=build_pk,
                version=version,
            )
            if build_to_retrigger != Build.objects.filter(
                    version=version).first():
                messages.add_message(
                    request,
                    messages.ERROR,
                    "This build can't be re-triggered because it's "
                    "not the latest build for this version.",
                )
                return HttpResponseRedirect(request.path)

            # Set either the build to re-trigger it or None
            if build_to_retrigger:
                commit_to_retrigger = build_to_retrigger.commit
                log.info(
                    'Re-triggering build.',
                    project_slug=project.slug,
                    version_slug=version.slug,
                    build_commit=build_to_retrigger.commit,
                    build_id=build_to_retrigger.pk,
                )
        else:
            # Use generic query when triggering a normal build
            version = get_object_or_404(
                self._get_versions(project),
                slug=version_slug,
            )

        update_docs_task, build = trigger_build(
            project=project,
            version=version,
            commit=commit_to_retrigger,
        )
        if (update_docs_task, build) == (None, None):
            # Build was skipped
            messages.add_message(
                request,
                messages.WARNING,
                "This project is currently disabled and can't trigger new builds.",
            )
            return HttpResponseRedirect(
                reverse('builds_project_list', args=[project.slug]), )

        return HttpResponseRedirect(
            reverse('builds_detail', args=[project.slug, build.pk]), )
Esempio n. 14
0
def is_admin(user, project):
    return AdminPermission.is_admin(user, project)