Skip to content
Snippets Groups Projects
Verified Commit 35542cb7 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

Add compatibility with django-auth-ldap >= 3.0 (and ldap3)

parent d3f28581
No related branches found
No related tags found
No related merge requests found
......@@ -5,7 +5,6 @@ import re
from django.apps import apps
from django.core.files import File
from django.db import DataError, IntegrityError, transaction
from django.db.models import fields
from django.db.models.fields.files import FileField
from django.utils.text import slugify
from django.utils.translation import gettext as _
......@@ -27,6 +26,13 @@ TQDM_DEFAULTS = {
}
def first_if_seq(value):
if isinstance(value, list):
return value[0]
else:
return value
def setting_name_from_field(model, field):
"""Generate a setting name from a model field."""
part_1 = model._meta.label_lower.replace(".", "_").replace("__", "_")
......@@ -44,13 +50,7 @@ def from_ldap(value, field, dn, ldap_field, instance=None):
This conversion is prone to error because LDAP deliberately breaks
standards to cope with ASN.1 limitations.
"""
from ldapdb.models.fields import datetime_from_ldap # noqa
# Pre-convert DateTimeField and DateField due to ISO 8601 limitations in RFC 4517
if isinstance(field, (fields.DateField, fields.DateTimeField)):
# Be opportunistic, but keep old value if conversion fails
value = datetime_from_ldap(value) or value
elif isinstance(field, FileField) and instance is not None:
if isinstance(field, FileField) and instance is not None:
name = ldap_field_to_filename(dn, ldap_field)
content = File(io.BytesIO(value))
......@@ -151,7 +151,7 @@ def get_ldap_value_for_field(model, field, attrs, dn, instance=None):
raise AttributeError(f"Field {field.name} not configured to be synced.")
if ldap_field in attrs:
value = attrs[ldap_field][0]
value = first_if_seq(attrs[ldap_field])
# Apply regex replace from config
patterns = get_site_preferences()[setting_name + "_re"]
......@@ -188,7 +188,7 @@ def ldap_sync_user_on_login(sender, instance, created, **kwargs):
try:
with transaction.atomic():
person = ldap_sync_from_user(
instance, instance.ldap_user.dn, instance.ldap_user.attrs.data
instance, instance.ldap_user.dn, instance.ldap_user.attrs
)
except Person.DoesNotExist:
logger.warn(f"No matching person for user {instance.username}")
......@@ -313,12 +313,14 @@ def ldap_sync_from_groups(group_infos):
# Apply regex replace from config
short_name = apply_templates(
ldap_group[1][get_site_preferences()["ldap__group_sync_field_short_name"]][0],
first_if_seq(
ldap_group[1][get_site_preferences()["ldap__group_sync_field_short_name"]]
),
get_site_preferences()["ldap__group_sync_field_short_name_re"],
get_site_preferences()["ldap__group_sync_field_short_name_replace"],
)
name = apply_templates(
ldap_group[1][get_site_preferences()["ldap__group_sync_field_name"]][0],
first_if_seq(ldap_group[1][get_site_preferences()["ldap__group_sync_field_name"]]),
get_site_preferences()["ldap__group_sync_field_name_re"],
get_site_preferences()["ldap__group_sync_field_name_replace"],
)
......@@ -339,7 +341,9 @@ def ldap_sync_from_groups(group_infos):
continue
else:
status = "Created" if created else "Updated"
value = ldap_group[1][get_site_preferences()["ldap__group_sync_field_name"]][0]
value = first_if_seq(
ldap_group[1][get_site_preferences()["ldap__group_sync_field_name"]]
)
logger.info(f"{status} LDAP group {value} for Django group {name}")
group_objects.append(group)
......@@ -374,7 +378,7 @@ def mass_ldap_import():
# 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]
uid = first_if_seq(attrs[uid_field])
# Prepare an empty LDAPUser object with the target username
ldap_user = _LDAPUser(backend, username=uid)
......@@ -412,6 +416,7 @@ def mass_ldap_import():
ldap_groups, desc="Sync. group members", total=len(group_objects), **TQDM_DEFAULTS,
):
dn, attrs = ldap_group
dn = dn.lower()
if dn not in group_dict:
logger.warning(f"Skip {dn} because there are no groups with this dn.")
......
......@@ -31,7 +31,6 @@ secondary = true
[tool.poetry.dependencies]
python = "^3.7"
django-ldapdb = "^1.4.0"
tqdm = "^4.44.1"
aleksis-core = {version = "^2.0a3.dev0", extras = ["ldap"]}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment