From cae2c52e8e52074b57e66e65178a44256c211e7d Mon Sep 17 00:00:00 2001 From: Krrish Sehgal <133865424+krrish-sehgal@users.noreply.github.com> Date: Mon, 11 Nov 2024 18:56:16 +0530 Subject: [PATCH] views fixes --- blt/urls.py | 3 +- website/views/report_ip.py | 123 +++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 website/views/report_ip.py diff --git a/blt/urls.py b/blt/urls.py index 5e8aec3a0..22de351da 100644 --- a/blt/urls.py +++ b/blt/urls.py @@ -138,12 +138,11 @@ ProjectBadgeView, ProjectDetailView, ProjectListView, - ReportedIpListView, - ReportIpView, blt_tomato, distribute_bacon, select_contribution, ) +from website.views.report_ip import ReportedIpListView, ReportIpView from website.views.user import ( CustomObtainAuthToken, EachmonthLeaderboardView, diff --git a/website/views/report_ip.py b/website/views/report_ip.py new file mode 100644 index 000000000..3b505059f --- /dev/null +++ b/website/views/report_ip.py @@ -0,0 +1,123 @@ + +import ipaddress +from urllib.parse import urlparse + +from django.contrib import messages +from django.shortcuts import redirect, render +from django.utils.timezone import now +from django.views.generic import FormView, ListView + +from blt import settings +from website.forms import CaptchaForm, IpReportForm +from website.models import IpReport +from website.utils import get_client_ip + + +class ReportIpView(FormView): + template_name = "report_ip.html" + form_class = IpReportForm + captcha = CaptchaForm() + + def is_valid_ip(self, ip_address, ip_type): + """ + Validates an IP address format based on the specified type (IPv4 or IPv6). + """ + try: + if ip_type == "ipv4": + ipaddress.IPv4Address(ip_address) + return True + elif ip_type == "ipv6": + ipaddress.IPv6Address(ip_address) + return True + else: + return False + except ValueError: + return False + + def post(self, request, *args, **kwargs): + # Check CAPTCHA + captcha_form = CaptchaForm(request.POST) + if not captcha_form.is_valid(): + messages.error(request, "Invalid CAPTCHA. Please try again.") + return render( + request, + self.template_name, + { + "form": self.get_form(), + "captcha_form": captcha_form, + }, + ) + + # Process form and duplicate IP check + form = self.get_form() + if form.is_valid(): + ip_address = form.cleaned_data.get("ip_address") + ip_type = form.cleaned_data.get("ip_type") + print(ip_address + " " + ip_type) + + if not self.is_valid_ip(ip_address, ip_type): + messages.error(request, f"Invalid {ip_type} address format.") + return render( + request, + self.template_name, + { + "form": form, + "captcha_form": captcha_form, + }, + ) + if IpReport.objects.filter(ip_address=ip_address, ip_type=ip_type).exists(): + messages.error(request, "This IP address has already been reported.") + return render( + request, + self.template_name, + { + "form": form, + "captcha_form": captcha_form, + }, + ) + + return self.form_valid(form) + else: + return self.form_invalid(form) + + def form_valid(self, form): + # Check daily report limit per IP + reporter_ip = get_client_ip(self.request) + limit = 50 if self.request.user.is_authenticated else 30 + today = now().date() + recent_reports_count = IpReport.objects.filter( + reporter_ip_address=reporter_ip, created=today + ).count() + + if recent_reports_count >= limit: + messages.error(self.request, "You have reached the daily limit for IP reports.") + return render( + self.request, + self.template_name, + { + "form": self.get_form(), + "captcha_form": CaptchaForm(), + }, + ) + + form.instance.reporter_ip_address = reporter_ip + form.instance.user = self.request.user if self.request.user.is_authenticated else None + form.save() + messages.success(self.request, "IP report successfully submitted.") + + return redirect("reported_ips_list") + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["captcha_form"] = CaptchaForm() + return context + + +class ReportedIpListView(ListView): + model = IpReport + template_name = "reported_ips_list.html" + context_object_name = "reported_ips" + paginate_by = 10 + + def get_queryset(self): + return IpReport.objects.all().order_by("-created")