core: add limit of 20 to group recursion
closes #3116 Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		@ -106,7 +106,10 @@ class Group(models.Model):
 | 
			
		||||
 | 
			
		||||
            SELECT authentik_core_group.*, parents.relative_depth - 1
 | 
			
		||||
            FROM authentik_core_group,parents
 | 
			
		||||
            WHERE authentik_core_group.parent_id = parents.group_uuid
 | 
			
		||||
            WHERE (
 | 
			
		||||
                authentik_core_group.parent_id = parents.group_uuid and
 | 
			
		||||
                parents.relative_depth > -20
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        SELECT group_uuid
 | 
			
		||||
        FROM parents
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@
 | 
			
		||||
from django.test.testcases import TestCase
 | 
			
		||||
 | 
			
		||||
from authentik.core.models import Group, User
 | 
			
		||||
from authentik.lib.generators import generate_id
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestGroups(TestCase):
 | 
			
		||||
@ -9,32 +10,43 @@ class TestGroups(TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_group_membership_simple(self):
 | 
			
		||||
        """Test simple membership"""
 | 
			
		||||
        user = User.objects.create(username="user")
 | 
			
		||||
        user2 = User.objects.create(username="user2")
 | 
			
		||||
        group = Group.objects.create(name="group")
 | 
			
		||||
        user = User.objects.create(username=generate_id())
 | 
			
		||||
        user2 = User.objects.create(username=generate_id())
 | 
			
		||||
        group = Group.objects.create(name=generate_id())
 | 
			
		||||
        group.users.add(user)
 | 
			
		||||
        self.assertTrue(group.is_member(user))
 | 
			
		||||
        self.assertFalse(group.is_member(user2))
 | 
			
		||||
 | 
			
		||||
    def test_group_membership_parent(self):
 | 
			
		||||
        """Test parent membership"""
 | 
			
		||||
        user = User.objects.create(username="user")
 | 
			
		||||
        user2 = User.objects.create(username="user2")
 | 
			
		||||
        first = Group.objects.create(name="first")
 | 
			
		||||
        second = Group.objects.create(name="second", parent=first)
 | 
			
		||||
        user = User.objects.create(username=generate_id())
 | 
			
		||||
        user2 = User.objects.create(username=generate_id())
 | 
			
		||||
        first = Group.objects.create(name=generate_id())
 | 
			
		||||
        second = Group.objects.create(name=generate_id(), parent=first)
 | 
			
		||||
        second.users.add(user)
 | 
			
		||||
        self.assertTrue(first.is_member(user))
 | 
			
		||||
        self.assertFalse(first.is_member(user2))
 | 
			
		||||
 | 
			
		||||
    def test_group_membership_parent_extra(self):
 | 
			
		||||
        """Test parent membership"""
 | 
			
		||||
        user = User.objects.create(username="user")
 | 
			
		||||
        user2 = User.objects.create(username="user2")
 | 
			
		||||
        first = Group.objects.create(name="first")
 | 
			
		||||
        second = Group.objects.create(name="second", parent=first)
 | 
			
		||||
        third = Group.objects.create(name="third", parent=second)
 | 
			
		||||
        user = User.objects.create(username=generate_id())
 | 
			
		||||
        user2 = User.objects.create(username=generate_id())
 | 
			
		||||
        first = Group.objects.create(name=generate_id())
 | 
			
		||||
        second = Group.objects.create(name=generate_id(), parent=first)
 | 
			
		||||
        third = Group.objects.create(name=generate_id(), parent=second)
 | 
			
		||||
        second.users.add(user)
 | 
			
		||||
        self.assertTrue(first.is_member(user))
 | 
			
		||||
        self.assertFalse(first.is_member(user2))
 | 
			
		||||
        self.assertFalse(third.is_member(user))
 | 
			
		||||
        self.assertFalse(third.is_member(user2))
 | 
			
		||||
 | 
			
		||||
    def test_group_membership_recursive(self):
 | 
			
		||||
        """Test group membership (recursive)"""
 | 
			
		||||
        user = User.objects.create(username=generate_id())
 | 
			
		||||
        group = Group.objects.create(name=generate_id())
 | 
			
		||||
        group2 = Group.objects.create(name=generate_id(), parent=group)
 | 
			
		||||
        group.users.add(user)
 | 
			
		||||
        group.parent = group2
 | 
			
		||||
        group.save()
 | 
			
		||||
        self.assertTrue(group.is_member(user))
 | 
			
		||||
        self.assertTrue(group2.is_member(user))
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,11 @@ slug: "2022.7"
 | 
			
		||||
 | 
			
		||||
    Instead, create an OAuth Source with the certificate configured as JWKS Data, and enable the source in the provider.
 | 
			
		||||
 | 
			
		||||
-   Maximum Limit of group recursion
 | 
			
		||||
 | 
			
		||||
    In earlier versions, cyclic group relations can lead to a deadlock when one of groups in the relationship are bound to an application/flow/etc.
 | 
			
		||||
    This is now limited to 20 levels of recursion.
 | 
			
		||||
 | 
			
		||||
## New features
 | 
			
		||||
 | 
			
		||||
-   User paths
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,8 @@ Groups can be children of another group. Members of children groups are effectiv
 | 
			
		||||
 | 
			
		||||
When you bind a group to an application or flow, any members of any child group of the selected group will have access.
 | 
			
		||||
 | 
			
		||||
Recursion is limited to 20 levels to prevent deadlocks.
 | 
			
		||||
 | 
			
		||||
## Attributes
 | 
			
		||||
 | 
			
		||||
Attributes of groups are recursively merged, for all groups the user is a _direct_ member of.
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user