diff --git a/apps/api/viewsets.py b/apps/api/viewsets.py
index cb32b09e4828ff7e2630dc1c1f563098c551e682..6c5a207a114e0ab1f41323d6f4c6ff777e776a98 100644
--- a/apps/api/viewsets.py
+++ b/apps/api/viewsets.py
@@ -13,7 +13,7 @@ class ReadProtectedModelViewSet(viewsets.ModelViewSet):
 
     def get_queryset(self):
         model = ContentType.objects.get_for_model(self.serializer_class.Meta.model)
-        return super().get_queryset().filter(PermissionBackend().filter_queryset(self.request.user, model, "view"))
+        return super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, model, "view"))
 
 
 class ReadOnlyProtectedModelViewSet(viewsets.ReadOnlyModelViewSet):
@@ -23,4 +23,4 @@ class ReadOnlyProtectedModelViewSet(viewsets.ReadOnlyModelViewSet):
 
     def get_queryset(self):
         model = ContentType.objects.get_for_model(self.serializer_class.Meta.model)
-        return super().get_queryset().filter(PermissionBackend().filter_queryset(self.request.user, model, "view"))
+        return super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, model, "view"))
diff --git a/apps/member/backends.py b/apps/member/backends.py
index 3fdbd8d1fd52b8ef8f39bb1343331d7416f9837a..f0b4e8f2925ca352e73481920a9b065149c4ba16 100644
--- a/apps/member/backends.py
+++ b/apps/member/backends.py
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 
 from django.contrib.auth.models import User
+from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import PermissionDenied
 from django.db.models import Q, F
 
@@ -15,7 +16,8 @@ class PermissionBackend(ModelBackend):
     supports_anonymous_user = False
     supports_inactive_user = False
 
-    def permissions(self, user):
+    @staticmethod
+    def permissions(user):
         for membership in Membership.objects.filter(user=user).all():
             if not membership.valid() or membership.roles is None:
                 continue
@@ -37,12 +39,13 @@ class PermissionBackend(ModelBackend):
                     )
                     yield permission
 
-    def filter_queryset(self, user, model, type, field=None):
+    @staticmethod
+    def filter_queryset(user, model, t, field=None):
         """
         Filter a queryset by considering the permissions of a given user.
         :param user: The owner of the permissions that are fetched
         :param model: The concerned model of the queryset
-        :param type: The type of modification (view, add, change, delete)
+        :param t: The type of modification (view, add, change, delete)
         :param field: The field of the model to test, if concerned
         :return: A query that corresponds to the filter to give to a queryset
         """
@@ -51,12 +54,15 @@ class PermissionBackend(ModelBackend):
             # Superusers have all rights
             return Q()
 
+        if not isinstance(model, ContentType):
+            model = ContentType.objects.get_for_model(model)
+
         # Never satisfied
         query = Q(pk=-1)
-        for perm in self.permissions(user):
-            if field and field != perm.field:
+        for perm in PermissionBackend.permissions(user):
+            if perm.field and field != perm.field:
                 continue
-            if perm.model != model or perm.type != type:
+            if perm.model != model or perm.type != t:
                 continue
             query = query | perm.query
         return query
diff --git a/apps/member/views.py b/apps/member/views.py
index 2213f37dd83c8d92cda1a8b6dcbae5d64f2f749b..293ad3a8c0b6e1aeca4d6d7a555e5a5eb02f83bf 100644
--- a/apps/member/views.py
+++ b/apps/member/views.py
@@ -23,6 +23,7 @@ from note.forms import AliasForm, ImageForm
 from note.models import Alias, NoteUser
 from note.models.transactions import Transaction
 from note.tables import HistoryTable, AliasTable
+from .backends import PermissionBackend
 
 from .filters import UserFilter, UserFilterFormHelper
 from .forms import SignUpForm, ProfileForm, ClubForm, MembershipForm, MemberFormSet, FormSetHelper
@@ -120,6 +121,9 @@ class UserDetailView(LoginRequiredMixin, DetailView):
     context_object_name = "user_object"
     template_name = "member/profile_detail.html"
 
+    def get_queryset(self, **kwargs):
+        return super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, User, "view"))
+
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
         user = context['user_object']
@@ -147,7 +151,7 @@ class UserListView(LoginRequiredMixin, SingleTableView):
     formhelper_class = UserFilterFormHelper
 
     def get_queryset(self, **kwargs):
-        qs = super().get_queryset()
+        qs = super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, User, "view"))
         self.filter = self.filter_class(self.request.GET, queryset=qs)
         self.filter.form.helper = self.formhelper_class()
         return self.filter.qs
@@ -296,7 +300,7 @@ class UserAutocomplete(autocomplete.Select2QuerySetView):
         if not self.request.user.is_authenticated:
             return User.objects.none()
 
-        qs = User.objects.all()
+        qs = User.objects.filter(PermissionBackend.filter_queryset(self.request.user, User, "view")).all()
 
         if self.q:
             qs = qs.filter(username__regex="^" + self.q)
@@ -327,11 +331,17 @@ class ClubListView(LoginRequiredMixin, SingleTableView):
     model = Club
     table_class = ClubTable
 
+    def get_queryset(self, **kwargs):
+        return super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))
+
 
 class ClubDetailView(LoginRequiredMixin, DetailView):
     model = Club
     context_object_name = "club"
 
+    def get_queryset(self, **kwargs):
+        return super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))
+
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
         club = context["club"]
@@ -350,6 +360,11 @@ class ClubAddMemberView(LoginRequiredMixin, CreateView):
     form_class = MembershipForm
     template_name = 'member/add_members.html'
 
+    def get_queryset(self, **kwargs):
+        return super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view")
+                                             | PermissionBackend.filter_queryset(self.request.user, Membership,
+                                                                                 "change"))
+
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
         context['formset'] = MemberFormSet()
diff --git a/apps/note/api/views.py b/apps/note/api/views.py
index 6a3bb41ec03be017330c56dad62783c999fd871f..a4fe6fc19ed9afe7ada81b8258bcb50436262904 100644
--- a/apps/note/api/views.py
+++ b/apps/note/api/views.py
@@ -6,6 +6,7 @@ from django_filters.rest_framework import DjangoFilterBackend
 from rest_framework.filters import OrderingFilter, SearchFilter
 
 from api.viewsets import ReadProtectedModelViewSet
+from member.backends import PermissionBackend
 from .serializers import NoteSerializer, NotePolymorphicSerializer, NoteClubSerializer, NoteSpecialSerializer, \
     NoteUserSerializer, AliasSerializer, \
     TemplateCategorySerializer, TransactionTemplateSerializer, TransactionPolymorphicSerializer
@@ -70,7 +71,7 @@ class NotePolymorphicViewSet(ReadProtectedModelViewSet):
         Parse query and apply filters.
         :return: The filtered set of requested notes
         """
-        queryset = super().get_queryset()
+        queryset = super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, Note, "view"))
 
         alias = self.request.query_params.get("alias", ".*")
         queryset = queryset.filter(
@@ -110,7 +111,7 @@ class AliasViewSet(ReadProtectedModelViewSet):
         :return: The filtered set of requested aliases
         """
 
-        queryset = super().get_queryset()
+        queryset = super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, Alias, "view"))
 
         alias = self.request.query_params.get("alias", ".*")
         queryset = queryset.filter(
diff --git a/apps/note/models/transactions.py b/apps/note/models/transactions.py
index ee890c9d55c1e70ae7516be35065cf1f1c04c93e..b7c8f0929e762dd4d7f7c31d56f21f8ba6a7e969 100644
--- a/apps/note/models/transactions.py
+++ b/apps/note/models/transactions.py
@@ -129,13 +129,14 @@ class Transaction(PolymorphicModel):
             models.Index(fields=['destination']),
         ]
 
-    def post_save(self, *args, **kwargs):
+    def save(self, *args, **kwargs):
         """
         When saving, also transfer money between two notes
         """
 
         if self.source.pk == self.destination.pk:
             # When source == destination, no money is transfered
+            super().save(*args, **kwargs)
             return
 
         created = self.pk is None
diff --git a/apps/note/views.py b/apps/note/views.py
index 31a79be7c992c8a70899d5b6f4d2d19480fdc1da..6b2cb37266917b2afb832638a857b300cc76618a 100644
--- a/apps/note/views.py
+++ b/apps/note/views.py
@@ -9,6 +9,7 @@ from django.utils.translation import gettext_lazy as _
 from django.views.generic import CreateView, ListView, UpdateView
 from django_tables2 import SingleTableView
 
+from member.backends import PermissionBackend
 from .forms import TransactionTemplateForm
 from .models import Transaction, TransactionTemplate, Alias, TemplateTransaction, NoteSpecial
 from .models.transactions import SpecialTransaction
@@ -18,16 +19,18 @@ from .tables import HistoryTable
 class TransactionCreate(LoginRequiredMixin, SingleTableView):
     """
     Show transfer page
-
-    TODO: If user have sufficient rights, they can transfer from an other note
     """
-    queryset = Transaction.objects.order_by("-id").all()[:50]
     template_name = "note/transaction_form.html"
 
     # Transaction history table
     table_class = HistoryTable
     table_pagination = {"per_page": 50}
 
+    def get_queryset(self):
+        return Transaction.objects.filter(PermissionBackend
+                                          .filter_queryset(self.request.user, Transaction, "view")) \
+                                            .order_by("-id").all()[:50]
+
     def get_context_data(self, **kwargs):
         """
         Add some context variables in template such as page title
@@ -117,21 +120,26 @@ class ConsoView(LoginRequiredMixin, SingleTableView):
     """
     Consume
     """
-    queryset = Transaction.objects.order_by("-id").all()[:50]
     template_name = "note/conso_form.html"
 
     # Transaction history table
     table_class = HistoryTable
     table_pagination = {"per_page": 50}
 
+    def get_queryset(self):
+        return Transaction.objects.filter(PermissionBackend
+                                          .filter_queryset(self.request.user, Transaction, "view")) \
+                                            .order_by("-id").all()[:50]
+
     def get_context_data(self, **kwargs):
         """
         Add some context variables in template such as page title
         """
         context = super().get_context_data(**kwargs)
         from django.db.models import Count
-        buttons = TransactionTemplate.objects.filter(display=True) \
-            .annotate(clicks=Count('templatetransaction')).order_by('category__name', 'name')
+        buttons = TransactionTemplate.objects.filter(PermissionBackend()
+                                                     .filter_queryset(self.request.user, TransactionTemplate, "view")) \
+            .filter(display=True).annotate(clicks=Count('templatetransaction')).order_by('category__name', 'name')
         context['transaction_templates'] = buttons
         context['most_used'] = buttons.order_by('-clicks', 'name')[:10]
         context['title'] = _("Consumptions")
diff --git a/apps/permission/templatetags/__init__.py b/apps/permission/templatetags/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/apps/permission/templatetags/perms.py b/apps/permission/templatetags/perms.py
new file mode 100644
index 0000000000000000000000000000000000000000..9b5ff93abff4c49940b639bdb6ee7d0b91b2590c
--- /dev/null
+++ b/apps/permission/templatetags/perms.py
@@ -0,0 +1,42 @@
+# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from django.contrib.contenttypes.models import ContentType
+from django.template.defaultfilters import stringfilter
+
+from logs.middlewares import get_current_authenticated_user
+from django import template
+
+from member.backends import PermissionBackend
+
+
+def has_perm(value):
+    return get_current_authenticated_user().has_perm(value)
+
+
+@stringfilter
+def not_empty_model_list(model_name):
+    user = get_current_authenticated_user()
+    if user.is_superuser:
+        return True
+    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"))
+    return qs.exists()
+
+
+@stringfilter
+def not_empty_model_change_list(model_name):
+    user = get_current_authenticated_user()
+    if user.is_superuser:
+        return True
+    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"))
+    return qs.exists()
+
+
+register = template.Library()
+register.filter('has_perm', has_perm)
+register.filter('not_empty_model_list', not_empty_model_list)
+register.filter('not_empty_model_change_list', not_empty_model_change_list)
diff --git a/templates/base.html b/templates/base.html
index e61937021c6f566f9b3125cc00dac9de9e66634c..fae864433187801b0cabdf6c7c8dfbfab923dbc5 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -1,4 +1,4 @@
-{% load static i18n pretty_money static getenv %}
+{% load static i18n pretty_money static getenv perms %}
 {% comment %}
 SPDX-License-Identifier: GPL-3.0-or-later
 {% endcomment %}
@@ -74,21 +74,29 @@ SPDX-License-Identifier: GPL-3.0-or-later
         </button>
         <div class="collapse navbar-collapse" id="navbarNavDropdown">
             <ul class="navbar-nav">
-                <li class="nav-item active">
-                    <a class="nav-link" href="{% url 'note:consos' %}"><i class="fa fa-coffee"></i> {% trans 'Consumptions' %}</a>
-                </li>
-                <li class="nav-item active">
-                    <a class="nav-link" href="{% url 'member:club_list' %}"><i class="fa fa-users"></i> {% trans 'Clubs' %}</a>
-                </li>
-                <li class="nav-item active">
-                    <a class="nav-link" href="#"><i class="fa fa-calendar"></i> {% trans 'Activities' %}</a>
-                </li>
-                <li class="nav-item active">
-                    <a class="nav-link" href="{% url 'note:template_list' %}"><i class="fa fa-coffee"></i> {% trans 'Buttons' %}</a>
-                </li>
-                <li class="nav-item active">
-                    <a class="nav-link" href="{% url 'note:transfer' %}"><i class="fa fa-exchange"></i>{% trans 'Transfer' %} </a>
-                </li>
+                {% if "note.transactiontemplate"|not_empty_model_list %}
+                    <li class="nav-item active">
+                        <a class="nav-link" href="{% url 'note:consos' %}"><i class="fa fa-coffee"></i> {% trans 'Consumptions' %}</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>
+                    </li>
+                {% endif %}
+                {% if "activity.activity"|not_empty_model_list %}
+                    <li class="nav-item active">
+                        <a class="nav-link" href="#"><i class="fa fa-calendar"></i> {% trans 'Activities' %}</a>
+                    </li>
+                {% endif %}
+                {% if "note.transactiontemplate"|not_empty_model_change_list %}
+                    <li class="nav-item active">
+                        <a class="nav-link" href="{% url 'note:template_list' %}"><i class="fa fa-coffee"></i> {% trans 'Buttons' %}</a>
+                    </li>
+                {% endif %}
+                    <li class="nav-item active">
+                        <a class="nav-link" href="{% url 'note:transfer' %}"><i class="fa fa-exchange"></i>{% trans 'Transfer' %} </a>
+                    </li>
             </ul>
             <ul class="navbar-nav ml-auto">
                 {% if user.is_authenticated %}