105 lines
3.7 KiB
Python
105 lines
3.7 KiB
Python
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["HTTP_X_REAL_IP"]
|
|
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":
|
|
VotingUser.objects.filter(name=name, 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"))
|