kadenios/elections/mixins.py

127 lines
4 KiB
Python
Raw Normal View History

2024-07-10 13:51:24 +02:00
from typing import Any
from django.contrib.auth.mixins import PermissionRequiredMixin
2024-07-10 13:51:24 +02:00
from django.db.models import Q, QuerySet
from django.http.request import HttpRequest
2020-12-21 00:07:07 +01:00
from django.urls import reverse
2020-12-20 01:58:38 +01:00
from django.utils import timezone
from django.views.generic.detail import SingleObjectMixin
2024-07-10 13:51:24 +02:00
from elections.typing import AuthenticatedRequest
2020-12-20 01:58:38 +01:00
from .models import Election, Option, Question
class AdminOnlyMixin(PermissionRequiredMixin):
"""Restreint l'accès aux admins"""
2024-07-10 13:51:24 +02:00
request: AuthenticatedRequest
2021-07-13 02:41:32 +02:00
permission_required = "elections.election_admin"
2020-12-20 02:31:56 +01:00
class SelectElectionMixin:
"""Sélectionne automatiquement les foreignkeys voulues"""
2024-07-10 13:51:24 +02:00
model: type
def get_queryset(self) -> QuerySet:
qs = super().get_queryset() # pyright: ignore
2020-12-20 02:31:56 +01:00
if self.model is Question:
return qs.select_related("election")
elif self.model is Option:
return qs.select_related("question__election")
return qs
class RestrictAccessMixin(SelectElectionMixin):
2020-12-20 01:58:38 +01:00
"""Permet de restreindre l'accès à des élections/questions/options"""
2024-07-10 13:51:24 +02:00
f_prefixes = {
Election: "",
Question: "election__",
Option: "question__election__",
}
2020-12-20 01:58:38 +01:00
2024-07-10 13:51:24 +02:00
def get_f_prefix(self) -> str:
return self.f_prefixes.get(self.model, "")
2020-12-20 01:58:38 +01:00
2024-07-10 13:51:24 +02:00
def get_filters(self) -> dict[str, Any]:
2020-12-20 01:58:38 +01:00
return {}
2020-12-19 23:48:18 +01:00
2024-07-10 13:51:24 +02:00
def get_queryset(self) -> QuerySet:
2020-12-20 01:58:38 +01:00
qs = super().get_queryset()
if self.model in self.f_prefixes:
return qs.filter(**self.get_filters())
# On ne sait pas ce qu'on manipule donc on ne renvoie rien
return qs.none()
2020-12-20 18:50:38 +01:00
class OpenElectionOnlyMixin(RestrictAccessMixin):
"""N'autorise la vue que lorsque l'élection est ouverte"""
2024-07-10 13:51:24 +02:00
def get_filters(self) -> dict[str, Any]:
f_prefix = self.get_f_prefix()
# On ne peut modifier que les élections qui n'ont pas commencé, et
# accessoirement qui ne sont pas dépouillées ou archivées
# TODO: décider si on choisit pas de juste garder les dates d'ouverture
filters = super().get_filters()
filters[f_prefix + "start_date__lt"] = timezone.now()
filters[f_prefix + "end_date__gt"] = timezone.now()
filters[f_prefix + "visible"] = True
filters[f_prefix + "tallied"] = False
filters[f_prefix + "archived"] = False
return filters
class CreatorOnlyMixin(AdminOnlyMixin, RestrictAccessMixin, SingleObjectMixin):
2020-12-20 01:58:38 +01:00
"""Restreint l'accès au créateurice de l'élection"""
2020-12-21 00:07:07 +01:00
def get_next_url(self):
return reverse("kadenios")
2024-07-10 13:51:24 +02:00
def get_filters(self) -> dict[str, Any]:
2020-12-20 01:58:38 +01:00
filters = super().get_filters()
2020-12-19 23:48:18 +01:00
# TODO: change the way we collect the user according to the model used
2020-12-20 01:58:38 +01:00
filters[self.get_f_prefix() + "created_by"] = self.request.user
return filters
class CreatorOnlyEditMixin(CreatorOnlyMixin):
2020-12-20 01:58:38 +01:00
"""Permet au créateurice de modifier l'élection implicitement"""
2024-07-10 13:51:24 +02:00
def get_filters(self) -> dict[str, Any]:
2020-12-20 01:58:38 +01:00
# On ne peut modifier que les élections qui n'ont pas commencé
filters = super().get_filters()
filters[self.get_f_prefix() + "start_date__gt"] = timezone.now()
return filters
2020-12-19 23:48:18 +01:00
class ClosedElectionMixin(CreatorOnlyMixin):
"""Permet d'agir sur une élection terminée"""
2024-07-10 13:51:24 +02:00
def get_filters(self) -> dict[str, Any]:
f_prefix = self.get_f_prefix()
# L'élection doit être terminée et non archivée
filters = super().get_filters()
filters[f_prefix + "end_date__lt"] = timezone.now()
filters[f_prefix + "archived"] = False
return filters
class NotArchivedMixin:
"""
Permet de ne garder que les élections non archivées, et visibles
ou dont on est l'admin
"""
2024-07-10 13:51:24 +02:00
request: HttpRequest
def get_queryset(self) -> QuerySet:
user = self.request.user
2024-07-10 13:51:24 +02:00
qs = super().get_queryset() # pyright: ignore
if user.is_authenticated:
return qs.filter(Q(archived=False, visible=True) | Q(created_by=user))
return qs.filter(archived=False, visible=True)