From 3f5faa0b0525c9a3331303b6807b08c614885a24 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <yohann.danello@gmail.com>
Date: Wed, 1 Apr 2020 20:56:24 +0200
Subject: [PATCH] Add tab for user list

---
 apps/member/views.py                    |  5 ++-
 apps/note/models/transactions.py        |  5 +++
 apps/note/tables.py                     | 10 ++++--
 apps/permission/templatetags/perms.py   | 48 +++++++++++++++++++++----
 templates/activity/activity_detail.html | 10 +++---
 templates/base.html                     |  5 +++
 6 files changed, 68 insertions(+), 15 deletions(-)

diff --git a/apps/member/views.py b/apps/member/views.py
index e507c2cf..96550e14 100644
--- a/apps/member/views.py
+++ b/apps/member/views.py
@@ -170,10 +170,13 @@ class UserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
         else:
             qs = qs.none()
 
-        return qs
+        return qs[:20]
 
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
+
+        context["title"] = _("Search user")
+
         return context
 
 
diff --git a/apps/note/models/transactions.py b/apps/note/models/transactions.py
index d9b860ae..83f8f914 100644
--- a/apps/note/models/transactions.py
+++ b/apps/note/models/transactions.py
@@ -46,12 +46,14 @@ class TransactionTemplate(models.Model):
         unique=True,
         error_messages={'unique': _("A template with this name already exist")},
     )
+
     destination = models.ForeignKey(
         NoteClub,
         on_delete=models.PROTECT,
         related_name='+',  # no reverse
         verbose_name=_('destination'),
     )
+
     amount = models.PositiveIntegerField(
         verbose_name=_('amount'),
         help_text=_('in centimes'),
@@ -62,9 +64,12 @@ class TransactionTemplate(models.Model):
         verbose_name=_('type'),
         max_length=31,
     )
+
     display = models.BooleanField(
         default=True,
+        verbose_name=_("display"),
     )
+
     description = models.CharField(
         verbose_name=_('description'),
         max_length=255,
diff --git a/apps/note/tables.py b/apps/note/tables.py
index 0d83e3cc..a38beb9a 100644
--- a/apps/note/tables.py
+++ b/apps/note/tables.py
@@ -118,7 +118,8 @@ class AliasTable(tables.Table):
 
     delete_col = tables.TemplateColumn(template_code=DELETE_TEMPLATE,
                                        extra_context={"delete_trans": _('delete')},
-                                       attrs={'td': {'class': 'col-sm-1'}})
+                                       attrs={'td': {'class': 'col-sm-1'}},
+                                       verbose_name=_("Delete"),)
 
 
 class ButtonTable(tables.Table):
@@ -134,17 +135,20 @@ class ButtonTable(tables.Table):
         }
 
         model = TransactionTemplate
+        exclude = ('id',)
 
     edit = tables.LinkColumn('note:template_update',
                              args=[A('pk')],
                              attrs={'td': {'class': 'col-sm-1'},
                                     'a': {'class': 'btn btn-sm btn-primary'}},
                              text=_('edit'),
-                             accessor='pk')
+                             accessor='pk',
+                             verbose_name=_("Edit"),)
 
     delete_col = tables.TemplateColumn(template_code=DELETE_TEMPLATE,
                                        extra_context={"delete_trans": _('delete')},
-                                       attrs={'td': {'class': 'col-sm-1'}})
+                                       attrs={'td': {'class': 'col-sm-1'}},
+                                       verbose_name=_("Delete"),)
 
     def render_amount(self, value):
         return pretty_money(value)
diff --git a/apps/permission/templatetags/perms.py b/apps/permission/templatetags/perms.py
index aa2feeca..b06fdd9a 100644
--- a/apps/permission/templatetags/perms.py
+++ b/apps/permission/templatetags/perms.py
@@ -4,6 +4,7 @@
 from django.contrib.contenttypes.models import ContentType
 from django.template.defaultfilters import stringfilter
 from django import template
+from note.models import Transaction
 from note_kfet.middlewares import get_current_authenticated_user, get_current_session
 from permission.backends import PermissionBackend
 
@@ -21,9 +22,7 @@ def not_empty_model_list(model_name):
         return True
     if session.get("not_empty_model_list_" + model_name, None):
         return session.get("not_empty_model_list_" + model_name, None) == 1
-    spl = model_name.split(".")
-    ct = ContentType.objects.get(app_label=spl[0], model=spl[1])
-    qs = ct.model_class().objects.filter(PermissionBackend.filter_queryset(user, ct, "view")).all()
+    qs = model_list(model_name)
     session["not_empty_model_list_" + model_name] = 1 if qs.exists() else 2
     return session.get("not_empty_model_list_" + model_name) == 1
 
@@ -41,18 +40,55 @@ def not_empty_model_change_list(model_name):
         return True
     if session.get("not_empty_model_change_list_" + model_name, None):
         return session.get("not_empty_model_change_list_" + model_name, None) == 1
-    spl = model_name.split(".")
-    ct = ContentType.objects.get(app_label=spl[0], model=spl[1])
-    qs = ct.model_class().objects.filter(PermissionBackend.filter_queryset(user, ct, "change"))
+    qs = model_list(model_name, "change")
     session["not_empty_model_change_list_" + model_name] = 1 if qs.exists() else 2
     return session.get("not_empty_model_change_list_" + model_name) == 1
 
 
+@stringfilter
+def model_list(model_name, t="view"):
+    """
+    Return the queryset of all visible instances of the given model.
+    """
+    user = get_current_authenticated_user()
+    if user is None:
+        return False
+    spl = model_name.split(".")
+    ct = ContentType.objects.get(app_label=spl[0], model=spl[1])
+    qs = ct.model_class().objects.filter(PermissionBackend.filter_queryset(user, ct, t)).all()
+    return qs
+
+
 def has_perm(perm, obj):
     return PermissionBackend().has_perm(get_current_authenticated_user(), perm, obj)
 
 
+def can_create_transaction():
+    """
+    :return: True iff the authenticated user can create a transaction.
+    """
+    user = get_current_authenticated_user()
+    session = get_current_session()
+    if user is None:
+        return False
+    elif user.is_superuser and session.get("permission_mask", 0) >= 42:
+        return True
+    if session.get("can_create_transaction", None):
+        return session.get("can_create_transaction", None) == 1
+
+    empty_transaction = Transaction(
+        source=user.note,
+        destination=user.note,
+        quantity=1,
+        amount=0,
+        reason="Check permissions",
+    )
+    session["can_create_transaction"] = PermissionBackend().has_perm(user, "note.add_transaction", empty_transaction)
+    return session.get("can_create_transaction") == 1
+
+
 register = template.Library()
 register.filter('not_empty_model_list', not_empty_model_list)
 register.filter('not_empty_model_change_list', not_empty_model_change_list)
+register.filter('model_list', model_list)
 register.filter('has_perm', has_perm)
diff --git a/templates/activity/activity_detail.html b/templates/activity/activity_detail.html
index 0ed3c719..84182065 100644
--- a/templates/activity/activity_detail.html
+++ b/templates/activity/activity_detail.html
@@ -25,7 +25,7 @@
                 <dt class="col-xl-6">{% trans 'end date'|capfirst %}</dt>
                 <dd class="col-xl-6">{{ activity.date_end }}</dd>
 
-                {% if "view_"|has_perm:activity.creater %}
+                {% if ".view_"|has_perm:activity.creater %}
                     <dt class="col-xl-6">{% trans 'creater'|capfirst %}</dt>
                     <dd class="col-xl-6"><a href="{% url "member:user_detail" pk=activity.creater.pk %}">{{ activity.creater }}</a></dd>
                 {% endif %}
@@ -53,17 +53,17 @@
         </div>
 
         <div class="card-footer text-center">
-            {% if activity.open and "change__open"|has_perm:activity %}
+            {% if activity.open and ".change__open"|has_perm:activity %}
                 <a class="btn btn-warning btn-sm my-1" href="{% url 'activity:activity_entry' pk=activity.pk %}"> {% trans "Entry page" %}</a>
             {% endif %}
 
-            {% if activity.valid and "change__open"|has_perm:activity %}
+            {% if activity.valid and ".change__open"|has_perm:activity %}
                 <a class="btn btn-warning btn-sm my-1" id="open_activity"> {% if activity.open %}{% trans "close"|capfirst %}{% else %}{% trans "open"|capfirst %}{% endif %}</a>
             {% endif %}
-            {% if not activity.open and "change__valid"|has_perm:activity %}
+            {% if not activity.open and ".change__valid"|has_perm:activity %}
                 <a class="btn btn-success btn-sm my-1" id="validate_activity"> {% if activity.valid %}{% trans "invalidate"|capfirst %}{% else %}{% trans "validate"|capfirst %}{% endif %}</a>
             {% endif %}
-            {% if "view_"|has_perm:activity %}
+            {% if ".view_"|has_perm:activity %}
                 <a class="btn btn-primary btn-sm my-1" href="{% url 'activity:activity_update' pk=activity.pk %}"> {% trans "edit"|capfirst %}</a>
             {% endif %}
             {% if activity.activity_type.can_invite and not activity_started %}
diff --git a/templates/base.html b/templates/base.html
index 26903c2f..c44e2467 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -84,6 +84,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
                         <a class="nav-link" href="{% url 'note:transfer' %}"><i class="fa fa-exchange"></i>{% trans 'Transfer' %} </a>
                     </li>
                 {% endif %}
+                {% if "auth.user"|model_list|length >= 2 %}
+                    <li class="nav-item active">
+                        <a class="nav-link" href="{% url 'member:user_list' %}"><i class="fa fa-user"></i> {% trans 'Users' %}</a>
+                    </li>
+                {% endif %}
                 {% if "member.club"|not_empty_model_list %}
                     <li class="nav-item active">
                         <a class="nav-link" href="{% url 'member:club_list' %}"><i class="fa fa-users"></i> {% trans 'Clubs' %}</a>
-- 
GitLab