diff options
author | Rob Crittenden <rcritten@redhat.com> | 2008-10-07 06:15:34 -0400 |
---|---|---|
committer | Rob Crittenden <rcritten@redhat.com> | 2008-10-07 06:15:34 -0400 |
commit | db9d8dd3e0924bb9c7f9c89a56e6b6057dabc710 (patch) | |
tree | 6b7cae394a0457bbcc3f87e5745f0fdfc4cf1ccf | |
parent | e012e860b472bcb5a00a089e73113fb6989fde20 (diff) | |
download | freeipa-db9d8dd3e0924bb9c7f9c89a56e6b6057dabc710.tar.gz freeipa-db9d8dd3e0924bb9c7f9c89a56e6b6057dabc710.tar.xz freeipa-db9d8dd3e0924bb9c7f9c89a56e6b6057dabc710.zip |
Implement a real user_find and move existing user_find to user_show
-rw-r--r-- | ipa_server/servercore.py | 105 | ||||
-rw-r--r-- | ipalib/plugins/f_user.py | 26 |
2 files changed, 127 insertions, 4 deletions
diff --git a/ipa_server/servercore.py b/ipa_server/servercore.py index 76c358ef6..f0d3dd9aa 100644 --- a/ipa_server/servercore.py +++ b/ipa_server/servercore.py @@ -18,6 +18,8 @@ # import ldap +import string +import re from ipa_server.context import context import ipautil @@ -56,6 +58,30 @@ def convert_scalar_values(orig_dict): return new_dict +def generate_match_filters(search_fields, criteria_words): + """Generates a search filter based on a list of words and a list + of fields to search against. + + Returns a tuple of two filters: (exact_match, partial_match)""" + + # construct search pattern for a single word + # (|(f1=word)(f2=word)...) + search_pattern = "(|" + for field in search_fields: + search_pattern += "(" + field + "=%(match)s)" + search_pattern += ")" + gen_search_pattern = lambda word: search_pattern % {'match':word} + + # construct the giant match for all words + exact_match_filter = "(&" + partial_match_filter = "(|" + for word in criteria_words: + exact_match_filter += gen_search_pattern(word) + partial_match_filter += gen_search_pattern("*%s*" % word) + exact_match_filter += ")" + partial_match_filter += ")" + + return (exact_match_filter, partial_match_filter) # TODO: rethink the get_entry vs get_list API calls. # they currently restrict the data coming back without @@ -159,6 +185,85 @@ def uid_too_long(uid): return False +def find_users (criteria, sattrs, sizelimit=-1, timelimit=-1): + """Returns a list: counter followed by the results. + If the results are truncated, counter will be set to -1.""" + + """ + if not isinstance(criteria,basestring) or len(criteria) == 0: + raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER) + if sattrs is not None and not isinstance(sattrs, list): + raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER) + if not isinstance(sizelimit,int): + raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER) + if not isinstance(timelimit,int): + raise ipaerror.gen_exception(ipaerror.INPUT_INVALID_PARAMETER) + """ + +# logging.info("IPA: find_users '%s'" % criteria) + config = get_ipa_config() + if timelimit < 0: + timelimit = float(config.get('ipasearchtimelimit')) + if sizelimit < 0: + sizelimit = int(config.get('ipasearchrecordslimit')) + + # Assume the list of fields to search will come from a central + # configuration repository. A good format for that would be + # a comma-separated list of fields + search_fields_conf_str = config.get('ipausersearchfields') + search_fields = string.split(search_fields_conf_str, ",") + +# criteria = self.__safe_filter(criteria) + criteria_words = re.split(r'\s+', criteria) + criteria_words = filter(lambda value:value!="", criteria_words) + if len(criteria_words) == 0: + return [0] + + (exact_match_filter, partial_match_filter) = generate_match_filters( + search_fields, criteria_words) + + # + # further constrain search to just the objectClass + # TODO - need to parameterize this into generate_match_filters, + # and work it into the field-specification search feature + # + exact_match_filter = "(&(objectClass=person)%s)" % exact_match_filter + partial_match_filter = "(&(objectClass=person)%s)" % partial_match_filter + + try: + exact_results = context.conn.getConn().getListAsync("cn=accounts," + basedn, ldap.SCOPE_SUBTREE, exact_match_filter, sattrs, 0, None, None, timelimit, sizelimit) +# except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): + except Exception: + exact_results = [0] + + try: + partial_results = context.conn.getConn().getListAsync("cn=accounts," + basedn, ldap.SCOPE_SUBTREE, partial_match_filter, sattrs, 0, None, None, timelimit, sizelimit) +# except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): + except Exception: + partial_results = [0] + + exact_counter = exact_results[0] + partial_counter = partial_results[0] + + exact_results = exact_results[1:] + partial_results = partial_results[1:] + + # Remove exact matches from the partial_match list + exact_dns = set(map(lambda e: e.dn, exact_results)) + partial_results = filter(lambda e: e.dn not in exact_dns, + partial_results) + + if (exact_counter == -1) or (partial_counter == -1): + counter = -1 + else: + counter = len(exact_results) + len(partial_results) + + users = [counter] + for u in exact_results + partial_results: + users.append(convert_entry(u)) + + return users + def update_entry (entry): """Update an LDAP entry diff --git a/ipalib/plugins/f_user.py b/ipalib/plugins/f_user.py index 0b424d351..e560d03ce 100644 --- a/ipalib/plugins/f_user.py +++ b/ipalib/plugins/f_user.py @@ -208,15 +208,33 @@ class user_find(crud.Find): 'Search the users.' def execute(self, *args, **kw): uid=args[0] - result = servercore.get_sub_entry(servercore.basedn, "uid=%s" % uid, ["*"]) + result = servercore.find_users(uid, ["*"]) return result def forward(self, *args, **kw): - result = super(crud.Find, self).forward(*args, **kw) - for a in result: - print a, ": ", result[a] + users = super(crud.Find, self).forward(*args, **kw) + counter = users[0] + users = users[1:] + if counter == 0: + print "No entries found for", args[0] + return + elif counter == -1: + print "These results are truncated." + print "Please refine your search and try again." + + for u in users: + for a in u.keys(): + print "%s: %s" % (a, u[a]) api.register(user_find) class user_show(crud.Get): 'Examine an existing user.' + def execute(self, *args, **kw): + uid=args[0] + result = servercore.get_user_by_uid(uid, ["*"]) + return result + def forward(self, *args, **kw): + result = super(crud.Get, self).forward(*args, **kw) + for a in result: + print a, ": ", result[a] api.register(user_show) |