def sync_ldap_users(self, ldap_users):
        """Synchronize users with local user model."""
        model = get_user_model()

        #Load total User starts
        self.stats_user_total = len(ldap_users)

        list_profiles = []
        #Load extra profiles. This way we don't even need a callback. The same code is used to populate both auth_user and user_profile
        for list_profile in self.conf_LDAP_SYNC_USER_EXTRA_PROFILES:
            list_profiles.append((list_profile, apps.get_model(list_profile)))

        if not model._meta.get_field(self.conf_LDAP_SYNC_USERNAME_FIELD).unique:
            raise ImproperlyConfigured("Field '%s' must be unique" % self.conf_LDAP_SYNC_USERNAME_FIELD)

        actualProgress = 0

        for cname, attributes in ldap_users:
            defaults = {}
            actualProgress += 1
            if (self.conf_LDAP_SYNC_USER_SHOW_PROGRESS and ((100 * actualProgress // self.stats_user_total) > (100 * (actualProgress - 1) // self.stats_user_total))):
                logger.info("AD User Sync: Processed %d/%d users (%d" % (actualProgress, self.stats_user_total, (100 * actualProgress) // self.stats_user_total) + "%)")
            try:
                for name, attribute in attributes.items():
                    try:
                        if ((name.lower() == 'thumbnailphoto') or (name.lower() == 'jpegphoto') or (name.lower() == 'thumbnaillogo')):
                            defaults[self.conf_LDAP_SYNC_USER_ATTRIBUTES[name]] = attribute[0]
                        else:
                            defaults[self.conf_LDAP_SYNC_USER_ATTRIBUTES[name]] = attribute[0].decode('utf-8')
                    except KeyError:
                        pass
                    except UnicodeDecodeError:
                        raise ImproperlyConfigured('Error in attribute ' + name + ' ' + str(attribute))
            except AttributeError:
                # In some cases attributes is a list instead of a dict; skip these invalid users
                continue

            try:
                username = defaults[self.conf_LDAP_SYNC_USERNAME_FIELD].lower()
            except KeyError:
                logger.warning("User is missing a required attribute '%s'" % self.conf_LDAP_SYNC_USERNAME_FIELD)
                continue

            #Don't import users if they are in LDAP_SYNC_USER_EXEMPT_FROM_SYNC settings
            if (username in self.conf_LDAP_SYNC_USER_EXEMPT_FROM_SYNC):
                logger.debug("Skip importing user %s, it appears in LDAP_SYNC_USER_EXEMPT_FROM_SYNC list" % username)
                continue

            kwargs = {
                self.conf_LDAP_SYNC_USERNAME_FIELD + '__iexact': username,
                'defaults': defaults,
            }

            ### Users Disable
            #Check disable bit 
            user_account_control = int(attributes[self.ATTRIBUTE_DISABLED][0].decode('utf-8'))
            user_is_disabled = (user_account_control and ((user_account_control & self.FLAG_UF_ACCOUNT_DISABLE) == self.FLAG_UF_ACCOUNT_DISABLE))
            if user_is_disabled:
                try:
                    #If disabled, we need to check if the user already exists on Django
                    user = model.objects.get(**{self.conf_LDAP_SYNC_USERNAME_FIELD + '__iexact': username,})
                    if (not user):
                        #Ignore disabled users, we won't import it, only update it
                        continue
                except Exception as e:
                    #Ignore disabled users, we won't import it, only update it
                    continue
                else:
                    #If the user already exists on Django we'll run the callbacks
                    if (self.conf_LDAP_SYNC_REMOVED_USER_CALLBACKS):
                        self.stats_user_deleted += 1
                    for path in self.conf_LDAP_SYNC_REMOVED_USER_CALLBACKS:
                        logger.debug("Calling %s for user %s" % (path, username))
                        callback = import_string(path)
                        callback(user)
            ### User creation and sinchronization
            updated = False
            try:
                if user_is_disabled:
                    created = False
                    #reload it because it may be deleted
                    user = model.objects.get(**{self.conf_LDAP_SYNC_USERNAME_FIELD + '__iexact': username,})
                else:
                    user, created = model.objects.get_or_create(**kwargs)
            except (ObjectDoesNotExist) as e:
                if (user_is_disabled):
                    continue
                else:
                    raise e
            except (IntegrityError, DataError) as e:
                logger.error("Error creating user %s: %s" % (username, e))
                self.stats_user_errors += 1
            else:
                user_updated = False
                if created:
                    logger.debug("Created user %s" % username)
                    self.stats_user_added += 1
                    user.set_unusable_password()
                else:
                    for name, attr in defaults.items():
                        current_attr = getattr(user, name, None)
                        if current_attr != attr:
                            setattr(user, name, attr)
                            if (not user_updated):
                                user_updated = True
                    if user_updated:
                        logger.debug("Updated user %s" % username)
                        updated = True

                for path in self.conf_LDAP_SYNC_USER_CALLBACKS:
                    callback = import_string(path)
                    callback(user, attributes, created, user_updated)

                try:
                    if (created or user_updated):
                        user.save()
                except Exception as e:
                    logger.error("Error saving user %s: %s" % (username, e))
                    self.stats_user_errors += 1
                ### LDAP Sync Membership
                if (self.conf_LDAP_SYNC_GROUP_MEMBERSHIP):
                    membership_uri, ldap_membership = self.get_ldap_user_membership(attributes[self.conf_LDAP_SYNC_GROUP_MEMBERSHIP_DN_FIELD][0].decode('utf-8'))
                    if ldap_membership:
                        self.sync_ldap_user_membership(user, ldap_membership)
            #Profile creation and update.
            for name_profile, profile_model in list_profiles:
                try:
                    profile, created = profile_model.objects.get_or_create(user=user)  # ,  **kwargs )
                except (IntegrityError, DataError) as e:
                    logger.error("Error creating profile %s for user %s: %s" % (name_profile, username, e))
                    self.stats_user_errors += 1
                else:
                    profile_updated = False
                    if (created):
                        logger.debug("Created profile '%s' for user '%s'" % (name_profile, username))
                        #profile.save()
                    for unchanged_name, attr in attributes.items():
                        name = unchanged_name
                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower"):
                            name = unchanged_name.lower()
                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper"):
                            name = unchanged_name.upper()

                        try:
                            if ((name.lower() != 'thumbnailphoto') and (name.lower() != 'jpegphoto') and (name.lower() != 'thumbnaillogo') ):
                                current_attr = getattr(profile, name)
                                new_value = ''
                                if (isinstance(attr, list)):
                                    for val in attr:
                                        new_value += val.decode("utf8") + self.conf_LDAP_SYNC_MULTIVALUE_SEPARATOR
                                    if (new_value != ""):
                                        new_value = new_value[:-len(self.conf_LDAP_SYNC_MULTIVALUE_SEPARATOR)]
                                else:
                                    new_value = attr
                                if current_attr != new_value:
                                    setattr(profile, name, new_value)
                                    #logger.debug("Updated profile %s: Attribute %s from '%s' to '%s' - '%s'" % (username,name, current_attr, new_value, attr))
                                    profile_updated = True
                            else:
                                if (isinstance(attr, list)):
                                    newthumbPhoto = attr[0]
                                else:
                                    newthumbPhoto = attr
                                actualPhoto = None
                                try:
                                    if (name.lower() == 'thumbnailphoto'):
                                        if (not self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE):
                                            actualPhoto = profile.thumbnailPhoto.read()
                                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower"):
                                            actualPhoto = profile.thumbnailphoto.read()
                                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper"):
                                            actualPhoto = profile.THUMBNAILPHOTO.read()
                                    elif (name.lower() == 'thumbnaillogo'):
                                        if (not self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE):
                                            actualPhoto = profile.thumbnailLogo.read()
                                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower"):
                                            actualPhoto = profile.thumbnaillogo.read()
                                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper"):
                                            actualPhoto = profile.THUMBNAILLOGO.read()                                            
                                    else:
                                        if (not self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE):
                                            actualPhoto = profile.jpegPhoto.read()
                                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower"):
                                            actualPhoto = profile.jpegphoto.read()
                                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper"):
                                            actualPhoto = profile.JPEGPHOTO.read()
                                except Exception as e:
                                    pass
                                if (actualPhoto != newthumbPhoto):
                                    #Saving thumbnailphoto
                                    #logger.debug("Photo in "+username+" are different... ")
                                    photo_name = self.conf_LDAP_SYNC_USER_THUMBNAILPHOTO_NAME
                                    #we don't format because I don't know if username it's being used at all
                                    photo_name = photo_name.replace('{username}', username)
                                    photo_name = photo_name.replace('{uuid4}', str(uuid.uuid4()))
                                    photo_name = datetime.now().strftime(photo_name)
                                    if (name.lower() == 'thumbnailphoto'):
                                        if (not self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE):
                                            if (actualPhoto):
                                                profile.thumbnailPhoto.delete()
                                            profile.thumbnailPhoto.save(name=photo_name, content=ContentFile(newthumbPhoto))
                                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower"):
                                            if (actualPhoto):
                                                profile.thumbnailphoto.delete()
                                            profile.thumbnailphoto.save(name=photo_name, content=ContentFile(newthumbPhoto))
                                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper"):
                                            if (actualPhoto):
                                                profile.THUMBNAILPHOTO.delete()
                                            profile.THUMBNAILPHOTO.save(name=photo_name, content=ContentFile(newthumbPhoto))
                                    elif (name.lower() == 'thumbnaillogo'):
                                        if (not self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE):
                                            if (actualPhoto):
                                                profile.thumbnailLogo.delete()
                                            profile.thumbnailLogo.save(name=photo_name, content=ContentFile(newthumbPhoto))
                                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower"):
                                            if (actualPhoto):
                                                profile.thumbnaillogo.delete()
                                            profile.thumbnaillogo.save(name=photo_name, content=ContentFile(newthumbPhoto))
                                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper"):
                                            if (actualPhoto):
                                                profile.THUMBNAILLOGO.delete()
                                            profile.THUMBNAILLOGO.save(name=photo_name, content=ContentFile(newthumbPhoto))                                            
                                    else:
                                        if (not self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE):
                                            if (actualPhoto):
                                                profile.jpegPhoto.delete()
                                            profile.jpegPhoto.save(name=photo_name, content=ContentFile(newthumbPhoto))
                                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower"):
                                            if (actualPhoto):
                                                profile.jpegphoto.delete()
                                            profile.jpegphoto.save(name=photo_name, content=ContentFile(newthumbPhoto))
                                        if (self.conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper"):
                                            if (actualPhoto):
                                                profile.JPEGPHOTO.delete()
                                            profile.JPEGPHOTO.save(name=photo_name, content=ContentFile(newthumbPhoto))
                                    profile_updated = True
                                else:
                                    pass
                                    #logger.debug("Photo "+username+" are equal")
                        except AttributeError:
                            pass
                            #logger.debug("Ignore Attribute %s on profile '%s'" % (name, name_profile))
                    if profile_updated:
                        logger.debug("Updated profile %s on user %s" % (name_profile, username))
                        updated = True
                    if (created or profile_updated):
                        try:
                            profile.save()
                        except Exception as e:
                            logger.error("Error saving profile %s for user %s: %s" % (name_profile, username, e))
                            self.stats_user_errors += 1
                    #profile.save()
                    #If either user record or any profile record is changed, we'll mark it as updated.
            if (updated):
                self.stats_user_updated += 1

        logger.info("Users are synchronized")
def sync_ldap_users ( self , ldap_users ) : model = get_user_model ( ) self . stats_user_total = len ( ldap_users ) list_profiles = [ ] for list_profile in self . conf_LDAP_SYNC_USER_EXTRA_PROFILES : list_profiles . append ( ( list_profile , apps . get_model ( list_profile ) ) ) if not model . _meta . get_field ( self . conf_LDAP_SYNC_USERNAME_FIELD ) . unique : raise ImproperlyConfigured ( "Field '%s' must be unique" % self . conf_LDAP_SYNC_USERNAME_FIELD ) actualProgress = 0 for cname , attributes in ldap_users : defaults = { } actualProgress += 1 if ( self . conf_LDAP_SYNC_USER_SHOW_PROGRESS and ( ( 100 * actualProgress // self . stats_user_total ) > ( 100 * ( actualProgress - 1 ) // self . stats_user_total ) ) ) : logger . info ( "AD User Sync: Processed %d/%d users (%d" % ( actualProgress , self . stats_user_total , ( 100 * actualProgress ) // self . stats_user_total ) + "%)" ) try : for name , attribute in attributes . items ( ) : try : if ( ( name . lower ( ) == 'thumbnailphoto' ) or ( name . lower ( ) == 'jpegphoto' ) or ( name . lower ( ) == 'thumbnaillogo' ) ) : defaults [ self . conf_LDAP_SYNC_USER_ATTRIBUTES [ name ] ] = attribute [ 0 ] else : defaults [ self . conf_LDAP_SYNC_USER_ATTRIBUTES [ name ] ] = attribute [ 0 ] . decode ( 'utf-8' ) except KeyError : pass except UnicodeDecodeError : raise ImproperlyConfigured ( 'Error in attribute ' + name + ' ' + str ( attribute ) ) except AttributeError : continue try : username = defaults [ self . conf_LDAP_SYNC_USERNAME_FIELD ] . lower ( ) except KeyError : logger . warning ( "User is missing a required attribute '%s'" % self . conf_LDAP_SYNC_USERNAME_FIELD ) continue if ( username in self . conf_LDAP_SYNC_USER_EXEMPT_FROM_SYNC ) : logger . debug ( "Skip importing user %s, it appears in LDAP_SYNC_USER_EXEMPT_FROM_SYNC list" % username ) continue kwargs = { self . conf_LDAP_SYNC_USERNAME_FIELD + '__iexact' : username , 'defaults' : defaults , } user_account_control = int ( attributes [ self . ATTRIBUTE_DISABLED ] [ 0 ] . decode ( 'utf-8' ) ) user_is_disabled = ( user_account_control and ( ( user_account_control & self . FLAG_UF_ACCOUNT_DISABLE ) == self . FLAG_UF_ACCOUNT_DISABLE ) ) if user_is_disabled : try : user = model . objects . get ( ** { self . conf_LDAP_SYNC_USERNAME_FIELD + '__iexact' : username , } ) if ( not user ) : continue except Exception as e : continue else : if ( self . conf_LDAP_SYNC_REMOVED_USER_CALLBACKS ) : self . stats_user_deleted += 1 for path in self . conf_LDAP_SYNC_REMOVED_USER_CALLBACKS : logger . debug ( "Calling %s for user %s" % ( path , username ) ) callback = import_string ( path ) callback ( user ) updated = False try : if user_is_disabled : created = False user = model . objects . get ( ** { self . conf_LDAP_SYNC_USERNAME_FIELD + '__iexact' : username , } ) else : user , created = model . objects . get_or_create ( ** kwargs ) except ( ObjectDoesNotExist ) as e : if ( user_is_disabled ) : continue else : raise e except ( IntegrityError , DataError ) as e : logger . error ( "Error creating user %s: %s" % ( username , e ) ) self . stats_user_errors += 1 else : user_updated = False if created : logger . debug ( "Created user %s" % username ) self . stats_user_added += 1 user . set_unusable_password ( ) else : for name , attr in defaults . items ( ) : current_attr = getattr ( user , name , None ) if current_attr != attr : setattr ( user , name , attr ) if ( not user_updated ) : user_updated = True if user_updated : logger . debug ( "Updated user %s" % username ) updated = True for path in self . conf_LDAP_SYNC_USER_CALLBACKS : callback = import_string ( path ) callback ( user , attributes , created , user_updated ) try : if ( created or user_updated ) : user . save ( ) except Exception as e : logger . error ( "Error saving user %s: %s" % ( username , e ) ) self . stats_user_errors += 1 if ( self . conf_LDAP_SYNC_GROUP_MEMBERSHIP ) : membership_uri , ldap_membership = self . get_ldap_user_membership ( attributes [ self . conf_LDAP_SYNC_GROUP_MEMBERSHIP_DN_FIELD ] [ 0 ] . decode ( 'utf-8' ) ) if ldap_membership : self . sync_ldap_user_membership ( user , ldap_membership ) for name_profile , profile_model in list_profiles : try : profile , created = profile_model . objects . get_or_create ( user = user ) except ( IntegrityError , DataError ) as e : logger . error ( "Error creating profile %s for user %s: %s" % ( name_profile , username , e ) ) self . stats_user_errors += 1 else : profile_updated = False if ( created ) : logger . debug ( "Created profile '%s' for user '%s'" % ( name_profile , username ) ) for unchanged_name , attr in attributes . items ( ) : name = unchanged_name if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower" ) : name = unchanged_name . lower ( ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper" ) : name = unchanged_name . upper ( ) try : if ( ( name . lower ( ) != 'thumbnailphoto' ) and ( name . lower ( ) != 'jpegphoto' ) and ( name . lower ( ) != 'thumbnaillogo' ) ) : current_attr = getattr ( profile , name ) new_value = '' if ( isinstance ( attr , list ) ) : for val in attr : new_value += val . decode ( "utf8" ) + self . conf_LDAP_SYNC_MULTIVALUE_SEPARATOR if ( new_value != "" ) : new_value = new_value [ : - len ( self . conf_LDAP_SYNC_MULTIVALUE_SEPARATOR ) ] else : new_value = attr if current_attr != new_value : setattr ( profile , name , new_value ) profile_updated = True else : if ( isinstance ( attr , list ) ) : newthumbPhoto = attr [ 0 ] else : newthumbPhoto = attr actualPhoto = None try : if ( name . lower ( ) == 'thumbnailphoto' ) : if ( not self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE ) : actualPhoto = profile . thumbnailPhoto . read ( ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower" ) : actualPhoto = profile . thumbnailphoto . read ( ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper" ) : actualPhoto = profile . THUMBNAILPHOTO . read ( ) elif ( name . lower ( ) == 'thumbnaillogo' ) : if ( not self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE ) : actualPhoto = profile . thumbnailLogo . read ( ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower" ) : actualPhoto = profile . thumbnaillogo . read ( ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper" ) : actualPhoto = profile . THUMBNAILLOGO . read ( ) else : if ( not self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE ) : actualPhoto = profile . jpegPhoto . read ( ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower" ) : actualPhoto = profile . jpegphoto . read ( ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper" ) : actualPhoto = profile . JPEGPHOTO . read ( ) except Exception as e : pass if ( actualPhoto != newthumbPhoto ) : photo_name = self . conf_LDAP_SYNC_USER_THUMBNAILPHOTO_NAME photo_name = photo_name . replace ( '{username}' , username ) photo_name = photo_name . replace ( '{uuid4}' , str ( uuid . uuid4 ( ) ) ) photo_name = datetime . now ( ) . strftime ( photo_name ) if ( name . lower ( ) == 'thumbnailphoto' ) : if ( not self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE ) : if ( actualPhoto ) : profile . thumbnailPhoto . delete ( ) profile . thumbnailPhoto . save ( name = photo_name , content = ContentFile ( newthumbPhoto ) ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower" ) : if ( actualPhoto ) : profile . thumbnailphoto . delete ( ) profile . thumbnailphoto . save ( name = photo_name , content = ContentFile ( newthumbPhoto ) ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper" ) : if ( actualPhoto ) : profile . THUMBNAILPHOTO . delete ( ) profile . THUMBNAILPHOTO . save ( name = photo_name , content = ContentFile ( newthumbPhoto ) ) elif ( name . lower ( ) == 'thumbnaillogo' ) : if ( not self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE ) : if ( actualPhoto ) : profile . thumbnailLogo . delete ( ) profile . thumbnailLogo . save ( name = photo_name , content = ContentFile ( newthumbPhoto ) ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower" ) : if ( actualPhoto ) : profile . thumbnaillogo . delete ( ) profile . thumbnaillogo . save ( name = photo_name , content = ContentFile ( newthumbPhoto ) ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper" ) : if ( actualPhoto ) : profile . THUMBNAILLOGO . delete ( ) profile . THUMBNAILLOGO . save ( name = photo_name , content = ContentFile ( newthumbPhoto ) ) else : if ( not self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE ) : if ( actualPhoto ) : profile . jpegPhoto . delete ( ) profile . jpegPhoto . save ( name = photo_name , content = ContentFile ( newthumbPhoto ) ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "lower" ) : if ( actualPhoto ) : profile . jpegphoto . delete ( ) profile . jpegphoto . save ( name = photo_name , content = ContentFile ( newthumbPhoto ) ) if ( self . conf_LDAP_SYNC_USER_CHANGE_FIELDCASE == "upper" ) : if ( actualPhoto ) : profile . JPEGPHOTO . delete ( ) profile . JPEGPHOTO . save ( name = photo_name , content = ContentFile ( newthumbPhoto ) ) profile_updated = True else : pass except AttributeError : pass if profile_updated : logger . debug ( "Updated profile %s on user %s" % ( name_profile , username ) ) updated = True if ( created or profile_updated ) : try : profile . save ( ) except Exception as e : logger . error ( "Error saving profile %s for user %s: %s" % ( name_profile , username , e ) ) self . stats_user_errors += 1 if ( updated ) : self . stats_user_updated += 1 logger . info ( "Users are synchronized" )
Synchronize users with local user model.