[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