diff --git a/arkindex/project/mixins.py b/arkindex/project/mixins.py
index 31039e42c44a40b5f2f8cba22441fb15f125461f..c805ccd753702fdffae7a020be664382408aa056 100644
--- a/arkindex/project/mixins.py
+++ b/arkindex/project/mixins.py
@@ -34,21 +34,30 @@ class ACLMixin(object):
         """
         if self.user.is_admin or self.user.is_internal:
             return model.objects.all()
-        filters = Q(max_level__gte=level)
-        if (public):
-            # Allow access to public instances if the public parameter is set
-            filters = filters | Q(public=True)
-        return model.objects \
+        queryset = model.objects \
             .filter(
+                # Filter instances with direct and groups rights for this user (They may be duplicated)
                 Q(memberships__user=self.user)
                 | Q(memberships__group__memberships__user=self.user)
             ) \
-            .annotate(max_level=functions.Least(
-                'memberships__level',
-                'memberships__group__memberships__level'
-            )) \
-            .filter(filters) \
-            .distinct()
+            .annotate(
+                # Keep only the lowest level for each right via group
+                max_level=functions.Least(
+                    # In case of direct right, group level will be skipped (Null value)
+                    'memberships__level',
+                    'memberships__group__memberships__level'
+                )
+            ) \
+            .filter(
+                # Ensure one of the right has an adequate level
+                max_level__gte=level
+            )
+
+        if (public):
+            # Allow access to public instances if the public parameter is set
+            queryset = queryset | model.objects.filter(public=True)
+
+        return queryset.distinct()
 
     def has_access(self, instance, level):
         if self.user.is_admin or self.user.is_internal: