On restreint l'accès au vote

This commit is contained in:
Tom Hubrecht 2020-12-20 18:50:38 +01:00
parent 5865583ace
commit e704e2a155
7 changed files with 128 additions and 24 deletions

View file

@ -21,7 +21,7 @@ class ElectionForm(forms.ModelForm):
class Meta:
model = Election
fields = ["name", "description", "start_date", "end_date"]
fields = ["name", "description", "restricted", "start_date", "end_date"]
class QuestionForm(forms.ModelForm):

View file

@ -0,0 +1,36 @@
# Generated by Django 2.2.17 on 2020-12-20 16:35
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("elections", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="user",
name="election",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="registered_voters",
to="elections.Election",
),
),
migrations.AlterField(
model_name="election",
name="created_by",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="elections_created",
to=settings.AUTH_USER_MODEL,
),
),
]

View file

@ -0,0 +1,20 @@
# Generated by Django 2.2.17 on 2020-12-20 17:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("elections", "0002_auto_20201220_1735"),
]
operations = [
migrations.AddField(
model_name="election",
name="restricted",
field=models.BooleanField(
default=True, verbose_name="restreint le vote à une liste de personnes"
),
),
]

View file

@ -0,0 +1,25 @@
# Generated by Django 2.2.17 on 2020-12-20 17:47
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("elections", "0003_election_restricted"),
]
operations = [
migrations.AlterField(
model_name="user",
name="election",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="registered_voters",
to="elections.Election",
),
),
]

View file

@ -35,7 +35,7 @@ class RestrictAccessMixin(SelectElectionMixin):
return qs.none()
class OpenElectionOnly(RestrictAccessMixin):
class OpenElectionOnlyMixin(RestrictAccessMixin):
"""N'autorise la vue que lorsque l'élection est ouverte"""
def get_filters(self):

View file

@ -1,16 +1,8 @@
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import gettext_lazy as _
# #############################################################################
# Modification of the base User Model
# #############################################################################
class User(AbstractUser):
pass
# #############################################################################
# Models regarding an election
# #############################################################################
@ -24,8 +16,16 @@ class Election(models.Model):
start_date = models.DateTimeField(_("date et heure de début"))
end_date = models.DateTimeField(_("date et heure de fin"))
restricted = models.BooleanField(
_("restreint le vote à une liste de personnes"), default=True
)
created_by = models.ForeignKey(
User, on_delete=models.SET_NULL, blank=True, null=True
settings.AUTH_USER_MODEL,
related_name="elections_created",
on_delete=models.SET_NULL,
blank=True,
null=True,
)
results_public = models.BooleanField(_("résultats publics"), default=False)
@ -58,7 +58,7 @@ class Option(models.Model):
)
text = models.TextField(_("texte"), blank=False)
voters = models.ManyToManyField(
User,
settings.AUTH_USER_MODEL,
related_name="votes",
)
# For now, we store the amount of votes received after the election is tallied
@ -66,3 +66,26 @@ class Option(models.Model):
class Meta:
ordering = ["id"]
# #############################################################################
# Modification of the base User Model
# #############################################################################
class User(AbstractUser):
election = models.ForeignKey(
Election,
related_name="registered_voters",
null=True,
blank=True,
on_delete=models.CASCADE,
)
def can_vote(self, election):
# Si c'est un·e utilisateur·ice CAS, iel peut voter dans les élections
# ouvertes à tou·te·s
if self.election is None:
return not election.restricted
# Pour les élections restreintes, il faut y être associé
return election.restricted and (self.election == election)

View file

@ -2,7 +2,7 @@ from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
# from django.db.models import Count, Prefetch
from django.http import HttpResponseRedirect
from django.http import Http404, HttpResponseRedirect
from django.urls import reverse
from django.utils import timezone
from django.utils.text import slugify
@ -16,7 +16,7 @@ from django.views.generic import (
)
from .forms import ElectionForm, OptionForm, OptionFormSet, QuestionForm
from .mixins import CreatorOnlyEditMixin, CreatorOnlyMixin, OpenElectionOnly
from .mixins import CreatorOnlyEditMixin, CreatorOnlyMixin, OpenElectionOnlyMixin
from .models import Election, Option, Question
# TODO: access control *everywhere*
@ -268,14 +268,6 @@ class ElectionView(DetailView):
def get_context_data(self, **kwargs):
kwargs.update({"current_time": timezone.now()})
return super().get_context_data(**kwargs)
# context = super().get_context_data(**kwargs)
# if self.object.tallied:
# options_qs = Option.objects.annotate(nb_votes=Count("voters"))
# questions = self.election.question.prefetch_related(
# Prefetch("options", queryset=options_qs)
# )
# context["questions"] = questions
# return context
def get_queryset(self):
return (
@ -286,7 +278,7 @@ class ElectionView(DetailView):
)
class VoteView(OpenElectionOnly, DetailView):
class VoteView(OpenElectionOnlyMixin, DetailView):
model = Question
template_name = "elections/vote.html"
@ -302,6 +294,14 @@ class VoteView(OpenElectionOnly, DetailView):
return reverse("election.vote", args=[q_next])
def get_object(self):
question = super().get_object()
# Seulement les utilisateur·ice·s ayant le droit de voter dans l'élection
# peuvent voir la page
if not self.request.user.can_vote(question.election):
raise Http404
return question
def get(self, request, *args, **kwargs):
self.object = self.get_object()
vote_form = OptionFormSet(instance=self.object)