Пример #1
0
def mass_ldap_import():
    """Add utility code for mass import from ldap."""
    from django_auth_ldap.backend import LDAPBackend, _LDAPUser  # noqa

    Person = apps.get_model("core", "Person")

    # Abuse pre-configured search object as general LDAP interface
    backend = LDAPBackend()
    connection = _LDAPUser(backend, "").connection

    # Synchronise all groups first
    if get_site_preferences()["ldap__enable_group_sync"]:
        ldap_groups = backend.settings.GROUP_SEARCH.execute(connection)
        group_objects = ldap_sync_from_groups(ldap_groups)

        # Create lookup table as cache for later code
        group_dict = {obj.ldap_dn: obj for obj in group_objects}

    # Guess LDAP username field from user filter
    uid_field = re.search(
        r"([a-zA-Z]+)=%\(user\)s",
        backend.settings.USER_SEARCH.searches[0].filterstr).group(1)

    # Synchronise user data for all found users
    ldap_users = backend.settings.USER_SEARCH.execute(connection,
                                                      {"user": "******"},
                                                      escape=False)
    for dn, attrs in tqdm(ldap_users, desc="Sync. user infos",
                          **TQDM_DEFAULTS):
        uid = attrs[uid_field][0]

        # Prepare an empty LDAPUser object with the target username
        ldap_user = _LDAPUser(backend, username=uid)

        # Get existing or new User object and pre-populate
        user, created = backend.get_or_build_user(uid, ldap_user)
        ldap_user._user = user
        ldap_user._attrs = attrs
        ldap_user._dn = dn
        ldap_user._populate_user_from_attributes()
        user.save()

        try:
            with transaction.atomic():
                person = ldap_sync_from_user(user, dn, attrs)
        except Person.DoesNotExist:
            logger.warn(f"No matching person for user {user.username}")
            continue
        except Person.MultipleObjectsReturned:
            logger.error(
                f"More than one matching person for user {user.username}")
            continue
        except (DataError, IntegrityError, KeyError, ValueError) as e:
            logger.error(
                f"Data error while synchronising user {user.username}:\n{e}")
            continue
        else:
            logger.info(f"Successfully imported user {uid}")

    # Synchronise group memberships now
    if get_site_preferences()["ldap__enable_group_sync"]:
        member_attr = getattr(backend.settings.GROUP_TYPE, "member_attr",
                              "memberUid")
        owner_attr = get_site_preferences()["ldap__group_sync_owner_attr"]

        for ldap_group in tqdm(
                ldap_groups,
                desc="Sync. group members",
                total=len(ldap_groups),
                **TQDM_DEFAULTS,
        ):
            dn, attrs = ldap_group

            if dn not in group_dict:
                logger.warning(
                    f"Skip {dn} because there are no groups with this dn.")
                continue

            group = group_dict[dn]

            ldap_members = [_.lower() for _ in attrs[member_attr]
                            ] if member_attr in attrs else []

            if member_attr.lower() == "memberuid":
                members = Person.objects.filter(
                    user__username__in=ldap_members)
            else:
                members = Person.objects.filter(ldap_dn__in=ldap_members)

            if get_site_preferences()["ldap__group_sync_owner_attr"]:
                ldap_owners = [_.lower() for _ in attrs[owner_attr]
                               ] if owner_attr in attrs else []
                if get_site_preferences(
                )["ldap__group_sync_owner_attr_type"] == "uid":
                    owners = Person.objects.filter(
                        user__username__in=ldap_owners)
                elif get_site_preferences(
                )["ldap__group_sync_owner_attr_type"] == "dn":
                    owners = Person.objects.filter(ldap_dn__in=ldap_owners)

            group.members.set(members)
            if get_site_preferences()["ldap__group_sync_owner_attr"]:
                group.owners.set(owners)
            group.save()
            logger.info(f"Set group members of group {group}")

    # Synchronise primary groups
    all_persons = set(Person.objects.all())
    for person in tqdm(all_persons,
                       desc="Sync. primary groups",
                       **TQDM_DEFAULTS):
        person.auto_select_primary_group()
    Person.objects.bulk_update(all_persons, ("primary_group", ))

    logger.info("Commiting transaction; this can take some time.")