ldap: allow provisionning of all user attributes (fixes #30535)

This commit is contained in:
Benjamin Dauvergne 2019-02-11 17:13:12 +01:00 committed by Thomas NOEL
parent 9d96274c7b
commit d28a6bba25
2 changed files with 76 additions and 0 deletions

View File

@ -316,6 +316,8 @@ class LDAPBackend(object):
'connect_with_user_credentials': True,
# can reset password
'can_reset_password': False,
# mapping from LDAP attributes to User attributes
'user_attributes': [],
}
_REQUIRED = ('url', 'basedn')
_TO_ITERABLE = ('url', 'groupsu', 'groupstaff', 'groupactive')
@ -498,6 +500,7 @@ class LDAPBackend(object):
return None
def populate_user_attributes(self, user, block, attributes):
# map legacy attributes (columns from Django user model)
for legacy_attribute, legacy_field in (('email', 'email_field'),
('first_name', 'fname_field'),
('last_name', 'lname_field')):
@ -511,6 +514,24 @@ class LDAPBackend(object):
if getattr(user, legacy_attribute) != value:
setattr(user, legacy_attribute, value)
user._changed = True
# map new style attributes
user_attributes = {}
for mapping in block.get('user_attributes', []):
from_ldap = mapping.get('from_ldap')
to_user = mapping.get('to_user')
if not from_ldap or not to_user:
continue
if not attributes.get(from_ldap):
user_attributes[to_user] = ''
else:
user_attributes[to_user] = attributes[from_ldap][0]
for name in user_attributes:
value = getattr(user.attributes, name, None)
if value != user_attributes[name]:
if not user.pk:
user.save()
setattr(user.attributes, name, user_attributes[name])
user._changed = True
def populate_admin_flags_by_group(self, user, block, group_dns):
'''Attribute admin flags based on groups.
@ -745,6 +766,10 @@ class LDAPBackend(object):
external_id_tuple))
for from_at, to_at in block['attribute_mappings']:
attributes.add(to_at)
for mapping in block['user_attributes']:
from_ldap = mapping.get('from_ldap')
if from_ldap:
attributes.add(from_ldap)
return list(set(map(str.lower, map(str, attributes))))
@classmethod

View File

@ -79,6 +79,7 @@ uid: {uid}
cn: Étienne Michu
sn: Michu
gn: Étienne
l: Paris
mail: etienne.michu@example.net
dn: cn=group1,o=ôrga
@ -94,6 +95,7 @@ uid: michu{i}
cn: Étienne Michu
sn: Michu
gn: Étienne
l: locality{i}
mail: etienne.michu@example.net
'''.format(i=i, password=PASS))
@ -649,3 +651,52 @@ def test_tls(db, tls_slapd, settings, client):
assert result.status_code == 200
assert 'Étienne Michu' in str(result)
assert 'name="username"' not in str(result)
def test_user_attributes(slapd, settings, client, db):
settings.LDAP_AUTH_SETTINGS = [{
'url': [slapd.ldap_url],
'basedn': u'o=ôrga',
'use_tls': False,
'user_attributes': [
{
'from_ldap': 'l',
'to_user': 'locality',
},
]
}]
# create a locality attribute
models.Attribute.objects.create(
label='locality',
name='locality',
kind='string',
required=False,
user_visible=True,
user_editable=False,
asked_on_registration=False,
multiple=False)
client.post('/login/',
{
'login-password-submit': '1',
'username': USERNAME,
'password': PASS
},
follow=True)
username = u'%s@ldap' % USERNAME
user = User.objects.get(username=username)
assert user.attributes.locality == u'Paris'
client.session.flush()
for i in range(5):
client.post('/login/',
{
'login-password-submit': '1',
'username': 'michu%s' % i,
'password': PASS,
},
follow=True)
username = u'michu%s@ldap' % i
user = User.objects.get(username=username)
assert user.attributes.locality == u'locality%s' % i
client.session.flush()