Django

Code

Ticket #2507: backends.py.diff

File backends.py.diff, 5.8 kB (added by spr@mahonri5.net, 2 years ago)

patch

  • backends.py

    old new  
    11from django.contrib.auth.models import User 
     2from django.conf import settings 
    23 
    34class ModelBackend: 
    45    """ 
     
    1920            return User.objects.get(pk=user_id) 
    2021        except User.DoesNotExist: 
    2122            return None 
     23 
     24class LDAPBackend(object): 
     25    """ 
     26    Authenticate a user against LDAP. 
     27    Requires python-ldap to be installed. 
     28 
     29    Requires the following things to be in settings.py: 
     30    LDAP_BINDDN -- string of the LDAP dn to use for binding 
     31    LDAP_SEARCHDN -- string of the LDAP dn to use for searching 
     32    LDAP_BIND_ATTRIBUTE -- string of the LDAP attribute to use in binding 
     33        also used to search for a user. 
     34    LDAP_SERVER_URI -- string, ldap uri 
     35    LDAP_SCOPE -- one of: ldap.SCOPE_*, used for searching 
     36        ldap.SCOPE_BASE = 0 
     37        ldap.SCOPE_ONELEVEL = 1 
     38        ldap.SCOPE_SUBTREE = 2 
     39        see python-ldap docs for the search function 
     40    LDAP_UPDATE_FIELDS -- boolean, do we sync the db with ldap with each auth 
     41 
     42    Required unless LDAP_FULL_NAME is set: 
     43    LDAP_FIRST_NAME -- string, LDAP attribute to get the given name from 
     44    LDAP_LAST_NAME -- string, LDAP attribute to get the last name from 
     45 
     46    Optional Settings: 
     47    LDAP_FULL_NAME -- string, LDAP attribute to get name from, splits on ' ' 
     48    LDAP_GID -- string, LDAP attribute to get group name/number from 
     49    LDAP_SU_GIDS -- list of strings, group names/numbers that are superusers 
     50    LDAP_STAFF_GIDS -- list of strings, group names/numbers that are staff 
     51    LDAP_EMAIL = string, LDAP attribute to get email from 
     52    LDAP_DEFAULT_EMAIL_SUFFIX = string, appened to username if no email found 
     53 
     54    Not yet implemented Settings: 
     55    LDAP_SSL = boolean, whether to use ssl or not 
     56 
     57    How Binds Work: 
     58    LDAP_BINDDN = 'ou=people,dc=example,dc=com' 
     59    LDAP_BIND_ATTRIBUTE = 'uid' 
     60    # The bind would be performed via: 
     61    # uid=username,ou=people,dc=example,dc=com 
     62    """  
     63    import ldap 
     64 
     65    def authenticate(self, username=None, password=None): 
     66        l = ldap.initialize(settings.LDAP_SERVER_URI) 
     67 
     68        if not username and password is not Null: # we need a user/pass 
     69            l.unbind_s() 
     70            return None 
     71 
     72        bind_string = "%s=%s,%s" % (settings.LDAP_BIND_ATTRIBUTE, username, 
     73                settings.LDAP_BINDDN) 
     74        try: 
     75            l.bind_s(bind_string, password) 
     76        except ldap.INVALID_CREDENTIALS: # Failed user/pass 
     77            l.unbind_s() 
     78            return None 
     79 
     80        try: 
     81            user = User.objects.get(username=username) 
     82        except User.DoesNotExist: 
     83            user = None 
     84 
     85        if user is not None: 
     86            if settings.LDAP_UPDATE_FIELDS: 
     87                LDAPBackend.update_user(l, user) 
     88        else: 
     89            user = LDAPBackend.get_ldap_user(l, username) 
     90 
     91        l.unbind_s() 
     92        return user 
     93 
     94    def get_user(self, user_id): 
     95        try: 
     96            return User.objects.get(pk=user_id) 
     97        except: 
     98            return None 
     99 
     100    def get_ldap_user(l, username): 
     101        """ 
     102        Helper method, makes a user object and call update_user to populate 
     103        """ 
     104 
     105        user = User(username=username, password='Made by LDAP') 
     106        LDAPBackend.update_user(l, user) 
     107        return user 
     108    get_ldap_user = staticmethod(get_ldap_user) 
     109 
     110    def update_user(l, user): 
     111        """ 
     112        Helper method, populates a user object with various attributes from 
     113        LDAP 
     114        """ 
     115 
     116        username = user.username 
     117        filter_str = "%s=%s" % (settings.LDAP_BIND_ATTRIBUTE, username) 
     118        attrs = l.search_s(settings.LDAP_SEARCHDN, settings.LDAP_SCOPE, 
     119                filterstr=filter_str)[0][1] 
     120 
     121        if (hasattr(settings, 'LDAP_FIRST_NAME') 
     122                and hasattr(settings, 'LDAP_LAST_NAME')): 
     123            if (settings.LDAP_FIRST_NAME in attrs 
     124                    and settings.LDAP_LAST_NAME in attrs): 
     125                user.first_name = attrs[settings.LDAP_FIRST_NAME][0] 
     126                user.last_name = attrs[settings.LDAP_LAST_NAME][0] 
     127            else: 
     128                raise NameError('Missing needed fields %s or %s in LDAP' 
     129                        % (settings.LDAP_FIRST_NAME, settings.LDAP_LAST_NAME)) 
     130        elif hasattr(settings, 'LDAP_FULL_NAME'): 
     131                if settings.LDAP_FULL_NAME in attrs: 
     132                    tmp = attrs[settings.FULL_NAME_FIELD][0] 
     133                    user.first_name = tmp.split(' ')[0] 
     134                    user.last_name = ' '.join(tmp.split(' ')[1:]) 
     135                else: 
     136                    raise NameError('Required field %s missing in LDAP' 
     137                            % (settings.LDAP_FULL_NAME)) 
     138        else: 
     139            raise NameError('Name fields not defined in settings.py') 
     140 
     141        if hasattr(settings, 'LDAP_EMAIL') and settings.LDAP_EMAIL in attrs: 
     142            user.email = attrs[settings.EMAIL_FIELD][0] 
     143        elif hasattr(settings, 'LDAP_DEFAULT_EMAIL_SUFFIX'): 
     144            user.email = username + settings.LDAP_DEFAULT_EMAIL_SUFFIX 
     145 
     146        if (hasattr(settings, 'LDAP_GID') 
     147                and settings.LDAP_GID in attrs  
     148                and hasattr(settings, 'LDAP_SU_GIDS') 
     149                and attrs[settings.LDAP_GID][0] in settings.LDAP_SU_GIDS): 
     150            user.is_superuser = True 
     151            user.is_staff = True 
     152        elif (hasattr(settings, 'LDAP_GID') 
     153                and settings.LDAP_GID in attrs  
     154                and hasattr(settings, 'LDAP_STAFF_GIDS') 
     155                and attrs[settings.LDAP_GID][0] in settings.LDAP_STAFF_GIDS): 
     156            user.is_superuser = False 
     157            user.is_staff = True 
     158        else: 
     159            user.is_superuser = False 
     160            user.is_staff = False 
     161 
     162        user.save() 
     163    update_user = staticmethod(update_user)