Browse Source

fix #606: added index on post's posted_on column

Rafał Pitoń 8 years ago
parent
commit
50357f5473

+ 6 - 2
misago/threads/api/postingendpoint/__init__.py

@@ -1,5 +1,6 @@
 from importlib import import_module
 
+from django.core.exceptions import PermissionDenied
 from django.utils import timezone
 
 from misago.conf import settings
@@ -105,8 +106,11 @@ class PostingEndpoint(object):
         except PostingInterrupt as e:
             raise ValueError("Posting process can only be interrupted from within interrupt_posting method")
 
-        for middleware, obj in self.middlewares:
-            obj.interrupt_posting(self._serializers.get(middleware))
+        try:
+            for middleware, obj in self.middlewares:
+                obj.interrupt_posting(self._serializers.get(middleware))
+        except PostingInterrupt as e:
+            raise PermissionDenied(e.message)
 
         try:
             for middleware, obj in self.middlewares:

+ 9 - 7
misago/threads/api/postingendpoint/floodprotection.py

@@ -4,13 +4,16 @@ from django.conf import settings
 from django.utils import timezone
 from django.utils.translation import ugettext as _
 
-from . import PostingInterrupt, PostingMiddleware
+from . import PostingEndpoint, PostingInterrupt, PostingMiddleware
 
 
 MIN_POSTING_PAUSE = 3
 
 
 class FloodProtectionMiddleware(PostingMiddleware):
+    def use_this_middleware(self):
+        return self.mode != PostingEndpoint.EDIT
+
     def interrupt_posting(self, serializer):
         now = timezone.now()
 
@@ -24,14 +27,13 @@ class FloodProtectionMiddleware(PostingMiddleware):
 
         if settings.MISAGO_HOURLY_POST_LIMIT:
             cutoff = now - timedelta(hours=24)
-            count_qs = self.user.post_set.filter(posted_on__gte=cutoff)
-            posts_count = count_qs.count()
-            if posts_count > settings.MISAGO_HOURLY_POST_LIMIT:
+            if self.is_limit_exceeded(cutoff, settings.MISAGO_HOURLY_POST_LIMIT):
                 raise PostingInterrupt(_("Your account has excceed hourly post limit."))
 
         if settings.MISAGO_DIALY_POST_LIMIT:
             cutoff = now - timedelta(hours=1)
-            count_qs = self.user.post_set.filter(posted_on__gte=cutoff)
-            posts_count = count_qs.count()
-            if posts_count > settings.MISAGO_DIALY_POST_LIMIT:
+            if self.is_limit_exceeded(cutoff, settings.MISAGO_DIALY_POST_LIMIT):
                 raise PostingInterrupt(_("Your account has excceed dialy post limit."))
+
+    def is_limit_exceeded(self, cutoff, limit):
+        return self.user.post_set.filter(posted_on__gte=cutoff).count() >= limit

+ 4 - 1
misago/threads/migrations/0001_initial.py

@@ -195,7 +195,10 @@ class Migration(migrations.Migration):
         ),
         migrations.AlterIndexTogether(
             name='post',
-            index_together=set([('is_event', 'is_hidden')]),
+            index_together=set([
+                ('is_event', 'is_hidden'),
+                ('poster', 'posted_on'),
+            ]),
         ),
         migrations.CreateModel(
             name='Subscription',

+ 3 - 2
misago/threads/models/post.py

@@ -66,7 +66,8 @@ class Post(models.Model):
 
     class Meta:
         index_together = [
-            ('is_event', 'is_hidden')
+            ('is_event', 'is_hidden'),
+            ('poster', 'posted_on')
         ]
 
     def __unicode__(self):
@@ -93,7 +94,7 @@ class Post(models.Model):
         update_post_checksum(other_post)
 
         from ..signals import merge_post
-        merge_post.send(sender=self, other_thread=other_post)
+        merge_post.send(sender=self, other_post=other_post)
 
     def move(self, new_thread):
         from ..signals import move_post

+ 46 - 0
misago/threads/tests/test_floodprotection.py

@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.core.urlresolvers import reverse
+
+from misago.acl.testutils import override_acl
+from misago.categories.models import Category
+from misago.users.testutils import AuthenticatedUserTestCase
+
+from .. import testutils
+
+
+class PostMentionsTests(AuthenticatedUserTestCase):
+    def setUp(self):
+        super(PostMentionsTests, self).setUp()
+
+        self.category = Category.objects.get(slug='first-category')
+        self.thread = testutils.post_thread(category=self.category)
+        self.override_acl()
+
+        self.post_link = reverse('misago:api:thread-post-list', kwargs={
+            'thread_pk': self.thread.pk
+        })
+
+    def override_acl(self):
+        new_acl = self.user.acl
+        new_acl['categories'][self.category.pk].update({
+            'can_see': 1,
+            'can_browse': 1,
+            'can_start_threads': 1,
+            'can_reply_threads': 1
+        })
+
+        override_acl(self.user, new_acl)
+
+    def test_flood_has_no_showstoppers(self):
+        """endpoint handles posting interruption"""
+        response = self.client.post(self.post_link, data={
+            'post': "This is test response!"
+        })
+        self.assertEqual(response.status_code, 200)
+
+        response = self.client.post(self.post_link, data={
+            'post': "This is test response!"
+        })
+        self.assertContains(response, "You can't post message so quickly after previous one.", status_code=403)