From 0455c73e498e93ba23a7e5b728af6d7d11867ccb Mon Sep 17 00:00:00 2001 From: Valentin Rigal <rigal@teklia.com> Date: Thu, 10 Dec 2020 13:29:22 +0100 Subject: [PATCH] Mixin tests --- arkindex/project/tests/test_acl_mixin.py | 102 ++++++++++++++++++++++ arkindex/sql_validation/right_access.sql | 13 +++ arkindex/sql_validation/rights_filter.sql | 17 ++++ 3 files changed, 132 insertions(+) create mode 100644 arkindex/project/tests/test_acl_mixin.py create mode 100644 arkindex/sql_validation/right_access.sql create mode 100644 arkindex/sql_validation/rights_filter.sql diff --git a/arkindex/project/tests/test_acl_mixin.py b/arkindex/project/tests/test_acl_mixin.py new file mode 100644 index 0000000000..6ddc9d45f6 --- /dev/null +++ b/arkindex/project/tests/test_acl_mixin.py @@ -0,0 +1,102 @@ +from django.contrib.contenttypes.models import ContentType + +from arkindex.dataimport.models import Repository, RepositoryType +from arkindex.documents.models import Corpus +from arkindex.project.mixins import ACLMixin +from arkindex.project.tests import FixtureTestCase +from arkindex.users.models import Group, Right, User + + +class TestACLMixin(FixtureTestCase): + + @classmethod + def setUpClass(cls): + r""" + Create user and groups with rights on a Corpus and a Repository + We use a simple rights configuration for those tests + + User1 User2 User3 + | | | / | + 100 10 | 80 | + \ / 90 | 75 + Group1 | Group2 | + / \ | /\ | + 100 75 | 100 50 | + | \ | / \ | + Repo1 Corpus1 Corpus2 + """ + + super().setUpClass() + cls.user1 = User.objects.create_user('user1@test.test', display_name='User1') + cls.user2 = User.objects.create_user('user2@test.test', display_name='User2') + cls.user3 = User.objects.create_user('user3@test.test', display_name='User3') + + cls.group1 = Group.objects.create(name='Group1') + cls.group2 = Group.objects.create(name='Group2') + + cls.repo1 = Repository.objects.create(type=RepositoryType.Worker, url='http://repo1') + cls.corpus1 = Corpus.objects.create(name="Corpus1") + cls.corpus2 = Corpus.objects.create(name="Corpus2") + + Right.objects.bulk_create([ + Right(user=cls.user1, content_object=cls.group1, level=100), + Right(user=cls.user2, content_object=cls.group1, level=10), + Right(user=cls.user3, content_object=cls.group2, level=80), + Right(user=cls.user2, content_object=cls.corpus1, level=90), + Right(user=cls.user3, content_object=cls.corpus2, level=75), + Right(group=cls.group1, content_object=cls.repo1, level=100), + Right(group=cls.group1, content_object=cls.corpus1, level=75), + Right(group=cls.group2, content_object=cls.corpus1, level=100), + Right(group=cls.group2, content_object=cls.corpus2, level=50), + ]) + cls.corpus_type = ContentType.objects.get_for_model(Corpus) + cls.group_type = ContentType.objects.get_for_model(Group) + + def test_right_via_group_restriction(self): + # User rights on corpora via a group are restricted to the group level + acl_mixin = ACLMixin(self.user3) + params = { + 'user_id': self.user3.id, + 'group_id': self.group2.id, + 'group_type_id': self.group_type.id, + 'corpus_type_id': self.corpus_type.id, + 'level': 80, + } + with self.assertExactQueries('rights_filter.sql', params=params): + # List to queryset to fire the DB request + queryset_list = list(acl_mixin.rights_filter(Corpus, 80)) + self.assertCountEqual( + queryset_list, + [self.corpus1] + ) + + def test_right_direct_access(self): + # User 2 has a direct access to the above corpus with a level of 90 + acl_mixin = ACLMixin(self.user2) + params = { + 'user_id': self.user2.id, + 'group_id': self.group2.id, + 'corpus_id': self.corpus1.id, + 'group_type_id': self.group_type.id, + 'corpus_type_id': self.corpus_type.id, + 'level': 80, + } + with self.assertExactQueries('right_access.sql', params=params): + has_access = acl_mixin.has_access(self.corpus1, 80) + self.assertTrue(has_access) + + def test_right_group_members_restriction(self): + # User rights on corpora via a group are restricted to user level inside the group + acl_mixin = ACLMixin(self.user1) + self.assertFalse( + acl_mixin.has_access(self.corpus1, 80) + ) + + def test_has_read_access_null(self): + # Only instances with defined level may pass mixin acces check + acl_mixin = ACLMixin(self.user1) + # User1 has the maximun level on the repository but write access level is not declared + self.assertFalse(hasattr(self.repo1, 'WRITE_LEVEL')) + self.assertFalse(acl_mixin.has_write_access(self.repo1)) + # However he has an execute privilege for this repository + self.assertTrue(acl_mixin.has_execute_access(self.repo1)) diff --git a/arkindex/sql_validation/right_access.sql b/arkindex/sql_validation/right_access.sql new file mode 100644 index 0000000000..b04ae0a56f --- /dev/null +++ b/arkindex/sql_validation/right_access.sql @@ -0,0 +1,13 @@ +SELECT (1) AS "a" +FROM "users_right" +LEFT OUTER JOIN "users_group" ON ("users_right"."group_id" = "users_group"."id") +LEFT OUTER JOIN "users_right" T5 ON ("users_group"."id" = T5."content_id" + AND (T5."content_type_id" = {group_type_id})) +WHERE ("users_right"."content_id" = '{corpus_id}'::uuid + AND "users_right"."content_type_id" = {corpus_type_id} + AND (("users_right"."user_id" = {user_id} + AND "users_right"."level" >= {level}) + OR (T5."user_id" = {user_id} + AND "users_right"."level" >= {level} + AND T5."level" >= {level}))) +LIMIT 1 diff --git a/arkindex/sql_validation/rights_filter.sql b/arkindex/sql_validation/rights_filter.sql new file mode 100644 index 0000000000..1ae974fc3a --- /dev/null +++ b/arkindex/sql_validation/rights_filter.sql @@ -0,0 +1,17 @@ +SELECT DISTINCT "documents_corpus"."created", + "documents_corpus"."updated", + "documents_corpus"."id", + "documents_corpus"."name", + "documents_corpus"."description", + "documents_corpus"."repository_id", + "documents_corpus"."public", + LEAST("users_right"."level", T5."level") AS "max_level" +FROM "documents_corpus" +INNER JOIN "users_right" ON ("documents_corpus"."id" = "users_right"."content_id" + AND ("users_right"."content_type_id" = {corpus_type_id})) +LEFT OUTER JOIN "users_group" ON ("users_right"."group_id" = "users_group"."id") +LEFT OUTER JOIN "users_right" T5 ON ("users_group"."id" = T5."content_id" + AND (T5."content_type_id" = {group_type_id})) +WHERE (("users_right"."user_id" = {user_id} + OR T5."user_id" = {user_id}) + AND LEAST("users_right"."level", T5."level") >= {level}) -- GitLab