diff --git a/readthedocs/projects/querysets.py b/readthedocs/projects/querysets.py index efd01c8026c..8eb93fa06da 100644 --- a/readthedocs/projects/querysets.py +++ b/readthedocs/projects/querysets.py @@ -15,6 +15,15 @@ class ProjectQuerySetBase(models.QuerySet): use_for_related_fields = True + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.users_not_banned = ( + Q(users__profile__banned=False) | + Q(users__profile__isnull=True) | + Q(users__isnull=True) + ) + def _add_user_repos(self, queryset, user): if user.has_perm('projects.view_project'): return self.all() @@ -36,21 +45,28 @@ def for_admin_user(self, user): return self.none() def public(self, user=None): - queryset = self.filter(privacy_level=constants.PUBLIC) + queryset = self.filter( + self.users_not_banned, + privacy_level=constants.PUBLIC + ) if user: queryset = self._add_user_repos(queryset, user) return queryset.distinct() def protected(self, user=None): queryset = self.filter( - privacy_level__in=[constants.PUBLIC, constants.PROTECTED], + self.users_not_banned, + privacy_level__in=[constants.PUBLIC, constants.PROTECTED] ) if user: queryset = self._add_user_repos(queryset, user) return queryset.distinct() def private(self, user=None): - queryset = self.filter(privacy_level=constants.PRIVATE) + queryset = self.filter( + self.users_not_banned, + privacy_level=constants.PRIVATE + ) if user: queryset = self._add_user_repos(queryset, user) return queryset.distinct() diff --git a/readthedocs/projects/views/public.py b/readthedocs/projects/views/public.py index 0b61a0ec5db..2bdf69804d7 100644 --- a/readthedocs/projects/views/public.py +++ b/readthedocs/projects/views/public.py @@ -45,7 +45,6 @@ class ProjectIndex(ListView): def get_queryset(self): queryset = Project.objects.public(self.request.user) - queryset = queryset.exclude(users__profile__banned=True) if self.kwargs.get('tag'): self.tag = get_object_or_404(Tag, slug=self.kwargs.get('tag')) diff --git a/readthedocs/rtd_tests/tests/test_project_querysets.py b/readthedocs/rtd_tests/tests/test_project_querysets.py index d48f7470090..03602315f99 100644 --- a/readthedocs/rtd_tests/tests/test_project_querysets.py +++ b/readthedocs/rtd_tests/tests/test_project_querysets.py @@ -18,7 +18,12 @@ class ProjectQuerySetTests(TestCase): def setUp(self): self.user = get(User) + self.user.profile.banned = False + self.user.profile.save() + self.another_user = get(User) + self.another_user.profile.banned = False + self.another_user.profile.save() self.project = get( Project, @@ -26,6 +31,11 @@ def setUp(self): users=[self.user], main_language_project=None, ) + self.project_no_user = get( + Project, + privacy_level=PUBLIC, + main_language_project=None, + ) self.project_private = get( Project, privacy_level=PRIVATE, @@ -145,6 +155,19 @@ def test_private(self): self.assertEqual(query.count(), len(projects)) self.assertEqual(set(query), projects) + def test_private_excludes_banned_projects(self): + self.user.profile.banned = True + self.user.profile.save() + + query = Project.objects.private() + + projects = { + self.another_project_private, + self.shared_project_private, + } + self.assertEqual(query.count(), len(projects)) + self.assertEqual(set(query), projects) + def test_private_user(self): query = Project.objects.private(user=self.user) projects = ( @@ -162,10 +185,43 @@ def test_private_user(self): self.assertEqual(query.count(), len(projects)) self.assertEqual(set(query), projects) + def test_private_with_banned_user(self): + self.user.profile.banned = True + self.user.profile.save() + + query = Project.objects.private(user=self.user) + projects = ( + self.user_projects | + {self.another_project_private} + ) + self.assertEqual(query.count(), len(projects)) + self.assertEqual(set(query), projects) + + query = Project.objects.private(user=self.another_user) + projects = ( + self.another_user_projects + ) + self.assertEqual(query.count(), len(projects)) + self.assertEqual(set(query), projects) + def test_public(self): query = Project.objects.public() projects = { self.project, + self.project_no_user, + self.another_project, + self.shared_project, + } + self.assertEqual(query.count(), len(projects)) + self.assertEqual(set(query), projects) + + def test_public_excludes_banned_projects(self): + self.user.profile.banned = True + self.user.profile.save() + + query = Project.objects.public() + projects = { + self.project_no_user, self.another_project, self.shared_project, } @@ -176,7 +232,27 @@ def test_public_user(self): query = Project.objects.public(user=self.user) projects = ( self.user_projects | - {self.another_project} + {self.project_no_user, self.another_project} + ) + self.assertEqual(query.count(), len(projects)) + self.assertEqual(set(query), projects) + + query = Project.objects.public(user=self.another_user) + projects = ( + self.another_user_projects | + {self.project, self.project_no_user} + ) + self.assertEqual(query.count(), len(projects)) + self.assertEqual(set(query), projects) + + def test_public_with_banned_user(self): + self.user.profile.banned = True + self.user.profile.save() + + query = Project.objects.public(user=self.user) + projects = ( + self.user_projects | + {self.project_no_user, self.another_project} ) self.assertEqual(query.count(), len(projects)) self.assertEqual(set(query), projects) @@ -184,7 +260,7 @@ def test_public_user(self): query = Project.objects.public(user=self.another_user) projects = ( self.another_user_projects | - {self.project} + {self.project_no_user} ) self.assertEqual(query.count(), len(projects)) self.assertEqual(set(query), projects) @@ -194,6 +270,7 @@ def test_protected(self): query = Project.objects.protected() projects = { self.project, + self.project_no_user, self.project_protected, self.another_project, self.another_project_protected, @@ -203,11 +280,54 @@ def test_protected(self): self.assertEqual(query.count(), len(projects)) self.assertEqual(set(query), projects) + def test_protected_excludes_banned_projects(self): + self.user.profile.banned = True + self.user.profile.save() + + query = Project.objects.protected() + projects = { + self.project_no_user, + self.another_project, + self.another_project_protected, + self.shared_project, + self.shared_project_protected, + } + self.assertEqual(query.count(), len(projects)) + self.assertEqual(set(query), projects) + def test_protected_user(self): query = Project.objects.protected(user=self.user) projects = ( self.user_projects | - {self.another_project, self.another_project_protected} + { + self.project_no_user, + self.another_project, + self.another_project_protected + } + ) + self.assertEqual(query.count(), len(projects)) + self.assertEqual(set(query), projects) + + query = Project.objects.protected(user=self.another_user) + projects = ( + self.another_user_projects | + {self.project, self.project_protected, self.project_no_user} + ) + self.assertEqual(query.count(), len(projects)) + self.assertEqual(set(query), projects) + + def test_protected_with_banned_user(self): + self.user.profile.banned = True + self.user.profile.save() + + query = Project.objects.protected(user=self.user) + projects = ( + self.user_projects | + { + self.project_no_user, + self.another_project, + self.another_project_protected + } ) self.assertEqual(query.count(), len(projects)) self.assertEqual(set(query), projects) @@ -215,7 +335,7 @@ def test_protected_user(self): query = Project.objects.protected(user=self.another_user) projects = ( self.another_user_projects | - {self.project, self.project_protected} + {self.project_no_user} ) self.assertEqual(query.count(), len(projects)) self.assertEqual(set(query), projects)