diff --git a/apps/api/viewsets.py b/apps/api/viewsets.py
index f4dd56f6b856fcdc92bf38ced262aebd5187f6b3..01fc7998b4d4efb2b506ea16877da7ff589b4439 100644
--- a/apps/api/viewsets.py
+++ b/apps/api/viewsets.py
@@ -4,7 +4,7 @@
 from django.contrib.contenttypes.models import ContentType
 from permission.backends import PermissionBackend
 from rest_framework import viewsets
-from note_kfet.middlewares import get_current_authenticated_user
+from note_kfet.middlewares import get_current_session
 
 
 class ReadProtectedModelViewSet(viewsets.ModelViewSet):
@@ -17,7 +17,8 @@ class ReadProtectedModelViewSet(viewsets.ModelViewSet):
         self.model = ContentType.objects.get_for_model(self.serializer_class.Meta.model).model_class()
 
     def get_queryset(self):
-        user = get_current_authenticated_user()
+        user = self.request.user
+        get_current_session().setdefault("permission_mask", 42)
         return self.model.objects.filter(PermissionBackend.filter_queryset(user, self.model, "view")).distinct()
 
 
@@ -31,5 +32,6 @@ class ReadOnlyProtectedModelViewSet(viewsets.ReadOnlyModelViewSet):
         self.model = ContentType.objects.get_for_model(self.serializer_class.Meta.model).model_class()
 
     def get_queryset(self):
-        user = get_current_authenticated_user()
+        user = self.request.user
+        get_current_session().setdefault("permission_mask", 42)
         return self.model.objects.filter(PermissionBackend.filter_queryset(user, self.model, "view")).distinct()
diff --git a/apps/note/api/views.py b/apps/note/api/views.py
index f806bbf25f4642fc7a7952e9acd4f4b8261c50d4..be11aa7f873b802620030464656165ebdee44d67 100644
--- a/apps/note/api/views.py
+++ b/apps/note/api/views.py
@@ -9,7 +9,7 @@ from rest_framework import viewsets
 from rest_framework.response import Response
 from rest_framework import status
 from api.viewsets import ReadProtectedModelViewSet, ReadOnlyProtectedModelViewSet
-from note_kfet.middlewares import get_current_authenticated_user
+from note_kfet.middlewares import  get_current_session
 from permission.backends import PermissionBackend
 
 from .serializers import NotePolymorphicSerializer, AliasSerializer, ConsumerSerializer,\
@@ -154,5 +154,7 @@ class TransactionViewSet(ReadProtectedModelViewSet):
     search_fields = ['$reason', ]
 
     def get_queryset(self):
-        user = get_current_authenticated_user()
-        return self.model.objects.filter(PermissionBackend.filter_queryset(user, self.model, "view"))
+        user = self.request.user
+        get_current_session().setdefault("permission_mask", 42)
+        return self.model.objects.filter(PermissionBackend.filter_queryset(user, self.model, "view"))\
+            .order_by("created_at", "id")
diff --git a/apps/note/models/transactions.py b/apps/note/models/transactions.py
index c4f880f695e665a70a9c96d6705bc79afa8405c9..3d7aeb581f158b6aba8393389cd7f5129f9a2666 100644
--- a/apps/note/models/transactions.py
+++ b/apps/note/models/transactions.py
@@ -1,7 +1,7 @@
 # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
 # SPDX-License-Identifier: GPL-3.0-or-later
 from django.core.exceptions import ValidationError
-from django.db import models
+from django.db import models, transaction
 from django.urls import reverse
 from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
@@ -196,38 +196,51 @@ class Transaction(PolymorphicModel):
                 or dest_balance > 2147483647 or dest_balance < -2147483648:
             raise ValidationError(_("The note balances must be between - 21 474 836.47 € and 21 474 836.47 €."))
 
+    @transaction.atomic
     def save(self, *args, **kwargs):
         """
         When saving, also transfer money between two notes
         """
-        self.validate(False)
-
-        if not self.source.is_active or not self.destination.is_active:
-            if 'force_insert' not in kwargs or not kwargs['force_insert']:
-                if 'force_update' not in kwargs or not kwargs['force_update']:
-                    raise ValidationError(_("The transaction can't be saved since the source note "
-                                            "or the destination note is not active."))
-
-        # If the aliases are not entered, we assume that the used alias is the name of the note
-        if not self.source_alias:
-            self.source_alias = str(self.source)
-
-        if not self.destination_alias:
-            self.destination_alias = str(self.destination)
-
-        if self.source.pk == self.destination.pk:
-            # When source == destination, no money is transferred
+        with transaction.atomic():
+            self.refresh_from_db()
+            self.source.refresh_from_db()
+            self.destination.refresh_from_db()
+            self.validate(False)
+
+            if not self.source.is_active or not self.destination.is_active:
+                if 'force_insert' not in kwargs or not kwargs['force_insert']:
+                    if 'force_update' not in kwargs or not kwargs['force_update']:
+                        raise ValidationError(_("The transaction can't be saved since the source note "
+                                                "or the destination note is not active."))
+
+            # If the aliases are not entered, we assume that the used alias is the name of the note
+            if not self.source_alias:
+                self.source_alias = str(self.source)
+
+            if not self.destination_alias:
+                self.destination_alias = str(self.destination)
+
+            if self.source.pk == self.destination.pk:
+                # When source == destination, no money is transferred
+                super().save(*args, **kwargs)
+                return
+
+            self.log("Saving")
+            # We save first the transaction, in case of the user has no right to transfer money
             super().save(*args, **kwargs)
-            return
-
-        # We save first the transaction, in case of the user has no right to transfer money
-        super().save(*args, **kwargs)
-
-        # Save notes
-        self.source._force_save = True
-        self.source.save()
-        self.destination._force_save = True
-        self.destination.save()
+            self.log("Saved")
+
+            # Save notes
+            self.source._force_save = True
+            self.source.save()
+            self.log("Source saved")
+            self.destination._force_save = True
+            self.destination.save()
+            self.log("Destination saved")
+
+    def log(self, msg):
+        with open("/tmp/log", "a") as f:
+            f.write(msg + "\n")
 
     def delete(self, **kwargs):
         """
diff --git a/apps/permission/models.py b/apps/permission/models.py
index 235977bb6e05b37bb937288c9d3140b5de7ed87b..a7e178b3cd39d22c58268960d0e5b90443eed33c 100644
--- a/apps/permission/models.py
+++ b/apps/permission/models.py
@@ -10,7 +10,7 @@ from time import sleep
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ValidationError
 from django.core.mail import mail_admins
-from django.db import models
+from django.db import models, transaction
 from django.db.models import F, Q, Model
 from django.forms import model_to_dict
 from django.utils.translation import gettext_lazy as _
@@ -43,35 +43,28 @@ class InstancedPermission:
 
                 obj = copy(obj)
                 obj.pk = 0
-                # Ensure previous models are deleted
-                for ignored in range(1000):
-                    if self.model.model_class().objects.filter(pk=0).exists():
-                        # If the object exists, that means that one permission is currently checked.
-                        # We wait before the other permission, at most 1 second.
-                        sleep(0.001)
-                        continue
-                    break
-                for o in self.model.model_class().objects.filter(pk=0).all():
-                    o._force_delete = True
-                    Model.delete(o)
-                    # An object with pk 0 wouldn't deleted. That's not normal, we alert admins.
-                    msg = "Lors de la vérification d'une permission d'ajout, un objet de clé primaire nulle était "\
-                          "encore présent.\n"\
-                          "Type de permission : " + self.type + "\n"\
-                          "Modèle : " + str(self.model) + "\n"\
-                          "Objet trouvé : " + str(model_to_dict(o)) + "\n\n"\
-                          "--\nLe BDE"
-                    mail_admins("[Note Kfet] Un objet a été supprimé de force", msg)
-
-                # Force insertion, no data verification, no trigger
-                obj._force_save = True
-                Model.save(obj, force_insert=True)
-                # We don't want log anything
-                obj._no_log = True
-                ret = self.model.model_class().objects.filter(self.query & Q(pk=0)).exists()
-                # Delete testing object
-                obj._force_delete = True
-                Model.delete(obj)
+                with transaction.atomic():
+                    for o in self.model.model_class().objects.filter(pk=0).all():
+                        o._force_delete = True
+                        Model.delete(o)
+                        # An object with pk 0 wouldn't deleted. That's not normal, we alert admins.
+                        msg = "Lors de la vérification d'une permission d'ajout, un objet de clé primaire nulle était "\
+                              "encore présent.\n"\
+                              "Type de permission : " + self.type + "\n"\
+                              "Modèle : " + str(self.model) + "\n"\
+                              "Objet trouvé : " + str(model_to_dict(o)) + "\n\n"\
+                              "--\nLe BDE"
+                        mail_admins("[Note Kfet] Un objet a été supprimé de force", msg)
+
+                    # Force insertion, no data verification, no trigger
+                    obj._force_save = True
+                    Model.save(obj, force_insert=True)
+                    # We don't want log anything
+                    obj._no_log = True
+                    ret = self.model.model_class().objects.filter(self.query & Q(pk=0)).exists()
+                    # Delete testing object
+                    obj._force_delete = True
+                    Model.delete(obj)
 
                 with open("/tmp/log", "w") as f:
                     f.write(str(obj) + ", " + str(obj.pk) + ", " + str(self.model.model_class().objects.filter(pk=0).exists()))