8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-12-23 15:33:45 +00:00

Merge branch 'rework_rights_ui' into 'master'

Refactor the rights info page

Closes #118

See merge request federez/re2o!181
This commit is contained in:
klafyvel 2018-07-12 14:37:43 +02:00
commit 77839fa448
13 changed files with 346 additions and 271 deletions

View file

@ -1,86 +0,0 @@
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load bootstrap3 %}
{% load acl %}
{% for droit,users in stats_list.items %}
<div class="panel panel-default">
<div class="panel-heading clearfix" data-parent="#accordion" data-toggle="collapse" data-target="#collapse{{droit.id}}">
<h2 class="panel-title pull-left">
<i class="fa fa-address-book"></i>
{{droit}}
<span class="badge">{{users.count}}</span>
</h2>
</div>
<div class="panel-collapse collapse" id="collapse{{droit.id}}">
<div class="panel-body">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Pseudo</th>
<th>Adhésion</th>
<th>Derniere connexion</th>
<th>Nombre d'actions</th>
<th>Date de la dernière action</th>
<th></th>
</tr>
</thead>
{% for utilisateur in users %}
<tr>
<td>{{ utilisateur.pseudo }}</td>
{% if utilisateur.is_adherent %}
<td><p class="text-success">Adhérent</p></td>
{% elif not utilisateur.end_adhesion %}
<td><p class="text-warning">On ne s'en souvient plus...</p></td>
{% else %}
<td><p class="text-danger">Plus depuis {{ utilisateur.end_adhesion }}</p></td>
{% endif %}
<td>{{ utilisateur.last_login }}</td>
<td>{{ utilisateur.num }}</td>
{% if not utilisateur.last %}
<td><p class="text-danger">Jamais</p></td>
{% else %}
<td><p class="text-success">{{utilisateur.last}}</p></td>
{% endif %}
<td>
{% if droit != 'Superuser' %}
<a href="{% url 'users:del-group' utilisateur.id droit.id %}">
{% else %}
<a href="{% url 'users:del-superuser' utilisateur.id %}">
{% endif %}
<button type="button" class="btn btn-danger" aria-label="Left Align">
<span class="fa fa-user-times" aria-hidden="true"></span>
</button>
</a>
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
</div>
{% endfor %}

View file

@ -51,9 +51,5 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<i class="fa fa-users"></i> <i class="fa fa-users"></i>
Utilisateurs Utilisateurs
</a> </a>
<a class="list-group-item list-group-item-info" href="{% url "logs:stats-droits" %}">
<i class="fa fa-balance-scale"></i>
Groupes de droit
</a>
{% acl_end %} {% acl_end %}
{% endblock %} {% endblock %}

View file

@ -1,36 +0,0 @@
{% extends "logs/sidebar.html" %}
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load bootstrap3 %}
{% block title %}Statistiques des droits{% endblock %}
{% block content %}
<h2>Statistiques des droits</h2>
{% include "logs/aff_stats_droits.html" with stats_list=stats_list %}
<br />
<br />
<br />
{% endblock %}

View file

@ -39,5 +39,4 @@ urlpatterns = [
url(r'^stats_models/$', views.stats_models, name='stats-models'), url(r'^stats_models/$', views.stats_models, name='stats-models'),
url(r'^stats_users/$', views.stats_users, name='stats-users'), url(r'^stats_users/$', views.stats_users, name='stats-users'),
url(r'^stats_actions/$', views.stats_actions, name='stats-actions'), url(r'^stats_actions/$', views.stats_actions, name='stats-actions'),
url(r'^stats_droits/$', views.stats_droits, name='stats-droits'),
] ]

View file

@ -453,27 +453,3 @@ def stats_actions(request):
}, },
} }
return render(request, 'logs/stats_users.html', {'stats_list': stats}) return render(request, 'logs/stats_users.html', {'stats_list': stats})
@login_required
@can_view_app('users')
def stats_droits(request):
"""Affiche la liste des droits et les users ayant chaque droit"""
stats_list = {}
for droit in ListRight.objects.all().select_related('group_ptr'):
stats_list[droit] = droit.user_set.all().annotate(
num=Count('revision'),
last=Max('revision__date_created'),
)
stats_list['Superuser'] = User.objects.filter(is_superuser=True).annotate(
num=Count('revision'),
last=Max('revision__date_created'),
)
return render(
request,
'logs/stats_droits.html',
{'stats_list': stats_list}
)

View file

@ -21,8 +21,10 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""Fonction de context, variables renvoyées à toutes les vues""" """Fonction de context, variables renvoyées à toutes les vues"""
from __future__ import unicode_literals from __future__ import unicode_literals
import datetime
from django.contrib import messages from django.contrib import messages
from preferences.models import GeneralOption, OptionalMachine from preferences.models import GeneralOption, OptionalMachine
@ -47,3 +49,12 @@ def context_user(request):
'name_website': GeneralOption.get_cached_value('site_name'), 'name_website': GeneralOption.get_cached_value('site_name'),
'ipv6_enabled': OptionalMachine.get_cached_value('ipv6'), 'ipv6_enabled': OptionalMachine.get_cached_value('ipv6'),
} }
def date_now(request):
"""Add the current date in the context for quick informations and
comparisons"""
return {
'now_aware': datetime.datetime.now(datetime.timezone.utc),
'now_naive': datetime.datetime.now()
}

View file

@ -125,6 +125,7 @@ TEMPLATES = [
'django.contrib.messages.context_processors.messages', 'django.contrib.messages.context_processors.messages',
'django.template.context_processors.request', 'django.template.context_processors.request',
're2o.context_processors.context_user', 're2o.context_processors.context_user',
're2o.context_processors.date_now',
], ],
}, },
}, },

View file

@ -108,3 +108,9 @@ footer a {
overflow-y: visible; overflow-y: visible;
} }
/* Make modal wider on wide screens */
@media (min-width: 1024px) {
.modal-dialog {
width: 1000px
}
}

Binary file not shown.

View file

@ -0,0 +1,123 @@
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
# se veut agnostique au réseau considéré, de manière à être installable en
# quelques clics.
#
# Copyright © 2018 Maël Kervella
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
msgid ""
msgstr ""
"Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-06-28 00:06+0200\n"
"PO-Revision-Date: 2018-06-27 23:35+0200\n"
"Last-Translator: Maël Kervella <dev@maelkervella.eu>\n"
"Language-Team: \n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: templates/users/aff_listright.html:37
msgid "Superuser"
msgstr "Superuser"
#: templates/users/aff_listright.html:39
msgid "Django's specific pre-defined right that supersed any other rights."
msgstr ""
"Droit prédéfini spécifique à Django qui outrepasse tous les autres droits."
#: templates/users/aff_listright.html:43
msgid "Total: All permissions"
msgstr "Total: Toutes les permissions"
#: templates/users/aff_listright.html:55
msgid "Users in Superuser"
msgstr "Utilisateurs dans Superuser"
#: templates/users/aff_listright.html:62 templates/users/aff_listright.html:167
msgid "Username"
msgstr "Pseudo"
#: templates/users/aff_listright.html:63 templates/users/aff_listright.html:168
msgid "Membership"
msgstr "Adhésion"
#: templates/users/aff_listright.html:64 templates/users/aff_listright.html:169
msgid "Last seen"
msgstr "Dernière connexion"
#: templates/users/aff_listright.html:65 templates/users/aff_listright.html:170
msgid "Actions"
msgstr "Actions"
#: templates/users/aff_listright.html:66 templates/users/aff_listright.html:171
msgid "Last action"
msgstr "Dernière action"
#: templates/users/aff_listright.html:74 templates/users/aff_listright.html:179
msgid "Member"
msgstr "Adhérent"
#: templates/users/aff_listright.html:76 templates/users/aff_listright.html:181
msgid "No membership records"
msgstr "Aucune adhésion"
#: templates/users/aff_listright.html:79 templates/users/aff_listright.html:184
#, python-format
msgid "Not since %(end_date)s"
msgstr "Plus depuis %(end_date)s"
#: templates/users/aff_listright.html:87 templates/users/aff_listright.html:192
msgid "Never"
msgstr "Jamais"
#: templates/users/aff_listright.html:122
#, python-format
msgid "%(right_name)s (gid: %(right_gid)s)"
msgstr "%(right_name)s (gid: %(right_gid)s)"
#: templates/users/aff_listright.html:131
#, python-format
msgid "Total: %(perm_count)s permission"
msgid_plural "Total: %(perm_count)s permissions"
msgstr[0] "Total: %(perm_count)s permission"
msgstr[1] "Total: %(perm_count)s permissions"
#: templates/users/aff_listright.html:157
#, python-format
msgid "Users in %(right_name)s"
msgstr "Utilisateurs dans %(right_name)s"
#: widgets.py:35
msgid "Close"
msgstr ""
#: widgets.py:36
msgid "Today"
msgstr ""
#: widgets.py:44
msgid "Next"
msgstr ""
#: widgets.py:45
msgid "Previous"
msgstr ""
#: widgets.py:46
msgid "Wk"
msgstr ""

View file

@ -22,85 +22,120 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %} {% endcomment %}
<table id="listRights_table" class="table"> {% load i18n %}
{% if superusers.count %}
<div class="panel panel-default">
<div class="panel-heading clearfix" data-toggle="collapse" data-target="#collapse_superuser">
<div class="pull-right">
<a type="button" class="btn btn-sm btn-default" data-toggle="modal" data-target="#modal_superuser">
{{superusers.count}} <i class="fa fa-user"></i>
</a>
</div>
<h4 class="text-danger">
<i class="fa fa-address-book"></i>
{% trans "Superuser" %}
</h4>
{% trans "Django's specific pre-defined right that supersed any other rights." %}
</div>
<div class="panel-collapse collapse" id="collapse_superuser">
<div class="panel-body">
<h4 class="text-danger">{% trans "Total: All permissions" %}</h4>
</div>
</div>
</div>
<div class="modal fade" id="modal_superuser" tabindex="-1" role="dialog" aria-labelledby="Users in Superuser">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<i class="fa fa-times"></i>
</button>
<h4 class="modal-title" id="myModalLabel">{% trans "Users in Superuser" %}</h4>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table table-striped">
<thead> <thead>
<tr> <tr>
<th>Droit</th> <th>{% trans "Username" %}</th>
<th>Gid</th> <th>{% trans "Membership" %}</th>
<th>Groupe/permission critique</th> <th>{% trans "Last seen" %}</th>
<th>Informations</th> <th>{% trans "Actions" %}</th>
<th>Details</th> <th>{% trans "Last action" %}</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
{% if superuser_right %} {% for user in superusers %}
<tr class="active">
<td>Superuser</td>
<td></td>
<td>True</td>
<td>
<button class="btn btn-default" data-parent="#accordion_superuser" type="button" data-toggle="collapse" data-target="#collapseListRight_user_superuser" aria-expanded="true" aria-controls="collapseListRight_user_superuser">
Utilisateurs ({{ superuser_right.count }})
</button>
</td>
<td>
Donne tous les droits sur Re2o.
</td>
<td class="text-right">
</td>
</tr>
<tr> <tr>
<td colspan=5> <td>{{ user.pseudo }}</td>
<div class="panel-group" id="accordion_superuser" role="tablist" aria-multiselectable="true" style="margin-bottom: 0px;"> {% if user.end_adhesion is not None and user.end_adhesion >= now_aware %}
<div class="panel" style="border: none;"> <td class="text-success">{% trans "Member" %}</td>
<div class="panel-collapse collapse in" id="collapseListRight_user_superuser" role="tabpanel"> {% elif not user.end_adhesion %}
<ul class="list-group" style="margin-bottom: 0px"> <td class="text-warning">{% trans "No membership records" %}</td>
{% for user in superuser_right %} {% else %}
<li class="list-group-item col-xs-12 col-sm-6 col-md-4" style="border:none;"> <td class="text-danger">
{{user}} {% blocktrans trimmed with user.end_adhesion as end_date %}
<a role="button" href="{% url 'users:del-superuser' user.pk %}" title="{{ desc|default:"Supprimer" }}"> Not since {{ end_date }}
<i class="fa fa-times" style="color:red"></i> {% endblocktrans %}
</a>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</td> </td>
</tr>
{% endif %} {% endif %}
{% for listright in listright_list %} <td>{{ user.last_login }}</td>
<tr class="active"> <td>{{ user.action_number }}</td>
{% if not user.last_seen %}
<td class="text-danger">{% trans "Never" %}</td>
{% else %}
<td class="text-success">{{ user.last_seen }}</td>
{% endif %}
<td> <td>
{{ listright.name }} <a class="btn btn-danger" role="button" href="{% url 'users:del-superuser' user.id %}">
</td> <span class="fa fa-user-times" aria-hidden="true"></span>
<td>{{ listright.gid }}</td> </a>
<td>{{ listright.critical }}</td>
<td>
<div class="dropdown">
<button class="btn btn-default" data-parent="#accordion_{{listright.gid}}" type="button" data-toggle="collapse" data-target="#collapseListRight_user_{{listright.gid}}" aria-expanded="true" aria-controls="collapseListRight_user_{{listright.gid}}">
Utilisateurs ({{ listright.user_set.all|length }})
</button>
<button class="btn btn-default" data-parent="#accordion_{{listright.gid}}" type="button" data-toggle="collapse" data-target="#collapseListRight_perm_{{listright.gid}}" aria-expanded="true" aria-controls="collapseListRight_perm_{{listright.gid}}">
Ensemble des permissions ({{ listright.permissions.all|length }})
</button>
</div>
</td>
<td>{{ listright.details }}</td>
<td class="text-right">
{% include 'buttons/edit.html' with href='users:edit-listright' id=listright.id %}
{% include 'buttons/history.html' with href='users:history' name='listright' id=listright.id %}
</td> </td>
</tr> </tr>
<tr> {% endfor %}
<td colspan=5> </table>
<div class="panel-group" id="accordion_{{listright.gid}}" role="tablist" aria-multiselectable="true" style="margin-bottom: 0px;"> </div>
<div class="panel" style="border: none;"> </div>
<div class="panel-collapse collapse in" id="collapseListRight_perm_{{listright.gid}}" role="tabpanel"> </div>
</div>
</div>
{% endif %}
{% for right, users in rights.items %}
<div class="panel panel-default">
<div class="panel-heading clearfix" data-toggle="collapse" data-target="#collapse_{{right.id}}">
<div class="pull-right">
{% if users %}
<a type="button" class="btn btn-sm btn-default" data-toggle="modal" data-target="#modal_{{right.id}}">
{% else %}
<a type="button" class="btn btn-sm btn-default" disabled="disabled">
{% endif %}
{{users.count}} <i class="fa fa-user"></i>
</a>
{% include 'buttons/edit.html' with href='users:edit-listright' id=right.id %}
{% include 'buttons/history.html' with href='users:history' name='listright' id=right.id %}
</div>
<h4 class="{% if right.critical %}text-danger{% endif %}">
<i class="fa fa-address-book"></i>
{% blocktrans trimmed with right.name as right_name and right.gid as right_gid %}
{{ right_name }} (gid: {{ right_gid }})
{% endblocktrans %}
</h4>
{{ right.details }}
</div>
<div class="panel-collapse collapse" id="collapse_{{right.id}}">
<div class="panel-body">
<h4>
{% blocktrans trimmed count right.permissions.count as perm_count%}
Total: {{ perm_count }} permission
{% plural %}
Total: {{ perm_count }} permissions
{% endblocktrans %}
</h4>
<ul class="list-group" style="margin-bottom: 0px"> <ul class="list-group" style="margin-bottom: 0px">
{% for perm in listright.permissions.all %} {% for perm in right.permissions.all %}
<li class="list-group-item col-xs-6 col-sm-4 col-md-3" style="border:none;"> <li class="list-group-item col-xs-6 col-sm-4 col-md-3" style="border:none;">
{{perm.name}} {{perm.name}}
</li> </li>
@ -108,32 +143,68 @@ with this program; if not, write to the Free Software Foundation, Inc.,
</ul> </ul>
</div> </div>
</div> </div>
<div class="panel" style="border: none;"> </div>
<div class="panel-collapse collapse in" id="collapseListRight_user_{{listright.gid}}" role="tabpanel">
<ul class="list-group" style="margin-bottom: 0px"> {% if users %}
{% for user in listright.user_set.all %} <div class="modal fade" id="modal_{{right.id}}" tabindex="-1" role="dialog" aria-labelledby="Users">
<li class="list-group-item col-xs-12 col-sm-6 col-md-4" style="border:none;"> <div class="modal-dialog" role="document">
{{user}} <div class="modal-content">
<a role="button" href="{% url 'users:del-group' user.id listright.id %}" title="{{ desc|default:"Supprimer" }}"> <div class="modal-header">
<i class="fa fa-times" style="color:red"></i> <button type="button" class="close" data-dismiss="modal" aria-label="Close">
<i class="fa fa-times"></i>
</button>
<h4 class="modal-title" id="myModalLabel">
{% blocktrans trimmed with right.name as right_name %}
Users in {{ right_name }}
{% endblocktrans %}
</h4>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>{% trans "Username" %}</th>
<th>{% trans "Membership" %}</th>
<th>{% trans "Last seen" %}</th>
<th>{% trans "Actions" %}</th>
<th>{% trans "Last action" %}</th>
<th></th>
</tr>
</thead>
{% for user in users %}
<tr>
<td>{{ user.pseudo }}</td>
{% if user.end_adhesion is not None and user.end_adhesion >= now_aware %}
<td class="text-success">{% trans "Member" %}</td>
{% elif not user.end_adhesion %}
<td class="text-warning">{% trans "No membership records" %}</td>
{% else %}
<td class="text-danger">
{% blocktrans trimmed with user.end_adhesion as end_date %}
Not since {{ end_date }}
{% endblocktrans %}
</td>
{% endif %}
<td>{{ user.last_login }}</td>
<td>{{ user.action_number }}</td>
{% if not user.last_seen %}
<td class="text-danger">{% trans "Never" %}</td>
{% else %}
<td class="text-success">{{user.last_seen}}</td>
{% endif %}
<td>
<a class="btn btn-danger" role="button" href="{% url 'users:del-group' user.id right.id %}">
<span class="fa fa-user-times" aria-hidden="true"></span>
</a> </a>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
</div>
<script> </div>
$("#listRights_table").ready( function () { </div>
var listRights_div = [{% for listright in listright_list %}[$("#accordion_{{listright.gid}}"), $("#collapseListRight_user_{{listright.gid}}"), $("#collapseListRight_perm_{{listright.gid}}")], {% endfor %}]; </div>
for (var i=0 ; i<listRights_div.length ; i++) { </div>
listRights_div[i][1].collapse({ toggle: true, parent: listRights_div[i][0] }); {% endif %}
listRights_div[i][2].collapse({ toggle: true, parent: listRights_div[i][0] }); {% endfor %}
}
} );
</script>

View file

@ -34,9 +34,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:add-listright' %}"><i class="fa fa-plus"></i> Ajouter un droit ou groupe</a> <a class="btn btn-primary btn-sm" role="button" href="{% url 'users:add-listright' %}"><i class="fa fa-plus"></i> Ajouter un droit ou groupe</a>
{% acl_end %} {% acl_end %}
<a class="btn btn-danger btn-sm" role="button" href="{% url 'users:del-listright' %}"><i class="fa fa-trash"></i> Supprimer un ou plusieurs droits/groupes</a> <a class="btn btn-danger btn-sm" role="button" href="{% url 'users:del-listright' %}"><i class="fa fa-trash"></i> Supprimer un ou plusieurs droits/groupes</a>
{% include "users/aff_listright.html" with listright_list=listright_list %}
<br />
<br /> <br />
<br /> <br />
{% include "users/aff_listright.html" %}
{% endblock %} {% endblock %}

View file

@ -39,7 +39,7 @@ from django.urls import reverse
from django.shortcuts import get_object_or_404, render, redirect from django.shortcuts import get_object_or_404, render, redirect
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.db.models import ProtectedError from django.db.models import ProtectedError, Count, Max
from django.utils import timezone from django.utils import timezone
from django.db import transaction from django.db import transaction
from django.http import HttpResponse from django.http import HttpResponse
@ -806,15 +806,30 @@ def index_shell(request):
@can_view_all(ListRight) @can_view_all(ListRight)
def index_listright(request): def index_listright(request):
""" Affiche l'ensemble des droits""" """ Affiche l'ensemble des droits"""
listright_list = ListRight.objects.order_by('unix_name')\ rights = {}
.prefetch_related('permissions').prefetch_related('user_set') for right in (ListRight.objects
superuser_right = User.objects.filter(is_superuser=True) .order_by('name')
.prefetch_related('permissions')
.prefetch_related('user_set')
.prefetch_related('user_set__facture_set__vente_set__cotisation')
):
rights[right] = (right.user_set
.annotate(action_number=Count('revision'),
last_seen=Max('revision__date_created'),
end_adhesion=Max('facture__vente__cotisation__date_end'))
)
superusers = (User.objects
.filter(is_superuser=True)
.annotate(action_number=Count('revision'),
last_seen=Max('revision__date_created'),
end_adhesion=Max('facture__vente__cotisation__date_end'))
)
return render( return render(
request, request,
'users/index_listright.html', 'users/index_listright.html',
{ {
'listright_list': listright_list, 'rights': rights,
'superuser_right' : superuser_right, 'superusers' : superusers,
} }
) )