ldap: don't crash on duplicated users (#27697)
Keep roles on the more recently used user, then delete the other ones'.
This commit is contained in:
parent
422bd6a5d7
commit
4db66981f0
|
@ -834,12 +834,23 @@ 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__iexact=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 is not None, u.last_login))
|
||||
if users:
|
||||
user = users[0]
|
||||
if len(users) > 1:
|
||||
log.info('found %d users, collectings roles into the first one and deleting the other ones.',
|
||||
len(users))
|
||||
for other in users[1:]:
|
||||
for r in other.roles.all():
|
||||
user.roles.add(r)
|
||||
other.delete()
|
||||
return user
|
||||
return None
|
||||
|
||||
def lookup_existing_user(self, username, block, attributes):
|
||||
for lookup_type in block['lookups']:
|
||||
|
|
|
@ -11,6 +11,7 @@ from django.contrib.auth import get_user_model
|
|||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core import mail
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils import timezone
|
||||
|
||||
from authentic2.a2_rbac.utils import get_default_ou
|
||||
from django_rbac.utils import get_ou_model
|
||||
|
@ -416,6 +417,20 @@ def test_get_users(slapd, settings):
|
|||
assert save.call_count == 0
|
||||
assert bulk_create.call_count == 0
|
||||
|
||||
# create user with the same username, but case-different
|
||||
save.reset_mock()
|
||||
bulk_create.reset_mock()
|
||||
u = ldap_backend.LDAPUser.objects.create(username=UID.capitalize())
|
||||
eid = ldap_backend.UserExternalId.objects.create(external_id=UID.capitalize(),
|
||||
source='ldap', user=u)
|
||||
# set user login time as if he logged in
|
||||
user = ldap_backend.LDAPUser.objects.get(username='%s@ldap'%UID)
|
||||
user.last_login = timezone.now()
|
||||
user.save()
|
||||
assert ldap_backend.LDAPUser.objects.count() == 102
|
||||
users = list(ldap_backend.LDAPBackend.get_users())
|
||||
assert len(users) == 101
|
||||
assert ldap_backend.LDAPUser.objects.filter(username='%s' % UID.capitalize()).count() == 0
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_set_mandatory_roles(slapd, settings):
|
||||
|
|
Loading…
Reference in New Issue