feat: Add analytics, incident, and alert models and APIs, along with user permissions and bulk profile lookups.

This commit is contained in:
pacnpal
2026-01-07 11:07:36 -05:00
parent 4da7e52fb0
commit 3ec5a4857d
46 changed files with 4012 additions and 199 deletions

View File

@@ -1,8 +1,16 @@
from django.utils import timezone
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters, permissions, viewsets
from rest_framework import filters, permissions, status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import Ticket
from .serializers import TicketSerializer
from .models import Report, Ticket
from .serializers import (
ReportCreateSerializer,
ReportResolveSerializer,
ReportSerializer,
TicketSerializer,
)
class TicketViewSet(viewsets.ModelViewSet):
@@ -33,3 +41,61 @@ class TicketViewSet(viewsets.ModelViewSet):
serializer.save(user=self.request.user, email=self.request.user.email)
else:
serializer.save()
class ReportViewSet(viewsets.ModelViewSet):
"""
ViewSet for handling user-submitted content reports.
- Authenticated users can CREATE reports
- Staff can LIST/RETRIEVE all reports
- Users can LIST/RETRIEVE their own reports
- Staff can RESOLVE reports
"""
queryset = Report.objects.select_related("reporter", "resolved_by", "content_type").all()
permission_classes = [permissions.IsAuthenticated]
filter_backends = [DjangoFilterBackend, filters.OrderingFilter, filters.SearchFilter]
filterset_fields = ["status", "report_type"]
search_fields = ["reason", "resolution_notes"]
ordering_fields = ["created_at", "status", "report_type"]
ordering = ["-created_at"]
def get_serializer_class(self):
if self.action == "create":
return ReportCreateSerializer
if self.action == "resolve":
return ReportResolveSerializer
return ReportSerializer
def get_queryset(self):
user = self.request.user
if user.is_staff:
return Report.objects.select_related("reporter", "resolved_by", "content_type").all()
return Report.objects.select_related("reporter", "resolved_by", "content_type").filter(reporter=user)
def perform_create(self, serializer):
serializer.save(reporter=self.request.user)
@action(detail=True, methods=["post"], permission_classes=[permissions.IsAdminUser])
def resolve(self, request, pk=None):
"""Mark a report as resolved or dismissed."""
report = self.get_object()
if report.is_resolved:
return Response(
{"detail": "Report is already resolved"},
status=status.HTTP_400_BAD_REQUEST,
)
serializer = ReportResolveSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
report.status = serializer.validated_data.get("status", "resolved")
report.resolved_at = timezone.now()
report.resolved_by = request.user
report.resolution_notes = serializer.validated_data.get("notes", "")
report.save()
return Response(ReportSerializer(report).data)