Big upheaval of how the reports system works

* There are now Reports and ReportRecords.
* Reports coordinate to what moderators see, and ReportRecords
  coordinate with the reports that are created by individual users.
* Reports keep track of the report reason and the creating user.
* ReportRecords keep track of the total weight and whether this report
  requires urgent attention or not.
* ReportRecord keeps track of its own weight and urgency because then we
  can sort by weight and urgency in the admin view.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2022-06-19 22:03:01 -07:00
parent 5742dc4dc2
commit 6bda7f4f2d
5 changed files with 85 additions and 13 deletions

View File

@@ -1,11 +1,11 @@
from datetime import timedelta
import os
from pathlib import Path
from django.db import models
from django.db.models import signals
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.files.base import ContentFile
from django.db import models
from django.db.models import signals
from django.dispatch import receiver
from django.urls import reverse
from django.utils import timezone
@@ -218,15 +218,51 @@ class ReportReason(models.Model):
return self.reason
class Report(models.Model):
class ReportRecord(models.Model):
# Post that this report is for
post = models.ForeignKey("Post", on_delete=models.CASCADE)
post = models.OneToOneField("Post", on_delete=models.CASCADE)
# Report weight
weight = models.IntegerField(default=0)
# If this report is urgent or not
urgent = models.BooleanField(default=False)
# def urgent(self) -> bool:
# return self.report_set().aggregate(
class Report(models.Model):
"""
There are two reasons why this model exists:
1. In the report view in the Django admin, there is probably not a good way
to specially modify the list of reports. Since we don't want to see every
single report, we need a way to limit this *in data* rather than in code.
We accomplish this by having:
- Report model, which is all reports unique to users.
- ReportRecord model, which is the collection of all reports unique to posts.
2. We want to keep a log of all reports created by users, in case we think
they are abusing the system.
"""
# The report that was made by this user
record = models.ForeignKey("ReportRecord", on_delete=models.CASCADE)
# Reason for this report
reason = models.ForeignKey("ReportReason", on_delete=models.SET_NULL, null=True)
# IP address of the reporter
ip = models.GenericIPAddressField()
@receiver(signals.post_save, sender=Report)
def report_created(sender, instance, created, **kwargs):
if created:
# get the total weight, this is probably going to be more reliable than
# adding the weight every time
weights = [report.reason.weight for report in instance.record.report_set.all()]
instance.record.weight = sum(weights)
instance.record.urgent |= instance.reason.urgent
instance.record.save()
class Ban(models.Model):
# IP address of the reporter
ip = models.GenericIPAddressField()
@@ -239,7 +275,7 @@ class Ban(models.Model):
# The time that this ban was created.
created = models.DateTimeField(auto_now_add=True)
# Expiration date of this ban.
expires = models.DateTimeField(auto_now_add=True)
expires = models.DateTimeField()
class BanTemplate(models.Model):
@@ -249,4 +285,5 @@ class BanTemplate(models.Model):
duration = models.DurationField()
def create_ban(self, ip: str) -> Ban:
return Ban.objects.create(ip=ip, ban_reason=self.ban_reason)
expires = timezone.now() + self.duration
return Ban.objects.create(ip=ip, ban_reason=self.ban_reason, expires=expires)