Example #1
0
    def get_queryset(self):
        """
        Get the set of projects that the user has access to and which meet filter criteria.

        Does not return temporary projects.

        TODO: Currently this ignores an authenticated user's access to
              projects inherited from membership of a team.
        """
        queryset = get_projects(self.request.user).select_related("account")

        account = self.request.GET.get("account")
        if account:
            queryset = queryset.filter(account_id=account)

        role = self.request.GET.get("role")
        if self.request.user.is_authenticated and role:
            roles = re.split(r"\s*,\s*", role)
            q = Q()
            for part in roles:
                match = re.match(r"([a-zA-Z]+)(\+)?", part)
                if match:
                    role_name, and_above = match.groups()
                    if role_name.lower() == "member":
                        q |= Q(role__isnull=False)
                    else:
                        try:
                            project_role = ProjectRole.from_string(role_name)
                        except ValueError as exc:
                            raise exceptions.ValidationError({"role": str(exc)})
                        else:
                            if and_above:
                                q |= Q(
                                    role__in=[
                                        role.name
                                        for role in ProjectRole.and_above(project_role)
                                    ]
                                )
                            else:
                                q |= Q(role=project_role.name)
                else:
                    raise exceptions.ValidationError(
                        {"role": "Invalid role specification {}".format(part)}
                    )
            queryset = queryset.filter(q)

        public = self.request.GET.get("public")
        if public:
            if public.lower() in ["false", "no", "0"]:
                queryset = queryset.filter(public=False)
            else:
                queryset = queryset.filter(public=True)

        source = self.request.GET.get("source")
        if source:
            try:
                query = Source.query_from_address(source, prefix="sources")
            except ValueError as exc:
                raise exceptions.ValidationError({"source": str(exc)})
            else:
                queryset = queryset.filter(query)

        search = self.request.GET.get("search")
        if search:
            queryset = queryset.filter(
                Q(name__icontains=search)
                | Q(title__icontains=search)
                | Q(description__icontains=search)
            )

        # Ordering favoring those that the user has a role
        # on, has an image set, has a description set, etc
        return (
            queryset.filter(temporary=False)
            .annotate(
                role_rank=Case(
                    When(role=ProjectRole.OWNER.name, then=Value(6)),
                    When(role=ProjectRole.MANAGER.name, then=Value(5)),
                    When(role=ProjectRole.AUTHOR.name, then=Value(4)),
                    When(role=ProjectRole.EDITOR.name, then=Value(3)),
                    When(role=ProjectRole.REVIEWER.name, then=Value(2)),
                    When(role=ProjectRole.READER.name, then=Value(1)),
                    When(role__isnull=True, then=Value(0)),
                    output_field=IntegerField(),
                )
                if self.request.user.is_authenticated
                else Value(0, output_field=IntegerField()),
                has_image=Case(
                    When(image_file__isnull=False, then=Value(True)),
                    default=Value(False),
                    output_field=BooleanField(),
                ),
                # Use regex filter here to exclude nulls, blanks and very short strings
                has_title=Case(
                    When(title__regex=r"^.{1,}$", then=Value(True)),
                    default=Value(False),
                    output_field=BooleanField(),
                ),
                has_description=Case(
                    When(description__regex=r"^.{1,}$", then=Value(True)),
                    default=Value(False),
                    output_field=BooleanField(),
                ),
            )
            .order_by(
                "-featured",
                "-has_image",
                "-has_title",
                "-has_description",
                "-role_rank",
                "-created",
            )
        )
Example #2
0
def test_project_role_from_string():
    assert ProjectRole.from_string("author") == ProjectRole.AUTHOR
    assert ProjectRole.from_string("AUTHOR") == ProjectRole.AUTHOR
    assert ProjectRole.from_string("AutHOr") == ProjectRole.AUTHOR
    with pytest.raises(ValueError, match='No project role matching "foo"'):
        ProjectRole.from_string("foo")