0001-ldap-don-t-crash-on-duplicated-users-27697.patch
src/authentic2/backends/ldap_backend.py | ||
---|---|---|
834 | 834 |
external_id = self.build_external_id(eid_tuple, attributes) |
835 | 835 |
if not external_id: |
836 | 836 |
continue |
837 |
try: |
|
838 |
log.debug('lookup using external_id %r: %r', eid_tuple, external_id) |
|
839 |
return LDAPUser.objects.prefetch_related('groups').get( |
|
840 |
userexternalid__external_id__iexact=external_id, userexternalid__source=block['realm']) |
|
841 |
except User.DoesNotExist: |
|
842 |
pass |
|
837 |
log.debug('lookup using external_id %r: %r', eid_tuple, external_id) |
|
838 |
users = LDAPUser.objects.prefetch_related('groups').filter( |
|
839 |
userexternalid__external_id__iexact=external_id, |
|
840 |
userexternalid__source=block['realm']).order_by('-last_login') |
|
841 |
# ordering of NULLs cannot be done through the ORM |
|
842 |
users = sorted(users, reverse=True, key=lambda u: (u.last_login is None, u.last_login)) |
|
843 |
if users: |
|
844 |
user = users[0] |
|
845 |
if len(users) > 1: |
|
846 |
log.info('found %d users, collectings roles into the first one and deleting the other ones.', |
|
847 |
len(users)) |
|
848 |
for other in users[1:]: |
|
849 |
for r in other.roles.all(): |
|
850 |
user.roles.add(r) |
|
851 |
other.delete() |
|
852 |
return user |
|
853 |
return None |
|
843 | 854 | |
844 | 855 |
def lookup_existing_user(self, username, block, attributes): |
845 | 856 |
for lookup_type in block['lookups']: |
tests/test_ldap.py | ||
---|---|---|
11 | 11 |
from django.core.exceptions import ImproperlyConfigured |
12 | 12 |
from django.core import mail |
13 | 13 |
from django.utils.encoding import force_text |
14 |
from django.utils import timezone |
|
14 | 15 | |
15 | 16 |
from authentic2.a2_rbac.utils import get_default_ou |
16 | 17 |
from django_rbac.utils import get_ou_model |
... | ... | |
416 | 417 |
assert save.call_count == 0 |
417 | 418 |
assert bulk_create.call_count == 0 |
418 | 419 | |
420 |
# create user with the same username, but case-different |
|
421 |
save.reset_mock() |
|
422 |
bulk_create.reset_mock() |
|
423 |
u = ldap_backend.LDAPUser.objects.create(username=UID.capitalize()) |
|
424 |
eid = ldap_backend.UserExternalId.objects.create(external_id=UID.capitalize(), |
|
425 |
source='ldap', user=u) |
|
426 |
# set user login time as if it loggued in |
|
427 |
user = ldap_backend.LDAPUser.objects.get(username='%s@ldap'%UID) |
|
428 |
user.last_login = timezone.now() |
|
429 |
user.save() |
|
430 |
assert ldap_backend.LDAPUser.objects.count() == 102 |
|
431 |
users = list(ldap_backend.LDAPBackend.get_users()) |
|
432 |
assert len(users) == 101 |
|
433 |
assert ldap_backend.LDAPUser.objects.filter(username='%s' % UID.capitalize()).count() == 1 |
|
419 | 434 | |
420 | 435 |
@pytest.mark.django_db |
421 | 436 |
def test_set_mandatory_roles(slapd, settings): |
422 |
- |