Browse Source

Fix post merge api

rafalp 6 years ago
parent
commit
b3dd25a959

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

@@ -15,7 +15,7 @@ def posts_merge_endpoint(request, thread):
         data=request.data,
         context={
             'thread': thread,
-            'user': request.user,
+            'user_acl': request.user_acl,
         },
     )
 

+ 59 - 49
misago/threads/tests/test_thread_postmerge_api.py

@@ -2,12 +2,12 @@ import json
 
 from django.urls import reverse
 
-from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.readtracker import poststracker
 from misago.threads import testutils
 from misago.threads.models import Post, Thread
 from misago.threads.serializers.moderation import POSTS_LIMIT
+from misago.threads.test import patch_category_acl
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
@@ -25,28 +25,6 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             }
         )
 
-        self.override_acl()
-
-    def refresh_thread(self):
-        self.thread = Thread.objects.get(pk=self.thread.pk)
-
-    def override_acl(self, extra_acl=None):
-        new_acl = self.user.acl_cache
-        new_acl['categories'][self.category.pk].update({
-            'can_see': 1,
-            'can_browse': 1,
-            'can_start_threads': 0,
-            'can_reply_threads': 0,
-            'can_edit_posts': 1,
-            'can_approve_content': 0,
-            'can_merge_posts': 1,
-        })
-
-        if extra_acl:
-            new_acl['categories'][self.category.pk].update(extra_acl)
-
-        override_acl(self.user, new_acl)
-
     def test_anonymous_user(self):
         """you need to authenticate to merge posts"""
         self.logout_user()
@@ -61,10 +39,9 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "This action is not available to guests.",
         })
 
+    @patch_category_acl({"can_merge_posts": False})
     def test_no_permission(self):
         """api validates permission to merge"""
-        self.override_acl({'can_merge_posts': 0})
-
         response = self.client.post(
             self.api_link,
             json.dumps({}),
@@ -75,6 +52,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "You can't merge posts in this thread.",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_empty_data_json(self):
         """api handles empty json data"""
         response = self.client.post(
@@ -85,6 +63,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "You have to select at least two posts to merge.",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_empty_data_form(self):
         """api handles empty form data"""
         response = self.client.post(self.api_link, {})
@@ -93,36 +72,34 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "You have to select at least two posts to merge.",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_invalid_data(self):
         """api handles post that is invalid type"""
-        self.override_acl()
         response = self.client.post(self.api_link, '[]', content_type="application/json")
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.json(), {
             "detail": "Invalid data. Expected a dictionary, but got list.",
         })
 
-        self.override_acl()
         response = self.client.post(self.api_link, '123', content_type="application/json")
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.json(), {
             "detail": "Invalid data. Expected a dictionary, but got int.",
         })
 
-        self.override_acl()
         response = self.client.post(self.api_link, '"string"', content_type="application/json")
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.json(), {
             "detail": "Invalid data. Expected a dictionary, but got str.",
         })
 
-        self.override_acl()
         response = self.client.post(self.api_link, 'malformed', content_type="application/json")
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.json(), {
             "detail": "JSON parse error - Expecting value: line 1 column 1 (char 0)",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_no_posts_ids(self):
         """api rejects no posts ids"""
         response = self.client.post(
@@ -137,6 +114,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "You have to select at least two posts to merge.",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_invalid_posts_data(self):
         """api handles invalid data"""
         response = self.client.post(
@@ -151,6 +129,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": 'Expected a list of items but got type "str".',
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_invalid_posts_ids(self):
         """api handles invalid post id"""
         response = self.client.post(
@@ -165,6 +144,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "One or more post ids received were invalid.",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_one_post_id(self):
         """api rejects one post id"""
         response = self.client.post(
@@ -179,6 +159,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "You have to select at least two posts to merge.",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_limit(self):
         """api rejects more posts than merge limit"""
         response = self.client.post(
@@ -193,6 +174,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "No more than %s posts can be merged at single time." % POSTS_LIMIT,
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_event(self):
         """api recjects events"""
         event = testutils.reply_thread(self.thread, is_event=True, poster=self.user)
@@ -209,6 +191,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "Events can't be merged.",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_notfound_pk(self):
         """api recjects nonexistant pk's"""
         response = self.client.post(
@@ -223,6 +206,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "One or more posts to merge could not be found.",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_cross_threads(self):
         """api recjects attempt to merge with post made in other thread"""
         other_thread = testutils.post_thread(category=self.category)
@@ -240,6 +224,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "One or more posts to merge could not be found.",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_authenticated_with_guest_post(self):
         """api recjects attempt to merge with post made by deleted user"""
         other_post = testutils.reply_thread(self.thread)
@@ -256,6 +241,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "Posts made by different users can't be merged.",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_guest_with_authenticated_post(self):
         """api recjects attempt to merge with post made by deleted user"""
         other_post = testutils.reply_thread(self.thread)
@@ -272,6 +258,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "Posts made by different users can't be merged.",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_guest_posts_different_usernames(self):
         """api recjects attempt to merge posts made by different guests"""
         response = self.client.post(
@@ -289,10 +276,9 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "Posts made by different users can't be merged.",
         })
 
+    @patch_category_acl({"can_merge_posts": True, "can_hide_posts": 1})
     def test_merge_different_visibility(self):
         """api recjects attempt to merge posts with different visibility"""
-        self.override_acl({'can_hide_posts': 1})
-
         response = self.client.post(
             self.api_link,
             json.dumps({
@@ -308,10 +294,9 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "Posts with different visibility can't be merged.",
         })
 
+    @patch_category_acl({"can_merge_posts": True, "can_approve_content": True})
     def test_merge_different_approval(self):
         """api recjects attempt to merge posts with different approval"""
-        self.override_acl({'can_approve_content': 1})
-
         response = self.client.post(
             self.api_link,
             json.dumps({
@@ -327,7 +312,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "Posts with different visibility can't be merged.",
         })
 
-    def test_closed_thread(self):
+    @patch_category_acl({"can_merge_posts": True, "can_close_threads": False})
+    def test_closed_thread_no_permission(self):
         """api validates permission to merge in closed thread"""
         self.thread.is_closed = True
         self.thread.save()
@@ -347,8 +333,16 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "This thread is closed. You can't merge posts in it.",
         })
 
-        # allow closing threads
-        self.override_acl({'can_close_threads': 1})
+    @patch_category_acl({"can_merge_posts": True, "can_close_threads": True})
+    def test_closed_thread(self):
+        """api validates permission to merge in closed thread"""
+        self.thread.is_closed = True
+        self.thread.save()
+
+        posts = [
+            testutils.reply_thread(self.thread, poster=self.user).pk,
+            testutils.reply_thread(self.thread, poster=self.user).pk,
+        ]
 
         response = self.client.post(
             self.api_link,
@@ -357,7 +351,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
-    def test_closed_category(self):
+    @patch_category_acl({"can_merge_posts": True, "can_close_threads": False})
+    def test_closed_category_no_permission(self):
         """api validates permission to merge in closed category"""
         self.category.is_closed = True
         self.category.save()
@@ -377,8 +372,16 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "This category is closed. You can't merge posts in it.",
         })
 
-        # allow closing threads
-        self.override_acl({'can_close_threads': 1})
+    @patch_category_acl({"can_merge_posts": True, "can_close_threads": True})
+    def test_closed_category(self):
+        """api validates permission to merge in closed category"""
+        self.category.is_closed = True
+        self.category.save()
+
+        posts = [
+            testutils.reply_thread(self.thread, poster=self.user).pk,
+            testutils.reply_thread(self.thread, poster=self.user).pk,
+        ]
 
         response = self.client.post(
             self.api_link,
@@ -387,6 +390,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_best_answer_first_post(self):
         """api recjects attempt to merge best_answer with first post"""
         self.thread.first_post.poster = self.user
@@ -413,6 +417,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             "detail": "Post marked as best answer can't be merged with thread's first post.",
         })
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_posts(self):
         """api merges two posts"""
         post_a = testutils.reply_thread(self.thread, poster=self.user, message="Battęry")
@@ -429,7 +434,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
-        self.refresh_thread()
+        self.thread.refresh_from_db()
         self.assertEqual(self.thread.replies, thread_replies - 1)
 
         with self.assertRaises(Post.DoesNotExist):
@@ -438,6 +443,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         merged_post = Post.objects.get(pk=post_a.pk)
         self.assertEqual(merged_post.parsed, '%s\n%s' % (post_a.parsed, post_b.parsed))
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_guest_posts(self):
         """api recjects attempt to merge posts made by same guest"""
         response = self.client.post(
@@ -452,10 +458,9 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
+    @patch_category_acl({"can_merge_posts": True, 'can_hide_posts': 1})
     def test_merge_hidden_posts(self):
         """api merges two hidden posts"""
-        self.override_acl({'can_hide_posts': 1})
-
         response = self.client.post(
             self.api_link,
             json.dumps({
@@ -468,10 +473,9 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
+    @patch_category_acl({"can_merge_posts": True, 'can_approve_content': True})
     def test_merge_unapproved_posts(self):
         """api merges two unapproved posts"""
-        self.override_acl({'can_approve_content': 1})
-
         response = self.client.post(
             self.api_link,
             json.dumps({
@@ -484,6 +488,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
+    @patch_category_acl({"can_merge_posts": True, 'can_hide_threads': True})
     def test_merge_with_hidden_thread(self):
         """api excludes thread's first post from visibility checks"""
         self.thread.first_post.is_hidden = True
@@ -492,8 +497,6 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
 
         post_visible = testutils.reply_thread(self.thread, poster=self.user, is_hidden=False)
 
-        self.override_acl({'can_hide_threads': 1})
-
         response = self.client.post(
             self.api_link,
             json.dumps({
@@ -503,6 +506,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_protected(self):
         """api preserves protected status after merge"""
         response = self.client.post(
@@ -520,6 +524,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         merged_post = self.thread.post_set.order_by('-id')[0]
         self.assertTrue(merged_post.is_protected)
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_best_answer(self):
         """api merges best answer with other post"""
         best_answer = testutils.reply_thread(self.thread, poster="Bob")
@@ -539,9 +544,10 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
-        self.refresh_thread()
+        self.thread.refresh_from_db()
         self.assertEqual(self.thread.best_answer, best_answer)
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_best_answer_in(self):
         """api merges best answer into other post"""
         other_post = testutils.reply_thread(self.thread, poster="Bob")
@@ -562,9 +568,10 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
-        self.refresh_thread()
+        self.thread.refresh_from_db()
         self.assertEqual(self.thread.best_answer, other_post)
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_best_answer_in_protected(self):
         """api merges best answer into protected post"""
         best_answer = testutils.reply_thread(self.thread, poster="Bob")
@@ -584,11 +591,14 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
-        self.refresh_thread()
+        self.thread.refresh_from_db()
         self.assertEqual(self.thread.best_answer, best_answer)
+
+        self.thread.best_answer.refresh_from_db()
         self.assertTrue(self.thread.best_answer.is_protected)
         self.assertTrue(self.thread.best_answer_is_protected)
 
+    @patch_category_acl({"can_merge_posts": True})
     def test_merge_remove_reads(self):
         """two posts merge removes read tracker from post"""
         post_a = testutils.reply_thread(self.thread, poster=self.user, message="Battęry")