from django.contrib.auth.mixins import PermissionRequiredMixin from django.db.models import Q from django.urls import reverse from django.utils import timezone from django.views.generic.detail import SingleObjectMixin from .models import Election, Option, Question class AdminOnlyMixin(PermissionRequiredMixin): """Restreint l'accès aux admins""" permission_required = "elections.is_admin" class SelectElectionMixin: """Sélectionne automatiquement les foreignkeys voulues""" def get_queryset(self): qs = super().get_queryset() 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): """Permet de restreindre l'accès à des élections/questions/options""" f_prefixes = {Election: "", Question: "election__", Option: "question__election__"} def get_f_prefix(self): return self.f_prefixes.get(self.model, None) def get_filters(self): return {} def get_queryset(self): 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() class OpenElectionOnlyMixin(RestrictAccessMixin): """N'autorise la vue que lorsque l'élection est ouverte""" def get_filters(self): 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): """Restreint l'accès au créateurice de l'élection""" def get_next_url(self): return reverse("kadenios") def get_filters(self): filters = super().get_filters() # TODO: change the way we collect the user according to the model used filters[self.get_f_prefix() + "created_by"] = self.request.user return filters class CreatorOnlyEditMixin(CreatorOnlyMixin): """Permet au créateurice de modifier l'élection implicitement""" def get_filters(self): # 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 class ClosedElectionMixin(CreatorOnlyMixin): """Permet d'agir sur une élection terminée""" def get_filters(self): 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 """ def get_queryset(self): user = self.request.user qs = super().get_queryset() if user.is_authenticated: return qs.filter(Q(archived=False, visible=True) | Q(created_by=user)) return qs.filter(archived=False, visible=True)