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.conf import settings
 from misago.threads.models import Thread
 from misago.threads.models import Thread
 from misago.threads.moderation import threads as moderation
 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
 from misago.threads.serializers import NewThreadSerializer
 
 
 
 
@@ -57,12 +57,10 @@ def clean_posts_for_split(request, thread):
 
 
     posts = []
     posts = []
     for post in posts_queryset:
     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)
         posts.append(post)
 
 

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

@@ -58,6 +58,8 @@ __all__ = [
     'can_merge_post',
     'can_merge_post',
     'allow_unhide_event',
     'allow_unhide_event',
     'can_unhide_event',
     'can_unhide_event',
+    'allow_split_post',
+    'can_split_post',
     'allow_hide_event',
     'allow_hide_event',
     'can_hide_event',
     'can_hide_event',
     'allow_delete_event',
     'allow_delete_event',
@@ -1114,6 +1116,34 @@ def allow_merge_post(user, target):
 can_merge_post = return_boolean(allow_merge_post)
 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):
 def allow_unhide_event(user, target):
     if user.is_anonymous:
     if user.is_anonymous:
         raise PermissionDenied(_("You have to sign in to reveal events."))
         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",
             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):
     def test_split_first_post(self):
         """api rejects first post split"""
         """api rejects first post split"""
@@ -197,7 +197,7 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
             }),
             }),
             content_type="application/json",
             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):
     def test_split_hidden_posts(self):
         """api recjects attempt to split urneadable hidden post"""
         """api recjects attempt to split urneadable hidden post"""
@@ -209,7 +209,43 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
             content_type="application/json",
             content_type="application/json",
         )
         )
         self.assertContains(
         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):
     def test_split_other_thread_posts(self):