From 24ac3ce45f51cc890678f6c855ef61f2baf76784 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <yohann.danello@gmail.com>
Date: Wed, 5 Aug 2020 21:07:31 +0200
Subject: [PATCH] Display users that have surnormal roles

---
 apps/permission/tables.py            |  51 ++++++++++
 apps/permission/views.py             |  15 +++
 locale/de/LC_MESSAGES/django.po      | 142 ++++++++++++++-------------
 locale/fr/LC_MESSAGES/django.po      | 142 ++++++++++++++-------------
 templates/permission/all_rights.html |  10 ++
 5 files changed, 226 insertions(+), 134 deletions(-)
 create mode 100644 apps/permission/tables.py

diff --git a/apps/permission/tables.py b/apps/permission/tables.py
new file mode 100644
index 00000000..7a07bd6a
--- /dev/null
+++ b/apps/permission/tables.py
@@ -0,0 +1,51 @@
+# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+import django_tables2 as tables
+from django.urls import reverse_lazy
+from django.utils.html import format_html
+
+from member.models import Membership
+from note_kfet.middlewares import get_current_authenticated_user
+from permission.backends import PermissionBackend
+
+
+class RightsTable(tables.Table):
+    """
+    List managers of a club.
+    """
+
+    def render_user(self, value):
+        # If the user has the right, link the displayed user with the page of its detail.
+        s = value.username
+        if PermissionBackend.check_perm(get_current_authenticated_user(), "auth.view_user", value):
+            s = format_html("<a href={url}>{name}</a>",
+                            url=reverse_lazy('member:user_detail', kwargs={"pk": value.pk}), name=s)
+        return s
+
+    def render_club(self, value):
+        # If the user has the right, link the displayed user with the page of its detail.
+        s = value.name
+        if PermissionBackend.check_perm(get_current_authenticated_user(), "member.view_club", value):
+            s = format_html("<a href={url}>{name}</a>",
+                            url=reverse_lazy('member:club_detail', kwargs={"pk": value.pk}), name=s)
+
+        return s
+
+    def render_roles(self, record):
+        # If the user has the right to manage the roles, display the link to manage them
+        roles = record.roles.all()
+        s = ", ".join(str(role) for role in roles)
+        if PermissionBackend.check_perm(get_current_authenticated_user(), "member.change_membership_roles", record):
+            s = format_html("<a href='" + str(reverse_lazy("member:club_manage_roles", kwargs={"pk": record.pk}))
+                            + "'>" + s + "</a>")
+        return s
+
+    class Meta:
+        attrs = {
+            'class': 'table table-condensed table-striped table-hover',
+            'style': 'table-layout: fixed;'
+        }
+        template_name = 'django_tables2/bootstrap4.html'
+        fields = ('user.last_name', 'user.first_name', 'user', 'club', 'roles', )
+        model = Membership
diff --git a/apps/permission/views.py b/apps/permission/views.py
index 9132e5f0..113f0443 100644
--- a/apps/permission/views.py
+++ b/apps/permission/views.py
@@ -2,13 +2,16 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 from datetime import date
 
+from django.db.models import Q
 from django.forms import HiddenInput
+from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 from django.views.generic import UpdateView, TemplateView
 from member.models import Membership
 
 from .backends import PermissionBackend
 from .models import Role
+from .tables import RightsTable
 
 
 class ProtectQuerysetMixin:
@@ -59,4 +62,16 @@ class RightsView(TemplateView):
         for role in roles:
             role.clubs = [membership.club for membership in active_memberships if role in membership.roles.all()]
 
+        if self.request.user.is_authenticated:
+            special_memberships = Membership.objects.filter(
+                date_start__lte=timezone.now().date(),
+                date_end__gte=timezone.now().date(),
+            ).filter(roles__in=Role.objects.filter(~(Q(name="Adhérent BDE")
+                                                     | Q(name="Adhérent Kfet")
+                                                     | Q(name="Membre de club")
+                                                     | Q(name="Adhérent WEI")
+                                                     | Q(name="1A")))).order_by("club", "user__last_name")\
+                .distinct().all()
+            context["special_memberships_table"] = RightsTable(special_memberships)
+
         return context
diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index 80397341..57663f94 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-05 16:49+0200\n"
+"POT-Creation-Date: 2020-08-05 21:06+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -46,7 +46,7 @@ msgstr ""
 #: apps/activity/models.py:24 apps/activity/models.py:49
 #: apps/member/models.py:162 apps/note/models/notes.py:212
 #: apps/note/models/transactions.py:25 apps/note/models/transactions.py:45
-#: apps/note/models/transactions.py:284 apps/permission/models.py:339
+#: apps/note/models/transactions.py:298 apps/permission/models.py:332
 #: apps/wei/models.py:67 apps/wei/models.py:119
 #: templates/member/club_info.html:13 templates/member/profile_info.html:14
 #: templates/registration/future_profile_detail.html:16
@@ -71,14 +71,14 @@ msgid "activity types"
 msgstr ""
 
 #: apps/activity/models.py:54 apps/note/models/transactions.py:81
-#: apps/permission/models.py:120 apps/permission/models.py:199
+#: apps/permission/models.py:113 apps/permission/models.py:192
 #: apps/wei/models.py:73 apps/wei/models.py:130
 #: templates/activity/activity_detail.html:16
 msgid "description"
 msgstr ""
 
 #: apps/activity/models.py:61 apps/note/models/notes.py:188
-#: apps/note/models/transactions.py:66 apps/permission/models.py:174
+#: apps/note/models/transactions.py:66 apps/permission/models.py:167
 #: templates/activity/activity_detail.html:19
 msgid "type"
 msgstr ""
@@ -187,13 +187,13 @@ msgid "Type"
 msgstr ""
 
 #: apps/activity/tables.py:77 apps/member/forms.py:103
-#: apps/registration/forms.py:70 apps/treasury/forms.py:126
+#: apps/registration/forms.py:70 apps/treasury/forms.py:130
 #: apps/wei/forms/registration.py:95
 msgid "Last name"
 msgstr ""
 
 #: apps/activity/tables.py:79 apps/member/forms.py:108
-#: apps/registration/forms.py:75 apps/treasury/forms.py:128
+#: apps/registration/forms.py:75 apps/treasury/forms.py:132
 #: apps/wei/forms/registration.py:100 templates/note/transaction_form.html:129
 msgid "First name"
 msgstr ""
@@ -242,7 +242,7 @@ msgstr ""
 msgid "IP Address"
 msgstr ""
 
-#: apps/logs/models.py:36 apps/permission/models.py:144
+#: apps/logs/models.py:36 apps/permission/models.py:137
 msgid "model"
 msgstr ""
 
@@ -268,7 +268,7 @@ msgid "edit"
 msgstr ""
 
 #: apps/logs/models.py:63 apps/note/tables.py:137 apps/note/tables.py:165
-#: apps/permission/models.py:137 apps/wei/tables.py:73
+#: apps/permission/models.py:130 apps/wei/tables.py:73
 msgid "delete"
 msgstr ""
 
@@ -347,7 +347,7 @@ msgid "Credit amount"
 msgstr ""
 
 #: apps/member/forms.py:113 apps/registration/forms.py:80
-#: apps/treasury/forms.py:130 apps/wei/forms/registration.py:105
+#: apps/treasury/forms.py:134 apps/wei/forms/registration.py:105
 #: templates/note/transaction_form.html:135
 msgid "Bank"
 msgstr ""
@@ -871,68 +871,68 @@ msgid ""
 "The note balances must be between - 21 474 836.47 € and 21 474 836.47 €."
 msgstr ""
 
-#: apps/note/models/transactions.py:208
+#: apps/note/models/transactions.py:214
 msgid ""
 "The transaction can't be saved since the source note or the destination note "
 "is not active."
 msgstr ""
 
-#: apps/note/models/transactions.py:246
+#: apps/note/models/transactions.py:260
 #: templates/activity/activity_entry.html:13 templates/base.html:99
 #: templates/note/transaction_form.html:15
 #: templates/note/transaction_form.html:143
 msgid "Transfer"
 msgstr ""
 
-#: apps/note/models/transactions.py:270
+#: apps/note/models/transactions.py:284
 msgid "Template"
 msgstr ""
 
-#: apps/note/models/transactions.py:273
+#: apps/note/models/transactions.py:287
 msgid "recurrent transaction"
 msgstr ""
 
-#: apps/note/models/transactions.py:274
+#: apps/note/models/transactions.py:288
 msgid "recurrent transactions"
 msgstr ""
 
-#: apps/note/models/transactions.py:289
+#: apps/note/models/transactions.py:303
 msgid "first_name"
 msgstr ""
 
-#: apps/note/models/transactions.py:294
+#: apps/note/models/transactions.py:308
 msgid "bank"
 msgstr ""
 
-#: apps/note/models/transactions.py:300
+#: apps/note/models/transactions.py:314
 #: templates/activity/activity_entry.html:17
 #: templates/note/transaction_form.html:20
 msgid "Credit"
 msgstr ""
 
-#: apps/note/models/transactions.py:300 templates/note/transaction_form.html:24
+#: apps/note/models/transactions.py:314 templates/note/transaction_form.html:24
 msgid "Debit"
 msgstr ""
 
-#: apps/note/models/transactions.py:311
+#: apps/note/models/transactions.py:325
 msgid ""
 "A special transaction is only possible between a Note associated to a "
 "payment method and a User or a Club"
 msgstr ""
 
-#: apps/note/models/transactions.py:315
+#: apps/note/models/transactions.py:329
 msgid "Special transaction"
 msgstr ""
 
-#: apps/note/models/transactions.py:316
+#: apps/note/models/transactions.py:330
 msgid "Special transactions"
 msgstr ""
 
-#: apps/note/models/transactions.py:332 apps/note/models/transactions.py:337
+#: apps/note/models/transactions.py:346 apps/note/models/transactions.py:351
 msgid "membership transaction"
 msgstr ""
 
-#: apps/note/models/transactions.py:333 apps/treasury/models.py:228
+#: apps/note/models/transactions.py:347 apps/treasury/models.py:228
 msgid "membership transactions"
 msgstr ""
 
@@ -955,7 +955,7 @@ msgid "Delete"
 msgstr ""
 
 #: apps/note/tables.py:162 apps/wei/tables.py:46 apps/wei/tables.py:47
-#: templates/member/club_info.html:67 templates/note/conso_form.html:128
+#: templates/member/club_info.html:67 templates/note/conso_form.html:130
 #: templates/wei/bus_tables.html:15 templates/wei/busteam_tables.html:15
 #: templates/wei/busteam_tables.html:33 templates/wei/weiclub_info.html:68
 msgid "Edit"
@@ -985,79 +985,79 @@ msgstr ""
 msgid "Search transactions"
 msgstr ""
 
-#: apps/permission/models.py:99
+#: apps/permission/models.py:92
 #, python-brace-format
 msgid "Can {type} {model}.{field} in {query}"
 msgstr ""
 
-#: apps/permission/models.py:101
+#: apps/permission/models.py:94
 #, python-brace-format
 msgid "Can {type} {model} in {query}"
 msgstr ""
 
-#: apps/permission/models.py:114
+#: apps/permission/models.py:107
 msgid "rank"
 msgstr ""
 
-#: apps/permission/models.py:127
+#: apps/permission/models.py:120
 msgid "permission mask"
 msgstr ""
 
-#: apps/permission/models.py:128
+#: apps/permission/models.py:121
 msgid "permission masks"
 msgstr ""
 
-#: apps/permission/models.py:134
+#: apps/permission/models.py:127
 msgid "add"
 msgstr ""
 
-#: apps/permission/models.py:135
+#: apps/permission/models.py:128
 msgid "view"
 msgstr ""
 
-#: apps/permission/models.py:136
+#: apps/permission/models.py:129
 msgid "change"
 msgstr ""
 
-#: apps/permission/models.py:168
+#: apps/permission/models.py:161
 msgid "query"
 msgstr ""
 
-#: apps/permission/models.py:181
+#: apps/permission/models.py:174
 msgid "mask"
 msgstr ""
 
-#: apps/permission/models.py:187
+#: apps/permission/models.py:180
 msgid "field"
 msgstr ""
 
-#: apps/permission/models.py:192
+#: apps/permission/models.py:185
 msgid ""
 "Tells if the permission should be granted even if the membership of the user "
 "is expired."
 msgstr ""
 
-#: apps/permission/models.py:193 templates/permission/all_rights.html:26
+#: apps/permission/models.py:186 templates/permission/all_rights.html:36
 msgid "permanent"
 msgstr ""
 
-#: apps/permission/models.py:204
+#: apps/permission/models.py:197
 msgid "permission"
 msgstr ""
 
-#: apps/permission/models.py:205 apps/permission/models.py:344
+#: apps/permission/models.py:198 apps/permission/models.py:337
 msgid "permissions"
 msgstr ""
 
-#: apps/permission/models.py:210
+#: apps/permission/models.py:203
 msgid "Specifying field applies only to view and change permission types."
 msgstr ""
 
-#: apps/permission/models.py:349
+#: apps/permission/models.py:342
 msgid "for club"
 msgstr ""
 
-#: apps/permission/models.py:359 apps/permission/models.py:360
+#: apps/permission/models.py:352 apps/permission/models.py:353
 msgid "role permissions"
 msgstr ""
 
@@ -1082,11 +1082,11 @@ msgid ""
 "{model_name}."
 msgstr ""
 
-#: apps/permission/views.py:44 templates/base.html:129
+#: apps/permission/views.py:47 templates/base.html:129
 msgid "Rights"
 msgstr ""
 
-#: apps/permission/views.py:49
+#: apps/permission/views.py:52
 msgid "All rights"
 msgstr ""
 
@@ -1169,7 +1169,7 @@ msgstr ""
 msgid "Treasury"
 msgstr ""
 
-#: apps/treasury/forms.py:84 apps/treasury/forms.py:138
+#: apps/treasury/forms.py:88 apps/treasury/forms.py:142
 #: templates/activity/activity_form.html:9
 #: templates/activity/activity_invite.html:8
 #: templates/django_filters/rest_framework/form.html:5
@@ -1181,19 +1181,19 @@ msgstr ""
 msgid "Submit"
 msgstr ""
 
-#: apps/treasury/forms.py:86
+#: apps/treasury/forms.py:90
 msgid "Close"
 msgstr ""
 
-#: apps/treasury/forms.py:95
+#: apps/treasury/forms.py:99
 msgid "Remittance is already closed."
 msgstr ""
 
-#: apps/treasury/forms.py:100
+#: apps/treasury/forms.py:104
 msgid "You can't change the type of the remittance."
 msgstr ""
 
-#: apps/treasury/forms.py:120 apps/treasury/models.py:207
+#: apps/treasury/forms.py:124 apps/treasury/models.py:207
 #: apps/treasury/tables.py:77 apps/treasury/tables.py:85
 #: templates/treasury/invoice_list.html:13
 #: templates/treasury/remittance_list.html:13
@@ -1201,11 +1201,11 @@ msgstr ""
 msgid "Remittance"
 msgstr ""
 
-#: apps/treasury/forms.py:121
+#: apps/treasury/forms.py:125
 msgid "No attached remittance"
 msgstr ""
 
-#: apps/treasury/forms.py:132 apps/treasury/tables.py:47
+#: apps/treasury/forms.py:136 apps/treasury/tables.py:47
 #: apps/treasury/tables.py:115 templates/note/transaction_form.html:97
 #: templates/treasury/remittance_form.html:18
 msgid "Amount"
@@ -1388,15 +1388,15 @@ msgstr ""
 msgid "Update a remittance"
 msgstr ""
 
-#: apps/treasury/views.py:301
+#: apps/treasury/views.py:299
 msgid "Attach a transaction to a remittance"
 msgstr ""
 
-#: apps/treasury/views.py:345
+#: apps/treasury/views.py:343
 msgid "List of credits from the Société générale"
 msgstr ""
 
-#: apps/treasury/views.py:379
+#: apps/treasury/views.py:377
 msgid "Manage credits from the Société générale"
 msgstr ""
 
@@ -2023,36 +2023,36 @@ msgstr ""
 msgid "Registrations"
 msgstr ""
 
-#: templates/note/conso_form.html:28
+#: templates/note/conso_form.html:30
 msgid "Consum"
 msgstr ""
 
-#: templates/note/conso_form.html:39 templates/note/transaction_form.html:57
+#: templates/note/conso_form.html:41 templates/note/transaction_form.html:57
 #: templates/note/transaction_form.html:78
 msgid "Name or alias..."
 msgstr ""
 
-#: templates/note/conso_form.html:48
+#: templates/note/conso_form.html:50
 msgid "Select consumptions"
 msgstr ""
 
-#: templates/note/conso_form.html:57
+#: templates/note/conso_form.html:59
 msgid "Consume!"
 msgstr ""
 
-#: templates/note/conso_form.html:71
+#: templates/note/conso_form.html:73
 msgid "Highlighted buttons"
 msgstr ""
 
-#: templates/note/conso_form.html:134
+#: templates/note/conso_form.html:136
 msgid "Single consumptions"
 msgstr ""
 
-#: templates/note/conso_form.html:139
+#: templates/note/conso_form.html:141
 msgid "Double consumptions"
 msgstr ""
 
-#: templates/note/conso_form.html:150 templates/note/transaction_form.html:154
+#: templates/note/conso_form.html:152 templates/note/transaction_form.html:154
 msgid "Recent transactions history"
 msgstr ""
 
@@ -2112,23 +2112,31 @@ msgstr ""
 msgid "Unable to delete button "
 msgstr ""
 
-#: templates/permission/all_rights.html:10
+#: templates/permission/all_rights.html:8
+msgid "Users that have surnormal rights"
+msgstr ""
+
+#: templates/permission/all_rights.html:14
+msgid "Roles description"
+msgstr ""
+
+#: templates/permission/all_rights.html:19
 msgid "Filter with roles that I have in at least one club"
 msgstr ""
 
-#: templates/permission/all_rights.html:21
+#: templates/permission/all_rights.html:31
 msgid "Own this role in the clubs"
 msgstr ""
 
-#: templates/permission/all_rights.html:26
+#: templates/permission/all_rights.html:36
 msgid "Mask:"
 msgstr ""
 
-#: templates/permission/all_rights.html:26
+#: templates/permission/all_rights.html:36
 msgid "Query:"
 msgstr ""
 
-#: templates/permission/all_rights.html:28
+#: templates/permission/all_rights.html:38
 msgid "No associated permission"
 msgstr ""
 
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index b87eaa1d..ac678a93 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-05 16:49+0200\n"
+"POT-Creation-Date: 2020-08-05 21:06+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -47,7 +47,7 @@ msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité."
 #: apps/activity/models.py:24 apps/activity/models.py:49
 #: apps/member/models.py:162 apps/note/models/notes.py:212
 #: apps/note/models/transactions.py:25 apps/note/models/transactions.py:45
-#: apps/note/models/transactions.py:284 apps/permission/models.py:339
+#: apps/note/models/transactions.py:298 apps/permission/models.py:332
 #: apps/wei/models.py:67 apps/wei/models.py:119
 #: templates/member/club_info.html:13 templates/member/profile_info.html:14
 #: templates/registration/future_profile_detail.html:16
@@ -72,14 +72,14 @@ msgid "activity types"
 msgstr "types d'activité"
 
 #: apps/activity/models.py:54 apps/note/models/transactions.py:81
-#: apps/permission/models.py:120 apps/permission/models.py:199
+#: apps/permission/models.py:113 apps/permission/models.py:192
 #: apps/wei/models.py:73 apps/wei/models.py:130
 #: templates/activity/activity_detail.html:16
 msgid "description"
 msgstr "description"
 
 #: apps/activity/models.py:61 apps/note/models/notes.py:188
-#: apps/note/models/transactions.py:66 apps/permission/models.py:174
+#: apps/note/models/transactions.py:66 apps/permission/models.py:167
 #: templates/activity/activity_detail.html:19
 msgid "type"
 msgstr "type"
@@ -188,13 +188,13 @@ msgid "Type"
 msgstr "Type"
 
 #: apps/activity/tables.py:77 apps/member/forms.py:103
-#: apps/registration/forms.py:70 apps/treasury/forms.py:126
+#: apps/registration/forms.py:70 apps/treasury/forms.py:130
 #: apps/wei/forms/registration.py:95
 msgid "Last name"
 msgstr "Nom de famille"
 
 #: apps/activity/tables.py:79 apps/member/forms.py:108
-#: apps/registration/forms.py:75 apps/treasury/forms.py:128
+#: apps/registration/forms.py:75 apps/treasury/forms.py:132
 #: apps/wei/forms/registration.py:100 templates/note/transaction_form.html:129
 msgid "First name"
 msgstr "Prénom"
@@ -243,7 +243,7 @@ msgstr "Logs"
 msgid "IP Address"
 msgstr "Adresse IP"
 
-#: apps/logs/models.py:36 apps/permission/models.py:144
+#: apps/logs/models.py:36 apps/permission/models.py:137
 msgid "model"
 msgstr "Modèle"
 
@@ -269,7 +269,7 @@ msgid "edit"
 msgstr "Modifier"
 
 #: apps/logs/models.py:63 apps/note/tables.py:137 apps/note/tables.py:165
-#: apps/permission/models.py:137 apps/wei/tables.py:73
+#: apps/permission/models.py:130 apps/wei/tables.py:73
 msgid "delete"
 msgstr "Supprimer"
 
@@ -348,7 +348,7 @@ msgid "Credit amount"
 msgstr "Montant à créditer"
 
 #: apps/member/forms.py:113 apps/registration/forms.py:80
-#: apps/treasury/forms.py:130 apps/wei/forms/registration.py:105
+#: apps/treasury/forms.py:134 apps/wei/forms/registration.py:105
 #: templates/note/transaction_form.html:135
 msgid "Bank"
 msgstr "Banque"
@@ -881,7 +881,7 @@ msgstr ""
 "Les montants des notes doivent se trouver entre - 21 474 836.47 € et 21 474 "
 "836.47 €. Ne cherchez pas à capitaliser l'argent du BDE."
 
-#: apps/note/models/transactions.py:208
+#: apps/note/models/transactions.py:214
 msgid ""
 "The transaction can't be saved since the source note or the destination note "
 "is not active."
@@ -889,44 +889,44 @@ msgstr ""
 "La transaction ne peut pas être sauvegardée puisque la note source ou la "
 "note de destination n'est pas active."
 
-#: apps/note/models/transactions.py:246
+#: apps/note/models/transactions.py:260
 #: templates/activity/activity_entry.html:13 templates/base.html:99
 #: templates/note/transaction_form.html:15
 #: templates/note/transaction_form.html:143
 msgid "Transfer"
 msgstr "Virement"
 
-#: apps/note/models/transactions.py:270
+#: apps/note/models/transactions.py:284
 msgid "Template"
 msgstr "Bouton"
 
-#: apps/note/models/transactions.py:273
+#: apps/note/models/transactions.py:287
 msgid "recurrent transaction"
 msgstr "Transaction issue de bouton"
 
-#: apps/note/models/transactions.py:274
+#: apps/note/models/transactions.py:288
 msgid "recurrent transactions"
 msgstr "Transactions issues de boutons"
 
-#: apps/note/models/transactions.py:289
+#: apps/note/models/transactions.py:303
 msgid "first_name"
 msgstr "prénom"
 
-#: apps/note/models/transactions.py:294
+#: apps/note/models/transactions.py:308
 msgid "bank"
 msgstr "banque"
 
-#: apps/note/models/transactions.py:300
+#: apps/note/models/transactions.py:314
 #: templates/activity/activity_entry.html:17
 #: templates/note/transaction_form.html:20
 msgid "Credit"
 msgstr "Crédit"
 
-#: apps/note/models/transactions.py:300 templates/note/transaction_form.html:24
+#: apps/note/models/transactions.py:314 templates/note/transaction_form.html:24
 msgid "Debit"
 msgstr "Débit"
 
-#: apps/note/models/transactions.py:311
+#: apps/note/models/transactions.py:325
 msgid ""
 "A special transaction is only possible between a Note associated to a "
 "payment method and a User or a Club"
@@ -934,19 +934,19 @@ msgstr ""
 "Une transaction spéciale n'est possible que entre une note associée à un "
 "mode de paiement et un utilisateur ou un club."
 
-#: apps/note/models/transactions.py:315
+#: apps/note/models/transactions.py:329
 msgid "Special transaction"
 msgstr "Transaction de crédit/retrait"
 
-#: apps/note/models/transactions.py:316
+#: apps/note/models/transactions.py:330
 msgid "Special transactions"
 msgstr "Transactions de crédit/retrait"
 
-#: apps/note/models/transactions.py:332 apps/note/models/transactions.py:337
+#: apps/note/models/transactions.py:346 apps/note/models/transactions.py:351
 msgid "membership transaction"
 msgstr "Transaction d'adhésion"
 
-#: apps/note/models/transactions.py:333 apps/treasury/models.py:228
+#: apps/note/models/transactions.py:347 apps/treasury/models.py:228
 msgid "membership transactions"
 msgstr "Transactions d'adhésion"
 
@@ -969,7 +969,7 @@ msgid "Delete"
 msgstr "Supprimer"
 
 #: apps/note/tables.py:162 apps/wei/tables.py:46 apps/wei/tables.py:47
-#: templates/member/club_info.html:67 templates/note/conso_form.html:128
+#: templates/member/club_info.html:67 templates/note/conso_form.html:130
 #: templates/wei/bus_tables.html:15 templates/wei/busteam_tables.html:15
 #: templates/wei/busteam_tables.html:33 templates/wei/weiclub_info.html:68
 msgid "Edit"
@@ -999,53 +999,53 @@ msgstr "Consommations"
 msgid "Search transactions"
 msgstr "Rechercher des transactions"
 
-#: apps/permission/models.py:99
+#: apps/permission/models.py:92
 #, python-brace-format
 msgid "Can {type} {model}.{field} in {query}"
 msgstr "Can {type} {model}.{field} in {query}"
 
-#: apps/permission/models.py:101
+#: apps/permission/models.py:94
 #, python-brace-format
 msgid "Can {type} {model} in {query}"
 msgstr "Can {type} {model} in {query}"
 
-#: apps/permission/models.py:114
+#: apps/permission/models.py:107
 msgid "rank"
 msgstr "Rang"
 
-#: apps/permission/models.py:127
+#: apps/permission/models.py:120
 msgid "permission mask"
 msgstr "masque de permissions"
 
-#: apps/permission/models.py:128
+#: apps/permission/models.py:121
 msgid "permission masks"
 msgstr "masques de permissions"
 
-#: apps/permission/models.py:134
+#: apps/permission/models.py:127
 msgid "add"
 msgstr "ajouter"
 
-#: apps/permission/models.py:135
+#: apps/permission/models.py:128
 msgid "view"
 msgstr "voir"
 
-#: apps/permission/models.py:136
+#: apps/permission/models.py:129
 msgid "change"
 msgstr "modifier"
 
-#: apps/permission/models.py:168
+#: apps/permission/models.py:161
 msgid "query"
 msgstr "requête"
 
-#: apps/permission/models.py:181
+#: apps/permission/models.py:174
 msgid "mask"
 msgstr "masque"
 
-#: apps/permission/models.py:187
+#: apps/permission/models.py:180
 msgid "field"
 msgstr "champ"
 
-#: apps/permission/models.py:192
+#: apps/permission/models.py:185
 msgid ""
 "Tells if the permission should be granted even if the membership of the user "
 "is expired."
@@ -1053,29 +1053,29 @@ msgstr ""
 "Indique si la permission doit être attribuée même si l'adhésion de "
 "l'utilisateur est expirée."
 
-#: apps/permission/models.py:193 templates/permission/all_rights.html:26
+#: apps/permission/models.py:186 templates/permission/all_rights.html:36
 msgid "permanent"
 msgstr "permanent"
 
-#: apps/permission/models.py:204
+#: apps/permission/models.py:197
 msgid "permission"
 msgstr "permission"
 
-#: apps/permission/models.py:205 apps/permission/models.py:344
+#: apps/permission/models.py:198 apps/permission/models.py:337
 msgid "permissions"
 msgstr "permissions"
 
-#: apps/permission/models.py:210
+#: apps/permission/models.py:203
 msgid "Specifying field applies only to view and change permission types."
 msgstr ""
 "Spécifie le champ concerné, ne fonctionne que pour les permissions view et "
 "change."
 
-#: apps/permission/models.py:349
+#: apps/permission/models.py:342
 msgid "for club"
 msgstr "s'applique au club"
 
-#: apps/permission/models.py:359 apps/permission/models.py:360
+#: apps/permission/models.py:352 apps/permission/models.py:353
 msgid "role permissions"
 msgstr "Permissions par rôles"
 
@@ -1106,11 +1106,11 @@ msgstr ""
 "Vous n'avez pas la permission de supprimer cette instance du modèle "
 "{app_label}.{model_name}."
 
-#: apps/permission/views.py:44 templates/base.html:129
+#: apps/permission/views.py:47 templates/base.html:129
 msgid "Rights"
 msgstr "Droits"
 
-#: apps/permission/views.py:49
+#: apps/permission/views.py:52
 msgid "All rights"
 msgstr "Tous les droits"
 
@@ -1198,7 +1198,7 @@ msgstr "Invalider l'inscription"
 msgid "Treasury"
 msgstr "Trésorerie"
 
-#: apps/treasury/forms.py:84 apps/treasury/forms.py:138
+#: apps/treasury/forms.py:88 apps/treasury/forms.py:142
 #: templates/activity/activity_form.html:9
 #: templates/activity/activity_invite.html:8
 #: templates/django_filters/rest_framework/form.html:5
@@ -1210,19 +1210,19 @@ msgstr "Trésorerie"
 msgid "Submit"
 msgstr "Envoyer"
 
-#: apps/treasury/forms.py:86
+#: apps/treasury/forms.py:90
 msgid "Close"
 msgstr "Fermer"
 
-#: apps/treasury/forms.py:95
+#: apps/treasury/forms.py:99
 msgid "Remittance is already closed."
 msgstr "La remise est déjà fermée."
 
-#: apps/treasury/forms.py:100
+#: apps/treasury/forms.py:104
 msgid "You can't change the type of the remittance."
 msgstr "Vous ne pouvez pas changer le type de la remise."
 
-#: apps/treasury/forms.py:120 apps/treasury/models.py:207
+#: apps/treasury/forms.py:124 apps/treasury/models.py:207
 #: apps/treasury/tables.py:77 apps/treasury/tables.py:85
 #: templates/treasury/invoice_list.html:13
 #: templates/treasury/remittance_list.html:13
@@ -1230,11 +1230,11 @@ msgstr "Vous ne pouvez pas changer le type de la remise."
 msgid "Remittance"
 msgstr "Remise"
 
-#: apps/treasury/forms.py:121
+#: apps/treasury/forms.py:125
 msgid "No attached remittance"
 msgstr "Pas de remise associée"
 
-#: apps/treasury/forms.py:132 apps/treasury/tables.py:47
+#: apps/treasury/forms.py:136 apps/treasury/tables.py:47
 #: apps/treasury/tables.py:115 templates/note/transaction_form.html:97
 #: templates/treasury/remittance_form.html:18
 msgid "Amount"
@@ -1419,15 +1419,15 @@ msgstr "Liste des remises"
 msgid "Update a remittance"
 msgstr "Modifier la remise"
 
-#: apps/treasury/views.py:301
+#: apps/treasury/views.py:299
 msgid "Attach a transaction to a remittance"
 msgstr "Joindre une transaction à une remise"
 
-#: apps/treasury/views.py:345
+#: apps/treasury/views.py:343
 msgid "List of credits from the Société générale"
 msgstr "Liste des crédits de la Société générale"
 
-#: apps/treasury/views.py:379
+#: apps/treasury/views.py:377
 msgid "Manage credits from the Société générale"
 msgstr "Gérer les crédits de la Société générale"
 
@@ -2090,36 +2090,36 @@ msgstr "Il n'y a pas d'utilisateur trouvé avec cette entrée."
 msgid "Registrations"
 msgstr "Inscriptions"
 
-#: templates/note/conso_form.html:28
+#: templates/note/conso_form.html:30
 msgid "Consum"
 msgstr "Consommer"
 
-#: templates/note/conso_form.html:39 templates/note/transaction_form.html:57
+#: templates/note/conso_form.html:41 templates/note/transaction_form.html:57
 #: templates/note/transaction_form.html:78
 msgid "Name or alias..."
 msgstr "Pseudo ou alias ..."
 
-#: templates/note/conso_form.html:48
+#: templates/note/conso_form.html:50
 msgid "Select consumptions"
 msgstr "Sélection des consommations"
 
-#: templates/note/conso_form.html:57
+#: templates/note/conso_form.html:59
 msgid "Consume!"
 msgstr "Consommer !"
 
-#: templates/note/conso_form.html:71
+#: templates/note/conso_form.html:73
 msgid "Highlighted buttons"
 msgstr "Boutons mis en avant"
 
-#: templates/note/conso_form.html:134
+#: templates/note/conso_form.html:136
 msgid "Single consumptions"
 msgstr "Consommations simples"
 
-#: templates/note/conso_form.html:139
+#: templates/note/conso_form.html:141
 msgid "Double consumptions"
 msgstr "Consommations doubles"
 
-#: templates/note/conso_form.html:150 templates/note/transaction_form.html:154
+#: templates/note/conso_form.html:152 templates/note/transaction_form.html:154
 msgid "Recent transactions history"
 msgstr "Historique des transactions récentes"
 
@@ -2179,23 +2179,31 @@ msgstr "Le bouton a bien été supprimé"
 msgid "Unable to delete button "
 msgstr "Impossible de supprimer le bouton "
 
-#: templates/permission/all_rights.html:10
+#: templates/permission/all_rights.html:8
+msgid "Users that have surnormal rights"
+msgstr "Liste des utilisateurs ayant des droits surnormaux"
+
+#: templates/permission/all_rights.html:14
+msgid "Roles description"
+msgstr "Description de tous les rôles"
+
+#: templates/permission/all_rights.html:19
 msgid "Filter with roles that I have in at least one club"
 msgstr "Filtrer les rôles que je possède dans au moins un club"
 
-#: templates/permission/all_rights.html:21
+#: templates/permission/all_rights.html:31
 msgid "Own this role in the clubs"
 msgstr "Possède ce rôle dans les clubs"
 
-#: templates/permission/all_rights.html:26
+#: templates/permission/all_rights.html:36
 msgid "Mask:"
 msgstr "Masque :"
 
-#: templates/permission/all_rights.html:26
+#: templates/permission/all_rights.html:36
 msgid "Query:"
 msgstr "Requête :"
 
-#: templates/permission/all_rights.html:28
+#: templates/permission/all_rights.html:38
 msgid "No associated permission"
 msgstr "Pas de permission associée"
 
diff --git a/templates/permission/all_rights.html b/templates/permission/all_rights.html
index 9bb6faf5..827532f9 100644
--- a/templates/permission/all_rights.html
+++ b/templates/permission/all_rights.html
@@ -1,8 +1,17 @@
 {% extends "base.html" %}
 
 {% load i18n %}
+{% load render_table from django_tables2 %}
 
 {% block content %}
+    {% if user.is_authenticated %}
+        <h2>{% trans "Users that have surnormal rights" %}</h2>
+        {% render_table special_memberships_table %}
+
+        <hr>
+    {% endif %}
+
+    <h2>{% trans "Roles description" %}</h2>
     {% if user.is_authenticated %}
         <div class="form-check">
             <label for="owned_only" class="form-check-label">
@@ -11,6 +20,7 @@
             </label>
         </div>
     {% endif %}
+
     <ul>
     {% regroup active_memberships by roles as memberships_per_role %}
     {% for role in roles %}
-- 
GitLab