Implement asynchronous search for groups.

Use the filter generation code to search on multiple fields.
This commit is contained in:
Kevin McCarthy
2007-09-19 08:42:34 -07:00
parent 6b3d1e85da
commit f17071533a
5 changed files with 71 additions and 21 deletions

View File

@@ -50,7 +50,9 @@ def main():
client = ipaclient.IPAClient()
groups = client.find_groups(args[1])
if len(groups) == 0:
counter = groups[0]
groups = groups[1:]
if counter == 0:
print "No entries found for", args[1]
return 0

View File

@@ -161,13 +161,14 @@ class IPAClient:
result = self.transport.add_group(group_dict, group_container)
return result
def find_groups(self, criteria, sattrs=None):
def find_groups(self, criteria, sattrs=None, searchlimit=0):
"""Find groups whose cn matches the criteria. Wildcards are
acceptable. Returns a list of Group objects."""
result = self.transport.find_groups(criteria, sattrs)
result = self.transport.find_groups(criteria, sattrs, searchlimit)
counter = result[0]
groups = []
for attrs in result:
groups = [counter]
for attrs in result[1:]:
if attrs is not None:
groups.append(group.Group(attrs))

View File

@@ -259,7 +259,7 @@ class RPCClient:
except socket.error, (value, msg):
raise xmlrpclib.Fault(value, msg)
def find_groups (self, criteria, sattrs=None):
def find_groups (self, criteria, sattrs=None, searchlimit=0):
"""Return a list containing a Group object for each group that matches
the criteria."""
@@ -268,7 +268,7 @@ class RPCClient:
# None values are not allowed in XML-RPC
if sattrs is None:
sattrs = "__NONE__"
result = server.find_groups(criteria, sattrs)
result = server.find_groups(criteria, sattrs, searchlimit)
except xmlrpclib.Fault, fault:
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
except socket.error, (value, msg):

View File

@@ -551,11 +551,11 @@ class Root(controllers.RootController):
if criteria != None and len(criteria) > 0:
try:
groups = client.find_groups(criteria.encode('utf-8'))
# counter = groups[0]
# groups = groups[1:]
# if counter == -1:
# turbogears.flash("These results are truncated.<br />" +
# "Please refine your search and try again.")
counter = groups[0]
groups = groups[1:]
if counter == -1:
turbogears.flash("These results are truncated.<br />" +
"Please refine your search and try again.")
except ipaerror.IPAError, e:
turbogears.flash("Find groups failed: " + str(e))
raise turbogears.redirect("/grouplist")

View File

@@ -585,23 +585,70 @@ class IPAServer:
finally:
self.releaseConnection(conn)
def find_groups (self, criteria, sattrs=None, opts=None):
def find_groups (self, criteria, sattrs=None, searchlimit=0, opts=None):
"""Return a list containing a User object for each
existing group that matches the criteria.
"""
criteria = self.__safe_filter(criteria)
# 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 = "cn,description"
search_fields = string.split(search_fields_conf_str, ",")
filter = "(&(cn=%s)(objectClass=posixGroup))" % criteria
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) = self.__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=posixGroup)%s)" % exact_match_filter
partial_match_filter = "(&(objectClass=posixGroup)%s)" % partial_match_filter
#
# TODO - copy/paste from find_users. needs to be refactored
#
conn = self.getConnection(opts)
try:
results = conn.getList(self.basedn, self.scope, filter, sattrs)
try:
exact_results = conn.getListAsync(self.basedn, self.scope,
exact_match_filter, sattrs, 0, None, None, -1, searchlimit)
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
results = []
exact_results = [0]
try:
partial_results = conn.getListAsync(self.basedn, self.scope,
partial_match_filter, sattrs, 0, None, None, -1, searchlimit)
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
partial_results = [0]
finally:
self.releaseConnection(conn)
groups = []
for u in results:
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)
groups = [counter]
for u in exact_results + partial_results:
groups.append(self.convert_entry(u))
return groups