authentik.sources.ldap.sync.forward_delete_groups

 1from collections.abc import Generator
 2from itertools import batched
 3from uuid import uuid4
 4
 5from ldap3 import SUBTREE
 6
 7from authentik.core.models import Group
 8from authentik.sources.ldap.models import GroupLDAPSourceConnection
 9from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer
10from authentik.sources.ldap.sync.forward_delete_users import DELETE_CHUNK_SIZE, UPDATE_CHUNK_SIZE
11
12
13class GroupLDAPForwardDeletion(BaseLDAPSynchronizer):
14    """Delete LDAP Groups from authentik"""
15
16    @staticmethod
17    def name() -> str:
18        return "group_deletions"
19
20    def get_objects(self, **kwargs) -> Generator:
21        if not self._source.sync_groups or not self._source.delete_not_found_objects:
22            self._task.info("Group syncing is disabled for this Source")
23            return iter(())
24
25        uuid = uuid4()
26        groups = self._source.connection().extend.standard.paged_search(
27            search_base=self.base_dn_groups,
28            search_filter=self._source.group_object_filter,
29            search_scope=SUBTREE,
30            attributes=[self._source.object_uniqueness_field],
31            generator=True,
32            **kwargs,
33        )
34        for batch in batched(groups, UPDATE_CHUNK_SIZE, strict=False):
35            identifiers = []
36            for group in batch:
37                if not (attributes := self.get_attributes(group)):
38                    continue
39                if identifier := self.get_identifier(attributes):
40                    identifiers.append(identifier)
41            GroupLDAPSourceConnection.objects.filter(identifier__in=identifiers).update(
42                validated_by=uuid
43            )
44
45        return batched(
46            GroupLDAPSourceConnection.objects.filter(source=self._source)
47            .exclude(validated_by=uuid)
48            .values_list("group", flat=True)
49            .iterator(chunk_size=DELETE_CHUNK_SIZE),
50            DELETE_CHUNK_SIZE,
51            strict=False,
52        )
53
54    def sync(self, group_pks: tuple) -> int:
55        """Delete authentik groups"""
56        if not self._source.sync_groups or not self._source.delete_not_found_objects:
57            self._task.info("Group syncing is disabled for this Source")
58            return -1
59        self._logger.debug("Deleting groups", group_pks=group_pks)
60        _, deleted_per_type = Group.objects.filter(pk__in=group_pks).delete()
61        return deleted_per_type.get(Group._meta.label, 0)
class GroupLDAPForwardDeletion(authentik.sources.ldap.sync.base.BaseLDAPSynchronizer):
14class GroupLDAPForwardDeletion(BaseLDAPSynchronizer):
15    """Delete LDAP Groups from authentik"""
16
17    @staticmethod
18    def name() -> str:
19        return "group_deletions"
20
21    def get_objects(self, **kwargs) -> Generator:
22        if not self._source.sync_groups or not self._source.delete_not_found_objects:
23            self._task.info("Group syncing is disabled for this Source")
24            return iter(())
25
26        uuid = uuid4()
27        groups = self._source.connection().extend.standard.paged_search(
28            search_base=self.base_dn_groups,
29            search_filter=self._source.group_object_filter,
30            search_scope=SUBTREE,
31            attributes=[self._source.object_uniqueness_field],
32            generator=True,
33            **kwargs,
34        )
35        for batch in batched(groups, UPDATE_CHUNK_SIZE, strict=False):
36            identifiers = []
37            for group in batch:
38                if not (attributes := self.get_attributes(group)):
39                    continue
40                if identifier := self.get_identifier(attributes):
41                    identifiers.append(identifier)
42            GroupLDAPSourceConnection.objects.filter(identifier__in=identifiers).update(
43                validated_by=uuid
44            )
45
46        return batched(
47            GroupLDAPSourceConnection.objects.filter(source=self._source)
48            .exclude(validated_by=uuid)
49            .values_list("group", flat=True)
50            .iterator(chunk_size=DELETE_CHUNK_SIZE),
51            DELETE_CHUNK_SIZE,
52            strict=False,
53        )
54
55    def sync(self, group_pks: tuple) -> int:
56        """Delete authentik groups"""
57        if not self._source.sync_groups or not self._source.delete_not_found_objects:
58            self._task.info("Group syncing is disabled for this Source")
59            return -1
60        self._logger.debug("Deleting groups", group_pks=group_pks)
61        _, deleted_per_type = Group.objects.filter(pk__in=group_pks).delete()
62        return deleted_per_type.get(Group._meta.label, 0)

Delete LDAP Groups from authentik

@staticmethod
def name() -> str:
17    @staticmethod
18    def name() -> str:
19        return "group_deletions"

UI name for the type of object this class synchronizes

def get_objects(self, **kwargs) -> Generator:
21    def get_objects(self, **kwargs) -> Generator:
22        if not self._source.sync_groups or not self._source.delete_not_found_objects:
23            self._task.info("Group syncing is disabled for this Source")
24            return iter(())
25
26        uuid = uuid4()
27        groups = self._source.connection().extend.standard.paged_search(
28            search_base=self.base_dn_groups,
29            search_filter=self._source.group_object_filter,
30            search_scope=SUBTREE,
31            attributes=[self._source.object_uniqueness_field],
32            generator=True,
33            **kwargs,
34        )
35        for batch in batched(groups, UPDATE_CHUNK_SIZE, strict=False):
36            identifiers = []
37            for group in batch:
38                if not (attributes := self.get_attributes(group)):
39                    continue
40                if identifier := self.get_identifier(attributes):
41                    identifiers.append(identifier)
42            GroupLDAPSourceConnection.objects.filter(identifier__in=identifiers).update(
43                validated_by=uuid
44            )
45
46        return batched(
47            GroupLDAPSourceConnection.objects.filter(source=self._source)
48            .exclude(validated_by=uuid)
49            .values_list("group", flat=True)
50            .iterator(chunk_size=DELETE_CHUNK_SIZE),
51            DELETE_CHUNK_SIZE,
52            strict=False,
53        )

Get objects from LDAP, implemented in subclass

def sync(self, group_pks: tuple) -> int:
55    def sync(self, group_pks: tuple) -> int:
56        """Delete authentik groups"""
57        if not self._source.sync_groups or not self._source.delete_not_found_objects:
58            self._task.info("Group syncing is disabled for this Source")
59            return -1
60        self._logger.debug("Deleting groups", group_pks=group_pks)
61        _, deleted_per_type = Group.objects.filter(pk__in=group_pks).delete()
62        return deleted_per_type.get(Group._meta.label, 0)

Delete authentik groups