Add authentication for voting
This commit is contained in:
parent
293c46631e
commit
242870aab2
@ -1,7 +1,7 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
from .models import Tobacco, TobaccoCategory, ClubhausEvent, EventDate, EventDateVotes
|
||||
from .models import Tobacco, TobaccoCategory, ClubhausEvent, EventDate, EventDateVotes, VotingUser
|
||||
|
||||
|
||||
@admin.register(Tobacco)
|
||||
@ -23,9 +23,15 @@ class EventDateAdmin(admin.ModelAdmin):
|
||||
ordering = ("id",)
|
||||
|
||||
|
||||
@admin.register(VotingUser)
|
||||
class VotingUserAdmin(admin.ModelAdmin):
|
||||
list_display = ("id", "name", "modify_key")
|
||||
ordering = ("id",)
|
||||
|
||||
|
||||
@admin.register(EventDateVotes)
|
||||
class EventDateVotesAdmin(admin.ModelAdmin):
|
||||
list_display = ("id", "name", "date")
|
||||
list_display = ("id", "voter", "date")
|
||||
ordering = ("id",)
|
||||
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
# Generated by Django 4.0.5 on 2022-08-02 22:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('homepage', '0010_alter_eventdatevotes_unique_together_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='eventdatevotes',
|
||||
name='modify_key',
|
||||
field=models.TextField(default=''),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -0,0 +1,41 @@
|
||||
# Generated by Django 4.0.5 on 2022-08-02 23:07
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('homepage', '0011_eventdatevotes_modify_key'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='VotingUser',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
],
|
||||
),
|
||||
migrations.RemoveConstraint(
|
||||
model_name='eventdatevotes',
|
||||
name='unique_name_date',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='eventdatevotes',
|
||||
name='modify_key',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='eventdatevotes',
|
||||
name='name',
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='eventdatevotes',
|
||||
constraint=models.UniqueConstraint(fields=('date',), name='unique_voter_day'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='eventdatevotes',
|
||||
name='voter',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='homepage.votinguser'),
|
||||
),
|
||||
]
|
@ -0,0 +1,29 @@
|
||||
# Generated by Django 4.0.5 on 2022-08-02 23:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('homepage', '0012_votinguser_remove_eventdatevotes_unique_name_date_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='votinguser',
|
||||
name='modify_key',
|
||||
field=models.CharField(default='', max_length=200),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='votinguser',
|
||||
name='name',
|
||||
field=models.CharField(default='', max_length=200),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='votinguser',
|
||||
constraint=models.UniqueConstraint(fields=('name', 'modify_key'), name='unique_name_modify_key'),
|
||||
),
|
||||
]
|
@ -0,0 +1,20 @@
|
||||
# Generated by Django 4.0.5 on 2022-08-02 23:09
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('homepage', '0013_votinguser_modify_key_votinguser_name_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='eventdatevotes',
|
||||
name='voter',
|
||||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='homepage.votinguser'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -0,0 +1,21 @@
|
||||
# Generated by Django 4.0.5 on 2022-08-02 23:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('homepage', '0014_alter_eventdatevotes_voter'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveConstraint(
|
||||
model_name='eventdatevotes',
|
||||
name='unique_voter_day',
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='eventdatevotes',
|
||||
constraint=models.UniqueConstraint(fields=('voter', 'date'), name='unique_voter_day'),
|
||||
),
|
||||
]
|
@ -0,0 +1,19 @@
|
||||
# Generated by Django 4.0.5 on 2022-08-02 23:40
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('homepage', '0015_remove_eventdatevotes_unique_voter_day_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='eventdatevotes',
|
||||
name='available',
|
||||
field=models.BooleanField(default=True),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -43,13 +43,27 @@ class ClubhausEvent(models.Model):
|
||||
|
||||
|
||||
class EventDateVotes(models.Model):
|
||||
name = models.CharField(max_length=200, blank=False)
|
||||
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 = [
|
||||
models.UniqueConstraint(fields=("name", "date"), name="unique_name_date")
|
||||
models.UniqueConstraint(fields=("voter", "date"), name="unique_voter_day")
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} - {self.date.date.isoformat()}"
|
||||
return f"{self.voter.name}({self.voter.id}) - {self.date.date.isoformat()}"
|
||||
|
||||
|
||||
class VotingUser(models.Model):
|
||||
name = models.CharField(max_length=200, blank=False)
|
||||
modify_key = models.CharField(max_length=200, blank=False)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=("name", "modify_key"), name="unique_name_modify_key")
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name}({self.id})"
|
||||
|
@ -99,11 +99,12 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="table-group-divider">
|
||||
{% for voter in votes.items %}
|
||||
{% regroup votes by voter as voter_grouped %}
|
||||
{% for indv_voter, indv_votes in voter_grouped %}
|
||||
<tr>
|
||||
<td>{{ voter.0 }}</td>
|
||||
{% for date in voter.1.items %}
|
||||
{% if date.1 %}
|
||||
<td>{{ indv_voter.name }}</td>
|
||||
{% for indv_vote in indv_votes %}
|
||||
{% if indv_vote.available %}
|
||||
<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>
|
||||
@ -175,22 +176,29 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="nameInput" class="form-label">Name</label>
|
||||
<input type="text" class="form-control" id="nameInput" name="name"
|
||||
{% if request.session.name %} value="{{ request.session.name }}" {% endif %}>
|
||||
</div>
|
||||
{% language 'de' %}
|
||||
{% for dateOption in dates %}
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox"
|
||||
id="{{ dateOption.date.isoformat }}"
|
||||
name="{{ dateOption.date.isoformat }}">
|
||||
<label class="form-check-label" for="flexCheckDefault">
|
||||
<label class="form-check-label" for="{{ dateOption.date.isoformat }}">
|
||||
{{ dateOption.date|date:'l, d. F H:i' }}
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endlanguage %}
|
||||
<div class="mb-3">
|
||||
<label for="nameInput" class="form-label">Name</label>
|
||||
<input type="text" class="form-control" id="nameInput" name="name" required
|
||||
{% if request.session.name %} value="{{ request.session.name }}" {% endif %}>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="modifyKeyInput" class="form-label">Passwort</label>
|
||||
<input type="text" class="form-control" id="modifyKeyInput" name="modifyKey"
|
||||
{% if request.session.modifyKey %} value="{{ request.session.modifyKey }}" {% endif %}>
|
||||
<div id="modifyKeyHelp" class="form-text">Damit nur du deine Einträge ändern kannst, solltest du ein Passwort vergeben. Tust du dies nicht, kann jeder deine Einträge ändern und löschen!</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">Abstimmen</button>
|
||||
|
@ -1,11 +1,11 @@
|
||||
import django.utils.timezone
|
||||
from django.core.cache import cache
|
||||
from django.http import HttpRequest, HttpResponseRedirect
|
||||
from django.http import HttpRequest, HttpResponseRedirect, HttpResponseForbidden
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
|
||||
from .models import Tobacco, ClubhausEvent, EventDate, EventDateVotes
|
||||
import clubhaus.settings as django_settings
|
||||
from .models import Tobacco, ClubhausEvent, EventDate, EventDateVotes, VotingUser
|
||||
|
||||
|
||||
def index(request: HttpRequest) -> django.http.HttpResponse:
|
||||
@ -22,20 +22,9 @@ def events(request: HttpRequest) -> django.http.HttpResponse:
|
||||
if len(next_events) == 1:
|
||||
next_event = next_events[0]
|
||||
dates = EventDate.objects.filter(event=next_event).order_by("date")
|
||||
votes = EventDateVotes.objects.filter(date__event=next_event)
|
||||
votes = EventDateVotes.objects.filter(date__event=next_event).order_by("voter_id", "date")
|
||||
|
||||
voter_names = sorted(set(map(lambda v: v.name, votes)))
|
||||
vote_map = {}
|
||||
for voter_name in voter_names:
|
||||
vote_map[voter_name] = {date.date.isoformat(): False for date in dates}
|
||||
|
||||
for vote in votes:
|
||||
v_name = vote.name
|
||||
v_date = vote.date.date.isoformat()
|
||||
if v_name in vote_map and v_date in vote_map[v_name]:
|
||||
vote_map[v_name][v_date] = True
|
||||
|
||||
return render(request, 'homepage/events.html', {'next_event': next_event, "dates": dates, 'votes': vote_map})
|
||||
return render(request, 'homepage/events.html', {'next_event': next_event, "dates": dates, 'votes': votes})
|
||||
else:
|
||||
return HttpResponseRedirect(reverse("index"))
|
||||
|
||||
@ -54,13 +43,20 @@ 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) < 3:
|
||||
if request.method != "POST" and rate_cache.get(cache_key) > django_settings.IP_RATE_LIMIT_COUNT:
|
||||
return HttpResponseRedirect(reverse("events"))
|
||||
|
||||
modify_key = request.POST["modifyKey"] or ""
|
||||
if name := request.POST["name"]:
|
||||
request.session["name"] = name
|
||||
for date in EventDate.objects.filter(event__active=True).order_by("date"):
|
||||
if date.date.isoformat() in request.POST:
|
||||
EventDateVotes.objects.update_or_create(name=name, date=date)
|
||||
else:
|
||||
EventDateVotes.objects.filter(name=name, date=date).delete()
|
||||
request.session["modifyKey"] = modify_key
|
||||
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:
|
||||
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})
|
||||
|
||||
return HttpResponseRedirect(reverse("events"))
|
||||
|
Loading…
Reference in New Issue
Block a user