From d43a09c25c39ccdd70c799fc5331e12dc127646a Mon Sep 17 00:00:00 2001
From: Julian Rother <julian@cccv.de>
Date: Wed, 6 Apr 2022 12:33:09 +0200
Subject: [PATCH] Deactivate users instead of deleting them in syncldap command

Deleting users can cause all kinds of inconsistencies (depending on the
Django application). The Django docs also recommends deactivating users
instead of deleting them.

Fixes #2
---
 .../management/commands/syncldap.py           | 25 ++++++++++++++-----
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/django_auth_ldap_remoteuser/management/commands/syncldap.py b/django_auth_ldap_remoteuser/management/commands/syncldap.py
index 92fd7d2..0d2bbee 100644
--- a/django_auth_ldap_remoteuser/management/commands/syncldap.py
+++ b/django_auth_ldap_remoteuser/management/commands/syncldap.py
@@ -36,11 +36,24 @@ class Command(BaseCommand):
 
 		user_search = django.conf.settings.AUTH_LDAP_USER_SEARCH_ALL_NAME
 		results = execute_ldap_search_without_hiding_errors(user_search, conn)
-		ldap_users = [list(attr.values())[0][0] for dn, attr in results ]
+		ldap_usernames = [list(attr.values())[0][0] for dn, attr in results]
 		django_users = get_user_model().objects.all()
-
-		for user in ldap_users:
-			ldap_backend.populate_user(user).save()
+		for username in ldap_usernames:
+			print('creating or updating', username)
+			# ldap_backend.populate_user also eats LDAP errors and returns None if
+			# they occur. It also returns None if the user is not found in the LDAP
+			# directory.
+			user = ldap_backend.populate_user(username)
+			if user is None:
+				# If we end up here due to an LDAP error, it is most likely temporary.
+				# Alternativly we end up here because the user was deleted in LDAP
+				# after our initial user search (for ldap_usernames) (i.e. a race
+				# condition, also temporary). So we abort and hope the next run of the
+				# sync command works.
+				raise Exception('LDAP lookup of a user failed for some reason, probably due to a connection error')
+			user.save()
 		for user in django_users:
-			if not user.username in ldap_users:
-				user.delete()
+			if not user.username in ldap_usernames:
+				print('deactivating', user.username)
+				user.is_active = False
+				user.save()
-- 
GitLab