diff --git a/djangoldp/__init__.py b/djangoldp/__init__.py
index ed2171212bcb88a02d02fa1822197a68c7a13df9..790f02aa4e153fc4e9fbf41a833590d4bba23a5e 100644
--- a/djangoldp/__init__.py
+++ b/djangoldp/__init__.py
@@ -1,3 +1,4 @@
 from django.db.models import options
 
+__version__ = '0.0.0'
 options.DEFAULT_NAMES += ('rdf_type', 'auto_author')
diff --git a/djangoldp/factories.py b/djangoldp/factories.py
new file mode 100644
index 0000000000000000000000000000000000000000..172e289b5b49acfaf4a80e711ba249cd77c2d3af
--- /dev/null
+++ b/djangoldp/factories.py
@@ -0,0 +1,14 @@
+import factory
+from django.contrib.auth.models import User
+from django.db.models.signals import post_save
+
+@factory.django.mute_signals(post_save)
+class UserFactory(factory.django.DjangoModelFactory):
+    class Meta:
+        model = User
+
+    username = factory.Faker('user_name')
+    first_name = factory.Faker('first_name')
+    last_name = factory.Faker('last_name')
+    email = factory.Faker('email')
+    password = factory.PostGenerationMethodCall('set_password', 'totototo')
diff --git a/djangoldp/management/__init__.py b/djangoldp/management/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/djangoldp/management/commands/__init__.py b/djangoldp/management/commands/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/djangoldp/management/commands/mock_user.py b/djangoldp/management/commands/mock_user.py
new file mode 100644
index 0000000000000000000000000000000000000000..30b4373e8dcd7d0bed9c4a8277bac1a3fbd49c4b
--- /dev/null
+++ b/djangoldp/management/commands/mock_user.py
@@ -0,0 +1,13 @@
+from django.core.management.base import BaseCommand, CommandError
+from djangoldp.factories import UserFactory
+
+class Command(BaseCommand):
+    help = 'Mock data'
+
+    def add_arguments(self, parser):
+        parser.add_argument('--size', type=int, default=0, help='Number of user to create')
+
+    def handle(self, *args, **options):
+        UserFactory.create_batch(size=options['size']);
+
+        self.stdout.write(self.style.SUCCESS('Successful data mock install'))
diff --git a/djangoldp/permissions.py b/djangoldp/permissions.py
index aed5ce3bc8c8d6f2ccc5c4cafa687920d6e4857c..90862a84ba142799f9bc1216eb1b09dbc9625e4b 100644
--- a/djangoldp/permissions.py
+++ b/djangoldp/permissions.py
@@ -1,4 +1,6 @@
 from rest_framework import permissions
+from rest_framework import filters
+from guardian.shortcuts import get_objects_for_user, get_user_perms
 
 """
 Liste des actions passées dans views selon le protocole REST :
@@ -9,105 +11,83 @@ Liste des actions passées dans views selon le protocole REST :
     destroy
 Pour chacune de ces actions, on va définir si on accepte la requête (True) ou non (False)
 """
+"""
+    The instance-level has_object_permission method will only be called if the view-level has_permission 
+    checks have already passed
+"""
+
+class WACPermissions(permissions.DjangoObjectPermissions):
+    perms_map = {
+        'GET': ['%(app_label)s.view_%(model_name)s'],
+        'OPTIONS': [],
+        'HEAD': ['%(app_label)s.view_%(model_name)s'],
+        'POST': ['%(app_label)s.add_%(model_name)s'],
+        'PUT': ['%(app_label)s.change_%(model_name)s'],
+        'PATCH': ['%(app_label)s.change_%(model_name)s'],
+        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
+    }
+    def has_permission(self, request, view):
+        if request.method == 'OPTIONS':
+            return True
+        return super().has_permission(request, view)
+
 
+class ObjectFilter(filters.BaseFilterBackend):
+    def filter_queryset(self, request, queryset, view):
+        """
+            Ensure that queryset only contains objects visible by current user
+        """
+        perm = "view_{}".format(queryset.model._meta.model_name.lower())
+        objects = get_objects_for_user(request.user, perm, klass=queryset)
+        return objects
 
-class PublicPostPermissions(permissions.BasePermission):
+class ObjectPermission(permissions.DjangoObjectPermissions):
+    filter_class = ObjectFilter
+
+class AnonymousReadOnly(permissions.DjangoObjectPermissions):
     """
         Anonymous users: can read all posts
         Logged in users: can read all posts + create new posts
         Author: can read all posts + create new posts + update their own
     """
     def has_permission(self, request, view):
-
-        if view.action == "list":
-            return True
-
-        if not request.user.is_authenticated():
-            return False
-        elif view.action == 'create':
-            return True
-        elif view.action in ['retrieve', 'update', 'partial_update', 'destroy']:
+        if view.action in ['list', 'retrieve']:
             return True
         else:
-            return False
+            return super().has_permission(request, view)
 
     def has_object_permission(self, request, view, obj):
-
-        if view.action == "create":
+        if view.action == "create" and request.user.is_authenticated():
             return True
-
-        elif view.action in ['retrieve', 'update', 'partial_update', 'destroy']:
+        elif view.action == "retrieve":
+            return True
+        elif view.action in ['update', 'partial_update', 'destroy']:
             if hasattr(obj._meta, 'auto_author'):
-                auth = getattr(obj, obj._meta.auto_author)
-                if auth == request.user:
+                author = getattr(obj, obj._meta.auto_author)
+                if author == request.user:
                     return True
         else:
-            return False
-
-
-class PrivateProjectPermissions(permissions.BasePermission):
-    """
-        Anonymous users: no permissions
-        Logged in users: can read projects if they're in the team
-        Users of group Partners: can see all projects + update all projects
-    """
-
-    def has_permission(self, request, view):
-        if not request.user.is_authenticated():
-            return False
-        if view.action == "list":
-            return True
-        elif view.action == 'create':
-            return True
-        elif view.action in ['retrieve', 'update', 'partial_update', 'destroy']:
-            return True
-        else:
-            return False
+            return super().has_object_permission(request, view)
 
-    def has_object_permission(self, request, view, obj):
-
-        if view.action in ['retrieve']:
-            # Is user in the team ?
-            for t in obj.team.all():
-                if request.user == t:
-                    return True
-
-        elif view.action in ['update', 'partial_update', 'destroy']:
-            if request.user.groups.filter(name='Partners').exists():
-                return True
 
-        return False
-
-
-class NotificationsPermissions(permissions.BasePermission):
+class InboxPermissions(permissions.DjangoObjectPermissions):
     """
         Anonymous users: can create notifications but can't read
         Logged in users: can create notifications but can't read
         Inbox owners: can read + update all notifications
     """
-
+    filter_class = ObjectFilter
     def has_permission(self, request, view):
-
-        if view.action == "list":
-            return False
-        elif view.action == 'create':
-            return True
-        elif view.action in ['retrieve', 'update', 'partial_update', 'destroy']:
+        if view.action in ['create', 'retrieve', 'update', 'partial_update', 'destroy']:
             return True
         else:
-            return False
+            return super().has_permission(request, view)
 
     def has_object_permission(self, request, view, obj):
-
-        if view.action in ["retrieve", 'update', 'partial_update', 'destroy']:
-            if hasattr(obj._meta, 'auto_author'):
-                auth = getattr(obj, obj._meta.auto_author)
-                if auth == request.user:
-                    return True
-            else:
-                return False
-
         if view.action == "create":
-            if request.user == "AnonymousUser" or request.user.is_authenticated():
+            return True
+        if hasattr(obj._meta, 'auto_author'):
+            if request.user == getattr(obj, obj._meta.auto_author):
                 return True
+        return super().has_object_permission(request, view)
 
diff --git a/djangoldp/views.py b/djangoldp/views.py
index 213d53dd2c6c806ff6ce587f55f0b02b1acd1bd3..bf72306cd9ed9a3b80df362e6529a4cd897a29f4 100644
--- a/djangoldp/views.py
+++ b/djangoldp/views.py
@@ -16,6 +16,7 @@ from rest_framework.viewsets import ModelViewSet
 from .models import LDPSource
 from .serializers import LDPSerializer
 from guardian.shortcuts import get_objects_for_user
+from djangoldp.permissions import ObjectFilter
 
 
 class JSONLDRenderer(JSONRenderer):
@@ -34,33 +35,6 @@ class NoCSRFAuthentication(SessionAuthentication):
     def enforce_csrf(self, request):
         return
 
-class WACPermissions(DjangoObjectPermissions):
-    perms_map = {
-        'GET': ['%(app_label)s.view_%(model_name)s'],
-        'OPTIONS': [],
-        'HEAD': ['%(app_label)s.view_%(model_name)s'],
-        'POST': ['%(app_label)s.add_%(model_name)s'],
-        'PUT': ['%(app_label)s.change_%(model_name)s'],
-        'PATCH': ['%(app_label)s.change_%(model_name)s'],
-        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
-    }
-    def has_permission(self, request, view):
-        if request.method == 'OPTIONS':
-            return True
-        return super().has_permission(request, view)
-
-class AnnonReadOnly(WACPermissions):
-    authenticated_users_only = False
-
-class DjangoObjectPermissionsFilter(BaseFilterBackend):
-    def filter_queryset(self, request, queryset, view):
-        """
-            Ensure that queryset only contains objects visible by current user
-        """
-        perm="view_{}".format(queryset.model._meta.model_name.lower())
-        objects = get_objects_for_user(request.user, perm, klass=queryset)
-        return  objects
-
 class LDPViewSetGenerator(ModelViewSet):
     """An extension of ModelViewSet that generates automatically URLs for the model"""
     model = None
@@ -113,9 +87,11 @@ class LDPViewSet(LDPViewSetGenerator):
     renderer_classes = (JSONLDRenderer, )
     parser_classes = (JSONLDParser, )
     authentication_classes = (NoCSRFAuthentication,)
-    
+
     def __init__(self, **kwargs):
         super().__init__(**kwargs)
+        if self.permission_classes and self.permission_classes.filter_class:
+            self.filter_backends = (self.permission_classes.filter_class,)
         self.serializer_class = self.build_serializer()