Overview
Users should be able to report an essay or a user profile for review by admins. When a report is submitted, admins receive an in-app notification via the existing Notification model rather than email.
Report targets
- Essay — report button on the essay detail page
- User — report button on the public profile page
Both use the same underlying Report model; only the FK target differs.
Data model
class Report(models.Model):
SPAM = "spam"
PLAGIARISM = "plagiarism"
HARASSMENT = "harassment"
INAPPROPRIATE = "inappropriate"
OTHER = "other"
REASON_CHOICES = [...]
PENDING = "pending"
REVIEWED = "reviewed"
DISMISSED = "dismissed"
STATUS_CHOICES = [...]
reporter = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name="reports_filed")
reported_user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="reports_received")
reported_essay = models.ForeignKey(Essay, on_delete=models.SET_NULL, null=True, blank=True, related_name="reports")
reason = models.CharField(max_length=20, choices=REASON_CHOICES)
note = models.TextField(blank=True)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default=PENDING)
created_at = models.DateTimeField(auto_now_add=True)
reviewed_at = models.DateTimeField(null=True, blank=True)
reviewed_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="reports_reviewed")
Constraint: one report per reporter per target (unique together on reporter + reported_essay and reporter + reported_user).
In-app notification
Add REPORT = "report" to Notification.TYPE_CHOICES. When a report is saved, fan out a Notification (type=report, sender=reporter) to every user where is_superuser=True. Admins see these alongside their regular notifications in the UI.
UI — reporter side
- Small "Report" link/button on essay detail page (below content, unobtrusive)
- "Report user" button on profile page (next to follow/other actions)
- Clicking opens a modal: dropdown for reason category + optional text area for note
- On submit: POST to report endpoint, show a brief confirmation ("Report submitted") — no page reload needed
- One report per user per target enforced at the backend; silently succeed if already reported (no error shown to prevent enumeration)
Admin side
Report registered in Django admin with list view: reporter, target (essay or user link), reason, status, created_at
- Status filter: pending / reviewed / dismissed
- Inline action to mark reviewed or dismissed with
reviewed_by and reviewed_at auto-filled
- Pending reports shown first by default (
ordering = ["-created_at"] filtered by status=pending)
Acceptance criteria
Overview
Users should be able to report an essay or a user profile for review by admins. When a report is submitted, admins receive an in-app notification via the existing
Notificationmodel rather than email.Report targets
Both use the same underlying
Reportmodel; only the FK target differs.Data model
Constraint: one report per reporter per target (unique together on
reporter + reported_essayandreporter + reported_user).In-app notification
Add
REPORT = "report"toNotification.TYPE_CHOICES. When a report is saved, fan out aNotification(type=report, sender=reporter) to every user whereis_superuser=True. Admins see these alongside their regular notifications in the UI.UI — reporter side
Admin side
Reportregistered in Django admin with list view: reporter, target (essay or user link), reason, status, created_atreviewed_byandreviewed_atauto-filledordering = ["-created_at"]filtered by status=pending)Acceptance criteria