From c294ae39fbbd774018ea512dd5e37b25fa317a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Wed, 31 Oct 2018 10:17:31 +0100 Subject: [PATCH] ldap: don't crash on duplicated users (#27697) And keep roles on the more recently used user, then delete the other ones. --- src/authentic2/backends/ldap_backend.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/authentic2/backends/ldap_backend.py b/src/authentic2/backends/ldap_backend.py index 257311d9..04a5643a 100644 --- a/src/authentic2/backends/ldap_backend.py +++ b/src/authentic2/backends/ldap_backend.py @@ -834,12 +834,22 @@ class LDAPBackend(object): external_id = self.build_external_id(eid_tuple, attributes) if not external_id: continue - try: - log.debug('lookup using external_id %r: %r', eid_tuple, external_id) - return LDAPUser.objects.prefetch_related('groups').get( - userexternalid__external_id=external_id, userexternalid__source=block['realm']) - except User.DoesNotExist: - pass + log.debug('lookup using external_id %r: %r', eid_tuple, external_id) + users = LDAPUser.objects.prefetch_related('groups').filter( + userexternalid__external_id__iexact=external_id, + userexternalid__source=block['realm']).order_by('-last_login') + # ordering of NULLs cannot be done through the ORM + users = sorted(users, reverse=True, key=lambda u: u.last_login) + if users: + user = users[0] + if len(users) > 1: + log.debug('found %d users, collectings roles into the first one and deleting the other ones.', + len(users)) + for other in users[1:]: + user.roles.add(other.roles.all()) + other.delete() + return user + return None def lookup_existing_user(self, username, block, attributes): for lookup_type in block['lookups']: -- 2.19.1