[Checkins] SVN: Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/ Tests for PrincipalRegistryAuthenticator.

Uli Fouquet uli at gnufix.de
Wed Aug 22 10:04:17 EDT 2007


Log message for revision 79124:
  Tests for PrincipalRegistryAuthenticator.

Changed:
  U   Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/__init__.py
  U   Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/auth.py
  A   Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/auth.txt
  U   Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/tests/test_grokadmin.py

-=-
Modified: Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/__init__.py
===================================================================
--- Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/__init__.py	2007-08-22 13:41:11 UTC (rev 79123)
+++ Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/__init__.py	2007-08-22 14:04:17 UTC (rev 79124)
@@ -33,6 +33,7 @@
 
 
 def setupSessionAuthentication(root_folder=None,
+                               fallback_only=False,
                                auth_foldername=AUTH_FOLDERNAME,
                                userfolder_name = USERFOLDER_NAME,
                                userfolder_prefix=USERFOLDER_PREFIX):
@@ -69,18 +70,21 @@
     registry_users.__name__ = u'registry_principals'
 
     # Configure the PAU...
-    pau.authenticatorPlugins = (userfolder_name,)
+    if fallback_only:
+        pau.authenticatorPlugins = ('registry_principals')
+    else:
+        pau.authenticatorPlugins = (userfolder_name, 'registry_principals')
     pau.credentialsPlugins = ("No Challenge if Authenticated",
                               "Session Credentials")
 
     # Add the pau and its plugin to the root_folder...
     sm[auth_foldername] = pau
     sm[auth_foldername][userfolder_name] = users
-    pau.authenticatorPlugins = (users.__name__, 'registry_principals')
 
     # Register the PAU with the site...
     sm.registerUtility(pau, IAuthentication)
-    sm.registerUtility(users, IAuthenticatorPlugin, name=userfolder_name)
+    if not fallback_only:
+        sm.registerUtility(users, IAuthenticatorPlugin, name=userfolder_name)
     sm.registerUtility(registry_users, IAuthenticatorPlugin,
                        name='registry_principals')
 

Modified: Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/auth.py
===================================================================
--- Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/auth.py	2007-08-22 13:41:11 UTC (rev 79123)
+++ Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/auth.py	2007-08-22 14:04:17 UTC (rev 79124)
@@ -23,6 +23,9 @@
     """An authenticator plugin, that authenticates principals against
     the global principal registry.
 
+    This authenticator does not support own prefixes, because the
+    prefix of its principals is already defined in another place
+    (site.zcml). Therefore we get and give back IDs as they are.
     """
 
     implements(IAuthenticatorPlugin, IQuerySchemaSearch)
@@ -43,7 +46,7 @@
         except KeyError:
             return
         if principal and principal.validate(password):
-            return PrincipalInfo(principal.id,
+            return PrincipalInfo(u''+principal.id,
                                  principal.getLogin(),
                                  principal.title,
                                  principal.description)
@@ -51,10 +54,11 @@
 
     def principalInfo(self, id):
         principal = principalRegistry.getPrincipal(id)
-        return PrincipalInfo(principal.id,
-                             principal.getLogin(),
-                             principal.title,
-                             principal.description)
+        if principal is not None:
+            return PrincipalInfo(u''+principal.id,
+                                 principal.getLogin(),
+                                 principal.title,
+                                 principal.description)
 
 
     def search(self, query, start=None, batch_size=None):
@@ -67,11 +71,13 @@
         n = 1
         values = [x for x in principalRegistry.getPrincipals('')
                   if x is not None]
+        values.sort(cmp=lambda x,y: cmp(str(x.id), str(y.id)))
         for i, value in enumerate(values):
-            if (search in value.title.lower() or
+            if (search in value.id.lower() or
+                search in value.title.lower() or
                 search in value.description.lower() or
                 search in value.getLogin().lower()):
                 if not ((start is not None and i < start)
                         or (batch_size is not None and n > batch_size)):
                     n += 1
-                    yield value.__name__
+                    yield u''+value.__name__

Added: Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/auth.txt
===================================================================
--- Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/auth.txt	                        (rev 0)
+++ Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/auth.txt	2007-08-22 14:04:17 UTC (rev 79124)
@@ -0,0 +1,168 @@
+================================
+Principal Registry Authenticator
+================================
+
+Principal registry authenticators provide an authenticator 'frontend'
+to the global principal registry. Such, you can use it to authenticate
+against principals in the global registry.
+
+Because the global principal registry is limited in functionality
+(compared to other principal containers), you cannot modify nor remove
+principals defined therein, except you ask the principal registry
+directly.
+
+The principal registry authenticator offers a plain fallback solution,
+you can put at the end of the list of authenticators in your
+PAU. Such, when every other authenticator fails to authenticate a
+user, the users defined in ``site.zcml`` should still be able to
+login.
+
+Different to other autenticators, we create principal registry
+authenticators *without* a prefix:
+
+  >>> from grok.admin.auth import PrincipalRegistryAuthenticator
+  >>> principals = PrincipalRegistryAuthenticator()
+
+Principal registry authenticators do not support adding of items. We
+can, however add principals to the global principal registry:
+
+  >>> from zope.app.security.principalregistry import principalRegistry
+  >>> reg = principalRegistry
+  >>> p1 = reg.definePrincipal('p1', 'Tim Peters', 'Sir Tim Peters',
+  ...                          'tim', '123')
+  >>> p1
+  <zope.app.security.principalregistry.Principal object at 0x...>
+
+  >>> p2 = reg.definePrincipal('p2', 'Jim Fulton', 'Sir Jim Fulton',
+  ...                          'jim', '456') 
+
+
+Authentication
+--------------
+
+Principal registry authenticators provide the `IAuthenticatorPlugin`
+interface. When we provide suitable credentials:
+
+  >>> from zope.testing.doctestunit import pprint
+  >>> principals.authenticateCredentials({'login': 'tim', 
+  ...                                     'password': '123'})
+  PrincipalInfo(u'p1')
+
+We get back a principal id and supplementary information, including
+the principal title and description.  Note that the principal id is
+*not* a concatenation of the principal-folder prefix and the name of
+the principal-information object within the folder (as it is with
+other authenticators), simply, because principal registry
+authenticators have no prefix.
+
+None is returned if the credentials are invalid:
+
+  >>> principals.authenticateCredentials({'login': 'login1',
+  ...                                     'password': '1234'})
+  >>> principals.authenticateCredentials(42)
+
+Search
+------
+Principal registry authenticators also provide the IQuerySchemaSearch
+interface.  This supports both finding principal information based on
+their ids:
+
+  >>> principals.principalInfo('p1')
+  PrincipalInfo(u'p1')
+
+and searching for principals based on a search string:
+
+  >>> list(principals.search({'search': 'ulto'}))
+  [u'p2']
+
+  >>> list(principals.search({'search': 'ULTO'}))
+  [u'p2']
+
+  >>> sorted(list(principals.search({'search': ''})))
+  [u'p1', u'p2']
+
+  >>> list(principals.search({'search': 'eek'}))
+  []
+
+  >>> list(principals.search({}))
+  []
+
+If there are a large number of matches:
+
+  >>> for i in range(20):
+  ...     i = str(i)
+  ...     trash = reg.definePrincipal(''+i, 'Dude '+i, 'Dude '+i,
+  ...                                 'jim' + i, i) 
+  ...     #p = InternalPrincipal('l'+i, i, "Dude "+i)
+  ...     #principals[i] = p
+
+  >>> pprint(list(principals.search({'search': 'D'})))
+  [u'0',
+   u'1',
+   u'10',
+   u'11',
+   u'12',
+   u'13',
+   u'14',
+   u'15',
+   u'16',
+   u'17',
+   u'18',
+   u'19',
+   u'2',
+   u'3',
+   u'4',
+   u'5',
+   u'6',
+   u'7',
+   u'8',
+   u'9']
+
+We can use batching parameters to specify a subset of results:
+
+  >>> pprint(list(principals.search({'search': 'D'}, start=17)))
+  [u'7',
+   u'8',
+   u'9']
+
+  >>> pprint(list(principals.search({'search': 'D'}, batch_size=5)))
+  [u'0',
+   u'1',
+   u'10',
+   u'11',
+   u'12']
+
+  >>> pprint(list(principals.search({'search': 'D'}, start=5, batch_size=5)))
+  [u'13',
+   u'14',
+   u'15',
+   u'16',
+   u'17']
+
+Changing credentials not supported
+----------------------------------
+Credentials of a principal registry authenticator can *not* be
+changed, because the principalRegistry, which is our 'principal
+container', does not support changing of principals. 
+
+So the usual techniques of modifying principal-information objects do
+not change credentials:
+
+  >>> p1.login = 'bob'
+  >>> p1.password = 'eek'
+
+  >>> p = principals.authenticateCredentials({'login': 'bob', 
+  ...                                         'password': 'eek'})
+  >>> p is None
+  True
+
+Removing principals not supported
+---------------------------------
+Due to the structure of principal registry, principals cannot be
+removed:
+
+  >>> del principals['p1']
+  Traceback (most recent call last):
+  ...
+  TypeError: object does not support item deletion
+

Modified: Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/tests/test_grokadmin.py
===================================================================
--- Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/tests/test_grokadmin.py	2007-08-22 13:41:11 UTC (rev 79123)
+++ Sandbox/ulif/grok-adminui-with-principals/src/grok/admin/tests/test_grokadmin.py	2007-08-22 14:04:17 UTC (rev 79124)
@@ -18,10 +18,22 @@
 from zope.testing import doctest, cleanup
 import zope.component.eventtesting
 from zope.annotation.attribute import AttributeAnnotations
+from zope.app.authentication.interfaces import IPasswordManager
+from zope.app.authentication.password import PlainTextPasswordManager
+from zope.app.authentication.password import MD5PasswordManager
+from zope.app.authentication.password import SHA1PasswordManager
+from zope.app.testing import ztapi
 
 def setUpZope(test):
     zope.component.eventtesting.setUp(test)
     zope.component.provideAdapter(AttributeAnnotations)
+    # The auth tests require available password managers:
+    ztapi.provideUtility(IPasswordManager, PlainTextPasswordManager(),
+                                  "Plain Text")
+    ztapi.provideUtility(IPasswordManager, MD5PasswordManager(),
+                                  "MD5")
+    ztapi.provideUtility(IPasswordManager, SHA1PasswordManager(),
+                                  "SHA1")
 
 def cleanUpZope(test):
     cleanup.cleanUp()
@@ -51,7 +63,7 @@
     suite = unittest.TestSuite()
     for name in []:
         suite.addTest(suiteFromPackage(name))
-    for name in ['docgrok.txt','objectinfo.txt', 'utilities.py']:
+    for name in ['docgrok.txt', 'objectinfo.txt', 'utilities.py', 'auth.txt']:
         suite.addTest(doctest.DocFileSuite(name,
                                            package='grok.admin',
                                            setUp=setUpZope,



More information about the Checkins mailing list