This commit is contained in:
Iliyan Angelov
2025-11-26 22:32:20 +02:00
commit ed94dd22dd
150 changed files with 14058 additions and 0 deletions

129
moderation/views.py Normal file
View File

@@ -0,0 +1,129 @@
"""
Views for moderation app.
"""
from django.shortcuts import get_object_or_404, redirect
from django.views.generic import ListView, DetailView, UpdateView
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.utils import timezone
from reports.models import ScamReport
from .models import ModerationQueue, ModerationAction
class ModeratorRequiredMixin(UserPassesTestMixin):
"""Mixin to require moderator role."""
def test_func(self):
return self.request.user.is_authenticated and self.request.user.is_moderator()
class ModerationDashboardView(LoginRequiredMixin, ModeratorRequiredMixin, ListView):
"""Moderation dashboard."""
template_name = 'moderation/dashboard.html'
context_object_name = 'reports'
def get_queryset(self):
return ScamReport.objects.filter(
status__in=['pending', 'under_review']
).order_by('-created_at')[:10]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['pending_count'] = ScamReport.objects.filter(status='pending').count()
context['under_review_count'] = ScamReport.objects.filter(status='under_review').count()
context['verified_count'] = ScamReport.objects.filter(status='verified').count()
return context
class ModerationQueueView(LoginRequiredMixin, ModeratorRequiredMixin, ListView):
"""Moderation queue."""
model = ModerationQueue
template_name = 'moderation/queue.html'
context_object_name = 'queue_items'
paginate_by = 20
def get_queryset(self):
return ModerationQueue.objects.select_related(
'report', 'assigned_to'
).order_by('-priority', 'created_at')
class ReportModerationView(LoginRequiredMixin, ModeratorRequiredMixin, DetailView):
"""View report for moderation."""
model = ScamReport
template_name = 'moderation/report_detail.html'
context_object_name = 'report'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['osint_results'] = self.object.osint_results.all()
context['verifications'] = self.object.verifications.all()
context['moderation_actions'] = self.object.moderation_actions.all()[:10]
return context
class ApproveReportView(LoginRequiredMixin, ModeratorRequiredMixin, SuccessMessageMixin, UpdateView):
"""Approve a report."""
model = ScamReport
fields = []
template_name = 'moderation/approve.html'
success_message = "Report approved successfully!"
def form_valid(self, form):
previous_status = form.instance.status
form.instance.status = 'verified'
form.instance.verified_at = timezone.now()
response = super().form_valid(form)
# Create moderation action
ModerationAction.objects.create(
report=form.instance,
moderator=self.request.user,
action_type='approve',
previous_status=previous_status,
new_status='verified'
)
# Remove from queue
ModerationQueue.objects.filter(report=form.instance).delete()
return response
def get_success_url(self):
return reverse_lazy('moderation:queue')
class RejectReportView(LoginRequiredMixin, ModeratorRequiredMixin, SuccessMessageMixin, UpdateView):
"""Reject a report."""
model = ScamReport
fields = []
template_name = 'moderation/reject.html'
success_message = "Report rejected."
def form_valid(self, form):
previous_status = form.instance.status
form.instance.status = 'rejected'
response = super().form_valid(form)
# Get reason from form
reason = self.request.POST.get('reason', '').strip()
notes = self.request.POST.get('notes', '').strip()
# Create moderation action
ModerationAction.objects.create(
report=form.instance,
moderator=self.request.user,
action_type='reject',
previous_status=previous_status,
new_status='rejected',
reason=reason,
notes=notes
)
# Remove from queue
ModerationQueue.objects.filter(report=form.instance).delete()
return response
def get_success_url(self):
return reverse_lazy('moderation:queue')