[Zope-CVS] SVN: ldapadapter/trunk/ Better README.txt and improved
fakeldap.
Florent Guillaume
fg at nuxeo.com
Sun Oct 10 13:02:14 EDT 2004
Log message for revision 27926:
Better README.txt and improved fakeldap.
Changed:
U ldapadapter/trunk/README.txt
U ldapadapter/trunk/tests/fakeldap.py
U ldapadapter/trunk/utility.py
-=-
Modified: ldapadapter/trunk/README.txt
===================================================================
--- ldapadapter/trunk/README.txt 2004-10-10 16:48:30 UTC (rev 27925)
+++ ldapadapter/trunk/README.txt 2004-10-10 17:02:14 UTC (rev 27926)
@@ -1,54 +1,143 @@
===========
-LDAPAdapter
+LDAPAdapter
===========
-The LDAPAdapter provides a mechanism for to connect to a LDAP server.
+The LDAPAdapter provides a mechanism to connect to an LDAP server and
+send commands to it.
LDAPAdapter
===========
-The primary job of an ldap adapter is to store the settings of
-a LDAP server connection.
+An LDAP adapter stores the settings to use to connect to an LDAP server.
+You get an LDAP adapter by calling LDAPAdapter, which implements
+ILDAPAdapter:
-Let's look at an example:
-
+ >>> from pprint import PrettyPrinter
+ >>> pprint = PrettyPrinter(width=60).pprint
+ >>> from ldapadapter.utility import LDAPAdapter
>>> from ldapadapter.interfaces import ILDAPAdapter
- >>> from ldapadapter.interfaces import ILDAPConnection
- >>> from ldapadapter.utility import LDAPAdapter
+ >>> from zope.interface.verify import verifyClass, verifyObject
+ >>> verifyClass(ILDAPAdapter, LDAPAdapter)
+ True
- >>> host = u'localhost'
- >>> port = 389
- >>> useSSL = False
- >>> da = LDAPAdapter(host, port)
+The adapter is set up by giving it a host name and a port.
+
+ >>> da = LDAPAdapter('localhost', 389)
+ >>> verifyObject(ILDAPAdapter, da)
+ True
>>> (da.host, da.port, da.useSSL)
- (u'localhost', 389, False)
+ ('localhost', 389, False)
- >>> dn = 'Manager'
- >>> pw = ''
- >>> conn = da.connect(dn, pw)
+If you want, you can request an SSL connection:
- >>> conn.add('cn=yo,o=test,dc=org', {'cn': ['yo']})
+ >>> da = LDAPAdapter('localhost', 389, useSSL=True)
+ >>> (da.host, da.port, da.useSSL)
+ ('localhost', 389, True)
-The fake implementation of ldap used for the tests returns a simpler
-result than a real server would:
+You can also provide a default bind DN and password to use by default
+for future connections:
- >>> conn.search('cn=yo,o=test,dc=org', 'sub')
- [(u'cn=yo,o=test,dc=org', {'cn': [u'yo']})]
+ >>> da = LDAPAdapter('localhost', 389,
+ ... bindDN='cn=Manager', bindPassword='secret')
+ >>> (da.host, da.port, da.bindDN)
+ ('localhost', 389, 'cn=Manager')
-Modify it.
+LDAPConnection
+==============
- >>> conn.modify('cn=yo,o=test,dc=org', {'givenName': ['bob']})
- >>> conn.search('cn=yo,o=test,dc=org', 'sub')[0][1]['givenName']
- [u'bob']
- >>> conn.modify('cn=yo,o=test,dc=org', {'givenName': ['bob', 'john']})
- >>> conn.search('cn=yo,o=test,dc=org', 'sub')[0][1]['givenName']
- [u'bob', u'john']
- >>> conn.modify('cn=yo,o=test,dc=org', {'givenName': []})
- >>> conn.search('cn=yo,o=test,dc=org', 'sub')
- [(u'cn=yo,o=test,dc=org', {'cn': [u'yo']})]
+Once you have an LDAP adapter, you can get an LDAP connection by calling
+connect() on the database adapter.
-Delete it.
+You can either use the default bind DN and password if these have been
+specified in the adapter:
- >>> conn.delete('cn=yo,o=test,dc=org')
- >>> conn.search('cn=yo,o=test,dc=org', 'sub')
+ >>> conn = da.connect()
+
+Or you can provide specific binding parameters:
+
+ >>> conn = da.connect('cn=Manager,dc=org', 'supersecret')
+
+You can bind anonymously by using an empty DN and password:
+
+ >>> conn = da.connect('', '')
+
+The connection object that is returned implements ILDAPConnection:
+
+ >>> from ldapadapter.interfaces import ILDAPConnection
+ >>> verifyObject(ILDAPConnection, conn)
+ True
+
+Commands
+========
+
+Once you have an LDAP connection, you can start sending commands using
+it. (The fake implementation of the ldap module used for the tests
+returns simpler results than a real server would.)
+
+Add
+---
+
+Let's add a few simple entries (simplified in this test setting):
+
+ >>> conn.add('dc=test', {'dc': ['test']})
+ >>> conn.add('cn=foo,dc=test', {'cn': ['foo'], 'givenName': ['John']})
+ >>> conn.add('cn=bar,dc=test', {'cn': ['bar'], 'givenName': ['Joey']})
+ >>> conn.add('cn=baz,dc=test', {'cn': ['baz'], 'givenName': ['Raoul']})
+
+Search
+------
+
+Let's now search for entries. The scope argument controls what kind of
+search is done. You can choose to return a subset of the attributes.
+
+ >>> conn.search('dc=test', scope='base')
+ [(u'dc=test', {'dc': [u'test']})]
+
+ >>> res = conn.search('dc=test', scope='one', attrs=['cn'])
+ >>> pprint(res)
+ [(u'cn=foo,dc=test', {'cn': [u'foo']}),
+ (u'cn=bar,dc=test', {'cn': [u'bar']}),
+ (u'cn=baz,dc=test', {'cn': [u'baz']})]
+
+ >>> res = conn.search('dc=test', scope='sub', attrs=['givenName'])
+ >>> pprint(res)
+ [(u'dc=test', {}),
+ (u'cn=foo,dc=test', {'givenName': [u'John']}),
+ (u'cn=bar,dc=test', {'givenName': [u'Joey']}),
+ (u'cn=baz,dc=test', {'givenName': [u'Raoul']})]
+
+You can use a search filter to filter the entries returned:
+
+ >>> res = conn.search('dc=test', scope='sub', filter='(cn=ba*)',
+ ... attrs=['cn'])
+ >>> pprint(res)
+ [(u'cn=bar,dc=test', {'cn': [u'bar']}),
+ (u'cn=baz,dc=test', {'cn': [u'baz']})]
+
+Modify
+------
+
+When modifying an entry, you pass new values for some attributes:
+
+ >>> conn.modify('cn=foo,dc=test', {'givenName': ['Pete']})
+ >>> conn.search('cn=foo,dc=test', attrs=['givenName'])
+ [(u'cn=foo,dc=test', {'givenName': [u'Pete']})]
+
+ >>> conn.modify('cn=foo,dc=test', {'givenName': ['Bob', 'Robert']})
+ >>> conn.search('cn=foo,dc=test', attrs=['givenName'])
+ [(u'cn=foo,dc=test', {'givenName': [u'Bob', u'Robert']})]
+
+Passing an empty value for an attribute remove it from the entry:
+
+ >>> conn.modify('cn=foo,dc=test', {'givenName': []})
+ >>> conn.search('cn=foo,dc=test')
+ [(u'cn=foo,dc=test', {'cn': [u'foo']})]
+
+Delete
+------
+
+You delete an entry.
+
+ >>> conn.delete('cn=foo,dc=test')
+ >>> conn.search('cn=foo,dc=test', 'sub')
[]
Modified: ldapadapter/trunk/tests/fakeldap.py
===================================================================
--- ldapadapter/trunk/tests/fakeldap.py 2004-10-10 16:48:30 UTC (rev 27925)
+++ ldapadapter/trunk/tests/fakeldap.py 2004-10-10 17:02:14 UTC (rev 27926)
@@ -53,8 +53,13 @@
def simple_bind_s(self, dn, password):
if dn.find('Manager') >= 0:
+ # Fake authentified connection.
return 1
+ if dn == '' and password == '':
+ # Fake anonymous connection.
+ return 1
+
results = self.search_s(dn)
pwd = None
for key, values in results:
@@ -130,21 +135,21 @@
if fval == '*' or match_all:
ok = 1
elif fval[0] == '*' and fval[-1] == '*':
- fval = fval[1:-1]
+ f = fval[1:-1]
for v in values:
- if fval in v:
+ if f in v:
ok = 1
break
elif fval[0] == '*':
- fval = fval[1:]
+ f = fval[1:]
for v in values:
- if v.endswith(fval):
+ if v.endswith(f):
ok = 1
break
elif fval[-1] == '*':
- fval = fval[:-1]
+ f = fval[:-1]
for v in values:
- if v.startswith(fval):
+ if v.startswith(f):
ok = 1
break
else:
@@ -155,7 +160,14 @@
if not ok:
continue
dn = ','.join(dnl)
- res.append((dn, deepcopy(entry)))
+ if attrs:
+ res_entry = {}
+ for attr in attrs:
+ if entry.has_key(attr):
+ res_entry[attr] = deepcopy(entry[attr])
+ else:
+ res_entry = deepcopy(entry)
+ res.append((dn, res_entry))
return res
def modify_s(self, dn, mod_list):
Modified: ldapadapter/trunk/utility.py
===================================================================
--- ldapadapter/trunk/utility.py 2004-10-10 16:48:30 UTC (rev 27925)
+++ ldapadapter/trunk/utility.py 2004-10-10 17:02:14 UTC (rev 27926)
@@ -125,8 +125,10 @@
def modify(self, dn, entry):
# Get current entry
- cur_dn, cur_entry = self.search(dn, 'base')[0]
- # TODO nice exception if missing entry
+ res = self.search(dn, 'base')
+ if not res:
+ raise Exception("No such entry") # FIXME use proper exception
+ cur_dn, cur_entry = res[0]
mod_list = []
for key, values in entry.items():
More information about the Zope-CVS
mailing list