feat: implement API security measures phase 1
This commit is contained in:
+29
-7
@@ -1,7 +1,7 @@
|
||||
from django.db.models import Count, Q
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
|
||||
@@ -14,16 +14,30 @@ from .serializers import (
|
||||
|
||||
|
||||
class JobApplicationViewSet(viewsets.ModelViewSet):
|
||||
queryset = JobApplication.objects.all().prefetch_related("updates")
|
||||
serializer_class = JobApplicationSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter by user for non-admin users; admins see all."""
|
||||
user = self.request.user
|
||||
qs = JobApplication.objects.all().prefetch_related("updates")
|
||||
if not user.is_admin:
|
||||
qs = qs.filter(user=user)
|
||||
return qs
|
||||
|
||||
|
||||
class JobUpdateViewSet(viewsets.ModelViewSet):
|
||||
queryset = JobUpdate.objects.select_related("job_application").all()
|
||||
serializer_class = JobUpdateSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter by user via job_application for non-admin users."""
|
||||
user = self.request.user
|
||||
qs = JobUpdate.objects.select_related("job_application").all()
|
||||
if not user.is_admin:
|
||||
qs = qs.filter(job_application__user=user)
|
||||
return qs
|
||||
|
||||
@action(detail=False, methods=["get"])
|
||||
def latest(self, request: Request) -> Response:
|
||||
"""Return the 3 most recent job updates with job info and metrics."""
|
||||
@@ -38,16 +52,24 @@ class JobUpdateViewSet(viewsets.ModelViewSet):
|
||||
@action(detail=False, methods=["get"])
|
||||
def metrics(self, request: Request) -> Response:
|
||||
"""Return dashboard metrics: total apps, status breakdown, interview/offer counts."""
|
||||
total = JobApplication.objects.count()
|
||||
qs = self.get_queryset()
|
||||
|
||||
total = qs.values("job_application").distinct().count()
|
||||
# Get status counts from the distinct job applications the user owns
|
||||
app_qs = JobApplication.objects.all()
|
||||
if not request.user.is_admin:
|
||||
app_qs = app_qs.filter(user=request.user)
|
||||
|
||||
total = app_qs.count()
|
||||
status_counts = dict(
|
||||
JobApplication.objects.values("status")
|
||||
app_qs.values("status")
|
||||
.annotate(count=Count("id"))
|
||||
.values_list("status", "count")
|
||||
)
|
||||
interview_count = JobApplication.objects.filter(
|
||||
interview_count = app_qs.filter(
|
||||
Q(status="INTERVIEW") | Q(status="OFFER")
|
||||
).count()
|
||||
offer_count = JobApplication.objects.filter(status="OFFER").count()
|
||||
offer_count = app_qs.filter(status="OFFER").count()
|
||||
rejection_rate = (
|
||||
round(
|
||||
status_counts.get("REJECTED", 0) / total * 100, 1
|
||||
|
||||
Reference in New Issue
Block a user