From 3721117128d3c449dd0001627854faa9c0c26d1e Mon Sep 17 00:00:00 2001 From: Tom Teichler <tom.teichler@teckids.org> Date: Sun, 3 May 2020 14:11:08 +0200 Subject: [PATCH] [Reformat] flake8 --- aleksis/apps/ldap/apps.py | 1 + aleksis/apps/ldap/preferences.py | 18 +++-- aleksis/apps/ldap/settings.py | 85 ----------------------- aleksis/apps/ldap/util/ldap_sync.py | 102 ++++++++++++++++------------ 4 files changed, 73 insertions(+), 133 deletions(-) delete mode 100644 aleksis/apps/ldap/settings.py diff --git a/aleksis/apps/ldap/apps.py b/aleksis/apps/ldap/apps.py index 632b3f9..e376ac2 100644 --- a/aleksis/apps/ldap/apps.py +++ b/aleksis/apps/ldap/apps.py @@ -2,6 +2,7 @@ from django.contrib.auth import get_user_model from django.db.models.signals import post_save from aleksis.core.util.apps import AppConfig +from aleksis.core.util.core_helpers import get_site_preferences from .util.ldap_sync import ldap_sync_user_on_login, update_dynamic_preferences diff --git a/aleksis/apps/ldap/preferences.py b/aleksis/apps/ldap/preferences.py index cb08a9a..3bc7d65 100644 --- a/aleksis/apps/ldap/preferences.py +++ b/aleksis/apps/ldap/preferences.py @@ -1,7 +1,11 @@ from django.utils.translation import gettext_lazy as _ from dynamic_preferences.preferences import Section -from dynamic_preferences.types import BooleanPreference, ChoicePreference, StringPreference +from dynamic_preferences.types import ( + BooleanPreference, + ChoicePreference, + StringPreference, +) from aleksis.core.registries import site_preferences_registry @@ -75,7 +79,8 @@ class LDAPGroupSyncFieldShortNameRE(StringPreference): 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 |" + "Regular expression to match LDAP value for group short name against," + "e.g. class_(?P<class>.*); separate multiple patterns by |" ) @@ -86,7 +91,8 @@ class LDAPGroupSyncFieldShortNameReplace(StringPreference): default = "" required = False verbose_name = _( - "Replacement template to apply to group short name, e.g. \\g<class>; separate multiple templates by |" + "Replacement template to apply to group short name," + "e.g. \\g<class>; separate multiple templates by |" ) @@ -106,7 +112,8 @@ class LDAPGroupSyncFieldNameRE(StringPreference): default = "" required = False verbose_name = _( - "Regular expression to match LDAP value for group name against, e.g. class_(?P<class>.*); separate multiple patterns by |" + "Regular expression to match LDAP value for group name against," + "e.g. class_(?P<class>.*); separate multiple patterns by |" ) @@ -117,7 +124,8 @@ class LDAPGroupSyncFieldNameReplace(StringPreference): default = "" required = False verbose_name = _( - "Replacement template to apply to group name, e.g. \\g<class>; separate multiple templates by |" + "Replacement template to apply to group name," + "e.g. \\g<class>; separate multiple templates by |" ) diff --git a/aleksis/apps/ldap/settings.py b/aleksis/apps/ldap/settings.py deleted file mode 100644 index 9be4129..0000000 --- a/aleksis/apps/ldap/settings.py +++ /dev/null @@ -1,85 +0,0 @@ -from django.apps import apps -from django.utils.translation import gettext_lazy as _ - -CONSTANCE_ADDITIONAL_FIELDS = { - "matching-fields-select": [ - "django.forms.fields.ChoiceField", - { - "widget": "django.forms.Select", - "choices": ( - (None, "-----"), - ("match-email", _("Match only on email")), - ("match-name", _("Match only on name")), - ("match-email-name", _("Match on email and name")), - ), - }, - ], - "owner-attr-type": [ - "django.forms.fields.ChoiceField", - { - "widget": "django.forms.Select", - "choices": (("dn", _("Distinguished Name")), ("uid", _("UID")),), - }, - ], -} - -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",), - "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_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_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", - ), -} -CONSTANCE_CONFIG_FIELDSETS = { - "LDAP-Sync settings": ( - "ENABLE_LDAP_SYNC", - "LDAP_SYNC_ON_UPDATE", - "LDAP_SYNC_CREATE_MISSING_PERSONS", - "LDAP_MATCHING_FIELDS", - "ENABLE_LDAP_GROUP_SYNC", - "LDAP_GROUP_SYNC_OWNER_ATTR", - "LDAP_GROUP_SYNC_OWNER_ATTR_TYPE", - "LDAP_GROUP_SYNC_FIELD_SHORT_NAME", - "LDAP_GROUP_SYNC_FIELD_SHORT_NAME_RE", - "LDAP_GROUP_SYNC_FIELD_SHORT_NAME_REPLACE", - "LDAP_GROUP_SYNC_FIELD_NAME", - "LDAP_GROUP_SYNC_FIELD_NAME_RE", - "LDAP_GROUP_SYNC_FIELD_NAME_REPLACE", - ), -} diff --git a/aleksis/apps/ldap/util/ldap_sync.py b/aleksis/apps/ldap/util/ldap_sync.py index e6afc9a..d8443ac 100644 --- a/aleksis/apps/ldap/util/ldap_sync.py +++ b/aleksis/apps/ldap/util/ldap_sync.py @@ -3,12 +3,10 @@ import logging import re from django.apps import apps -from django.conf import settings -from django.contrib.auth import get_user_model 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 FieldFile, FileField +from django.db.models.fields.files import FieldFile from django.utils.text import slugify from django.utils.translation import gettext as _ @@ -30,14 +28,12 @@ TQDM_DEFAULTS = { def setting_name_from_field(model, field): - """ Generate a setting name from a model field """ - + """Generate a setting name from a model field.""" return "additional_field_%s_%s" % (model._meta.label, field.name) def syncable_fields(model): - """ Collect all fields that can be synced on a model """ - + """Collect all fields that can be synced on a model.""" return [ field for field in model._meta.fields @@ -46,18 +42,16 @@ def syncable_fields(model): def ldap_field_to_filename(dn, fieldname): - """ Generate a reproducible filename from a DN and a field name """ - + """Generate a reproducible filename from a DN and a field name.""" return "%s__%s" % (slugify(dn), slugify(fieldname)) def from_ldap(value, instance, field, dn, ldap_field): - """ Convert an LDAP value to the Python type of the target field + """Convert an LDAP value to the Python type of the target field 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 @@ -79,8 +73,7 @@ def from_ldap(value, instance, field, dn, ldap_field): def update_dynamic_preferences(): - """ Auto-generate sync field settings from models """ - + """Auto-generate sync field settings from models.""" Person = apps.get_model("core", "Person") for model in (Person,): # Collect fields that are matchable @@ -102,10 +95,9 @@ def update_dynamic_preferences(): 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 = "" @@ -122,8 +114,7 @@ def update_dynamic_preferences(): def apply_templates(value, patterns, templates, separator="|"): - """ Regex-replace patterns in value in order """ - + """Regex-replace patterns in value in order.""" if isinstance(patterns, str): patterns = patterns.split(separator) if isinstance(templates, str): @@ -142,8 +133,7 @@ def apply_templates(value, patterns, templates, separator="|"): @transaction.atomic def ldap_sync_user_on_login(sender, instance, created, **kwargs): - """ Synchronise Person meta-data and groups from ldap_user on User update. """ - + """Synchronise Person meta-data and groups from ldap_user on User update.""" # Semaphore to guard recursive saves within this signal if getattr(instance, "_skip_signal", False): return @@ -168,7 +158,9 @@ def ldap_sync_user_on_login(sender, instance, created, **kwargs): logger.error("More than one matching person for user %s" % user.username) return 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)) + ) return if get_site_preferences()["ldap__enable_group_sync"]: @@ -194,15 +186,17 @@ def ldap_sync_user_on_login(sender, instance, created, **kwargs): @transaction.atomic def ldap_sync_from_user(user, dn, attrs): - """ Synchronise person information from a User object (with ldap_user) to Django """ - + """Synchronise person information from a User object (with ldap_user) to Django""" Person = apps.get_model("core", "Person") # Check if there is an existing person connected to the user. if Person.objects.filter(user__username=user.username).exists(): person = user.person created = False - logger.info("Existing person %s already linked to user %s" % (str(person), user.username)) + logger.info( + "Existing person %s already linked to user %s" + % (str(person), user.username) + ) # FIXME ALso account for existing person with DN here else: # Build filter criteria depending on config @@ -253,7 +247,9 @@ def ldap_sync_from_user(user, dn, attrs): value = from_ldap(value, person, field, dn, ldap_field) setattr(person, field.name, value) - logger.debug("Field %s set to %s for %s" % (field.name, str(value), str(person))) + logger.debug( + "Field %s set to %s for %s" % (field.name, str(value), str(person)) + ) person.save() return person @@ -261,8 +257,7 @@ def ldap_sync_from_user(user, dn, attrs): @transaction.atomic def ldap_sync_from_groups(group_infos): - """ Synchronise group information from LDAP results to Django """ - + """Synchronise group information from LDAP results to Django.""" Group = apps.get_model("core", "Group") # Resolve Group objects from LDAP group objects @@ -270,10 +265,16 @@ def ldap_sync_from_groups(group_infos): for ldap_group in tqdm(group_infos, desc="Sync. group infos", **TQDM_DEFAULTS): # 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]: + 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"]) + % ( + 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]: @@ -285,7 +286,9 @@ 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], + 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"], ) @@ -303,7 +306,8 @@ def ldap_sync_from_groups(group_infos): 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( @@ -316,7 +320,9 @@ def ldap_sync_from_groups(group_infos): "%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], + ldap_group[1][ + get_site_preferences()["ldap__group_sync_field_name"] + ][0], name, ) ) @@ -328,8 +334,7 @@ def ldap_sync_from_groups(group_infos): @transaction.atomic def mass_ldap_import(): - """ Utility code for mass import from ldap """ - + """Utility code for mass import from ldap.""" from django_auth_ldap.backend import LDAPBackend, _LDAPUser # noqa Person = apps.get_model("core", "Person") @@ -344,12 +349,14 @@ 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) + 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] @@ -372,11 +379,14 @@ def mass_ldap_import(): logger.warn("No matching person for user %s" % user.username) continue except Person.MultipleObjectsReturned: - logger.error("More than one matching person for user %s" % user.username) + 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)) + "Data error while synchronising user %s:\n%s" + % (user.username, str(e)) ) continue else: @@ -394,7 +404,9 @@ def mass_ldap_import(): **TQDM_DEFAULTS ): dn, attrs = ldap_group - ldap_members = [_.lower() for _ in attrs[member_attr]] if member_attr in attrs else [] + 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) @@ -402,7 +414,11 @@ def mass_ldap_import(): 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 [] + 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": -- GitLab