ldap: Continue syncing other fields even if a field is missing.

Earlier the behavior was to raise an exception thereby stopping the
whole sync. Now we log an error message and skip the field. Also
fixes the `query_ldap` command to report missing fields without
error.

Fixes: #11780.
This commit is contained in:
Harshit Bansal 2019-03-05 08:40:40 +00:00 committed by Tim Abbott
parent 58d28eed5d
commit 4a9bd89f47
3 changed files with 26 additions and 3 deletions

View File

@ -17,9 +17,9 @@ def query_ldap(**options: str) -> None:
print("No such user found")
else:
for django_field, ldap_field in settings.AUTH_LDAP_USER_ATTR_MAP.items():
value = ldap_attrs[ldap_field]
value = ldap_attrs.get(ldap_field, ["LDAP field not present", ])[0]
if django_field == "avatar":
if isinstance(value[0], bytes):
if isinstance(value, bytes):
value = "(An avatar image file)"
print("%s: %s" % (django_field, value))
if settings.LDAP_EMAIL_ATTR is not None:

View File

@ -2897,6 +2897,23 @@ class TestZulipLDAPUserPopulator(ZulipLDAPTestCase):
self.perform_ldap_sync(self.example_user('hamlet'))
f.assert_called_once_with(*expected_call_args)
def test_update_custom_profile_field_not_present_in_ldap(self) -> None:
self.mock_ldap.directory = {
'uid=hamlet,ou=users,dc=zulip,dc=com': {
'cn': ['King Hamlet', ],
}
}
hamlet = self.example_user('hamlet')
no_op_field = CustomProfileField.objects.get(realm=hamlet.realm, name='Birthday')
expected_value = CustomProfileFieldValue.objects.get(user_profile=hamlet, field=no_op_field).value
with self.settings(AUTH_LDAP_USER_ATTR_MAP={'full_name': 'cn',
'custom_profile_field__birthday': 'birthDate'}):
self.perform_ldap_sync(self.example_user('hamlet'))
actual_value = CustomProfileFieldValue.objects.get(user_profile=hamlet, field=no_op_field).value
self.assertEqual(actual_value, expected_value)
class TestZulipAuthMixin(ZulipTestCase):
def test_get_user(self) -> None:
backend = ZulipAuthMixin()

View File

@ -347,7 +347,13 @@ class ZulipLDAPAuthBackendBase(ZulipAuthMixin, LDAPBackend):
if not attr.startswith('custom_profile_field__'):
continue
var_name = attr.split('custom_profile_field__')[1]
try:
value = ldap_user.attrs[ldap_attr][0]
except KeyError:
# If this user doesn't have this field set then ignore this
# field and continue syncing other fields. `django-auth-ldap`
# automatically logs error about missing field.
continue
values_by_var_name[var_name] = value
fields_by_var_name = {} # type: Dict[str, CustomProfileField]