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