Browse Source

#646: exclude disabled users from users lists, unless client is admin

Rafał Pitoń 8 years ago
parent
commit
4b9719cb9d

+ 4 - 1
misago/users/activepostersranking.py

@@ -34,7 +34,10 @@ def build_active_posters_ranking():
     for category in Category.objects.all_categories():
     for category in Category.objects.all_categories():
         ranked_categories.append(category.pk)
         ranked_categories.append(category.pk)
 
 
-    queryset = get_user_model().objects.filter(posts__gt=0).filter(
+    queryset = get_user_model().objects.filter(
+        is_active=True,
+        posts__gt=0
+    ).filter(
         post__posted_on__gte=tracked_since,
         post__posted_on__gte=tracked_since,
         post__category__in=ranked_categories
         post__category__in=ranked_categories
     ).annotate(score=Count('post'))
     ).annotate(score=Count('post'))

+ 3 - 0
misago/users/api/userendpoints/list.py

@@ -36,6 +36,9 @@ def generic(request):
     allow_name_search = True
     allow_name_search = True
     queryset = get_user_model().objects
     queryset = get_user_model().objects
 
 
+    if not request.user.is_staff:
+        queryset = queryset.filter(is_active=True)
+
     if request.query_params.get('followers'):
     if request.query_params.get('followers'):
         user_pk = get_int_or_404(request.query_params.get('followers'))
         user_pk = get_int_or_404(request.query_params.get('followers'))
         queryset = get_object_or_404(queryset, pk=user_pk).followed_by
         queryset = get_object_or_404(queryset, pk=user_pk).followed_by

+ 7 - 1
misago/users/search.py

@@ -22,7 +22,10 @@ class SearchUsers(SearchProvider):
 
 
     def search(self, query, page=1):
     def search(self, query, page=1):
         if query:
         if query:
-            results = search_users(username=query)
+            results = search_users(
+                search_disabled=self.request.user.is_staff,
+                username=query
+            )
         else:
         else:
             results = []
             results = []
 
 
@@ -37,6 +40,9 @@ def search_users(**filters):
     queryset = User.objects.order_by('slug').select_related(
     queryset = User.objects.order_by('slug').select_related(
         'rank', 'ban_cache', 'online_tracker')
         'rank', 'ban_cache', 'online_tracker')
 
 
+    if not filters.get('search_disabled', False):
+        queryset = queryset.filter(is_active=True)
+
     username = filters.get('username').lower()
     username = filters.get('username').lower()
 
 
     results = []
     results = []

+ 24 - 1
misago/users/tests/test_activepostersranking.py

@@ -16,7 +16,7 @@ class TestActivePostersRanking(AuthenticatedUserTestCase):
         cache.clear()
         cache.clear()
         threadstore.clear()
         threadstore.clear()
 
 
-        self.category = Category.objects.all_categories()[:1][0]
+        self.category = Category.objects.get(slug='first-category')
 
 
     def tearDown(self):
     def tearDown(self):
         super(TestActivePostersRanking, self).tearDown()
         super(TestActivePostersRanking, self).tearDown()
@@ -63,3 +63,26 @@ class TestActivePostersRanking(AuthenticatedUserTestCase):
 
 
         self.assertEqual(ranking['users'][0].score, 2)
         self.assertEqual(ranking['users'][0].score, 2)
         self.assertEqual(ranking['users'][1].score, 1)
         self.assertEqual(ranking['users'][1].score, 1)
+
+        # disabled users are not ranked
+        disabled = User.objects.create_user(
+            "DisabledUser", "disabled@user.com", "pass123")
+
+        disabled.is_active = False
+        disabled.save()
+
+        post_thread(self.category, poster=disabled)
+        post_thread(self.category, poster=disabled)
+        post_thread(self.category, poster=disabled)
+
+        disabled.posts = 3
+        disabled.save()
+
+        build_active_posters_ranking()
+        ranking = get_active_posters_ranking()
+
+        self.assertEqual(ranking['users'], [self.user, other_user])
+        self.assertEqual(ranking['users_count'], 2)
+
+        self.assertEqual(ranking['users'][0].score, 2)
+        self.assertEqual(ranking['users'][1].score, 1)

+ 66 - 3
misago/users/tests/test_lists_views.py

@@ -3,7 +3,10 @@ from django.urls import reverse
 from django.utils.six.moves import range
 from django.utils.six.moves import range
 
 
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
+from misago.categories.models import Category
+from misago.threads.testutils import post_thread
 
 
+from ..activepostersranking import build_active_posters_ranking
 from ..models import Rank
 from ..models import Rank
 from ..testutils import AuthenticatedUserTestCase
 from ..testutils import AuthenticatedUserTestCase
 
 
@@ -35,18 +38,29 @@ class UsersListLanderTests(UsersListTestCase):
 
 
 
 
 class ActivePostersTests(UsersListTestCase):
 class ActivePostersTests(UsersListTestCase):
+    def test_empty_active_posters_list(self):
+        """empty active posters page has no showstoppers"""
+        view_link = reverse('misago:users-active-posters')
+
+        response = self.client.get(view_link)
+        self.assertEqual(response.status_code, 200)
+
     def test_active_posters_list(self):
     def test_active_posters_list(self):
         """active posters page has no showstoppers"""
         """active posters page has no showstoppers"""
+        category = Category.objects.get(slug='first-category')
         view_link = reverse('misago:users-active-posters')
         view_link = reverse('misago:users-active-posters')
 
 
         response = self.client.get(view_link)
         response = self.client.get(view_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
-        # Create 200 test users and see if errors appeared
+        # Create 50 test users and see if errors appeared
         User = get_user_model()
         User = get_user_model()
-        for i in range(200):
-            User.objects.create_user(
+        for i in range(50):
+            user = User.objects.create_user(
                 'Bob%s' % i, 'm%s@te.com' % i, 'Pass.123', posts=12345)
                 'Bob%s' % i, 'm%s@te.com' % i, 'Pass.123', posts=12345)
+            post_thread(category, poster=user)
+
+        build_active_posters_ranking()
 
 
         response = self.client.get(view_link)
         response = self.client.get(view_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -55,11 +69,60 @@ class ActivePostersTests(UsersListTestCase):
 class UsersRankTests(UsersListTestCase):
 class UsersRankTests(UsersListTestCase):
     def test_ranks(self):
     def test_ranks(self):
         """ranks lists are handled correctly"""
         """ranks lists are handled correctly"""
+        User = get_user_model()
+        rank_user = User.objects.create_user(
+            'Visible', 'visible@te.com', 'Pass.123')
+
+        for rank in Rank.objects.iterator():
+            rank_user.rank = rank
+            rank_user.save()
+
+            rank_link = reverse('misago:users-rank', kwargs={'slug': rank.slug})
+            response = self.client.get(rank_link)
+
+            if rank.is_tab:
+                self.assertEqual(response.status_code, 200)
+                self.assertContains(response, rank_user.get_absolute_url())
+            else:
+                self.assertEqual(response.status_code, 404)
+
+    def test_disabled_users(self):
+        """ranks lists excludes disabled accounts"""
+        User = get_user_model()
+        rank_user = User.objects.create_user(
+            'Visible', 'visible@te.com', 'Pass.123', is_active=False)
+
         for rank in Rank.objects.iterator():
         for rank in Rank.objects.iterator():
+            rank_user.rank = rank
+            rank_user.save()
+
+            rank_link = reverse('misago:users-rank', kwargs={'slug': rank.slug})
+            response = self.client.get(rank_link)
+
+            if rank.is_tab:
+                self.assertEqual(response.status_code, 200)
+                self.assertNotContains(response, rank_user.get_absolute_url())
+            else:
+                self.assertEqual(response.status_code, 404)
+
+    def test_staff_see_disabled_users(self):
+        """ranks lists shows disabled accounts for staff members"""
+        self.user.is_staff = True
+        self.user.save()
+
+        User = get_user_model()
+        rank_user = User.objects.create_user(
+            'Visible', 'visible@te.com', 'Pass.123', is_active=False)
+
+        for rank in Rank.objects.iterator():
+            rank_user.rank = rank
+            rank_user.save()
+
             rank_link = reverse('misago:users-rank', kwargs={'slug': rank.slug})
             rank_link = reverse('misago:users-rank', kwargs={'slug': rank.slug})
             response = self.client.get(rank_link)
             response = self.client.get(rank_link)
 
 
             if rank.is_tab:
             if rank.is_tab:
                 self.assertEqual(response.status_code, 200)
                 self.assertEqual(response.status_code, 200)
+                self.assertContains(response, rank_user.get_absolute_url())
             else:
             else:
                 self.assertEqual(response.status_code, 404)
                 self.assertEqual(response.status_code, 404)

+ 33 - 0
misago/users/tests/test_search.py

@@ -1,3 +1,4 @@
+from django.contrib.auth import get_user_model
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
@@ -98,6 +99,38 @@ class SearchApiTests(AuthenticatedUserTestCase):
             if provider['id'] == 'users':
             if provider['id'] == 'users':
                 self.assertEqual(provider['results']['results'], [])
                 self.assertEqual(provider['results']['results'], [])
 
 
+    def test_search_disabled(self):
+        """api respects disabled users visibility"""
+        User = get_user_model()
+        disabled_user = User.objects.create_user(
+            'DisabledUser', 'visible@te.com', 'Pass.123', is_active=False)
+
+        response = self.client.get('%s?q=DisabledUser' % self.api_link)
+        self.assertEqual(response.status_code, 200)
+
+        reponse_json = response.json()
+        self.assertIn('users', [p['id'] for p in reponse_json])
+
+        for provider in reponse_json:
+            if provider['id'] == 'users':
+                self.assertEqual(provider['results']['results'], [])
+
+        # user shows in searchech performed by staff
+        self.user.is_staff = True
+        self.user.save()
+
+        response = self.client.get('%s?q=DisabledUser' % self.api_link)
+        self.assertEqual(response.status_code, 200)
+
+        reponse_json = response.json()
+        self.assertIn('users', [p['id'] for p in reponse_json])
+
+        for provider in reponse_json:
+            if provider['id'] == 'users':
+                results = provider['results']['results']
+                self.assertEqual(len(results), 1)
+                self.assertEqual(results[0]['id'], disabled_user.id)
+
 
 
 class SearchProviderApiTests(SearchApiTests):
 class SearchProviderApiTests(SearchApiTests):
     def setUp(self):
     def setUp(self):

+ 24 - 0
misago/users/tests/test_users_api.py

@@ -187,6 +187,30 @@ class RankListTests(AuthenticatedUserTestCase):
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertContains(response, self.user.username)
         self.assertContains(response, self.user.username)
 
 
+    def test_disabled_users(self):
+        """api follows disabled users visibility"""
+        test_rank = Rank.objects.create(
+            name="Test rank",
+            slug="test-rank",
+            is_tab=True
+        )
+
+        User = get_user_model()
+        test_user = User.objects.create_user(
+            'Visible', 'visible@te.com', 'Pass.123',
+            rank=test_rank, is_active=False
+        )
+
+        response = self.client.get(self.link % test_rank.pk)
+        self.assertNotContains(response, test_user.get_absolute_url())
+
+        # api shows disabled accounts to staff
+        self.user.is_staff = True
+        self.user.save()
+
+        response = self.client.get(self.link % test_rank.pk)
+        self.assertContains(response, test_user.get_absolute_url())
+
 
 
 class SearchNamesListTests(AuthenticatedUserTestCase):
 class SearchNamesListTests(AuthenticatedUserTestCase):
     """
     """

+ 3 - 0
misago/users/views/lists.py

@@ -99,6 +99,9 @@ def rank(request, slug, page=0):
     rank = get_object_or_404(Rank.objects.filter(is_tab=True), slug=slug)
     rank = get_object_or_404(Rank.objects.filter(is_tab=True), slug=slug)
     queryset = rank.user_set.select_related('rank').order_by('slug')
     queryset = rank.user_set.select_related('rank').order_by('slug')
 
 
+    if not request.user.is_staff:
+        queryset = queryset.filter(is_active=True)
+
     page = paginate(queryset, page, settings.MISAGO_USERS_PER_PAGE, 4)
     page = paginate(queryset, page, settings.MISAGO_USERS_PER_PAGE, 4)
     paginator = pagination_dict(page)
     paginator = pagination_dict(page)