diff --git a/arkindex/documents/managers.py b/arkindex/documents/managers.py
index a3cdf753b8e6d89ef9f7082018d2d8565d0d5165..97f0ea2f5724068e8381cbea0871d45a6f8127b7 100644
--- a/arkindex/documents/managers.py
+++ b/arkindex/documents/managers.py
@@ -130,8 +130,8 @@ class CorpusManager(models.Manager):
         if user.is_anonymous:
             return qs.filter(public=True)
 
-        # An admin has access to every corpus
-        if user.is_admin:
+        # Admins and internal users have access to every corpus
+        if user.is_admin or user.is_internal:
             return qs.all()
 
         # An authenticated user has access to:
@@ -148,8 +148,8 @@ class CorpusManager(models.Manager):
 
         qs = super().get_queryset().order_by('name')
 
-        # Admins have access to every corpus
-        if user.is_admin:
+        # Admins and internal users have access to every corpus
+        if user.is_admin or user.is_internal:
             return qs.all()
 
         # Authenticated users can write only on corpora with ACL
diff --git a/arkindex/documents/models.py b/arkindex/documents/models.py
index b8588b8e9acec5164fbf306943caf71bd9b8d898..06c94d2003e656ee142437f16312419d4bdae5e7 100644
--- a/arkindex/documents/models.py
+++ b/arkindex/documents/models.py
@@ -54,8 +54,8 @@ class Corpus(models.Model):
         if user.is_anonymous:
             return self.public and [Right.Read] or []
 
-        # Full rights for admin
-        if user.is_admin:
+        # Full rights for admins and internal users
+        if user.is_admin or user.is_internal:
             return [Right.Read, Right.Write, Right.Admin]
 
         # Check acl
diff --git a/arkindex/project/mixins.py b/arkindex/project/mixins.py
index e9591a3c6fc85ad20371737d77c160f669356f4e..b98de5186186ac058483749bf50a4feb727dad39 100644
--- a/arkindex/project/mixins.py
+++ b/arkindex/project/mixins.py
@@ -16,17 +16,15 @@ class CorpusACLMixin(object):
 
     def has_read_access(self, corpus):
         assert isinstance(corpus, Corpus)
-        return corpus.public or self.request.user.is_admin or Right.Read in corpus.get_acl_rights(self.request.user)
+        return Right.Read in corpus.get_acl_rights(self.request.user)
 
     def has_write_access(self, corpus):
         assert isinstance(corpus, Corpus)
-        return self.request.user.is_admin or not self.request.user.is_anonymous and \
-            Right.Write in corpus.get_acl_rights(self.request.user)
+        return Right.Write in corpus.get_acl_rights(self.request.user)
 
     def has_admin_access(self, corpus):
         assert isinstance(corpus, Corpus)
-        return self.request.user.is_admin or not self.request.user.is_anonymous and \
-            Right.Admin in corpus.get_acl_rights(self.request.user)
+        return Right.Admin in corpus.get_acl_rights(self.request.user)
 
 
 class SearchAPIMixin(CorpusACLMixin):
diff --git a/arkindex/users/managers.py b/arkindex/users/managers.py
index 28c144bfaa05972b626530bf0a1eaadaa4d9e770..34f2ea9122143bf2db0d06e456530c678782ca07 100644
--- a/arkindex/users/managers.py
+++ b/arkindex/users/managers.py
@@ -37,3 +37,8 @@ class UserManager(BaseUserManager):
             # Do not set a token for demo users
             user.auth_token.delete()
         return user
+
+    def create_internal_user(self, email):
+        user = self.create_user(email)
+        user.groups.add(Group.objects.get(id=settings.INTERNAL_GROUP_ID))
+        return user
diff --git a/arkindex/users/tests/test_acl.py b/arkindex/users/tests/test_acl.py
index 950f85631c26cd1d1dbb9767f4cee27d526527b9..efba6b834f28f5ca3e51f1217b005594f2b527c3 100644
--- a/arkindex/users/tests/test_acl.py
+++ b/arkindex/users/tests/test_acl.py
@@ -9,15 +9,18 @@ class TestACL(TestCase):
     Test Corpus ACL
     '''
 
-    def setUp(self):
-        self.anon = AnonymousUser()
-        self.admin = User.objects.create_superuser('admin@address.com', 'P4$5w0Rd')
-        self.user = User.objects.create_user('user@address.com', 'P4$5w0Rd')
+    @classmethod
+    def setUpTestData(cls):
+        super().setUpTestData()
+        cls.anon = AnonymousUser()
+        cls.admin = User.objects.create_superuser('admin@address.com', 'P4$5w0Rd')
+        cls.user = User.objects.create_user('user@address.com', 'P4$5w0Rd')
+        cls.internal = User.objects.create_internal_user('internal@address.com')
 
-        self.corpus_public = Corpus.objects.create(name='A Public', public=True)
-        self.corpus_private = Corpus.objects.create(name='B Private')
-        self.user.corpus_right.create(corpus=self.corpus_private, user=self.user, can_write=True)
-        self.corpus_hidden = Corpus.objects.create(name='C Hidden')
+        cls.corpus_public = Corpus.objects.create(name='A Public', public=True)
+        cls.corpus_private = Corpus.objects.create(name='B Private')
+        cls.user.corpus_right.create(corpus=cls.corpus_private, can_write=True)
+        cls.corpus_hidden = Corpus.objects.create(name='C Hidden')
 
     def test_anon(self):
         # An anonymous user has only access to public
@@ -37,10 +40,19 @@ class TestACL(TestCase):
         )
 
     def test_admin(self):
-        # An admin has access to all
+        # An admin has access to all corpora
         self.assertTrue(self.admin.is_admin)
         self.assertQuerysetEqual(
             Corpus.objects.readable(self.admin),
             Corpus.objects.order_by('name').values_list('id', flat=True),
             transform=lambda x: x.id,
         )
+
+    def test_internal(self):
+        # Internal users have access to all corpora
+        self.assertTrue(self.internal.is_internal)
+        self.assertQuerysetEqual(
+            Corpus.objects.readable(self.admin),
+            Corpus.objects.order_by('name').values_list('id', flat=True),
+            transform=lambda x: x.id,
+        )