Add posting cooldown

If a user tries to post more than once in a certain amount of time, they
will be blocked from doing so until their cooldown is over. This
required a little bit of hacking to get the board and IP address set
*before* the validation checks were made, but it all appears to work.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2022-05-07 13:24:43 -07:00
parent 771dba1515
commit 3a35a35caf
3 changed files with 99 additions and 37 deletions

View File

@@ -1,3 +1,4 @@
from datetime import timedelta
import os
from pathlib import Path
from django.db import models
@@ -43,6 +44,9 @@ class Board(models.Model):
max_pages = models.IntegerField(default=10)
# Threads per page
threads_per_page = models.IntegerField(default=10)
# The amount of time that users from the same IP address are allowed to make
# consecutive posts
post_cooldown = models.DurationField(default=timedelta(seconds=60))
@property
def threads(self):
@@ -139,11 +143,24 @@ class Post(models.Model):
)
def clean(self):
# Image upload size check
if self.image and self.image.size > settings.MAX_UPLOAD_SIZE:
raise ValidationError(
"Image supplied is too large. Maximum image size is %(max)s",
params={"max": settings.MAX_UPLOAD_SIZE},
)
# Rate limiting for posts
# BUG: if a user's last post is deleted, and it is their only post, they
# will not hit rate limit. This could probably be abused
last_post = self.board.post_set.filter(ip=self.ip).order_by("-created").first()
if last_post:
now = timezone.now()
delta = now - last_post.created
if delta < self.board.post_cooldown:
cooldown = self.board.post_cooldown - delta
raise ValidationError(
f"Please wait {int(cooldown.total_seconds())} seconds before posting again"
)
@receiver(signals.post_save, sender=Post)