Rajoute une page listant les admins et des icônes pour voir plus facilement les permissions

This commit is contained in:
Tom Hubrecht 2021-09-06 15:38:25 +02:00
parent 77e085458c
commit f65c3a991a
8 changed files with 214 additions and 73 deletions

View file

@ -14,4 +14,5 @@ urlpatterns = [
"permissions", views.PermissionManagementView.as_view(), name="auth.permissions" "permissions", views.PermissionManagementView.as_view(), name="auth.permissions"
), ),
path("accounts", views.AccountListView.as_view(), name="auth.accounts"), path("accounts", views.AccountListView.as_view(), name="auth.accounts"),
path("admins", views.AdminAccountsView.as_view(), name="auth.admins"),
] ]

View file

@ -1,7 +1,7 @@
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
from django.contrib.auth.hashers import make_password from django.contrib.auth.hashers import make_password
from django.contrib.auth.mixins import UserPassesTestMixin from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
@ -13,6 +13,8 @@ from .utils import generate_password
User = get_user_model() User = get_user_model()
election_perm = Permission.objects.get(codename="election_admin")
faq_perm = Permission.objects.get(codename="faq_admin")
# ############################################################################# # #############################################################################
# Mixin to restrict access to staff members # Mixin to restrict access to staff members
@ -89,6 +91,12 @@ class AccountListView(StaffMemberMixin, ListView):
ctx["cas_users"] = qs.filter(username__startswith="cas__") ctx["cas_users"] = qs.filter(username__startswith="cas__")
ctx["pwd_users"] = qs.filter(username__startswith="pwd__") ctx["pwd_users"] = qs.filter(username__startswith="pwd__")
ctx["e_manager"] = User.objects.with_perm(
election_perm, backend="shared.auth.backends.PwdBackend"
)
ctx["f_manager"] = User.objects.with_perm(
faq_perm, backend="shared.auth.backends.PwdBackend"
)
return ctx return ctx
@ -133,18 +141,37 @@ class PermissionManagementView(StaffMemberMixin, SuccessMessageMixin, FormView):
user.is_staff = form.cleaned_data["full_admin"] user.is_staff = form.cleaned_data["full_admin"]
# Election admin # Election admin
perm_election = Permission.objects.get(codename="election_admin")
if form.cleaned_data["election_admin"]: if form.cleaned_data["election_admin"]:
perm_election.user_set.add(user) election_perm.user_set.add(user)
else: else:
perm_election.user_set.remove(user) election_perm.user_set.remove(user)
# FAQ admin # FAQ admin
perm_faq = Permission.objects.get(codename="faq_admin")
if form.cleaned_data["faq_admin"]: if form.cleaned_data["faq_admin"]:
perm_faq.user_set.add(user) faq_perm.user_set.add(user)
else: else:
perm_faq.user_set.remove(user) faq_perm.user_set.remove(user)
user.save() user.save()
return super().form_valid(form) return super().form_valid(form)
# #############################################################################
# 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(
election_perm, backend="shared.auth.backends.PwdBackend"
)
ctx["f_manager"] = User.objects.with_perm(
faq_perm, backend="shared.auth.backends.PwdBackend"
)
return ctx

View file

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 0.1\n" "Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-08-24 23:14+0200\n" "POT-Creation-Date: 2021-09-06 15:37+0200\n"
"PO-Revision-Date: 2021-08-24 23:14+0200\n" "PO-Revision-Date: 2021-09-05 17:31+0200\n"
"Last-Translator: Test Translator <test@translator>\n" "Last-Translator: Test Translator <test@translator>\n"
"Language-Team: \n" "Language-Team: \n"
"Language: en\n" "Language: en\n"
@ -226,7 +226,7 @@ msgstr ""
#: elections/templates/elections/admin/option.html:12 #: elections/templates/elections/admin/option.html:12
#: elections/templates/elections/admin/question.html:29 #: elections/templates/elections/admin/question.html:29
#: elections/templates/elections/election_admin.html:156 #: elections/templates/elections/election_admin.html:153
#: faqs/templates/faqs/faq.html:22 #: faqs/templates/faqs/faq.html:22
msgid "Modifier" msgid "Modifier"
msgstr "Edit" msgstr "Edit"
@ -241,7 +241,7 @@ msgstr "Change the question"
#: elections/templates/elections/admin/question.html:59 #: elections/templates/elections/admin/question.html:59
#: elections/templates/elections/admin/question.html:63 #: elections/templates/elections/admin/question.html:63
#: elections/templates/elections/election_admin.html:276 #: elections/templates/elections/election_admin.html:273
msgid "Rajouter une option" msgid "Rajouter une option"
msgstr "Add an option" msgstr "Add an option"
@ -334,55 +334,51 @@ msgstr "Invisible election"
msgid "Élection visible" msgid "Élection visible"
msgstr "Visible election" msgstr "Visible election"
#: elections/templates/elections/election_admin.html:115 #: elections/templates/elections/election_admin.html:124
msgid "Actions"
msgstr "Actions"
#: elections/templates/elections/election_admin.html:127
msgid "Vue classique" msgid "Vue classique"
msgstr "Classic view" msgstr "Classic view"
#: elections/templates/elections/election_admin.html:138 #: elections/templates/elections/election_admin.html:135
msgid "Rendre l'élection visible" msgid "Rendre l'élection visible"
msgstr "Make the election visible" msgstr "Make the election visible"
#: elections/templates/elections/election_admin.html:147 #: elections/templates/elections/election_admin.html:144
msgid "Exporter les votant·e·s" msgid "Exporter les votant·e·s"
msgstr "Export the list of voters" msgstr "Export the list of voters"
#: elections/templates/elections/election_admin.html:165 #: elections/templates/elections/election_admin.html:162
#: elections/templates/elections/election_upload_voters.html:32 #: elections/templates/elections/election_upload_voters.html:32
msgid "Gestion de la liste de votant·e·s" msgid "Gestion de la liste de votant·e·s"
msgstr "Management of the voters' list" msgstr "Management of the voters' list"
#: elections/templates/elections/election_admin.html:177 #: elections/templates/elections/election_admin.html:174
#: elections/templates/elections/election_voters.html:76 #: elections/templates/elections/election_voters.html:76
msgid "Liste des votant·e·s" msgid "Liste des votant·e·s"
msgstr "Voters' list" msgstr "Voters' list"
#: elections/templates/elections/election_admin.html:185 #: elections/templates/elections/election_admin.html:182
msgid "Dépouiller" msgid "Dépouiller"
msgstr "Count" msgstr "Count"
#: elections/templates/elections/election_admin.html:197 #: elections/templates/elections/election_admin.html:194
msgid "Publier" msgid "Publier"
msgstr "Publish" msgstr "Publish"
#: elections/templates/elections/election_admin.html:199 #: elections/templates/elections/election_admin.html:196
msgid "Dépublier" msgid "Dépublier"
msgstr "De-publish" msgstr "De-publish"
#: elections/templates/elections/election_admin.html:209 #: elections/templates/elections/election_admin.html:206
msgid "Télécharger les résultats" msgid "Télécharger les résultats"
msgstr "Download the results" msgstr "Download the results"
#: elections/templates/elections/election_admin.html:218 #: elections/templates/elections/election_admin.html:215
msgid "Archiver" msgid "Archiver"
msgstr "Archive" msgstr "Archive"
#: elections/templates/elections/election_admin.html:280 #: elections/templates/elections/election_admin.html:277
#: elections/templates/elections/election_admin.html:285 #: elections/templates/elections/election_admin.html:282
#: elections/templates/elections/election_admin.html:289 #: elections/templates/elections/election_admin.html:286
msgid "Rajouter une question" msgid "Rajouter une question"
msgstr "Add a question" msgstr "Add a question"
@ -392,7 +388,7 @@ msgstr "Add a question"
#: elections/templates/elections/vote.html:49 #: elections/templates/elections/vote.html:49
#: shared/templates/auth/create-user.html:32 #: shared/templates/auth/create-user.html:32
#: shared/templates/auth/election_login.html:34 #: shared/templates/auth/election_login.html:34
#: shared/templates/auth/permission-management.html:48 #: shared/templates/auth/permission-management.html:38
#: shared/templates/authens/pwd_login.html:34 #: shared/templates/authens/pwd_login.html:34
#: shared/templates/authens/pwd_reset.html:34 #: shared/templates/authens/pwd_reset.html:34
#: shared/templates/forms/common-form.html:25 #: shared/templates/forms/common-form.html:25
@ -560,7 +556,7 @@ msgstr "Vote for the question:"
#: elections/templates/elections/vote.html:40 #: elections/templates/elections/vote.html:40
#: shared/templates/auth/create-user.html:23 #: shared/templates/auth/create-user.html:23
#: shared/templates/auth/election_login.html:25 #: shared/templates/auth/election_login.html:25
#: shared/templates/auth/permission-management.html:39 #: shared/templates/auth/permission-management.html:29
#: shared/templates/authens/pwd_login.html:25 #: shared/templates/authens/pwd_login.html:25
#: shared/templates/authens/pwd_reset_confirm.html:25 #: shared/templates/authens/pwd_reset_confirm.html:25
#: shared/templates/forms/modal-form.html:23 #: shared/templates/forms/modal-form.html:23
@ -703,7 +699,7 @@ msgstr "Question deleted!"
msgid "Option supprimée !" msgid "Option supprimée !"
msgstr "Option deleted!" msgstr "Option deleted!"
#: elections/views.py:521 #: elections/views.py:522
msgid "Votre choix a bien été enregistré !" msgid "Votre choix a bien été enregistré !"
msgstr "Your choice has been recorded!" msgstr "Your choice has been recorded!"
@ -803,11 +799,11 @@ msgstr "Invalid username format, only CAS or password accounts are editable"
msgid "Pas d'utilisateur·rice avec ce login" msgid "Pas d'utilisateur·rice avec ce login"
msgstr "No user with this username" msgstr "No user with this username"
#: shared/auth/views.py:68 #: shared/auth/views.py:70
msgid "Compte créé avec succès" msgid "Compte créé avec succès"
msgstr "Account successfully created" msgstr "Account successfully created"
#: shared/auth/views.py:104 #: shared/auth/views.py:112
msgid "Permissions modifiées avec succès !" msgid "Permissions modifiées avec succès !"
msgstr "Permissions successfully modified!" msgstr "Permissions successfully modified!"
@ -838,24 +834,37 @@ msgstr "500 error"
msgid "Erreur interne du serveur." msgid "Erreur interne du serveur."
msgstr "Internal server error." msgstr "Internal server error."
#: shared/templates/auth/account-list.html:35 #: shared/templates/auth/account-list.html:33
#: shared/templates/auth/admin-panel.html:31 #: shared/templates/auth/admin-panel.html:31
msgid "Liste des comptes" msgid "Liste des comptes"
msgstr "List of accounts" msgstr "List of accounts"
#: shared/templates/auth/account-list.html:42 #: shared/templates/auth/account-list.html:40
msgid "Comptes avec mot de passe" msgid "Comptes avec mot de passe"
msgstr "Password accounts" msgstr "Password accounts"
#: shared/templates/auth/account-list.html:47 #: shared/templates/auth/account-list.html:45
#: shared/templates/auth/account-list.html:74 #: shared/templates/auth/account-list.html:90
msgid "Search" msgid "Search"
msgstr "" msgstr ""
#: shared/templates/auth/account-list.html:69 #: shared/templates/auth/account-list.html:85
msgid "Comptes CAS" msgid "Comptes CAS"
msgstr "CAS accounts" msgstr "CAS accounts"
#: shared/templates/auth/admin-accounts.html:6
#: shared/templates/kadenios.html:14
msgid "Liste des comptes spéciaux"
msgstr "List of special accounts"
#: shared/templates/auth/admin-accounts.html:10
msgid "Gestionnaires de Kadenios"
msgstr "Kadenios managers"
#: shared/templates/auth/admin-accounts.html:32
msgid "Gestionnaires d'élections"
msgstr "Election managers"
#: shared/templates/auth/admin-panel.html:7 #: shared/templates/auth/admin-panel.html:7
msgid "Gestion de Kadenios" msgid "Gestion de Kadenios"
msgstr "Kadenios Management" msgstr "Kadenios Management"
@ -874,11 +883,11 @@ msgstr "Create a password account"
msgid "Connexion par mot de passe" msgid "Connexion par mot de passe"
msgstr "Password login" msgstr "Password login"
#: shared/templates/auth/permission-management.html:17 #: shared/templates/auth/permission-management.html:7
msgid "Gestion des permissions" msgid "Gestion des permissions"
msgstr "Permission management" msgstr "Permission management"
#: shared/templates/auth/permission-management.html:22 #: shared/templates/auth/permission-management.html:12
msgid "" msgid ""
"Pour modifier un compte CAS, le nom d'utilisateur doit commencer par " "Pour modifier un compte CAS, le nom d'utilisateur doit commencer par "
"<code>cas__</code>, pour un compte avec mot de passe, <code>pwd__</code>." "<code>cas__</code>, pour un compte avec mot de passe, <code>pwd__</code>."
@ -997,6 +1006,9 @@ msgstr "Log back in"
msgid "Accueil" msgid "Accueil"
msgstr "Home" msgstr "Home"
#~ msgid "Actions"
#~ msgstr "Actions"
#~ msgid "Modification d'une option" #~ msgid "Modification d'une option"
#~ msgstr "Editing an option" #~ msgstr "Editing an option"

View file

@ -2,29 +2,27 @@
{% load i18n %} {% load i18n %}
{% block extra_head %} {% block custom_js %}
<script> <script>
function initSearch(input) { function initSearch(input) {
const $search = document.getElementById(input); const s = _id(input);
const $users = $search.closest('div.panel').querySelectorAll('a.panel-block') || []; const us = _$('a.panel-block', s.closest('div.panel'));
$search.addEventListener('input', () => { s.addEventListener('input', () => {
const username = $search.value.toLowerCase(); const username = s.value.toLowerCase();
$users.forEach(user => { us.forEach(u => {
if (user.id.includes(username)) { if (u.id.includes(username)) {
user.classList.remove('is-hidden'); u.classList.remove('is-hidden');
} else { } else {
user.classList.add('is-hidden'); u.classList.add('is-hidden');
} }
}); });
}); });
} }
document.addEventListener('DOMContentLoaded', () => { initSearch('pwd_search');
initSearch('pwd_search'); initSearch('cas_search');
initSearch('cas_search');
});
</script> </script>
{% endblock %} {% endblock %}
@ -54,10 +52,28 @@
{# List of users #} {# List of users #}
{% for u in pwd_users %} {% for u in pwd_users %}
<a class="panel-block" href="{% url 'auth.permissions' %}?user={{ u.username }}" id={{ u.base_username|lower }}> <a class="panel-block" href="{% url 'auth.permissions' %}?user={{ u.username }}" id={{ u.base_username|lower }}>
<span class="panel-icon"> <div class="level is-mobile is-flex-grow-1">
<i class="fas fa-user-cog"></i> <div class="level-left is-flex-shrink-1 pr-3">
</span> <span class="panel-icon">
<span class="ml-2">{{ u.full_name }} ({{ u.base_username }})</span> <i class="fas fa-user-cog"></i>
</span>
<span class="ml-2" style="overlay=clip">{{ u.full_name }} ({{ u.base_username }})</span>
</div>
<div class="level-right">
<span class="panel-icon has-text-{% if u in e_manager %}primary{% else %}grey-lighter{% endif %}">
<i class="fas fa-vote-yea"></i>
</span>
<span class="panel-icon has-text-{% if u in f_manager %}primary{% else %}grey-lighter{% endif %}">
<i class="fas fa-question"></i>
</span>
<span class="panel-icon has-text-{% if u.is_staff %}danger{% else %}grey-lighter{% endif %}">
<i class="fas fa-user-shield"></i>
</span>
</div>
</div>
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
@ -81,10 +97,28 @@
{# List of users #} {# List of users #}
{% for u in cas_users %} {% for u in cas_users %}
<a class="panel-block" href="{% url 'auth.permissions' %}?user={{ u.username }}" id={{ u.base_username|lower }}> <a class="panel-block" href="{% url 'auth.permissions' %}?user={{ u.username }}" id={{ u.base_username|lower }}>
<span class="panel-icon"> <div class="level is-mobile is-flex-grow-1">
<i class="fas fa-user-cog"></i> <div class="level-left is-flex-shrink-1 pr-3">
</span> <span class="panel-icon">
<span class="ml-2">{{ u.full_name }} ({{ u.base_username }})</span> <i class="fas fa-user-cog"></i>
</span>
<span class="ml-2">{{ u.full_name }} ({{ u.base_username }})</span>
</div>
<div class="level-right">
<span class="panel-icon has-text-{% if u in e_manager %}primary{% else %}grey-lighter{% endif %}">
<i class="fas fa-vote-yea"></i>
</span>
<span class="panel-icon has-text-{% if u in f_manager %}primary{% else %}grey-lighter{% endif %}">
<i class="fas fa-question"></i>
</span>
<span class="panel-icon has-text-{% if u.is_staff %}danger{% else %}grey-lighter{% endif %}">
<i class="fas fa-user-shield"></i>
</span>
</div>
</div>
</a> </a>
{% endfor %} {% endfor %}
</div> </div>

View file

@ -0,0 +1,72 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<h1 class="title">{% trans "Liste des comptes spéciaux" %}</h1>
<hr>
<div class="notification">
<h3 class="subtitle has-text-weight-semibold">{% trans "Gestionnaires de Kadenios" %}</h3>
<div class="field is-grouped">
{% for a in admin %}
<div class="control">
<span class="tags has-addons">
<span class="tag is-primary">{{ a.full_name }}</span>
{% comment %}
<a class="tag is-danger has-text-white" href="mailto:{{ a.email }}">
<span class="icon">
<i class="fas fa-at"></i>
</span>
</a>
{% endcomment %}
</span>
</div>
{% endfor %}
</div>
</div>
<div class="notification">
<h3 class="subtitle has-text-weight-semibold">{% trans "Gestionnaires d'élections" %}</h3>
<div class="field is-grouped">
{% for m in e_manager %}
<div class="control">
<span class="tags has-addons">
<span class="tag is-primary">{{ m.full_name }}</span>
{% comment %}
<a class="tag is-danger has-text-white" href="mailto:{{ m.email }}">
<span class="icon">
<i class="fas fa-at"></i>
</span>
</a>
{% endcomment %}
</span>
</div>
{% endfor %}
</div>
</div>
{% comment %}
<div class="notification">
<h3 class="subtitle has-text-weight-semibold">{% trans "Gestionnaires de FAQs" %}</h3>
<div class="field is-grouped">
{% for m in f_manager %}
<div class="control">
<span class="tags has-addons">
<span class="tag is-primary">{{ m.full_name }}</span>
<a class="tag is-danger has-text-white" href="mailto:{{ m.email }}">
<span class="icon">
<i class="fas fa-at"></i>
</span>
</a>
</span>
</div>
{% endfor %}
</div>
</div>
{% endcomment %}
{% endblock %}

View file

@ -2,16 +2,6 @@
{% load i18n %} {% load i18n %}
{% block extra_head %}
<script>
const cas_users = {{ cas_users|safe }};
const pwd_users = {{ pwd_users|safe }};
</script>
{% endblock %}
{% block content %} {% block content %}
<h1 class="title">{% trans "Gestion des permissions" %}</h1> <h1 class="title">{% trans "Gestion des permissions" %}</h1>
@ -41,7 +31,7 @@
</div> </div>
<div class="control"> <div class="control">
<a class="button is-primary" href="{% url 'auth.accounts' %}#{{ username }}"> <a class="button is-primary" href="{% url 'auth.accounts' %}">
<span class="icon"> <span class="icon">
<i class="fas fa-undo-alt"></i> <i class="fas fa-undo-alt"></i>
</span> </span>

View file

@ -7,6 +7,11 @@
<h1 class="title">{% trans "Bienvenue sur Kadenios" %}</h1> <h1 class="title">{% trans "Bienvenue sur Kadenios" %}</h1>
<hr> <hr>
{% trans "La plateforme Kadenios permet de créer des élections." %} <p>{% trans "La plateforme Kadenios permet de créer des élections." %}</p>
{% if user.is_authenticated %}
<br>
<a href="{% url 'auth.admins' %}">{% trans "Liste des comptes spéciaux" %}</a>
{% endif %}
{% endblock %} {% endblock %}