0001-ldap-perform-extensive-user-lookup-regardless-of-the.patch
src/authentic2/backends/ldap_backend.py | ||
---|---|---|
1359 | 1359 |
return ' '.join(part for part in parts) |
1360 | 1360 | |
1361 | 1361 |
def _lookup_user_queryset(self, block): |
1362 |
return LDAPUser.objects.prefetch_related('groups').exclude(userexternalid__source=block['realm']) |
|
1362 |
ueids = UserExternalId.objects.filter(source=block['realm']) |
|
1363 |
return User.objects.prefetch_related('groups').exclude( |
|
1364 |
id__in=ueids.values_list('user__id', flat=True) |
|
1365 |
) |
|
1363 | 1366 | |
1364 | 1367 |
def _lookup_by_username(self, ou, block, username): |
1365 | 1368 |
try: |
1366 | 1369 |
log.debug('ldap: lookup using username %r', username) |
1367 | 1370 |
return self._lookup_user_queryset(block=block).get(ou=ou, username=username) |
1368 |
except LDAPUser.DoesNotExist:
|
|
1371 |
except User.DoesNotExist: |
|
1369 | 1372 |
return None |
1370 |
except LDAPUser.MultipleObjectsReturned:
|
|
1373 |
except User.MultipleObjectsReturned: |
|
1371 | 1374 |
log.warning( |
1372 | 1375 |
'ldap: lookup using username %r, too many users with this username in ou "%s"', username, ou |
1373 | 1376 |
) |
... | ... | |
1384 | 1387 |
try: |
1385 | 1388 |
log.debug('ldap: lookup using email %r', email) |
1386 | 1389 |
return self._lookup_user_queryset(block=block).get(ou=ou, email=email) |
1387 |
except LDAPUser.DoesNotExist:
|
|
1390 |
except User.DoesNotExist: |
|
1388 | 1391 |
return None |
1389 |
except LDAPUser.MultipleObjectsReturned:
|
|
1392 |
except User.MultipleObjectsReturned: |
|
1390 | 1393 |
log.warning('ldap: lookup using email %r, too many users with this email in ou "%s"', email, ou) |
1391 | 1394 |
return None |
1392 | 1395 | |
... | ... | |
1583 | 1586 |
user = LDAPUser(username=username) |
1584 | 1587 |
user._created = True |
1585 | 1588 |
user.set_unusable_password() |
1586 |
user.ldap_init(block, dn) |
|
1587 |
user.keep_password(password) |
|
1588 |
self.populate_user(user, dn, username, conn, block, attributes) |
|
1589 |
if isinstance(user, LDAPUser): |
|
1590 |
user.ldap_init(block, dn) |
|
1591 |
user.keep_password(password) |
|
1592 |
self.populate_user(user, dn, username, conn, block, attributes) |
|
1589 | 1593 |
if not user.pk or getattr(user, '_changed', False): |
1590 | 1594 |
user.save() |
1591 | 1595 | |
... | ... | |
1652 | 1656 |
if not user: |
1653 | 1657 |
log.warning('unable to retrieve user for dn %s', dn) |
1654 | 1658 |
continue |
1655 |
if user._changed or user._created:
|
|
1659 |
if isinstance(user, LDAPUser) and (user._changed or user._created):
|
|
1656 | 1660 |
log.info( |
1657 | 1661 |
'%s user %s (uuid %s) from %s', |
1658 | 1662 |
'Created' if user._created else 'Updated', |
tests/test_ldap.py | ||
---|---|---|
771 | 771 |
'group_to_role_mapping': [ |
772 | 772 |
['cn=unknown,o=dn', ['Role2']], |
773 | 773 |
], |
774 |
'lookups': ['external_id', 'username'], |
|
774 |
'lookups': ['external_id', 'username', 'email'],
|
|
775 | 775 |
} |
776 | 776 |
] |
777 | 777 |
save = mock.Mock(wraps=ldap_backend.LDAPUser.save) |
... | ... | |
2324 | 2324 |
return ldap_backend.LDAPBackend() |
2325 | 2325 | |
2326 | 2326 |
def test_by_email(self, backend, slapd, settings, client, db): |
2327 |
user = User.objects.create(email=EMAIL, ou=get_default_ou()) |
|
2327 |
user = User.objects.create(email=EMAIL, ou=get_default_ou(), username=USERNAME)
|
|
2328 | 2328 |
assert backend.authenticate(None, username=USERNAME, password=PASS) == user |
2329 |
assert models.UserExternalId.objects.get(user=user, source='ldap', external_id=UID) |
|
2329 |
# user existed before ldap authn, we do not consider ldap as its source |
|
2330 |
assert not models.UserExternalId.objects.filter(user=user, source='ldap', external_id=UID).count() |
|
2330 | 2331 |
user.email = '' |
2331 | 2332 |
user.save() |
2332 |
# if email is changed |
|
2333 | 2333 |
auth_user = backend.authenticate(None, username=USERNAME, password=PASS) |
2334 |
# we do not modify pre-existing users |
|
2334 | 2335 |
assert auth_user == user |
2335 |
assert auth_user.email == EMAIL
|
|
2336 |
assert auth_user.email == ''
|
|
2336 | 2337 | |
2337 | 2338 |
def test_by_email_only(self, backend, slapd, settings, client, db): |
2338 | 2339 |
settings.LDAP_AUTH_SETTINGS[0]['lookups'] = ['email'] |
... | ... | |
2346 | 2347 |
assert new_user.email == EMAIL |
2347 | 2348 | |
2348 | 2349 |
def test_by_username(self, backend, slapd, settings, client, db): |
2349 |
user = User.objects.create(username=UID, ou=get_default_ou()) |
|
2350 |
user = User.objects.create(username=UID, email=EMAIL, ou=get_default_ou())
|
|
2350 | 2351 |
assert backend.authenticate(None, username=EMAIL, password=PASS) == user |
2351 |
assert models.UserExternalId.objects.get(user=user, source='ldap', external_id=UID) |
|
2352 |
# user existed before ldap authn, we do not consider ldap as its source |
|
2353 |
assert not models.UserExternalId.objects.filter(user=user, source='ldap', external_id=UID).count() |
|
2352 | 2354 |
user.username = '' |
2353 | 2355 |
user.save() |
2354 | 2356 |
auth_user = backend.authenticate(None, username=EMAIL, password=PASS) |
... | ... | |
2356 | 2358 |
assert auth_user.username == '' |
2357 | 2359 |
settings.LDAP_AUTH_SETTINGS[0]['update_username'] = True |
2358 | 2360 |
auth_user = backend.authenticate(None, username=EMAIL, password=PASS) |
2361 |
# we do not modify pre-existing users |
|
2359 | 2362 |
assert auth_user == user |
2360 |
assert auth_user.username == f'{UID}@ldap'
|
|
2363 |
assert auth_user.username == ''
|
|
2361 | 2364 | |
2362 | 2365 |
def test_by_guid_migration(self, backend, slapd, settings, client, db): |
2363 | 2366 |
settings.LDAP_AUTH_SETTINGS[0]['lookups'] = ['external_id'] |
2364 |
- |