Browse Source

wip #887: split posts closed thread/category handling

Rafał Pitoń 7 years ago
parent
commit
0ac500079f

+ 5 - 7
misago/threads/api/postendpoints/split.py

@@ -7,7 +7,7 @@ from django.utils.translation import ungettext
 from misago.conf import settings
 from misago.threads.models import Thread
 from misago.threads.moderation import threads as moderation
-from misago.threads.permissions import exclude_invisible_posts
+from misago.threads.permissions import allow_split_post, exclude_invisible_posts
 from misago.threads.serializers import NewThreadSerializer
 
 
@@ -57,12 +57,10 @@ def clean_posts_for_split(request, thread):
 
     posts = []
     for post in posts_queryset:
-        if post.is_event:
-            raise SplitError(_("Events can't be split."))
-        if post.pk == thread.first_post_id:
-            raise SplitError(_("You can't split thread's first post."))
-        if post.is_hidden and not thread.category.acl['can_hide_posts']:
-            raise SplitError(_("You can't split posts the content you can't see."))
+        post.category = thread.category
+        post.thread = thread
+
+        allow_split_post(request.user, post)
 
         posts.append(post)
 

+ 30 - 0
misago/threads/permissions/threads.py

@@ -58,6 +58,8 @@ __all__ = [
     'can_merge_post',
     'allow_unhide_event',
     'can_unhide_event',
+    'allow_split_post',
+    'can_split_post',
     'allow_hide_event',
     'can_hide_event',
     'allow_delete_event',
@@ -1114,6 +1116,34 @@ def allow_merge_post(user, target):
 can_merge_post = return_boolean(allow_merge_post)
 
 
+def allow_split_post(user, target):
+    if user.is_anonymous:
+        raise PermissionDenied(_("You have to sign in to split posts."))
+
+    category_acl = user.acl_cache['categories'].get(
+        target.category_id, {
+            'can_move_posts': False,
+        }
+    )
+
+    if not category_acl['can_move_posts']:
+        raise PermissionDenied(_("You can't split posts in this category."))
+    if target.is_event:
+        raise PermissionDenied(_("Events can't be split."))
+    if target.is_first_post:
+        raise PermissionDenied(_("You can't split thread's first post."))
+    if not category_acl['can_hide_posts'] and target.is_hidden:
+        raise PermissionDenied(_("You can't split posts the content you can't see."))
+
+    if not category_acl['can_close_threads']:
+        if target.category.is_closed:
+            raise PermissionDenied(_("This category is closed. You can't split posts in it."))
+        if target.thread.is_closed:
+            raise PermissionDenied(_("This thread is closed. You can't split posts in it."))
+
+can_split_post = return_boolean(allow_split_post)
+
+
 def allow_unhide_event(user, target):
     if user.is_anonymous:
         raise PermissionDenied(_("You have to sign in to reveal events."))

+ 39 - 3
misago/threads/tests/test_thread_postsplit_api.py

@@ -186,7 +186,7 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
             }),
             content_type="application/json",
         )
-        self.assertContains(response, "Events can't be split.", status_code=400)
+        self.assertContains(response, "Events can't be split.", status_code=403)
 
     def test_split_first_post(self):
         """api rejects first post split"""
@@ -197,7 +197,7 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
             }),
             content_type="application/json",
         )
-        self.assertContains(response, "You can't split thread's first post.", status_code=400)
+        self.assertContains(response, "You can't split thread's first post.", status_code=403)
 
     def test_split_hidden_posts(self):
         """api recjects attempt to split urneadable hidden post"""
@@ -209,7 +209,43 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
             content_type="application/json",
         )
         self.assertContains(
-            response, "You can't split posts the content you can't see.", status_code=400
+            response, "You can't split posts the content you can't see.", status_code=403
+        )
+
+    def test_split_posts_closed_thread_no_permission(self):
+        """api recjects attempt to split posts from closed thread"""
+        self.thread.is_closed = True
+        self.thread.save()
+
+        self.override_acl({'can_close_threads': 0})
+
+        response = self.client.post(
+            self.api_link,
+            json.dumps({
+                'posts': [testutils.reply_thread(self.thread).pk],
+            }),
+            content_type="application/json",
+        )
+        self.assertContains(
+            response, "This thread is closed. You can't split posts in it.", status_code=403
+        )
+
+    def test_split_posts_closed_category_no_permission(self):
+        """api recjects attempt to split posts from closed thread"""
+        self.category.is_closed = True
+        self.category.save()
+
+        self.override_acl({'can_close_threads': 0})
+
+        response = self.client.post(
+            self.api_link,
+            json.dumps({
+                'posts': [testutils.reply_thread(self.thread).pk],
+            }),
+            content_type="application/json",
+        )
+        self.assertContains(
+            response, "This category is closed. You can't split posts in it.", status_code=403
         )
 
     def test_split_other_thread_posts(self):