import django.utils.timezone from django.core.cache import cache 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, EventDateVote, 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') def impressum(request: HttpRequest) -> django.http.HttpResponse: return render(request, 'homepage/impressum.html') def cookies(request: HttpRequest) -> django.http.HttpResponse: return render(request, 'homepage/cookies.html') def tobacco(request: HttpRequest) -> django.http.HttpResponse: context = {'tobaccos': Tobacco.objects.all().order_by('-in_stock', "category__name", "name")} return render(request, 'homepage/tobacco.html', context) def events(request: HttpRequest) -> django.http.HttpResponse: next_events = ClubhausEvent.objects.filter(active=True).order_by('-id') if len(next_events) == 1: next_event = next_events[0] dates = EventDate.objects.filter(event=next_event).order_by("date") votes = EventDateVote.objects.filter(date__event=next_event).order_by("voter_id", "date") unique_voters = list(set(map(lambda v: v.voter, votes))) vote_map = {} for voter in unique_voters: vote_map[voter] = {date.date.isoformat(): None 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] = vote.available return render(request, 'homepage/events.html', context={ 'next_event': next_event, "dates": dates, 'votes': vote_map }) else: return render(request, 'homepage/coming-soon.html') def voting(request: HttpRequest) -> django.http.HttpResponse: request.session.clear_expired() # Proxy use is forbidden if proxy := request.META.get("HTTP_X_FORWARDED_FOR"): raise ProxyUsageDetected(proxy) if request.method != "POST": return HttpResponseRedirect(reverse("events")) # Check rate limit ip = request.META.get("HTTP_X_REAL_IP") or "" cache_key = f"voting_block_{ip}" rate_cache: django.core.cache.BaseCache = cache if ip not in rate_cache: rate_cache.add(cache_key, 0, django_settings.IP_RATE_LIMIT_TIME) rate_cache.incr(cache_key) if rate_cache.get(cache_key) > django_settings.IP_RATE_LIMIT_COUNT: raise RateLimitHit(ip) # check params if not request.POST["name"]: return HttpResponseRedirect(reverse("events")) name = request.POST["name"] modify_key = request.POST["modifyKey"] or "" request.session["name"] = name request.session["modifyKey"] = modify_key # handle delete if request.POST["deleteClicked"] == "1": EventDateVote.objects.filter( date__event__active=True, voter__name=name, voter__modify_key=modify_key).delete() return HttpResponseRedirect(reverse("events")) # handle normal voting user, _ = VotingUser.objects.get_or_create(name=name, modify_key=modify_key) event_dates = EventDate.objects.filter(event__active=True).order_by("date") for date in event_dates: available = date.date.isoformat() in request.POST EventDateVote.objects.update_or_create(voter=user, date=date, defaults={"available": available}) return HttpResponseRedirect(reverse("events"))