Skip to content
Snippets Groups Projects
Verified Commit 3be502a5 authored by Tom Teichler's avatar Tom Teichler :beers:
Browse files

[Reformat] black

parent 03bbbe90
No related branches found
No related tags found
No related merge requests found
......@@ -5,6 +5,7 @@ from aleksis.core.util.apps import AppConfig
from .util.ldap_sync import ldap_sync_user_on_login, update_dynamic_preferences
class LDAPConfig(AppConfig):
name = "aleksis.apps.ldap"
verbose_name = "AlekSIS — LDAP (General LDAP import/export)"
......
from django.utils.translation import gettext_lazy as _
from dynamic_preferences.types import BooleanPreference, StringPreference, ChoicePreference
from dynamic_preferences.preferences import Section
from dynamic_preferences.types import BooleanPreference, ChoicePreference, StringPreference
from aleksis.core.registries import site_preferences_registry
ldap = Section('ldap')
ldap = Section("ldap")
@site_preferences_registry.register
......@@ -75,7 +74,9 @@ class LDAPGroupSyncFieldShortNameRE(StringPreference):
name = "group_sync_field_short_name_re"
default = ""
required = False
verbose_name = _("Regular expression to match LDAP value for group short name against, e.g. class_(?P<class>.*); separate multiple patterns by |")
verbose_name = _(
"Regular expression to match LDAP value for group short name against, e.g. class_(?P<class>.*); separate multiple patterns by |"
)
@site_preferences_registry.register
......@@ -84,7 +85,9 @@ class LDAPGroupSyncFieldShortNameReplace(StringPreference):
name = "group_sync_field_short_name_replace"
default = ""
required = False
verbose_name = _("Replacement template to apply to group short name, e.g. \\g<class>; separate multiple templates by |")
verbose_name = _(
"Replacement template to apply to group short name, e.g. \\g<class>; separate multiple templates by |"
)
@site_preferences_registry.register
......@@ -102,7 +105,9 @@ class LDAPGroupSyncFieldNameRE(StringPreference):
name = "group_sync_field_name_re"
default = ""
required = False
verbose_name = _("Regular expression to match LDAP value for group name against, e.g. class_(?P<class>.*); separate multiple patterns by |")
verbose_name = _(
"Regular expression to match LDAP value for group name against, e.g. class_(?P<class>.*); separate multiple patterns by |"
)
@site_preferences_registry.register
......@@ -111,7 +116,9 @@ class LDAPGroupSyncFieldNameReplace(StringPreference):
name = "group_sync_field_name_replace"
default = ""
required = False
verbose_name = _("Replacement template to apply to group name, e.g. \\g<class>; separate multiple templates by |")
verbose_name = _(
"Replacement template to apply to group name, e.g. \\g<class>; separate multiple templates by |"
)
@site_preferences_registry.register
......
......@@ -18,10 +18,7 @@ CONSTANCE_ADDITIONAL_FIELDS = {
"django.forms.fields.ChoiceField",
{
"widget": "django.forms.Select",
"choices": (
("dn", _("Distinguished Name")),
("uid", _("UID")),
),
"choices": (("dn", _("Distinguished Name")), ("uid", _("UID")),),
},
],
}
......@@ -30,20 +27,44 @@ CONSTANCE_CONFIG = {
"ENABLE_LDAP_SYNC": (True, _("Enable ldap sync"), bool),
"LDAP_SYNC_ON_UPDATE": (True, _("Also sync if user updates"), bool),
"LDAP_SYNC_CREATE_MISSING_PERSONS": (True, _("Create missing persons for LDAP users"), bool),
"LDAP_MATCHING_FIELDS": (
None,
_("LDAP sync matching fields"),
"matching-fields-select",
),
"LDAP_MATCHING_FIELDS": (None, _("LDAP sync matching fields"), "matching-fields-select",),
"ENABLE_LDAP_GROUP_SYNC": (True, _("Enable ldap group sync"), bool),
"LDAP_GROUP_SYNC_FIELD_SHORT_NAME": ("cn", _("Field for short name of group"), str),
"LDAP_GROUP_SYNC_FIELD_SHORT_NAME_RE": ("", _("Regular expression to match LDAP value for group short name against, e.g. class_(?P<class>.*); separate multiple patterns by |"), str),
"LDAP_GROUP_SYNC_FIELD_SHORT_NAME_REPLACE": ("", _("Replacement template to apply to group short name, e.g. \\g<class>; separate multiple templates by |"), str),
"LDAP_GROUP_SYNC_FIELD_SHORT_NAME_RE": (
"",
_(
"Regular expression to match LDAP value for group short name against, e.g. class_(?P<class>.*); separate multiple patterns by |"
),
str,
),
"LDAP_GROUP_SYNC_FIELD_SHORT_NAME_REPLACE": (
"",
_(
"Replacement template to apply to group short name, e.g. \\g<class>; separate multiple templates by |"
),
str,
),
"LDAP_GROUP_SYNC_FIELD_NAME": ("cn", _("Field for name of group"), str),
"LDAP_GROUP_SYNC_FIELD_NAME_RE": ("", _("Regular expression to match LDAP value for group name against, e.g. class_(?P<class>.*); separate multiple patterns by |"), str),
"LDAP_GROUP_SYNC_FIELD_NAME_REPLACE": ("", _("Replacement template to apply to group name, e.g. \\g<class>; separate multiple templates by |"), str),
"LDAP_GROUP_SYNC_FIELD_NAME_RE": (
"",
_(
"Regular expression to match LDAP value for group name against, e.g. class_(?P<class>.*); separate multiple patterns by |"
),
str,
),
"LDAP_GROUP_SYNC_FIELD_NAME_REPLACE": (
"",
_(
"Replacement template to apply to group name, e.g. \\g<class>; separate multiple templates by |"
),
str,
),
"LDAP_GROUP_SYNC_OWNER_ATTR": ("", _("LDAP field with dn of group owner"), str),
"LDAP_GROUP_SYNC_OWNER_ATTR_TYPE": ("dn", _("Type of data in the ldap_field. Either DN or UID"), "owner-attr-type"),
"LDAP_GROUP_SYNC_OWNER_ATTR_TYPE": (
"dn",
_("Type of data in the ldap_field. Either DN or UID"),
"owner-attr-type",
),
}
CONSTANCE_CONFIG_FIELDSETS = {
"LDAP-Sync settings": (
......
......@@ -2,6 +2,7 @@ from aleksis.core.util.core_helpers import celery_optional
from .util.ldap_sync import mass_ldap_import
@celery_optional
def ldap_import():
mass_ldap_import()
......@@ -23,11 +23,12 @@ from ..preferences import ldap as section_ldap
logger = logging.getLogger(__name__)
TQDM_DEFAULTS = {
"disable": None,
"unit": "obj",
"dynamic_ncols": True,
"disable": None,
"unit": "obj",
"dynamic_ncols": True,
}
def setting_name_from_field(model, field):
""" Generate a setting name from a model field """
......@@ -37,8 +38,11 @@ def setting_name_from_field(model, field):
def syncable_fields(model):
""" Collect all fields that can be synced on a model """
return [field for field in model._meta.fields if (
field.editable and not field.auto_created and not field.is_relation)]
return [
field
for field in model._meta.fields
if (field.editable and not field.auto_created and not field.is_relation)
]
def ldap_field_to_filename(dn, fieldname):
......@@ -87,23 +91,32 @@ def update_dynamic_preferences():
class _GeneratedPreference(StringPreference):
section = section_ldap
name = setting_name
verbose_name = _("LDAP field for %s on %s") % (field.verbose_name, model._meta.label)
verbose_name = _("LDAP field for %s on %s") % (
field.verbose_name,
model._meta.label,
)
required = False
default = ""
@site_preferences_registry.register
class _GeneratedPreferenceRe(StringPreference):
section = section_ldap
name = setting_name + "_re"
verbose_name = _("Regular expression to match LDAP value for %s on %s against") % (field.verbose_name, model._meta.label)
verbose_name = _("Regular expression to match LDAP value for %s on %s against") % (
field.verbose_name,
model._meta.label,
)
required = False
default = ""
@site_preferences_registry.register
class _GeneratedPreferenceReplace(StringPreference):
section = section_ldap
name = setting_name + "_replace"
verbose_name = _("Replacement template to apply to %s on %s") % (field.verbose_name, model._meta.label)
verbose_name = _("Replacement template to apply to %s on %s") % (
field.verbose_name,
model._meta.label,
)
required = False
default = ""
......@@ -138,10 +151,16 @@ def ldap_sync_user_on_login(sender, instance, created, **kwargs):
Person = apps.get_model("core", "Person")
if get_site_preferences()["ldap__enable_sync"] and (created or get_site_preferences()["ldap__sync_on_update"]) and hasattr(instance, "ldap_user"):
if (
get_site_preferences()["ldap__enable_sync"]
and (created or get_site_preferences()["ldap__sync_on_update"])
and hasattr(instance, "ldap_user")
):
try:
with transaction.atomic():
person = ldap_sync_from_user(instance, instance.ldap_user.dn, instance.ldap_user.attrs.data)
person = ldap_sync_from_user(
instance, instance.ldap_user.dn, instance.ldap_user.attrs.data
)
except Person.DoesNotExist:
logger.warn("No matching person for user %s" % user.username)
return
......@@ -205,7 +224,10 @@ def ldap_sync_from_user(user, dn, attrs):
created = False
person.user = user
logger.info("%s person %s linked to user %s" % ("New" if created else "Existing", str(person), user.username))
logger.info(
"%s person %s linked to user %s"
% ("New" if created else "Existing", str(person), user.username)
)
person.ldap_dn = dn.lower()
if not created:
......@@ -249,53 +271,55 @@ def ldap_sync_from_groups(group_infos):
# Skip group if one of the name fields is missing
# FIXME Throw exceptions and catch outside
if get_site_preferences()["ldap__group_sync_field_short_name"] not in ldap_group[1]:
logger.error("LDAP group with DN %s does not have field %s" % (
ldap_group[0],
get_site_preferences()["ldap__group_sync_field_short_name"]
))
logger.error(
"LDAP group with DN %s does not have field %s"
% (ldap_group[0], get_site_preferences()["ldap__group_sync_field_short_name"])
)
continue
if get_site_preferences()["ldap__group_sync_field_name"] not in ldap_group[1]:
logger.error("LDAP group with DN %s does not have field %s" % (
ldap_group[0],
get_site_preferences()["ldap__group_sync_field_name"]
))
logger.error(
"LDAP group with DN %s does not have field %s"
% (ldap_group[0], get_site_preferences()["ldap__group_sync_field_name"])
)
continue
# Apply regex replace from config
short_name = apply_templates(
ldap_group[1][get_site_preferences()["ldap__group_sync_field_short_name"]][0],
get_site_preferences()["ldap__group_sync_field_short_name_re"],
get_site_preferences()["ldap__group_sync_field_short_name_replace"]
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],
get_site_preferences()["ldap__group_sync_field_name_re"],
get_site_preferences()["ldap__group_sync_field_name_replace"]
get_site_preferences()["ldap__group_sync_field_name_replace"],
)
# Shorten names to fit into model fields
short_name = short_name[:Group._meta.get_field("short_name").max_length]
name = name[:Group._meta.get_field("name").max_length]
short_name = short_name[: Group._meta.get_field("short_name").max_length]
name = name[: Group._meta.get_field("name").max_length]
# FIXME FInd a way to throw exceptions correctly but still continue import
try:
with transaction.atomic():
group, created = Group.objects.update_or_create(
ldap_dn = ldap_group[0].lower(),
defaults = {
"short_name": short_name,
"name": name
}
ldap_dn=ldap_group[0].lower(), defaults={"short_name": short_name, "name": name}
)
except IntegrityError as e:
logger.error("Integrity error while trying to import LDAP group %s:\n%s" % (ldap_group[0], str(e)))
logger.error(
"Integrity error while trying to import LDAP group %s:\n%s"
% (ldap_group[0], str(e))
)
continue
else:
logger.info("%s LDAP group %s for Django group %s" % (
("Created" if created else "Updated"),
ldap_group[1][get_site_preferences()["ldap__group_sync_field_name"]][0],
name
))
logger.info(
"%s LDAP group %s for Django group %s"
% (
("Created" if created else "Updated"),
ldap_group[1][get_site_preferences()["ldap__group_sync_field_name"]][0],
name,
)
)
group_objects.append(group)
......@@ -320,7 +344,9 @@ def mass_ldap_import():
group_objects = ldap_sync_from_groups(ldap_groups)
# Guess LDAP username field from user filter
uid_field = re.search(r"([a-zA-Z]+)=%\(user\)s", backend.settings.USER_SEARCH.filterstr).group(1)
uid_field = re.search(r"([a-zA-Z]+)=%\(user\)s", backend.settings.USER_SEARCH.filterstr).group(
1
)
# Synchronise user data for all found users
ldap_users = backend.settings.USER_SEARCH.execute(connection, {"user": "*"}, escape=False)
......@@ -349,7 +375,9 @@ def mass_ldap_import():
logger.error("More than one matching person for user %s" % user.username)
continue
except (DataError, IntegrityError, ValueError) as e:
logger.error("Data error while synchronising user %s:\n%s" % (user.username, str(e)))
logger.error(
"Data error while synchronising user %s:\n%s" % (user.username, str(e))
)
continue
else:
logger.info("Successfully imported user %s" % uid)
......@@ -359,7 +387,12 @@ def mass_ldap_import():
member_attr = getattr(backend.settings.GROUP_TYPE, "member_attr", "memberUid")
owner_attr = get_site_preferences()["ldap__group_sync_owner_attr"]
for group, ldap_group in tqdm(zip(group_objects, ldap_groups), desc="Sync. group members", total=len(group_objects), **TQDM_DEFAULTS):
for group, ldap_group in tqdm(
zip(group_objects, ldap_groups),
desc="Sync. group members",
total=len(group_objects),
**TQDM_DEFAULTS
):
dn, attrs = ldap_group
ldap_members = [_.lower() for _ in attrs[member_attr]] if member_attr in attrs else []
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment