Просмотр исходного кода

Fix private threads to work with new acl

rafalp 6 лет назад
Родитель
Сommit
0d79134d7b

+ 12 - 3
misago/threads/api/postingendpoint/participants.py

@@ -4,6 +4,7 @@ from django.contrib.auth import get_user_model
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _, ngettext
 
+from misago.acl import useracl
 from misago.categories import PRIVATE_THREADS_ROOT_NAME
 from misago.threads.participants import add_participants, set_owner
 from misago.threads.permissions import allow_message_user
@@ -21,7 +22,14 @@ class ParticipantsMiddleware(PostingMiddleware):
         return False
 
     def get_serializer(self):
-        return ParticipantsSerializer(data=self.request.data, context={'user': self.user})
+        return ParticipantsSerializer(
+            data=self.request.data,
+            context={
+                'request': self.request,
+                'user': self.user,
+                'user_acl': self.user_acl,
+            },
+        )
 
     def save(self, serializer):
         set_owner(self.thread, self.user)
@@ -51,7 +59,7 @@ class ParticipantsSerializer(serializers.Serializer):
         if not clean_usernames:
             raise serializers.ValidationError(_("You have to enter user names."))
 
-        max_participants = self.context['user'].acl_cache['max_private_thread_participants']
+        max_participants = self.context['user_acl']['max_private_thread_participants']
         if max_participants and len(clean_usernames) > max_participants:
             message = ngettext(
                 "You can't add more than %(users)s user to private thread (you've added %(added)s).",
@@ -71,7 +79,8 @@ class ParticipantsSerializer(serializers.Serializer):
         users = []
         for user in UserModel.objects.filter(slug__in=usernames):
             try:
-                allow_message_user(self.context['user'], user)
+                user_acl = useracl.get_user_acl(user, self.context["request"].cache_versions)
+                allow_message_user(self.context['user_acl'], user, user_acl)
             except PermissionDenied as e:
                 raise serializers.ValidationError(str(e))
             users.append(user)

+ 1 - 1
misago/threads/api/postingendpoint/privatethread.py

@@ -16,7 +16,7 @@ class PrivateThreadMiddleware(PostingMiddleware):
     def pre_save(self, serializer):
         category = Category.objects.private_threads()
 
-        add_acl(self.user, category)
+        add_acl(self.user_acl, category)
 
         # set flags for savechanges middleware
         category.update_all = False

+ 3 - 2
misago/threads/api/threadendpoints/patch.py

@@ -7,7 +7,7 @@ from django.http import Http404
 from django.shortcuts import get_object_or_404
 from django.utils.translation import gettext as _
 
-from misago.acl import add_acl
+from misago.acl import add_acl, useracl
 from misago.categories.models import Category
 from misago.categories.permissions import allow_browse_category, allow_see_category
 from misago.categories.serializers import CategorySerializer
@@ -281,7 +281,8 @@ def patch_add_participant(request, thread, value):
     if participant in [p.user for p in thread.participants_list]:
         raise PermissionDenied(_("This user is already thread participant."))
 
-    allow_add_participant(request.user_acl, participant)
+    participant_acl = useracl.get_user_acl(participant, request.cache_versions)
+    allow_add_participant(request.user_acl, participant, participant_acl)
     add_participant(request, thread, participant)
 
     make_participants_aware(request.user, thread)

+ 1 - 1
misago/threads/api/threads.py

@@ -118,7 +118,7 @@ class PrivateThreadViewSet(ViewSet):
 
     @transaction.atomic
     def create(self, request):
-        allow_use_private_threads(request.user)
+        allow_use_private_threads(request.user_acl)
         if not request.user_acl['can_start_private_threads']:
             raise PermissionDenied(_("You can't start private threads."))
 

+ 4 - 6
misago/threads/permissions/privatethreads.py

@@ -247,10 +247,10 @@ def allow_remove_participant(user_acl, thread, target):
 can_remove_participant = return_boolean(allow_remove_participant)
 
 
-def allow_add_participant(user_acl, target):
+def allow_add_participant(user_acl, target, target_acl):
     message_format = {'user': target.username}
 
-    if not can_use_private_threads(target):
+    if not can_use_private_threads(target_acl):
         raise PermissionDenied(
             _("%(user)s can't participate in private threads.") % message_format
         )
@@ -258,7 +258,6 @@ def allow_add_participant(user_acl, target):
     if user_acl['can_add_everyone_to_private_threads']:
         return
 
-    # FIXME: User.is_blocking() needs to work with ids
     if user_acl['can_be_blocked'] and target.is_blocking(user_acl["user_id"]):
         raise PermissionDenied(_("%(user)s is blocking you.") % message_format)
 
@@ -267,7 +266,6 @@ def allow_add_participant(user_acl, target):
             _("%(user)s is not allowing invitations to private threads.") % message_format
         )
 
-    # FIXME: User.is_following() needs to work with ids
     if target.can_be_messaged_by_followed and not target.is_following(user_acl["user_id"]):
         message = _("%(user)s limits invitations to private threads to followed users.")
         raise PermissionDenied(message % message_format)
@@ -276,9 +274,9 @@ def allow_add_participant(user_acl, target):
 can_add_participant = return_boolean(allow_add_participant)
 
 
-def allow_message_user(user_acl, target):
+def allow_message_user(user_acl, target, target_acl):
     allow_use_private_threads(user_acl)
-    allow_add_participant(user_acl, target)
+    allow_add_participant(user_acl, target, target_acl)
 
 
 can_message_user = return_boolean(allow_message_user)

+ 17 - 0
misago/threads/test.py

@@ -45,6 +45,23 @@ def patch_other_category_acl(acl_patch=None):
     return patch_user_acl(patch_acl)
 
 
+def patch_private_threads_acl(acl_patch=None):
+    def patch_acl(_, user_acl):
+        category = Category.objects.private_threads()
+        category_acl = user_acl['categories'][category.id]
+        category_acl.update(default_category_acl)
+        if acl_patch:
+            category_acl.update(acl_patch)
+        cleanup_patched_acl(user_acl, category_acl, category)
+
+    return patch_user_acl(patch_acl)
+
+
+def other_user_cant_use_private_threads(user, user_acl):
+    if user.slug == "bobboberson":
+        user_acl.update({"can_use_private_threads": False})
+
+
 def create_category_acl_patch(category_slug, acl_patch):
     def created_category_acl_patch(_, user_acl):
         category = Category.objects.get(slug=category_slug)

+ 11 - 18
misago/threads/tests/test_privatethread_patch_api.py

@@ -3,13 +3,13 @@ import json
 from django.contrib.auth import get_user_model
 from django.core import mail
 
-from misago.acl.testutils import override_acl
+from misago.acl.test import patch_user_acl
 from misago.threads import testutils
+from misago.threads.test import other_user_cant_use_private_threads
 from misago.threads.models import Thread, ThreadParticipant
 
 from .test_privatethreads import PrivateThreadsTestCase
 
-
 UserModel = get_user_model()
 
 
@@ -125,12 +125,11 @@ class PrivateThreadAddParticipantApiTests(PrivateThreadPatchApiTestCase):
             'detail': ["BobBoberson is blocking you."],
         })
 
+    @patch_user_acl(other_user_cant_use_private_threads)
     def test_add_no_perm_user(self):
         """can't add user that has no permission to use private threads"""
         ThreadParticipant.objects.set_owner(self.thread, self.user)
 
-        override_acl(self.other_user, {'can_use_private_threads': 0})
-
         response = self.patch(
             self.api_link, [
                 {
@@ -219,6 +218,7 @@ class PrivateThreadAddParticipantApiTests(PrivateThreadPatchApiTestCase):
         self.assertIn(self.user.username, email.subject)
         self.assertIn(self.thread.title, email.subject)
 
+    @patch_user_acl({'can_moderate_private_threads': True})
     def test_add_user_to_other_user_thread_moderator(self):
         """moderators can add users to other users threads"""
         ThreadParticipant.objects.set_owner(self.thread, self.other_user)
@@ -226,8 +226,6 @@ class PrivateThreadAddParticipantApiTests(PrivateThreadPatchApiTestCase):
         self.thread.has_reported_posts = True
         self.thread.save()
 
-        override_acl(self.user, {'can_moderate_private_threads': 1})
-
         self.patch(
             self.api_link, [
                 {
@@ -246,6 +244,7 @@ class PrivateThreadAddParticipantApiTests(PrivateThreadPatchApiTestCase):
         # notification about new private thread wasn't send because we invited ourselves
         self.assertEqual(len(mail.outbox), 0)
 
+    @patch_user_acl({'can_moderate_private_threads': True})
     def test_add_user_to_closed_moderator(self):
         """moderators can add users to closed threads"""
         ThreadParticipant.objects.set_owner(self.thread, self.user)
@@ -253,8 +252,6 @@ class PrivateThreadAddParticipantApiTests(PrivateThreadPatchApiTestCase):
         self.thread.is_closed = True
         self.thread.save()
 
-        override_acl(self.user, {'can_moderate_private_threads': 1})
-
         self.patch(
             self.api_link, [
                 {
@@ -458,6 +455,7 @@ class PrivateThreadRemoveParticipantApiTests(PrivateThreadPatchApiTestCase):
         self.assertEqual(self.thread.participants.count(), 1)
         self.assertEqual(self.thread.participants.filter(pk=self.user.pk).count(), 0)
 
+    @patch_user_acl({'can_moderate_private_threads': True})
     def test_moderator_remove_user(self):
         """api allows moderator to remove other user"""
         removed_user = UserModel.objects.create_user('Vigilante', 'test@test.com', 'pass123')
@@ -465,8 +463,6 @@ class PrivateThreadRemoveParticipantApiTests(PrivateThreadPatchApiTestCase):
         ThreadParticipant.objects.set_owner(self.thread, self.other_user)
         ThreadParticipant.objects.add_participants(self.thread, [self.user, removed_user])
 
-        override_acl(self.user, {'can_moderate_private_threads': True})
-
         response = self.patch(
             self.api_link, [
                 {
@@ -742,6 +738,7 @@ class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
         self.assertTrue(event.is_event)
         self.assertTrue(event.event_type, 'changed_owner')
 
+    @patch_user_acl({'can_moderate_private_threads': True})
     def test_moderator_change_owner(self):
         """moderator can change thread owner to other user"""
         new_owner = UserModel.objects.create_user('NewOwner', 'new@owner.com', 'pass123')
@@ -749,8 +746,6 @@ class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
         ThreadParticipant.objects.set_owner(self.thread, self.other_user)
         ThreadParticipant.objects.add_participants(self.thread, [self.user, new_owner])
 
-        override_acl(self.user, {'can_moderate_private_threads': 1})
-
         response = self.patch(
             self.api_link, [
                 {
@@ -768,7 +763,7 @@ class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
         self.assertFalse(UserModel.objects.get(pk=self.user.pk).sync_unread_private_threads)
         self.assertTrue(UserModel.objects.get(pk=self.other_user.pk).sync_unread_private_threads)
 
-        # ownership was transfered
+        # ownership was transferred
         self.assertEqual(self.thread.participants.count(), 3)
         self.assertTrue(ThreadParticipant.objects.get(user=new_owner).is_owner)
         self.assertFalse(ThreadParticipant.objects.get(user=self.user).is_owner)
@@ -779,13 +774,12 @@ class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
         self.assertTrue(event.is_event)
         self.assertTrue(event.event_type, 'changed_owner')
 
+    @patch_user_acl({'can_moderate_private_threads': True})
     def test_moderator_takeover(self):
         """moderator can takeover the thread"""
         ThreadParticipant.objects.set_owner(self.thread, self.other_user)
         ThreadParticipant.objects.add_participants(self.thread, [self.user])
 
-        override_acl(self.user, {'can_moderate_private_threads': 1})
-
         response = self.patch(
             self.api_link, [
                 {
@@ -812,6 +806,7 @@ class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
         self.assertTrue(event.is_event)
         self.assertTrue(event.event_type, 'tookover')
 
+    @patch_user_acl({'can_moderate_private_threads': True})
     def test_moderator_closed_thread_takeover(self):
         """moderator can takeover closed thread thread"""
         ThreadParticipant.objects.set_owner(self.thread, self.other_user)
@@ -820,8 +815,6 @@ class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
         self.thread.is_closed = True
         self.thread.save()
 
-        override_acl(self.user, {'can_moderate_private_threads': 1})
-
         response = self.patch(
             self.api_link, [
                 {
@@ -838,7 +831,7 @@ class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
         self.assertFalse(UserModel.objects.get(pk=self.user.pk).sync_unread_private_threads)
         self.assertTrue(UserModel.objects.get(pk=self.other_user.pk).sync_unread_private_threads)
 
-        # ownership was transfered
+        # ownership was transferred
         self.assertEqual(self.thread.participants.count(), 2)
         self.assertTrue(ThreadParticipant.objects.get(user=self.user).is_owner)
         self.assertFalse(ThreadParticipant.objects.get(user=self.other_user).is_owner)

+ 41 - 45
misago/threads/tests/test_privatethread_start_api.py

@@ -3,12 +3,12 @@ from django.core import mail
 from django.urls import reverse
 from django.utils.encoding import smart_str
 
-from misago.acl.testutils import override_acl
+from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.threads.models import ThreadParticipant
+from misago.threads.test import other_user_cant_use_private_threads
 from misago.users.testutils import AuthenticatedUserTestCase
 
-
 UserModel = get_user_model()
 
 
@@ -30,20 +30,18 @@ class StartPrivateThreadTests(AuthenticatedUserTestCase):
         response = self.client.post(self.api_link)
         self.assertEqual(response.status_code, 403)
 
+    @patch_user_acl({'can_use_private_threads': False})
     def test_cant_use_private_threads(self):
         """has no permission to use private threads"""
-        override_acl(self.user, {'can_use_private_threads': 0})
-
         response = self.client.post(self.api_link)
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.json(), {
             "detail": "You can't use private threads.",
         })
 
+    @patch_user_acl({'can_start_private_threads': False})
     def test_cant_start_private_thread(self):
         """permission to start private thread is validated"""
-        override_acl(self.user, {'can_start_private_threads': 0})
-
         response = self.client.post(self.api_link)
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.json(), {
@@ -153,10 +151,9 @@ class StartPrivateThreadTests(AuthenticatedUserTestCase):
             }
         )
 
+    @patch_user_acl(other_user_cant_use_private_threads)
     def test_cant_invite_no_permission(self):
         """api validates invited user permission to private thread"""
-        override_acl(self.other_user, {'can_use_private_threads': 0})
-
         response = self.client.post(
             self.api_link,
             data={
@@ -191,8 +188,10 @@ class StartPrivateThreadTests(AuthenticatedUserTestCase):
             'to': ["BobBoberson is blocking you."],
         })
 
-        # allow us to bypass blocked check
-        override_acl(self.user, {'can_add_everyone_to_private_threads': 1})
+    @patch_user_acl({'can_add_everyone_to_private_threads': 1})
+    def test_cant_invite_blocking_override(self):
+        """api validates that you cant invite blocking user to thread"""
+        self.other_user.blocks.add(self.user)
 
         response = self.client.post(
             self.api_link,
@@ -233,26 +232,24 @@ class StartPrivateThreadTests(AuthenticatedUserTestCase):
         )
 
         # allow us to bypass following check
-        override_acl(self.user, {'can_add_everyone_to_private_threads': 1})
-
-        response = self.client.post(
-            self.api_link,
-            data={
-                'to': [self.other_user.username],
-                'title': "-----",
-                'post': "Lorem ipsum dolor.",
-            }
-        )
-
-        self.assertEqual(response.status_code, 400)
-        self.assertEqual(
-            response.json(), {
-                'title': ["Thread title should contain alpha-numeric characters."],
-            }
-        )
+        with patch_user_acl({'can_add_everyone_to_private_threads': 1}):
+            response = self.client.post(
+                self.api_link,
+                data={
+                    'to': [self.other_user.username],
+                    'title': "-----",
+                    'post': "Lorem ipsum dolor.",
+                }
+            )
+
+            self.assertEqual(response.status_code, 400)
+            self.assertEqual(
+                response.json(), {
+                    'title': ["Thread title should contain alpha-numeric characters."],
+                }
+            )
 
         # make user follow us
-        override_acl(self.user, {'can_add_everyone_to_private_threads': 0})
         self.other_user.follows.add(self.user)
 
         response = self.client.post(
@@ -294,23 +291,22 @@ class StartPrivateThreadTests(AuthenticatedUserTestCase):
         )
 
         # allow us to bypass user preference check
-        override_acl(self.user, {'can_add_everyone_to_private_threads': 1})
-
-        response = self.client.post(
-            self.api_link,
-            data={
-                'to': [self.other_user.username],
-                'title': "-----",
-                'post': "Lorem ipsum dolor.",
-            }
-        )
-
-        self.assertEqual(response.status_code, 400)
-        self.assertEqual(
-            response.json(), {
-                'title': ["Thread title should contain alpha-numeric characters."],
-            }
-        )
+        with patch_user_acl({'can_add_everyone_to_private_threads': 1}):
+            response = self.client.post(
+                self.api_link,
+                data={
+                    'to': [self.other_user.username],
+                    'title': "-----",
+                    'post': "Lorem ipsum dolor.",
+                }
+            )
+
+            self.assertEqual(response.status_code, 400)
+            self.assertEqual(
+                response.json(), {
+                    'title': ["Thread title should contain alpha-numeric characters."],
+                }
+            )
 
     def test_can_start_thread(self):
         """endpoint creates new thread"""

+ 4 - 7
misago/threads/tests/test_privatethread_view.py

@@ -1,4 +1,4 @@
-from misago.acl.testutils import override_acl
+from misago.acl.test import patch_user_acl
 from misago.threads import testutils
 from misago.threads.models import ThreadParticipant
 
@@ -19,10 +19,9 @@ class PrivateThreadViewTests(PrivateThreadsTestCase):
         response = self.client.get(self.test_link)
         self.assertContains(response, "sign in to use private threads", status_code=403)
 
+    @patch_user_acl({"can_use_private_threads": False})
     def test_no_permission(self):
         """user needs to have permission to see private thread"""
-        override_acl(self.user, {'can_use_private_threads': 0})
-
         response = self.client.get(self.test_link)
         self.assertContains(response, "t use private threads", status_code=403)
 
@@ -31,10 +30,9 @@ class PrivateThreadViewTests(PrivateThreadsTestCase):
         response = self.client.get(self.test_link)
         self.assertEqual(response.status_code, 404)
 
+    @patch_user_acl({"can_moderate_private_threads": True})
     def test_mod_not_reported(self):
         """moderator can't see private thread that has no reports"""
-        override_acl(self.user, {'can_moderate_private_threads': 1})
-
         response = self.client.get(self.test_link)
         self.assertEqual(response.status_code, 404)
 
@@ -60,10 +58,9 @@ class PrivateThreadViewTests(PrivateThreadsTestCase):
         response = self.client.get(self.test_link)
         self.assertContains(response, self.thread.title)
 
+    @patch_user_acl({"can_moderate_private_threads": True})
     def test_mod_can_see_reported(self):
         """moderator can see private thread that has reports"""
-        override_acl(self.user, {'can_moderate_private_threads': 1})
-
         self.thread.has_reported_posts = True
         self.thread.save()
 

+ 0 - 32
misago/threads/tests/test_privatethreads.py

@@ -1,4 +1,3 @@
-from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 
@@ -7,34 +6,3 @@ class PrivateThreadsTestCase(AuthenticatedUserTestCase):
     def setUp(self):
         super().setUp()
         self.category = Category.objects.private_threads()
-
-        override_acl(self.user, {
-            'can_use_private_threads': 1,
-            'can_start_private_threads': 1,
-        })
-
-        self.override_acl()
-
-    def override_acl(self, acl=None):
-        final_acl = self.user.acl_cache['categories'][self.category.pk]
-        final_acl.update({
-            'can_see': 1,
-            'can_browse': 1,
-            'can_see_all_threads': 1,
-            'can_see_own_threads': 0,
-            'can_hide_threads': 0,
-            'can_approve_content': 0,
-            'can_edit_posts': 0,
-            'can_hide_posts': 0,
-            'can_hide_own_posts': 0,
-            'can_merge_threads': 0,
-        })
-
-        if acl:
-            final_acl.update(acl)
-
-        override_acl(self.user, {
-            'categories': {
-                self.category.pk: final_acl,
-            },
-        })

+ 35 - 25
misago/threads/tests/test_privatethreads_api.py

@@ -1,8 +1,9 @@
 from django.urls import reverse
 
-from misago.acl.testutils import override_acl
+from misago.acl.test import patch_user_acl
 from misago.threads import testutils
 from misago.threads.models import Thread, ThreadParticipant
+from misago.threads.test import patch_private_threads_acl
 
 from .test_privatethreads import PrivateThreadsTestCase
 
@@ -23,16 +24,16 @@ class PrivateThreadsListApiTests(PrivateThreadsTestCase):
             "detail": "You have to sign in to use private threads."
         })
 
+    @patch_user_acl({"can_use_private_threads": False})
     def test_no_permission(self):
         """api requires user to have permission to be able to access it"""
-        override_acl(self.user, {'can_use_private_threads': 0})
-
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.json(), {
             "detail": "You can't use private threads."
         })
 
+    @patch_user_acl({"can_use_private_threads": True})
     def test_empty_list(self):
         """api has no showstoppers on returning empty list"""
         response = self.client.get(self.api_link)
@@ -41,6 +42,7 @@ class PrivateThreadsListApiTests(PrivateThreadsTestCase):
         response_json = response.json()
         self.assertEqual(response_json['count'], 0)
 
+    @patch_user_acl({"can_use_private_threads": True})
     def test_thread_visibility(self):
         """only participated threads are returned by private threads api"""
         visible = testutils.post_thread(category=self.category, poster=self.user)
@@ -62,15 +64,14 @@ class PrivateThreadsListApiTests(PrivateThreadsTestCase):
         self.assertEqual(response_json['results'][0]['id'], visible.id)
 
         # threads with reported posts will also show to moderators
-        override_acl(self.user, {'can_moderate_private_threads': 1})
-
-        response = self.client.get(self.api_link)
-        self.assertEqual(response.status_code, 200)
+        with patch_user_acl({"can_moderate_private_threads": True}):
+            response = self.client.get(self.api_link)
+            self.assertEqual(response.status_code, 200)
 
-        response_json = response.json()
-        self.assertEqual(response_json['count'], 2)
-        self.assertEqual(response_json['results'][0]['id'], reported.id)
-        self.assertEqual(response_json['results'][1]['id'], visible.id)
+            response_json = response.json()
+            self.assertEqual(response_json['count'], 2)
+            self.assertEqual(response_json['results'][0]['id'], reported.id)
+            self.assertEqual(response_json['results'][1]['id'], visible.id)
 
 
 class PrivateThreadRetrieveApiTests(PrivateThreadsTestCase):
@@ -90,28 +91,34 @@ class PrivateThreadRetrieveApiTests(PrivateThreadsTestCase):
             "detail": "You have to sign in to use private threads."
         })
 
+    @patch_user_acl({"can_use_private_threads": False})
     def test_no_permission(self):
         """user needs to have permission to see private thread"""
-        override_acl(self.user, {'can_use_private_threads': 0})
-
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.json(), {
             "detail": "You can't use private threads."
         })
 
+    @patch_user_acl({"can_use_private_threads": True})
     def test_no_participant(self):
         """user cant see thread he isn't part of"""
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 404)
 
+    @patch_user_acl({
+        "can_use_private_threads": True,
+        "can_moderate_private_threads": True,
+    })
     def test_mod_not_reported(self):
         """moderator can't see private thread that has no reports"""
-        override_acl(self.user, {'can_moderate_private_threads': 1})
-
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 404)
 
+    @patch_user_acl({
+        "can_use_private_threads": True,
+        "can_moderate_private_threads": False,
+    })
     def test_reported_not_mod(self):
         """non-mod can't see private thread that has reported posts"""
         self.thread.has_reported_posts = True
@@ -120,6 +127,7 @@ class PrivateThreadRetrieveApiTests(PrivateThreadsTestCase):
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 404)
 
+    @patch_user_acl({"can_use_private_threads": True})
     def test_can_see_owner(self):
         """user can see thread he is owner of"""
         ThreadParticipant.objects.set_owner(self.thread, self.user)
@@ -141,6 +149,7 @@ class PrivateThreadRetrieveApiTests(PrivateThreadsTestCase):
             ]
         )
 
+    @patch_user_acl({"can_use_private_threads": True})
     def test_can_see_participant(self):
         """user can see thread he is participant of"""
         ThreadParticipant.objects.add_participants(self.thread, [self.user])
@@ -162,10 +171,12 @@ class PrivateThreadRetrieveApiTests(PrivateThreadsTestCase):
             ]
         )
 
+    @patch_user_acl({
+        "can_use_private_threads": True,
+        "can_moderate_private_threads": True,
+    })
     def test_mod_can_see_reported(self):
         """moderator can see private thread that has reports"""
-        override_acl(self.user, {'can_moderate_private_threads': 1})
-
         self.thread.has_reported_posts = True
         self.thread.save()
 
@@ -186,30 +197,29 @@ class PrivateThreadDeleteApiTests(PrivateThreadsTestCase):
 
         ThreadParticipant.objects.add_participants(self.thread, [self.user])
 
-    def test_delete_thread_no_permission(self):
+    @patch_private_threads_acl({"can_hide_threads": 0})
+    def test_hide_thread_no_permission(self):
         """api tests permission to delete threads"""
-        self.override_acl({'can_hide_threads': 0})
-
+        
         response = self.client.delete(self.api_link)
         self.assertEqual(response.status_code, 403)
-
         self.assertEqual(
             response.json()['detail'], "You can't delete threads in this category."
         )
 
-        self.override_acl({'can_hide_threads': 1})
 
+    @patch_private_threads_acl({"can_hide_threads": 1})
+    def test_delete_thread_no_permission(self):
+        """api tests permission to delete threads"""
         response = self.client.delete(self.api_link)
         self.assertEqual(response.status_code, 403)
-
         self.assertEqual(
             response.json()['detail'], "You can't delete threads in this category."
         )
 
+    @patch_private_threads_acl({"can_hide_threads": 2})
     def test_delete_thread(self):
         """DELETE to API link with permission deletes thread"""
-        self.override_acl({'can_hide_threads': 2})
-
         response = self.client.delete(self.api_link)
         self.assertEqual(response.status_code, 200)
 

+ 7 - 9
misago/threads/tests/test_privatethreads_lists.py

@@ -1,6 +1,6 @@
 from django.urls import reverse
 
-from misago.acl.testutils import override_acl
+from misago.acl.test import patch_user_acl
 from misago.threads import testutils
 from misago.threads.models import ThreadParticipant
 
@@ -20,10 +20,9 @@ class PrivateThreadsListTests(PrivateThreadsTestCase):
         response = self.client.get(self.test_link)
         self.assertContains(response, "sign in to use private threads", status_code=403)
 
+    @patch_user_acl({"can_use_private_threads": False})
     def test_no_permission(self):
         """view requires user to have permission to be able to access it"""
-        override_acl(self.user, {'can_use_private_threads': 0})
-
         response = self.client.get(self.test_link)
         self.assertContains(response, "use private threads", status_code=403)
 
@@ -51,9 +50,8 @@ class PrivateThreadsListTests(PrivateThreadsTestCase):
         self.assertContains(response, visible.get_absolute_url())
 
         # threads with reported posts will also show to moderators
-        override_acl(self.user, {'can_moderate_private_threads': 1})
-
-        response = self.client.get(self.test_link)
-        self.assertEqual(response.status_code, 200)
-        self.assertContains(response, reported.get_absolute_url())
-        self.assertContains(response, visible.get_absolute_url())
+        with patch_user_acl({"can_moderate_private_threads": True}):
+            response = self.client.get(self.test_link)
+            self.assertEqual(response.status_code, 200)
+            self.assertContains(response, reported.get_absolute_url())
+            self.assertContains(response, visible.get_absolute_url())