Project

General

Profile

0002-ldap-allow-provisionning-of-all-user-attributes-fixe.patch

Benjamin Dauvergne, 12 Feb 2019 09:50 AM

Download (5.03 KB)

View differences:

Subject: [PATCH 2/2] ldap: allow provisionning of all user attributes (fixes
 #30535)

 src/authentic2/backends/ldap_backend.py | 25 ++++++++++++
 tests/test_ldap.py                      | 51 +++++++++++++++++++++++++
 2 files changed, 76 insertions(+)
src/authentic2/backends/ldap_backend.py
316 316
        'connect_with_user_credentials': True,
317 317
        # can reset password
318 318
        'can_reset_password': False,
319
        # mapping from LDAP attributes to User attributes
320
        'user_attributes': [],
319 321
    }
320 322
    _REQUIRED = ('url', 'basedn')
321 323
    _TO_ITERABLE = ('url', 'groupsu', 'groupstaff', 'groupactive')
......
498 500
            return None
499 501

  
500 502
    def populate_user_attributes(self, user, block, attributes):
503
        # map legacy attributes (columns from Django user model)
501 504
        for legacy_attribute, legacy_field in (('email', 'email_field'),
502 505
                                               ('first_name', 'fname_field'),
503 506
                                               ('last_name', 'lname_field')):
......
511 514
            if getattr(user, legacy_attribute) != value:
512 515
                setattr(user, legacy_attribute, value)
513 516
                user._changed = True
517
        # map new style attributes
518
        user_attributes = {}
519
        for mapping in block.get('user_attributes', []):
520
            from_ldap = mapping.get('from_ldap')
521
            to_user = mapping.get('to_user')
522
            if not from_ldap or not to_user:
523
                continue
524
            if not attributes.get(from_ldap):
525
                user_attributes[to_user] = ''
526
            else:
527
                user_attributes[to_user] = attributes[from_ldap][0]
528
        for name in user_attributes:
529
            value = getattr(user.attributes, name, None)
530
            if value != user_attributes[name]:
531
                if not user.pk:
532
                    user.save()
533
                setattr(user.attributes, name, user_attributes[name])
534
                user._changed = True
514 535

  
515 536
    def populate_admin_flags_by_group(self, user, block, group_dns):
516 537
        '''Attribute admin flags based on groups.
......
745 766
                external_id_tuple))
746 767
        for from_at, to_at in block['attribute_mappings']:
747 768
            attributes.add(to_at)
769
        for mapping in block['user_attributes']:
770
            from_ldap = mapping.get('from_ldap')
771
            if from_ldap:
772
                attributes.add(from_ldap)
748 773
        return list(set(map(str.lower, map(str, attributes))))
749 774

  
750 775
    @classmethod
tests/test_ldap.py
79 79
cn: Étienne Michu
80 80
sn: Michu
81 81
gn: Étienne
82
l: Paris
82 83
mail: etienne.michu@example.net
83 84

  
84 85
dn: cn=group1,o=ôrga
......
94 95
cn: Étienne Michu
95 96
sn: Michu
96 97
gn: Étienne
98
l: locality{i}
97 99
mail: etienne.michu@example.net
98 100

  
99 101
'''.format(i=i, password=PASS))
......
649 651
    assert result.status_code == 200
650 652
    assert 'Étienne Michu' in str(result)
651 653
    assert 'name="username"' not in str(result)
654

  
655

  
656
def test_user_attributes(slapd, settings, client, db):
657
    settings.LDAP_AUTH_SETTINGS = [{
658
        'url': [slapd.ldap_url],
659
        'basedn': u'o=ôrga',
660
        'use_tls': False,
661
        'user_attributes': [
662
            {
663
                'from_ldap': 'l',
664
                'to_user': 'locality',
665
            },
666
        ]
667
    }]
668

  
669
    # create a locality attribute
670
    models.Attribute.objects.create(
671
        label='locality',
672
        name='locality',
673
        kind='string',
674
        required=False,
675
        user_visible=True,
676
        user_editable=False,
677
        asked_on_registration=False,
678
        multiple=False)
679

  
680
    client.post('/login/',
681
                {
682
                    'login-password-submit': '1',
683
                    'username': USERNAME,
684
                    'password': PASS
685
                },
686
                follow=True)
687
    username = u'%s@ldap' % USERNAME
688
    user = User.objects.get(username=username)
689
    assert user.attributes.locality == u'Paris'
690
    client.session.flush()
691
    for i in range(5):
692
        client.post('/login/',
693
                    {
694
                        'login-password-submit': '1',
695
                        'username': 'michu%s' % i,
696
                        'password': PASS,
697
                    },
698
                    follow=True)
699
        username = u'michu%s@ldap' % i
700
        user = User.objects.get(username=username)
701
        assert user.attributes.locality == u'locality%s' % i
702
        client.session.flush()
652
-