diff --git a/cps/admin.py b/cps/admin.py index f1f865da..531d855d 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -566,6 +566,7 @@ def _configuration_ldap_helper(to_save, gdriveError): reboot_required |= _config_string(to_save, "config_ldap_user_object") reboot_required |= _config_string(to_save, "config_ldap_group_object_filter") reboot_required |= _config_string(to_save, "config_ldap_group_members_field") + reboot_required |= _config_string(to_save, "config_ldap_member_user_object") reboot_required |= _config_checkbox(to_save, "config_ldap_openldap") reboot_required |= _config_int(to_save, "config_ldap_encryption") reboot_required |= _config_string(to_save, "config_ldap_cacert_path") @@ -608,14 +609,26 @@ def _configuration_ldap_helper(to_save, gdriveError): gdriveError) if config.config_ldap_user_object.count("(") != config.config_ldap_user_object.count(")"): return reboot_required, _configuration_result(_('LDAP User Object Filter Has Unmatched Parenthesis'), - gdriveError) + gdriveError) + + if to_save["ldap_import_user_filter"] == '0': + config.config_ldap_member_user_object = "" + else: + if config.config_ldap_member_user_object.count("%s") != 1: + return reboot_required, \ + _configuration_result(_('LDAP Member User Filter needs to Have One "%s" Format Identifier'), + gdriveError) + if config.config_ldap_member_user_object.count("(") != config.config_ldap_member_user_object.count(")"): + return reboot_required, _configuration_result(_('LDAP Member User Filter Has Unmatched Parenthesis'), + gdriveError) if config.config_ldap_cacert_path or config.config_ldap_cert_path or config.config_ldap_key_path: if not (os.path.isfile(config.config_ldap_cacert_path) and os.path.isfile(config.config_ldap_cert_path) and os.path.isfile(config.config_ldap_key_path)): return reboot_required, \ - _configuration_result(_('LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path'), + _configuration_result(_('LDAP CACertificate, Certificate or Key Location is not Valid, ' + 'Please Enter Correct Path'), gdriveError) return reboot_required, None diff --git a/cps/config_sql.py b/cps/config_sql.py index 7363e75c..877ad1c2 100644 --- a/cps/config_sql.py +++ b/cps/config_sql.py @@ -113,6 +113,7 @@ class _Settings(_Base): config_ldap_key_path = Column(String, default="") config_ldap_dn = Column(String, default='dc=example,dc=org') config_ldap_user_object = Column(String, default='uid=%s') + config_ldap_member_user_object = Column(String, default='') # config_ldap_openldap = Column(Boolean, default=True) config_ldap_group_object_filter = Column(String, default='(&(objectclass=posixGroup)(cn=%s))') config_ldap_group_members_field = Column(String, default='memberUid') diff --git a/cps/templates/config_edit.html b/cps/templates/config_edit.html index ab8050dc..fdf1e687 100644 --- a/cps/templates/config_edit.html +++ b/cps/templates/config_edit.html @@ -331,6 +331,20 @@ +
+ + +
+
+
+ + +
+
+ {% endif %} {% if feature_support['oauth'] %} diff --git a/cps/web.py b/cps/web.py index a458af3e..0146e5ca 100644 --- a/cps/web.py +++ b/cps/web.py @@ -323,31 +323,34 @@ def import_ldap_users(): showtext['text'] = _(u'Error: No user returned in response of LDAP server') return json.dumps(showtext) + imported = 0 for username in new_users: user = username.decode('utf-8') if '=' in user: - match = re.search("([a-zA-Z0-9-]+)=%s", config.config_ldap_user_object, re.IGNORECASE | re.UNICODE) - if match: - match_filter = match.group(1) - match = re.search(match_filter + "=([\d\s\w-]+)", user, re.IGNORECASE | re.UNICODE) - if match: - user = match.group(1) + # if member object field is empty take user object as filter + try: + if config.config_ldap_member_user_object: + user_identifier = extract_user_identifier(user, config.config_ldap_member_user_object) else: - log.warning("Could Not Parse LDAP User: %s", user) - continue - else: - log.warning("Could Not Parse LDAP User: %s", user) + user_identifier = extract_user_identifier(user, config.config_ldap_user_object) + + except Exception as e: + log.warning(e) continue - if ub.session.query(ub.User).filter(ub.User.nickname == user.lower()).first(): - log.warning("LDAP User: %s Already in Database", user) + else: + user_identifier = user + + if ub.session.query(ub.User).filter(ub.User.nickname == user_identifier.lower()).first(): + log.warning("LDAP User: %s Already in Database", user_identifier) continue - user_data = services.ldap.get_object_details(user=user, + user_data = services.ldap.get_object_details(user=user_identifier, group=None, query_filter=None, dn_only=False) if user_data: content = ub.User() - content.nickname = user + # user_login_field = extract_dynamic_field_from_filter(user, config.config_ldap_user_object) + content.nickname = user_identifier # user_data[user_login_field][0].decode('utf-8') content.password = '' # dummy password which will be replaced by ldap one if 'mail' in user_data: content.email = user_data['mail'][0].decode('utf-8') @@ -365,6 +368,7 @@ def import_ldap_users(): ub.session.add(content) try: ub.session.commit() + imported +=1 except Exception as e: log.warning("Failed to create LDAP user: %s - %s", user, e) ub.session.rollback() @@ -373,10 +377,28 @@ def import_ldap_users(): log.warning("LDAP User: %s Not Found", user) showtext['text'] = _(u'At Least One LDAP User Not Found in Database') if not showtext: - showtext['text'] = _(u'User Successfully Imported') + showtext['text'] = _(u'{} User Successfully Imported'.format(imported)) return json.dumps(showtext) +def extract_user_data_from_field(user, field): + match = re.search(field + "=([\d\s\w-]+)", user, re.IGNORECASE | re.UNICODE) + if match: + return match.group(1) + else: + raise Exception("Could Not Parse LDAP User: %s", user) + +# CN=Firstname LastName,OU=Laba,OU=...,DC=...,DC=... +# CN=user displayname,OU=ouname1,OU=ouname2,OU=ouname3,DC=domain,DC=domain +def extract_user_identifier(user, filter): + match = re.search("([a-zA-Z0-9-]+)=%s", filter, re.IGNORECASE | re.UNICODE) + if match: + dynamic_field = match.group(1) + else: + raise Exception("Could Not Parse LDAP User: %s", user) + return extract_user_data_from_field(user, dynamic_field) + + # ################################### data provider functions #########################################################