1
0

Fix issue when adding a date when some votes already exist, Add 400 page

This commit is contained in:
Marcel Schwarz 2022-08-03 21:00:33 +02:00
parent 4d58bf529c
commit 986b529794
9 changed files with 85 additions and 16 deletions

View File

@ -24,7 +24,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = os.getenv("SECRET_KEY", "django-insecure-!@gqe(nmv4ylos+2p14nk+&8h$j7g%=n4sdrwqzvr6!8ee$y9@")
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.getenv("DEBUG_MODE", True)
DEBUG = os.getenv("DEBUG_MODE", "True") == "True"
ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "* 192.168.235.51 127.0.0.1 localhost 192.168.0.52 192.168.235.35").split(" ")

View File

@ -22,3 +22,5 @@ urlpatterns = [
path('', include('homepage.urls')),
path('admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
handler400 = "homepage.views.bad_request"

View File

@ -0,0 +1,17 @@
from django.core import exceptions
class RateLimitHit(exceptions.SuspiciousOperation):
def __init__(self):
self.text = "You made to many request in a short period of time! Please try again later"
def __str__(self):
return f"{self.__class__.__name__}: {self.text}"
class ProxyUsageDetected(exceptions.SuspiciousOperation):
def __init__(self):
self.text = "It appears you are using a proxy! We don't want you to do that!"
def __str__(self):
return f"{self.__class__.__name__}: {self.text}"

View File

@ -0,0 +1,17 @@
# Generated by Django 4.0.5 on 2022-08-03 17:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('homepage', '0016_eventdatevotes_available'),
]
operations = [
migrations.RemoveField(
model_name='eventdatevotes',
name='available',
),
]

View File

@ -45,7 +45,6 @@ class ClubhausEvent(models.Model):
class EventDateVotes(models.Model):
voter = models.ForeignKey(to="VotingUser", on_delete=models.CASCADE)
date = models.ForeignKey(to="EventDate", to_field="date", on_delete=models.CASCADE)
available = models.BooleanField(blank=False)
class Meta:
constraints = [

View File

@ -0,0 +1,16 @@
{% extends 'homepage/base.html' %}
{% block main %}
<div class="d-flex h-100 mx-3">
<main class="d-flex flex-column flex-grow-1 w-100 my-5 mx-auto text-white" style="max-width: 42rem">
<div class="row">
<h1>Bad Request (400)</h1>
</div>
<div class="row">
{% if exception %}
<h6>{{ exception }}</h6>
{% endif %}
</div>
</main>
</div>
{% endblock %}

View File

@ -99,12 +99,11 @@
</tr>
</thead>
<tbody class="table-group-divider">
{% regroup votes by voter as voter_grouped %}
{% for indv_voter, indv_votes in voter_grouped %}
{% for voter in votes.items %}
<tr>
<td>{{ indv_voter.name }}</td>
{% for indv_vote in indv_votes %}
{% if indv_vote.available %}
<td>{{ voter.0.name }}</td>
{% for date in voter.1.items %}
{% if date.1 %}
<td><i class="fs-4 text-success bi-check-circle"></i></td>
{% else %}
<td><i class="fs-4 text-danger bi-x-circle"></i></td>

View File

@ -7,4 +7,4 @@ urlpatterns = [
path('event', views.events, name='events'),
path('tobacco', views.tobacco, name='tobacco'),
path('voting', views.voting, name='voting'),
]
]

View File

@ -1,13 +1,18 @@
import django.utils.timezone
from django.core.cache import cache
from django.http import HttpRequest, HttpResponseRedirect, HttpResponseForbidden
from django.http import HttpRequest, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
import clubhaus.settings as django_settings
from .exceptions import RateLimitHit, ProxyUsageDetected
from .models import Tobacco, ClubhausEvent, EventDate, EventDateVotes, VotingUser
def bad_request(request, exception, template_name="homepage/400.html"):
return render(request, template_name, context={"exception": exception}, status=400)
def index(request: HttpRequest) -> django.http.HttpResponse:
return render(request, 'homepage/index.html', {})
@ -24,7 +29,18 @@ def events(request: HttpRequest) -> django.http.HttpResponse:
dates = EventDate.objects.filter(event=next_event).order_by("date")
votes = EventDateVotes.objects.filter(date__event=next_event).order_by("voter_id", "date")
return render(request, 'homepage/events.html', {'next_event': next_event, "dates": dates, 'votes': votes})
unique_voters = list(set(map(lambda v: v.voter, votes)))
vote_map = {}
for voter in unique_voters:
vote_map[voter] = {date.date.isoformat(): False for date in dates}
for vote in votes:
voter = vote.voter
v_date = vote.date.date.isoformat()
if voter in vote_map and v_date in vote_map[voter]:
vote_map[voter][v_date] = True
return render(request, 'homepage/events.html', {'next_event': next_event, "dates": dates, 'votes': vote_map})
else:
return HttpResponseRedirect(reverse("index"))
@ -34,7 +50,7 @@ def voting(request: HttpRequest) -> django.http.HttpResponse:
# Proxy use is forbidden
if request.META.get("X-Forwarded-For"):
return HttpResponseForbidden()
raise ProxyUsageDetected()
ip = request.META.get("REMOTE_ADDR")
cache_key = f"voting_block_{ip}"
@ -43,9 +59,12 @@ def voting(request: HttpRequest) -> django.http.HttpResponse:
rate_cache.add(cache_key, 0, django_settings.IP_RATE_LIMIT_TIME)
rate_cache.incr(cache_key)
if request.method != "POST" and rate_cache.get(cache_key) > django_settings.IP_RATE_LIMIT_COUNT:
if request.method != "POST":
return HttpResponseRedirect(reverse("events"))
if rate_cache.get(cache_key) > django_settings.IP_RATE_LIMIT_COUNT:
raise RateLimitHit()
modify_key = request.POST["modifyKey"] or ""
if name := request.POST["name"]:
request.session["name"] = name
@ -54,9 +73,9 @@ def voting(request: HttpRequest) -> django.http.HttpResponse:
event_dates = EventDate.objects.filter(event__active=True).order_by("date")
for date in event_dates:
date_in_request = date.date.isoformat() in request.POST
EventDateVotes.objects.update_or_create(
voter=user, date=date,
defaults={"voter": user, "date": date, "available": date_in_request})
if date.date.isoformat() in request.POST:
EventDateVotes.objects.update_or_create(voter=user, date=date)
else:
EventDateVotes.objects.filter(voter=user, date=date).delete()
return HttpResponseRedirect(reverse("events"))