summaryrefslogtreecommitdiffstats
path: root/ipa_server/servercore.py
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2008-10-07 06:15:34 -0400
committerRob Crittenden <rcritten@redhat.com>2008-10-07 06:15:34 -0400
commitdb9d8dd3e0924bb9c7f9c89a56e6b6057dabc710 (patch)
tree6b7cae394a0457bbcc3f87e5745f0fdfc4cf1ccf /ipa_server/servercore.py
parente012e860b472bcb5a00a089e73113fb6989fde20 (diff)
downloadfreeipa-db9d8dd3e0924bb9c7f9c89a56e6b6057dabc710.tar.gz
freeipa-db9d8dd3e0924bb9c7f9c89a56e6b6057dabc710.tar.xz
freeipa-db9d8dd3e0924bb9c7f9c89a56e6b6057dabc710.zip
Implement a real user_find and move existing user_find to user_show
Diffstat (limited to 'ipa_server/servercore.py')
-rw-r--r--ipa_server/servercore.py105
1 files changed, 105 insertions, 0 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