Added changes for Malicious User reporting

This commit is contained in:
2024-04-20 20:10:40 -04:00
parent 7c81755cda
commit b9b405fba8
7 changed files with 186 additions and 22 deletions

View File

@@ -0,0 +1,57 @@
# Generated by Django 4.2.11 on 2024-04-20 23:10
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("api", "0007_remove_file_points_file_downvotes_file_upvotes"),
]
operations = [
migrations.CreateModel(
name="UserReport",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("description", models.TextField(max_length=300)),
(
"file",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="file_report",
to="api.file",
),
),
(
"reporting_user",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="user_report_generated",
to=settings.AUTH_USER_MODEL,
),
),
(
"user",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="user_report",
to=settings.AUTH_USER_MODEL,
),
),
],
),
]

View File

@@ -61,10 +61,28 @@ class File(models.Model):
upvotes = models.ManyToManyField(PeerUser, related_name="upvoted_file")
downvotes = models.ManyToManyField(PeerUser, related_name="downvoted_file")
@property
def points(self):
return self.upvotes.count() - self.downvotes.count()
def __str__(self):
return self.filename
class UserReport(models.Model):
user = models.ForeignKey(
PeerUser, on_delete=models.SET_NULL, null=True, related_name="user_report"
)
reporting_user = models.ForeignKey(
PeerUser,
on_delete=models.SET_NULL,
null=True,
related_name="user_report_generated",
)
description = models.TextField(blank=False, null=False, max_length=300)
file = models.ForeignKey(
File, on_delete=models.CASCADE, null=True, related_name="file_report"
)
def __str__(self) -> str:
return f"{self.user}:{self.file}:{self.reporting_user}"

View File

@@ -46,4 +46,17 @@ class FileSerializer(serializers.ModelSerializer):
class Meta:
model = File
fields = "__all__"
fields = [
"id",
"filename",
"points",
"original_author",
"peer_users",
"topic",
"professor",
"semester",
"course",
"created_at",
"upvotes",
"downvotes",
]

View File

@@ -65,6 +65,7 @@ urlpatterns = [
name="downvote-file",
),
path("api/files/<int:pk>/", views.FileDetailAPIView.as_view(), name="file-detail"),
path("api/report_user/", views.ReportUserView.as_view(), name="report-user"),
path("api/register/", views.RegisterFile.as_view(), name="file-register"),
path("api/files/filter/", views.FileFilterView.as_view(), name="file-filter-view"),
]

View File

@@ -6,7 +6,7 @@ from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from api.utils.get_client_ip import get_client_ip
from api.utils.get_client_ip import get_client_ip, PollMiddleware
from django.utils import timezone

View File

@@ -1,3 +1,4 @@
from typing import Any
from django.utils import timezone
@@ -16,3 +17,15 @@ def update_user_ip(request):
user.ip_address = ip_address
user.last_poll = timezone.now()
user.save()
class PollMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
print("Updating user last online and IP address")
update_user_ip(request)
response = self.get_response(request)
return response

View File

@@ -1,4 +1,4 @@
from api.models import Course, File, Professor, Semester, Topic, PeerUser
from api.models import Course, File, Professor, Semester, Topic, PeerUser, UserReport
from api.serializers import (
CourseSerializer,
FileSerializer,
@@ -7,13 +7,13 @@ from api.serializers import (
TopicSerializer,
UserSerializer,
)
from datetime import datetime, timedelta
from datetime import timedelta
from django.contrib.auth import authenticate
from django.db import transaction
from django.db.models import Count, Value, F, IntegerField
from django.utils import timezone
from rest_framework import generics, status
from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
@@ -235,15 +235,6 @@ class RegisterFile(APIView):
)
from django.utils import timezone
from datetime import timedelta
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import File, PeerUser
from .serializers import FileSerializer
class FileFilterView(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
@@ -251,6 +242,7 @@ class FileFilterView(APIView):
def get(self, request, format=None):
try:
# Extract filters from the query parameters
update_user_ip(request)
topic_id = request.query_params.get("topic")
professor_id = request.query_params.get("professor")
course_id = request.query_params.get("course")
@@ -291,19 +283,26 @@ class FileFilterView(APIView):
if semester_id:
queryset = queryset.filter(semester__id=semester_id)
queryset = queryset.annotate(
upvote_count=Count("upvotes"), downvote_count=Count("downvotes")
).order_by(F("downvote_count") - F("upvote_count"))
# Filter files based on active peers in the past hour
active_peer_ids = PeerUser.objects.filter(
last_poll__gte=timezone.now() - timedelta(hours=1)
).values_list("id", flat=True)
queryset = queryset.filter(peer_users__in=active_peer_ids).distinct()
# Sort files based on points column in descending order
queryset = queryset.order_by("-points")
# Serialize files
serializer = FileSerializer(queryset, many=True)
# Loop through each serialized file to sort its peer_users
for file_data in serializer.data:
try:
serialized_data = serializer.data
print(serialized_data)
except Exception as e:
print(str(e))
for file_data in serialized_data:
print(file_data)
file_obj = File.objects.get(id=file_data["id"])
sorted_peer_users = sorted(
file_obj.peer_users.all(), key=lambda x: x.points, reverse=True
@@ -312,9 +311,72 @@ class FileFilterView(APIView):
sorted_peer_users, many=True
).data
return Response(serializer.data)
return Response(serialized_data)
except Exception as e:
return Response(
{"error": f"Something went wrong: {str(e)}"},
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)
class ReportUserView(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
def post(self, request):
data = request.data
update_user_ip(request)
try:
assert "file_id" in data
assert "user_id" in data
assert "description" in data
except AssertionError as e:
return Response(
{"error": f"Missing Parameters. {str(e)}"},
status=status.HTTP_400_BAD_REQUEST,
)
try:
file = File.objects.get(id=data["file_id"])
malicious_user = PeerUser.objects.get(id=data["user_id"])
reporting_user = request.user
description = data["description"]
except Exception as e:
return Response(
{"error": f"Missing/Incorrect Parameters. {str(e)}"},
status=status.HTTP_400_BAD_REQUEST,
)
existing_user_report_queryset = UserReport.objects.filter(
user=malicious_user, file=file, reporting_user=reporting_user
)
if len(existing_user_report_queryset):
existing_report = existing_user_report_queryset.first()
existing_report.description = description
existing_report.save()
return Response(
{
"msg": "User report already exists for this file. Updated description"
},
status=status.HTTP_208_ALREADY_REPORTED,
)
if (
file not in malicious_user.owned_files.all()
or file not in malicious_user.shared_files.all()
):
return Response(
{"error": "User does not own or host the file reported"},
status=status.HTTP_404_NOT_FOUND,
)
UserReport.objects.create(
user=malicious_user,
reporting_user=reporting_user,
file=file,
description=description,
)
malicious_user.points -= 1
malicious_user.save()
return Response({"msg": "Report Created!"}, status=status.HTTP_201_CREATED)