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"
),
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 views as auth_views
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.messages.views import SuccessMessageMixin
from django.urls import reverse, reverse_lazy
@ -13,6 +13,8 @@ from .utils import generate_password
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
@ -89,6 +91,12 @@ class AccountListView(StaffMemberMixin, ListView):
ctx["cas_users"] = qs.filter(username__startswith="cas__")
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
@ -133,18 +141,37 @@ class PermissionManagementView(StaffMemberMixin, SuccessMessageMixin, FormView):
user.is_staff = form.cleaned_data["full_admin"]
# Election admin
perm_election = Permission.objects.get(codename="election_admin")
if form.cleaned_data["election_admin"]:
perm_election.user_set.add(user)
election_perm.user_set.add(user)
else:
perm_election.user_set.remove(user)
election_perm.user_set.remove(user)
# FAQ admin
perm_faq = Permission.objects.get(codename="faq_admin")
if form.cleaned_data["faq_admin"]:
perm_faq.user_set.add(user)
faq_perm.user_set.add(user)
else:
perm_faq.user_set.remove(user)
faq_perm.user_set.remove(user)
user.save()
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 ""
"Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-08-24 23:14+0200\n"
"PO-Revision-Date: 2021-08-24 23:14+0200\n"
"POT-Creation-Date: 2021-09-06 15:37+0200\n"
"PO-Revision-Date: 2021-09-05 17:31+0200\n"
"Last-Translator: Test Translator <test@translator>\n"
"Language-Team: \n"
"Language: en\n"
@ -226,7 +226,7 @@ msgstr ""
#: elections/templates/elections/admin/option.html:12
#: 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
msgid "Modifier"
msgstr "Edit"
@ -241,7 +241,7 @@ msgstr "Change the question"
#: elections/templates/elections/admin/question.html:59
#: 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"
msgstr "Add an option"
@ -334,55 +334,51 @@ msgstr "Invisible election"
msgid "Élection visible"
msgstr "Visible election"
#: elections/templates/elections/election_admin.html:115
msgid "Actions"
msgstr "Actions"
#: elections/templates/elections/election_admin.html:127
#: elections/templates/elections/election_admin.html:124
msgid "Vue classique"
msgstr "Classic view"
#: elections/templates/elections/election_admin.html:138
#: elections/templates/elections/election_admin.html:135
msgid "Rendre l'élection 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"
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
msgid "Gestion de la liste de votant·e·s"
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
msgid "Liste des votant·e·s"
msgstr "Voters' list"
#: elections/templates/elections/election_admin.html:185
#: elections/templates/elections/election_admin.html:182
msgid "Dépouiller"
msgstr "Count"
#: elections/templates/elections/election_admin.html:197
#: elections/templates/elections/election_admin.html:194
msgid "Publier"
msgstr "Publish"
#: elections/templates/elections/election_admin.html:199
#: elections/templates/elections/election_admin.html:196
msgid "Dépublier"
msgstr "De-publish"
#: elections/templates/elections/election_admin.html:209
#: elections/templates/elections/election_admin.html:206
msgid "Télécharger les résultats"
msgstr "Download the results"
#: elections/templates/elections/election_admin.html:218
#: elections/templates/elections/election_admin.html:215
msgid "Archiver"
msgstr "Archive"
#: elections/templates/elections/election_admin.html:280
#: elections/templates/elections/election_admin.html:285
#: elections/templates/elections/election_admin.html:289
#: elections/templates/elections/election_admin.html:277
#: elections/templates/elections/election_admin.html:282
#: elections/templates/elections/election_admin.html:286
msgid "Rajouter une question"
msgstr "Add a question"
@ -392,7 +388,7 @@ msgstr "Add a question"
#: elections/templates/elections/vote.html:49
#: shared/templates/auth/create-user.html:32
#: 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_reset.html:34
#: shared/templates/forms/common-form.html:25
@ -560,7 +556,7 @@ msgstr "Vote for the question:"
#: elections/templates/elections/vote.html:40
#: shared/templates/auth/create-user.html:23
#: 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_reset_confirm.html:25
#: shared/templates/forms/modal-form.html:23
@ -703,7 +699,7 @@ msgstr "Question deleted!"
msgid "Option supprimée !"
msgstr "Option deleted!"
#: elections/views.py:521
#: elections/views.py:522
msgid "Votre choix a bien été enregistré !"
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"
msgstr "No user with this username"
#: shared/auth/views.py:68
#: shared/auth/views.py:70
msgid "Compte créé avec succès"
msgstr "Account successfully created"
#: shared/auth/views.py:104
#: shared/auth/views.py:112
msgid "Permissions modifiées avec succès !"
msgstr "Permissions successfully modified!"
@ -838,24 +834,37 @@ msgstr "500 error"
msgid "Erreur interne du serveur."
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
msgid "Liste des comptes"
msgstr "List of accounts"
#: shared/templates/auth/account-list.html:42
#: shared/templates/auth/account-list.html:40
msgid "Comptes avec mot de passe"
msgstr "Password accounts"
#: shared/templates/auth/account-list.html:47
#: shared/templates/auth/account-list.html:74
#: shared/templates/auth/account-list.html:45
#: shared/templates/auth/account-list.html:90
msgid "Search"
msgstr ""
#: shared/templates/auth/account-list.html:69
#: shared/templates/auth/account-list.html:85
msgid "Comptes CAS"
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
msgid "Gestion de Kadenios"
msgstr "Kadenios Management"
@ -874,11 +883,11 @@ msgstr "Create a password account"
msgid "Connexion par mot de passe"
msgstr "Password login"
#: shared/templates/auth/permission-management.html:17
#: shared/templates/auth/permission-management.html:7
msgid "Gestion des permissions"
msgstr "Permission management"
#: shared/templates/auth/permission-management.html:22
#: shared/templates/auth/permission-management.html:12
msgid ""
"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>."
@ -997,6 +1006,9 @@ msgstr "Log back in"
msgid "Accueil"
msgstr "Home"
#~ msgid "Actions"
#~ msgstr "Actions"
#~ msgid "Modification d'une option"
#~ msgstr "Editing an option"

View file

@ -2,29 +2,27 @@
{% load i18n %}
{% block extra_head %}
{% block custom_js %}
<script>
function initSearch(input) {
const $search = document.getElementById(input);
const $users = $search.closest('div.panel').querySelectorAll('a.panel-block') || [];
const s = _id(input);
const us = _$('a.panel-block', s.closest('div.panel'));
$search.addEventListener('input', () => {
const username = $search.value.toLowerCase();
s.addEventListener('input', () => {
const username = s.value.toLowerCase();
$users.forEach(user => {
if (user.id.includes(username)) {
user.classList.remove('is-hidden');
us.forEach(u => {
if (u.id.includes(username)) {
u.classList.remove('is-hidden');
} else {
user.classList.add('is-hidden');
u.classList.add('is-hidden');
}
});
});
}
document.addEventListener('DOMContentLoaded', () => {
initSearch('pwd_search');
initSearch('cas_search');
});
initSearch('pwd_search');
initSearch('cas_search');
</script>
{% endblock %}
@ -54,10 +52,28 @@
{# List of users #}
{% for u in pwd_users %}
<a class="panel-block" href="{% url 'auth.permissions' %}?user={{ u.username }}" id={{ u.base_username|lower }}>
<span class="panel-icon">
<i class="fas fa-user-cog"></i>
</span>
<span class="ml-2">{{ u.full_name }} ({{ u.base_username }})</span>
<div class="level is-mobile is-flex-grow-1">
<div class="level-left is-flex-shrink-1 pr-3">
<span class="panel-icon">
<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>
{% endfor %}
</div>
@ -81,10 +97,28 @@
{# List of users #}
{% for u in cas_users %}
<a class="panel-block" href="{% url 'auth.permissions' %}?user={{ u.username }}" id={{ u.base_username|lower }}>
<span class="panel-icon">
<i class="fas fa-user-cog"></i>
</span>
<span class="ml-2">{{ u.full_name }} ({{ u.base_username }})</span>
<div class="level is-mobile is-flex-grow-1">
<div class="level-left is-flex-shrink-1 pr-3">
<span class="panel-icon">
<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>
{% endfor %}
</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 %}
{% block extra_head %}
<script>
const cas_users = {{ cas_users|safe }};
const pwd_users = {{ pwd_users|safe }};
</script>
{% endblock %}
{% block content %}
<h1 class="title">{% trans "Gestion des permissions" %}</h1>
@ -41,7 +31,7 @@
</div>
<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">
<i class="fas fa-undo-alt"></i>
</span>

View file

@ -7,6 +7,11 @@
<h1 class="title">{% trans "Bienvenue sur Kadenios" %}</h1>
<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 %}