Browse Source

#468: posting quotas

Rafał Pitoń 10 years ago
parent
commit
5040e3a1ed

+ 12 - 0
docs/developers/settings.rst

@@ -223,6 +223,12 @@ MISAGO_CONTENT_COUNTING_FREQUENCY
 Maximum allowed age of content counts cache in minutes. The lower the number, the more accurate will be numbers of new and unread threads in navbar, but greater the stress on database.
 Maximum allowed age of content counts cache in minutes. The lower the number, the more accurate will be numbers of new and unread threads in navbar, but greater the stress on database.
 
 
 
 
+MISAGO_DIALY_POST_LIMIT
+-----------------------
+
+Dialy limit of posts that may be posted from single account. Fail-safe for situations when forum is flooded by spam bot. Change to 0 to lift this restriction.
+
+
 MISAGO_DYNAMIC_AVATAR_DRAWER
 MISAGO_DYNAMIC_AVATAR_DRAWER
 ----------------------------
 ----------------------------
 
 
@@ -234,6 +240,12 @@ MISAGO_FRESH_CONTENT_PERIOD
 Controls amount of data used in building "New threads" and "Threads with unread replies" lists. Active forums can try lowering this value while less active ones may wish to increase this number.
 Controls amount of data used in building "New threads" and "Threads with unread replies" lists. Active forums can try lowering this value while less active ones may wish to increase this number.
 
 
 
 
+MISAGO_HOURL_POST_LIMIT
+-----------------------
+
+Hourly limit of posts that may be posted from single account. Fail-safe for situations when forum is flooded by spam bot. Change to 0 to lift this restriction.
+
+
 MISAGO_MAILER_BATCH_SIZE
 MISAGO_MAILER_BATCH_SIZE
 ------------------------
 ------------------------
 
 

+ 7 - 0
misago/conf/defaults.py

@@ -283,6 +283,13 @@ MISAGO_ADMIN_SESSION_EXPIRATION = 60
 MISAGO_NOTIFICATIONS_MAX_AGE = 40
 MISAGO_NOTIFICATIONS_MAX_AGE = 40
 
 
 
 
+# Fail-safe limits in case forum is raided by spambot
+# No user may exceed those limits, however you may disable
+# them by changing them to 0
+MISAGO_DIALY_POST_LIMIT = 600
+MISAGO_HOURLY_POST_LIMIT = 100
+
+
 # Function used for generating individual avatar for user
 # Function used for generating individual avatar for user
 MISAGO_DYNAMIC_AVATAR_DRAWER = 'misago.users.avatars.dynamic.draw_default'
 MISAGO_DYNAMIC_AVATAR_DRAWER = 'misago.users.avatars.dynamic.draw_default'
 
 

+ 24 - 3
misago/threads/posting/floodprotection.py

@@ -1,3 +1,6 @@
+from datetime import timedelta
+
+from django.conf import settings
 from django.utils import timezone
 from django.utils import timezone
 from django.utils.translation import ugettext as _
 from django.utils.translation import ugettext as _
 
 
@@ -9,11 +12,29 @@ MIN_POSTING_PAUSE = 3
 
 
 class FloodProtectionMiddleware(PostingMiddleware):
 class FloodProtectionMiddleware(PostingMiddleware):
     def interrupt_posting(self, form):
     def interrupt_posting(self, form):
-        message = _("You can't post message so quickly after previous one.")
+        now = timezone.now()
+
         if self.user.last_posted_on:
         if self.user.last_posted_on:
-            previous_post = timezone.now() - self.user.last_posted_on
+            previous_post = now - self.user.last_posted_on
             if previous_post.total_seconds() < MIN_POSTING_PAUSE:
             if previous_post.total_seconds() < MIN_POSTING_PAUSE:
-                raise PostingInterrupt(message)
+                raise PostingInterrupt(_("You can't post message so "
+                                         "quickly after previous one."))
 
 
         self.user.last_posted_on = timezone.now()
         self.user.last_posted_on = timezone.now()
         self.user.update_fields.append('last_posted_on')
         self.user.update_fields.append('last_posted_on')
+
+        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:
+                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:
+                raise PostingInterrupt(_("Your account has excceed "
+                                         "dialy post limit."))