kadenios/shared/auth/views.py

201 lines
6.8 KiB
Python

from django.contrib.auth import get_user_model
from django.contrib.auth import views as auth_views
from django.contrib.auth.hashers import make_password
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import Permission
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, FormView, ListView, TemplateView
from shared.mixins import LogMixin
from shared.models import Event
from .forms import ElectionAuthForm, PwdUserForm, UserAdminForm
from .utils import generate_password
User = get_user_model()
# #############################################################################
# Mixin to restrict access to staff members
# #############################################################################
class StaffMemberMixin(LogMixin, UserPassesTestMixin):
"""
Mixin permettant de restreindre l'accès aux membres `staff`, si la personne
n'est pas connectée, renvoie sur la page d'authentification
"""
def test_func(self):
return self.request.user.is_active and self.request.user.is_staff
# #############################################################################
# Election Specific Login
# #############################################################################
class ElectionLoginView(auth_views.LoginView):
template_name = "auth/election_login.html"
authentication_form = ElectionAuthForm
def get_initial(self):
return {"election_id": self.kwargs.get("election_id")}
def get_context_data(self, **kwargs):
kwargs.update({"election_id": self.kwargs.get("election_id")})
return super().get_context_data(**kwargs)
# #############################################################################
# Admin Panel
# #############################################################################
class AdminPanelView(StaffMemberMixin, TemplateView):
template_name = "auth/admin-panel.html"
# #############################################################################
# Creation of Password Accounts
# #############################################################################
class CreatePwdAccount(StaffMemberMixin, SuccessMessageMixin, CreateView):
model = User
form_class = PwdUserForm
template_name = "auth/create-user.html"
success_url = reverse_lazy("auth.admin")
success_message = _("Compte créé avec succès")
def form_valid(self, form):
# On enregistre un mot de passe aléatoire
form.instance.password = make_password(generate_password(32))
self.log_info(
"Password account created", data={"user": form.instance.get_data()}
)
return super().form_valid(form)
# #############################################################################
# List of password and CAS users
# #############################################################################
class AccountListView(StaffMemberMixin, ListView):
model = User
template_name = "auth/account-list.html"
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
qs = self.get_queryset()
ctx["cas_users"] = qs.filter(username__startswith="cas__")
ctx["pwd_users"] = qs.filter(username__startswith="pwd__")
ctx["e_manager"] = User.objects.with_perm(
Permission.objects.get(codename="election_admin"),
backend="shared.auth.backends.PwdBackend",
)
ctx["f_manager"] = User.objects.with_perm(
Permission.objects.get(codename="faq_admin"),
backend="shared.auth.backends.PwdBackend",
)
return ctx
# #############################################################################
# Permission management
# #############################################################################
class PermissionManagementView(StaffMemberMixin, SuccessMessageMixin, FormView):
form_class = UserAdminForm
template_name = "auth/permission-management.html"
success_message = _("Permissions modifiées avec succès !")
def get_context_data(self, **kwargs):
kwargs.update({"username": self.request.GET.get("user", None)})
return super().get_context_data(**kwargs)
def get_initial(self):
username = self.request.GET.get("user", None)
if username is not None:
user = User.objects.filter(username=username).first()
if user is not None:
return {
"username": username,
"full_admin": user.is_staff,
"election_admin": user.has_perm("elections.election_admin"),
"faq_admin": user.has_perm("faqs.faq_admin"),
}
return {}
def get_success_url(self):
return reverse("auth.permissions") + f"?user={self.user}"
def form_valid(self, form):
user = User.objects.get(username=form.cleaned_data["username"])
self.user = user.username
# Kadenios admin
user.is_staff = form.cleaned_data["full_admin"]
# Election admin
election_perm = Permission.objects.get(codename="election_admin")
if form.cleaned_data["election_admin"]:
election_perm.user_set.add(user)
else:
election_perm.user_set.remove(user)
# FAQ admin
faq_perm = Permission.objects.get(codename="faq_admin")
if form.cleaned_data["faq_admin"]:
faq_perm.user_set.add(user)
else:
faq_perm.user_set.remove(user)
user.save()
self.log_info("Permissions changed", data={"user": user.get_data()})
return super().form_valid(form)
# #############################################################################
# Log history
# #############################################################################
class JournalView(StaffMemberMixin, ListView):
model = Event
template_name = "auth/journal.html"
# #############################################################################
# List of special accounts
# #############################################################################
class AdminAccountsView(LoginRequiredMixin, TemplateView):
template_name = "auth/admin-accounts.html"
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx["admin"] = User.objects.filter(is_staff=True)
ctx["e_manager"] = User.objects.with_perm(
Permission.objects.get(codename="election_admin"),
backend="shared.auth.backends.PwdBackend",
)
ctx["f_manager"] = User.objects.with_perm(
Permission.objects.get(codename="faq_admin"),
backend="shared.auth.backends.PwdBackend",
)
return ctx