[Checkins] SVN: z3c.authenticator/trunk/src/z3c/authenticator/ Implemented principal source widget based on z3c.form

Roger Ineichen roger at projekt01.ch
Wed Mar 26 01:00:13 EDT 2008


Log message for revision 84952:
  Implemented principal source widget based on z3c.form
  Now there is a widget which uses forms and doesn't use the vocabulary hook.
  This is all done with the widget, form and term implementation from z3c.form.
  It's really impressive how flexible z3c.form is.
  Removed the latest dependencies to zope.app.authentication and zope.app.form
  
  TODO:
  write more tests, check import and setup dependencies

Changed:
  U   z3c.authenticator/trunk/src/z3c/authenticator/README.txt
  U   z3c.authenticator/trunk/src/z3c/authenticator/authentication.py
  U   z3c.authenticator/trunk/src/z3c/authenticator/browser/configure.zcml
  D   z3c.authenticator/trunk/src/z3c/authenticator/browser/edit.py
  U   z3c.authenticator/trunk/src/z3c/authenticator/browser/group.py
  D   z3c.authenticator/trunk/src/z3c/authenticator/browser/schemasearch.py
  U   z3c.authenticator/trunk/src/z3c/authenticator/browser/user.py
  U   z3c.authenticator/trunk/src/z3c/authenticator/configure.zcml
  U   z3c.authenticator/trunk/src/z3c/authenticator/group.py
  U   z3c.authenticator/trunk/src/z3c/authenticator/group.zcml
  U   z3c.authenticator/trunk/src/z3c/authenticator/interfaces.py
  A   z3c.authenticator/trunk/src/z3c/authenticator/password.py
  A   z3c.authenticator/trunk/src/z3c/authenticator/password.zcml
  U   z3c.authenticator/trunk/src/z3c/authenticator/testing.py
  U   z3c.authenticator/trunk/src/z3c/authenticator/tests.py
  U   z3c.authenticator/trunk/src/z3c/authenticator/user.py
  A   z3c.authenticator/trunk/src/z3c/authenticator/widget.pt
  A   z3c.authenticator/trunk/src/z3c/authenticator/widget.py
  A   z3c.authenticator/trunk/src/z3c/authenticator/widget.zcml
  A   z3c.authenticator/trunk/src/z3c/authenticator/widget_search_form.pt
  A   z3c.authenticator/trunk/src/z3c/authenticator/widget_source_search_input.pt

-=-
Modified: z3c.authenticator/trunk/src/z3c/authenticator/README.txt
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/README.txt	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/README.txt	2008-03-26 05:00:12 UTC (rev 84952)
@@ -1,10 +1,10 @@
-========================
-X Authentication Utility
-========================
+=======================
+IAuthentication Utility
+=======================
 
-The X Authentication Utility provides a framework for authenticating 
-principals and associating information with them. It uses plugins and 
-subscribers to get its work done.
+The Authenticator Utility provides a framework for authenticating principals 
+and associating information with them. It uses plugins and subscribers to get 
+its work done.
 
 For a simple authentication utility to be used, it should be registered as a
 utility providing the `zope.app.security.interfaces.IAuthentication` interface.
@@ -67,11 +67,10 @@
 extracted by a credentials plugin. They are also typically able to create
 principal objects for credentials they successfully authenticate.
 
-Given a request object, the Authenticator returns a principal object, 
-if it can. The X Autentication utility does this by first iterateing 
-through its credentials plugins to obtain a set of credentials. If it gets 
-credentials, it iterates through its authenticator plugins to authenticate 
-them.
+Given a request object, the Authenticator returns a principal object, if it 
+can. The Authenticator utility does this by first iterateing through its 
+credentials plugins to obtain a set of credentials. If it gets credentials, it 
+iterates through its authenticator plugins to authenticate them.
 
 If an authenticator succeeds in authenticating a set of credentials, the 
 Authenticator uses the authenticator to create a principal 

Modified: z3c.authenticator/trunk/src/z3c/authenticator/authentication.py
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/authentication.py	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/authentication.py	2008-03-26 05:00:12 UTC (rev 84952)
@@ -144,34 +144,4 @@
                 next.logout(request)
 
 
-class QuerySchemaSearchAdapter(object):
-    """Performs schema-based principal searches on behalf of a PAU.
 
-    Delegates the search to the adapted authenticator (which also provides
-    IQuerySchemaSearch)..
-    """
-    zope.component.adapts(
-        interfaces.IQuerySchemaSearch,
-        interfaces.IAuthenticator)
-
-    zope.interface.implements(
-        interfaces.IQueriableAuthenticator,
-        interfaces.IQuerySchemaSearch,
-        ILocation)
-
-    def __init__(self, authplugin, pau):
-        if ILocation.providedBy(authplugin):
-            self.__parent__ = authplugin.__parent__
-            self.__name__ = authplugin.__name__
-        else:
-            self.__parent__ = pau
-            self.__name__ = ""
-        self.authplugin = authplugin
-        self.pau = pau
-        self.schema = authplugin.schema
-
-    def search(self, query, start=None, batch_size=None):
-        for id in self.authplugin.search(query, start, batch_size):
-            yield id
-
-

Modified: z3c.authenticator/trunk/src/z3c/authenticator/browser/configure.zcml
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/browser/configure.zcml	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/browser/configure.zcml	2008-03-26 05:00:12 UTC (rev 84952)
@@ -3,13 +3,6 @@
     xmlns="http://namespaces.zope.org/browser"
     i18n_domain="z3c">
 
-  <zope:adapter
-      for="..interfaces.IQuerySchemaSearch
-           zope.publisher.interfaces.browser.IBrowserRequest"
-      provides="zope.app.form.browser.interfaces.ISourceQueryView"
-      factory=".schemasearch.QuerySchemaSearchView"
-      />
-
   <include file="authenticator.zcml" />
   <include file="credential.zcml" />
   <include file="group.zcml" />

Deleted: z3c.authenticator/trunk/src/z3c/authenticator/browser/edit.py
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/browser/edit.py	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/browser/edit.py	2008-03-26 05:00:12 UTC (rev 84952)
@@ -1,44 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2008 Zope Foundation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""
-$Id:$
-"""
-__docformat__ = "reStructuredText"
-
-
-from z3c.i18n import MessageFactory as _
-from z3c.authenticator import interfaces
-from z3c.formui import form
-from z3c.form import field
-
-from z3c.i18n import MessageFactory as _
-from z3c.authenticator import interfaces
-
-
-class AuthenticatorEditForm(form.EditForm):
-    """Group edit form."""
-
-    label = _('Edit Authenticator.')
-
-    fields = field.Fields(interfaces.IAuthenticator).select(
-        'credentialsPlugins', 'authenticatorPlugins')
-
-
-class EditGroup(form.EditForm):
-    """Group edit form."""
-
-    label = _('Edit Group.')
-
-    form_fields = form.Fields(interfaces.IGroup).select('title', 
-        'description', 'principals')

Modified: z3c.authenticator/trunk/src/z3c/authenticator/browser/group.py
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/browser/group.py	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/browser/group.py	2008-03-26 05:00:12 UTC (rev 84952)
@@ -27,6 +27,7 @@
 from z3c.authenticator import interfaces
 from z3c.authenticator import group
 from z3c.authenticator import user
+from z3c.authenticator.widget import getSourceInputWidget
 from z3c.form import field
 from z3c.form import button
 from z3c.formui import form
@@ -34,6 +35,7 @@
 from z3c.configurator import configurator
 
 
+
 class IAddName(zope.interface.Interface):
     """Object name."""
 
@@ -103,5 +105,25 @@
     """Group edit form."""
 
     label = _('Edit Group.')
+    groupCycleErrorMessage = _('There is a cyclic relationship among groups.')
 
-    fields = field.Fields(interfaces.IGroup).select('title', 'description')
+    fields = field.Fields(interfaces.IGroup).select('title', 'description',
+        'principals')
+
+    fields['principals'].widgetFactory = getSourceInputWidget
+
+    @button.buttonAndHandler(_('Apply'), name='apply')
+    def handleApply(self, action):
+        data, errors = self.extractData()
+        if errors:
+            self.status = self.formErrorsMessage
+            return
+        try:
+            changes = self.applyChanges(data)
+        except group.GroupCycle, e:
+            self.status = self.groupCycleErrorMessage
+            return
+        if changes:
+            self.status = self.successMessage
+        else:
+            self.status = self.noChangesMessage
\ No newline at end of file

Deleted: z3c.authenticator/trunk/src/z3c/authenticator/browser/schemasearch.py
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/browser/schemasearch.py	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/browser/schemasearch.py	2008-03-26 05:00:12 UTC (rev 84952)
@@ -1,111 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2008 Zope Foundation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""
-$Id:$
-"""
-__docformat__ = "reStructuredText"
-
-from zope.interface import implements
-from zope.i18n import translate
-from zope.schema import getFieldsInOrder
-from zope.app.zapi import getName, getPath
-from zope.app.form.utility import setUpWidgets, getWidgetsData
-from zope.app.form.interfaces import IInputWidget
-from zope.app.form.browser.interfaces import ISourceQueryView
-
-from z3c.i18n import MessageFactory as _
-
-
-search_label = _('search-button', 'Search')
-source_label = _(u"Source path")
-source_title = _(u"Path to the source utility")
-
-
-class QuerySchemaSearchView(object):
-    implements(ISourceQueryView)
-
-    def __init__(self, context, request):
-        self.context = context
-        self.request = request
-
-    def render(self, name):
-        schema = self.context.schema
-        sourcename = getName(self.context)
-        sourcepath = getPath(self.context)
-        setUpWidgets(self, schema, IInputWidget, prefix=name+'.field')
-        html = []
-
-        # add sub title for source search field
-        html.append('<h4>%s</h4>' % sourcename)
-
-        # start row for path display field
-        html.append('<div class="row">')
-
-        # for each source add path of source
-        html.append('  <div class="label">')
-        label = translate(source_label, context=self.request)
-        title = translate(source_title, context=self.request)
-        html.append('    <label for="%s" title="%s">' % (sourcename, title))
-        html.append('      %s' % label)
-        html.append('    </label>')
-        html.append('  </div>')
-        html.append('  <div class="field">')
-        html.append('      %s' % sourcepath)
-        html.append('  </div>')
-        html.append('</div>')
-
-        # start row for search fields
-        html.append('<div class="row">')
-
-        for field_name, field in getFieldsInOrder(schema):
-            widget = getattr(self, field_name+'_widget')
-
-            # for each field add label...
-            html.append('  <div class="label">')
-            html.append('    <label for="%s" title="%s">'
-                        % (widget.name, widget.hint))
-            html.append('      %s' % widget.label)
-            html.append('    </label>')
-            html.append('  </div>')
-
-            # ...and field widget
-            html.append('  <div class="field">')
-            html.append('    %s' % widget())
-
-            if widget.error():
-                html.append('    <div class="error">')
-                html.append('      %s' % widget.error())
-                html.append('    </div>')
-            html.append('  </div>')
-        # end row
-        html.append('</div>')
-
-        # add search button for search fields
-        html.append('<div class="row">')
-        html.append('  <div class="field">')
-        html.append('    <input type="submit" name="%s" value="%s" />'
-                     % (name+'.search',
-                        translate(search_label, context=self.request)))
-        html.append('  </div>')
-        html.append('</div>')
-
-        return '\n'.join(html)
-
-    def results(self, name):
-        if not (name+'.search' in self.request):
-            return None
-        schema = self.context.schema
-        setUpWidgets(self, schema, IInputWidget, prefix=name+'.field')
-        data = getWidgetsData(self, schema)
-        return self.context.search(data)

Modified: z3c.authenticator/trunk/src/z3c/authenticator/browser/user.py
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/browser/user.py	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/browser/user.py	2008-03-26 05:00:12 UTC (rev 84952)
@@ -73,8 +73,7 @@
 
     label = _('Add User.')
 
-    fields = field.Fields(IAddName)
-    fields += field.Fields(interfaces.IUser).select('login', 'password', 
+    fields = field.Fields(interfaces.IUser).select('login', 'password', 
         'title', 'description', 'passwordManagerName')
 
     def createAndAdd(self, data):
@@ -85,9 +84,8 @@
         passwordManagerName = data.get('passwordManagerName', u'')
         obj = user.User(login, password, title, description, 
             passwordManagerName)
-        self.contentName = data.get('__name__', u'')
         zope.event.notify(zope.lifecycleevent.ObjectCreatedEvent(obj))
-        self.context[self.contentName] = obj
+        self.contentName, usr = self.context.add(obj)
 
         #configure
         configurator.configure(obj, data)

Modified: z3c.authenticator/trunk/src/z3c/authenticator/configure.zcml
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/configure.zcml	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/configure.zcml	2008-03-26 05:00:12 UTC (rev 84952)
@@ -17,13 +17,6 @@
         />
   </class>
 
-  <adapter
-      for=".interfaces.IQuerySchemaSearch
-           .interfaces.IAuthenticator"
-      provides=".interfaces.IQueriableAuthenticator"
-      factory=".authentication.QuerySchemaSearchAdapter"
-      />
-
   <utility
       component=".vocabulary.authenticatorPlugins"
       name="Z3CAuthenticatorPlugins"
@@ -34,10 +27,12 @@
       name="Z3CCredentialsPlugins"
       />
 
-  <include file="principal.zcml" />
+  <include file="credential.zcml" />
   <include file="group.zcml" />
+  <include file="password.zcml" />
+  <include file="principal.zcml" />
   <include file="user.zcml" />
-  <include file="credential.zcml" />
+  <include file="widget.zcml" />
 
   <include package=".browser" />
 

Modified: z3c.authenticator/trunk/src/z3c/authenticator/group.py
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/group.py	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/group.py	2008-03-26 05:00:12 UTC (rev 84952)
@@ -93,11 +93,8 @@
 
 class GroupContainer(btree.BTreeContainer):
 
-    zope.interface.implements(interfaces.IGroupContainer,
-        interfaces.IQuerySchemaSearch,)
+    zope.interface.implements(interfaces.IGroupContainer)
 
-    schema = interfaces.IGroupSearchCriteria
-
     def __init__(self, prefix=u''):
         self.prefix = prefix
         super(GroupContainer,self).__init__()

Modified: z3c.authenticator/trunk/src/z3c/authenticator/group.zcml
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/group.zcml	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/group.zcml	2008-03-26 05:00:12 UTC (rev 84952)
@@ -31,12 +31,6 @@
       factory=".group.GroupPrincipal"
       />
 
-  <adapter
-      provides="zope.app.container.interfaces.INameChooser"
-      for=".interfaces.IGroupContainer"
-      factory="zope.app.authentication.idpicker.IdPicker"
-      />
-
   <subscriber
       for=".interfaces.IPrincipalCreated"
       handler=".group.specialGroups"

Modified: z3c.authenticator/trunk/src/z3c/authenticator/interfaces.py
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/interfaces.py	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/interfaces.py	2008-03-26 05:00:12 UTC (rev 84952)
@@ -21,7 +21,6 @@
 
 from zope.security.interfaces import IGroupClosureAwarePrincipal
 from zope.security.interfaces import IMemberAwareGroup
-from zope.app.authentication.interfaces import ICredentialsPlugin
 from zope.app.container.interfaces import IContainer
 from zope.app.container.constraints import contains
 from zope.app.container.constraints import containers
@@ -31,6 +30,18 @@
 from z3c.i18n import MessageFactory as _
 
 
+# TODO: this shoulld really, really go to another place then 
+#       zope.app.authentication
+class IPasswordManager(zope.interface.Interface):
+    """Password manager."""
+
+    def encodePassword(password):
+        """Return encoded data for the password."""
+
+    def checkPassword(storedPassword, password):
+        """Return whether the password coincide with the storedPassword."""
+
+
 class IPlugin(zope.interface.Interface):
     """A plugin for IAuthenticator component."""
 
@@ -93,11 +104,30 @@
         """
 
 
+class ISearchable(zope.interface.Interface):
+    """An interface for searching using schema-constrained input."""
+
+    def search(query, start=None, batch_size=None):
+        """Returns an iteration of principal IDs matching the query.
+
+        query is a mapping of name/value pairs for fields specified by the
+        schema.
+
+        If the start argument is provided, then it should be an
+        integer and the given number of initial items should be
+        skipped.
+
+        If the batch_size argument is provided, then it should be an
+        integer and no more than the given number of items should be
+        returned.
+        """
+
+
 class IAuthenticator(ILogout, IContainer):
     """Authentication utility.
     
     The Authenticator supports NOT IAuthenticatorPlugin plugins defined 
-    in zope.app.authentication.interfaces. Because they use and return a 
+    in z3c.authenticator.interfaces. Because they use and return a 
     IPrincipalInfo object in the authenticateCredentials method.
     
     Note: you have to write your own authenticator plugins because we do not 
@@ -185,7 +215,7 @@
         default=u'')
 
 
-class IUserSearchCriteria(zope.interface.Interface):
+class ISourceSearchCriteria(zope.interface.Interface):
     """Search Interface for this Principal Provider"""
 
     search = zope.schema.TextLine(
@@ -196,12 +226,15 @@
         missing_value=u'')
 
 
-class IUserContainer(IContainer, IAuthenticatorPlugin):
+class IUserContainer(IContainer, IAuthenticatorPlugin, ISearchable):
     """Principal container."""
 
     contains(IUser)
 
+    def add(user):
+        """Add a user and returns a the assigned token (principal id)."""
 
+
 # principal interfaces
 class IFoundPrincipal(IGroupClosureAwarePrincipal):
     """A factory adapting IUser and offering read access to the principal.
@@ -277,15 +310,16 @@
         required=False)
 
     principals = zope.schema.List(
-        title=_("Principals"),
+        title=_('Group Principals'),
+        description=_("List of ids of principals which belong to the group"),
         value_type=zope.schema.Choice(
+            title=_('Group Principals'),
+            description=_('Group Principals'),
             source=PrincipalSource()),
-        description=_(
-        "List of ids of principals which belong to the group"),
         required=False)
 
 
-class IGroupContainer(IContainer, IAuthenticatorPlugin):
+class IGroupContainer(IContainer, IAuthenticatorPlugin, ISearchable):
 
     contains(IGroup)
 
@@ -304,15 +338,6 @@
         """Get principals which belong to the group"""
 
 
-class IGroupSearchCriteria(zope.interface.Interface):
-
-    search = zope.schema.TextLine(
-        title=_("Group Search String"),
-        required=False,
-        missing_value=u'',
-        )
-
-
 class IGroupPrincipal(IFoundPrincipal, IMemberAwareGroup):
     """IGroup that acts as a principal representing a group."""
 
@@ -442,32 +467,6 @@
 
 
 # queriable search interfaces
-class IQueriableAuthenticator(zope.interface.Interface):
+class IQueriableAuthenticator(ISearchable):
     """Indicates the authenticator provides a search UI for principals."""
 
-
-class IQuerySchemaSearch(zope.interface.Interface):
-    """An interface for searching using schema-constrained input."""
-
-    schema = zope.interface.Attribute("""
-        The schema that constrains the input provided to the search method.
-
-        A mapping of name/value pairs for each field in this schema is used
-        as the query argument in the search method.
-        """)
-
-    def search(query, start=None, batch_size=None):
-        """Returns an iteration of principal IDs matching the query.
-
-        query is a mapping of name/value pairs for fields specified by the
-        schema.
-
-        If the start argument is provided, then it should be an
-        integer and the given number of initial items should be
-        skipped.
-
-        If the batch_size argument is provided, then it should be an
-        integer and no more than the given number of items should be
-        returned.
-        """
-

Added: z3c.authenticator/trunk/src/z3c/authenticator/password.py
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/password.py	                        (rev 0)
+++ z3c.authenticator/trunk/src/z3c/authenticator/password.py	2008-03-26 05:00:12 UTC (rev 84952)
@@ -0,0 +1,160 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Password managers
+
+$Id: password.py 74706 2007-04-24 16:15:34Z hdima $
+"""
+__docformat__ = 'restructuredtext'
+
+import md5
+import sha
+from random import randint
+from codecs import getencoder
+
+from zope.interface import implements, classProvides
+from zope.schema.interfaces import IVocabularyFactory
+from zope.app.component.vocabulary import UtilityVocabulary
+
+from z3c.authenticator.interfaces import IPasswordManager
+
+
+_encoder = getencoder("utf-8")
+
+
+class PlainTextPasswordManager(object):
+    """Plain text password manager.
+
+    >>> from zope.interface.verify import verifyObject
+
+    >>> manager = PlainTextPasswordManager()
+    >>> verifyObject(IPasswordManager, manager)
+    True
+
+    >>> password = u"right \N{CYRILLIC CAPITAL LETTER A}"
+    >>> encoded = manager.encodePassword(password)
+    >>> encoded
+    u'right \u0410'
+    >>> manager.checkPassword(encoded, password)
+    True
+    >>> manager.checkPassword(encoded, password + u"wrong")
+    False
+    """
+
+    implements(IPasswordManager)
+
+    def encodePassword(self, password):
+        return password
+
+    def checkPassword(self, storedPassword, password):
+        return storedPassword == self.encodePassword(password)
+
+
+class MD5PasswordManager(PlainTextPasswordManager):
+    """MD5 password manager.
+
+    >>> from zope.interface.verify import verifyObject
+
+    >>> manager = MD5PasswordManager()
+    >>> verifyObject(IPasswordManager, manager)
+    True
+
+    >>> password = u"right \N{CYRILLIC CAPITAL LETTER A}"
+    >>> encoded = manager.encodePassword(password, salt="")
+    >>> encoded
+    '86dddccec45db4599f1ac00018e54139'
+    >>> manager.checkPassword(encoded, password)
+    True
+    >>> manager.checkPassword(encoded, password + u"wrong")
+    False
+
+    >>> encoded = manager.encodePassword(password)
+    >>> encoded[-32:]
+    '86dddccec45db4599f1ac00018e54139'
+    >>> manager.checkPassword(encoded, password)
+    True
+    >>> manager.checkPassword(encoded, password + u"wrong")
+    False
+
+    >>> manager.encodePassword(password) != manager.encodePassword(password)
+    True
+    """
+
+    implements(IPasswordManager)
+
+    def encodePassword(self, password, salt=None):
+        if salt is None:
+            salt = "%08x" % randint(0, 0xffffffff)
+        return salt + md5.new(_encoder(password)[0]).hexdigest()
+
+    def checkPassword(self, storedPassword, password):
+        salt = storedPassword[:-32]
+        return storedPassword == self.encodePassword(password, salt)
+
+
+class SHA1PasswordManager(PlainTextPasswordManager):
+    """SHA1 password manager.
+
+    >>> from zope.interface.verify import verifyObject
+
+    >>> manager = SHA1PasswordManager()
+    >>> verifyObject(IPasswordManager, manager)
+    True
+
+    >>> password = u"right \N{CYRILLIC CAPITAL LETTER A}"
+    >>> encoded = manager.encodePassword(password, salt="")
+    >>> encoded
+    '04b4eec7154c5f3a2ec6d2956fb80b80dc737402'
+    >>> manager.checkPassword(encoded, password)
+    True
+    >>> manager.checkPassword(encoded, password + u"wrong")
+    False
+
+    >>> encoded = manager.encodePassword(password)
+    >>> encoded[-40:]
+    '04b4eec7154c5f3a2ec6d2956fb80b80dc737402'
+    >>> manager.checkPassword(encoded, password)
+    True
+    >>> manager.checkPassword(encoded, password + u"wrong")
+    False
+
+    >>> manager.encodePassword(password) != manager.encodePassword(password)
+    True
+    """
+
+    implements(IPasswordManager)
+
+    def encodePassword(self, password, salt=None):
+        if salt is None:
+            salt = "%08x" % randint(0, 0xffffffff)
+        return salt + sha.new(_encoder(password)[0]).hexdigest()
+
+    def checkPassword(self, storedPassword, password):
+        salt = storedPassword[:-40]
+        return storedPassword == self.encodePassword(password, salt)
+
+
+# Simple registry used by mkzopeinstance script
+managers = [
+    ("Plain Text", PlainTextPasswordManager()), # default
+    ("MD5", MD5PasswordManager()),
+    ("SHA1", SHA1PasswordManager()),
+]
+
+
+class PasswordManagerNamesVocabulary(UtilityVocabulary):
+    """Vocabulary of password managers."""
+
+    classProvides(IVocabularyFactory)
+    interface = IPasswordManager
+    nameOnly = True


Property changes on: z3c.authenticator/trunk/src/z3c/authenticator/password.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.authenticator/trunk/src/z3c/authenticator/password.zcml
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/password.zcml	                        (rev 0)
+++ z3c.authenticator/trunk/src/z3c/authenticator/password.zcml	2008-03-26 05:00:12 UTC (rev 84952)
@@ -0,0 +1,41 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    i18n_domain="z3c">
+
+  <utility
+      component=".password.PasswordManagerNamesVocabulary"
+      name="Password Manager Names"
+      provides=".interfaces.IPasswordManager"
+      />
+
+  <class class=".password.PlainTextPasswordManager">
+    <allow interface=".interfaces.IPasswordManager" />
+  </class>
+
+  <utility
+      name="Plain Text"
+      provides=".interfaces.IPasswordManager"
+      factory=".password.PlainTextPasswordManager"
+      />
+
+  <class class=".password.MD5PasswordManager">
+    <allow interface=".interfaces.IPasswordManager" />
+  </class>
+
+  <utility
+      name="MD5"
+      provides=".interfaces.IPasswordManager"
+      factory=".password.MD5PasswordManager"
+      />
+
+  <class class=".password.SHA1PasswordManager">
+    <allow interface=".interfaces.IPasswordManager" />
+  </class>
+
+  <utility
+      name="SHA1"
+      provides=".interfaces.IPasswordManager"
+      factory=".password.SHA1PasswordManager"
+      />
+
+</configure>


Property changes on: z3c.authenticator/trunk/src/z3c/authenticator/password.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: z3c.authenticator/trunk/src/z3c/authenticator/testing.py
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/testing.py	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/testing.py	2008-03-26 05:00:12 UTC (rev 84952)
@@ -17,8 +17,8 @@
 __docformat__ = "reStructuredText"
 
 import zope.component
-from zope.app.authentication.interfaces import IPasswordManager
-from zope.app.authentication.password import PlainTextPasswordManager
+from z3c.authenticator.interfaces import IPasswordManager
+from z3c.authenticator.password import PlainTextPasswordManager
 from zope.app.testing import setup
 
 ###############################################################################
@@ -41,6 +41,7 @@
 def siteSetUp(test):
     site = setup.placefulSetUp(site=True)
     test.globs['rootFolder'] = site
+    setUpPasswordManager()
 
 
 def siteTearDown(test):

Modified: z3c.authenticator/trunk/src/z3c/authenticator/tests.py
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/tests.py	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/tests.py	2008-03-26 05:00:12 UTC (rev 84952)
@@ -158,6 +158,7 @@
             setUp=placelesssetup.setUp, tearDown=placelesssetup.tearDown),
         doctest.DocFileSuite('vocabulary.txt',
             setUp=placelesssetup.setUp, tearDown=placelesssetup.tearDown),
+        doctest.DocTestSuite('z3c.authenticator.password'),
         unittest.makeSuite(AuthenticatorTest),
         unittest.makeSuite(UserContainerTest),
         unittest.makeSuite(UserTest),

Modified: z3c.authenticator/trunk/src/z3c/authenticator/user.py
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/user.py	2008-03-25 22:52:09 UTC (rev 84951)
+++ z3c.authenticator/trunk/src/z3c/authenticator/user.py	2008-03-26 05:00:12 UTC (rev 84952)
@@ -26,7 +26,6 @@
 from zope.app.container import contained
 from zope.app.container import btree
 from zope.app.container.interfaces import DuplicateIDError
-from zope.app.authentication.interfaces import IPasswordManager
 
 from z3c.authenticator import interfaces
 
@@ -63,7 +62,7 @@
     passwordManagerName = property(getPasswordManagerName)
 
     def _getPasswordManager(self):
-        return zope.component.getUtility(IPasswordManager, 
+        return zope.component.getUtility(interfaces.IPasswordManager, 
             self.passwordManagerName)
 
     def getPassword(self):
@@ -103,11 +102,8 @@
     See principalfolder.txt for details.
     """
 
-    zope.interface.implements(interfaces.IUserContainer, 
-        interfaces.IQuerySchemaSearch)
+    zope.interface.implements(interfaces.IUserContainer)
 
-    schema = interfaces.IUserSearchCriteria
-
     def __init__(self):
         super(UserContainer, self).__init__()
         self.__id_by_login = self._newContainerData()

Added: z3c.authenticator/trunk/src/z3c/authenticator/widget.pt
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/widget.pt	                        (rev 0)
+++ z3c.authenticator/trunk/src/z3c/authenticator/widget.pt	2008-03-26 05:00:12 UTC (rev 84952)
@@ -0,0 +1,80 @@
+<table border="0" cellspacing="0" cellpadding="0">
+  <tr>
+    <td valign="top" style="padding-right:20px;">
+      <div class="option"
+            tal:repeat="item view/items">
+        <input type="checkbox" id="" name="" class="" alt="" title=""
+               tabindex="" disabled="" readonly="" accesskey="" value=""
+               checked="checked"
+               tal:condition="item/checked"
+               tal:attributes="id item/id;
+                               name item/name;
+                               value item/value;
+                               class view/klass;
+                               style view/style;
+                               title view/title;
+                               lang view/lang;
+                               onclick view/onclick;
+                               ondblclick view/ondblclick;
+                               onmousedown view/onmousedown;
+                               onmouseup view/onmouseup;
+                               onmouseover view/onmouseover;
+                               onmousemove view/onmousemove;
+                               onmouseout view/onmouseout;
+                               onkeypress view/onkeypress;
+                               onkeydown view/onkeydown;
+                               onkeyup view/onkeyup;
+                               disabled view/disabled;
+                               tabindex view/tabindex;
+                               onfocus view/onfocus;
+                               onblur view/onblur;
+                               onchange view/onchange;
+                               readonly view/readonly;
+                               alt view/alt;
+                               accesskey view/accesskey;
+                               onselect view/onselect"
+        /><input type="checkbox" id="" name="" class="" alt="" title="" tabindex=""
+                 disabled="" readonly="" accesskey="" value=""
+               tal:condition="not:item/checked"
+               tal:attributes="id item/id;
+                               name item/name;
+                               value item/value;
+                               class view/klass;
+                               style view/style;
+                               title view/title;
+                               lang view/lang;
+                               onclick view/onclick;
+                               ondblclick view/ondblclick;
+                               onmousedown view/onmousedown;
+                               onmouseup view/onmouseup;
+                               onmouseover view/onmouseover;
+                               onmousemove view/onmousemove;
+                               onmouseout view/onmouseout;
+                               onkeypress view/onkeypress;
+                               onkeydown view/onkeydown;
+                               onkeyup view/onkeyup;
+                               disabled view/disabled;
+                               tabindex view/tabindex;
+                               onfocus view/onfocus;
+                               onblur view/onblur;
+                               onchange view/onchange;
+                               readonly view/readonly;
+                               alt view/alt;
+                               accesskey view/accesskey;
+                               onselect view/onselect" />
+        <label for=""
+               tal:attributes="for item/id">
+          <span class="label" tal:content="item/label">Label</span>
+        </label>
+      </div>
+      <input name="field-empty-marker" type="hidden" value="1"
+             tal:attributes="name string:${view/name}-empty-marker" />
+
+    </td>
+    <td valign="top">
+      <div tal:repeat="searchForm view/getSearchForms">
+        <tal:block replace="structure searchForm/render" />
+      </div>
+    </td>
+  </tr>
+</table>


Property changes on: z3c.authenticator/trunk/src/z3c/authenticator/widget.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.authenticator/trunk/src/z3c/authenticator/widget.py
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/widget.py	                        (rev 0)
+++ z3c.authenticator/trunk/src/z3c/authenticator/widget.py	2008-03-26 05:00:12 UTC (rev 84952)
@@ -0,0 +1,470 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Principal Source Widget Implementation
+
+$Id: select.py 78513 2007-07-31 23:03:47Z srichter $
+"""
+__docformat__ = "reStructuredText"
+
+import zope.component
+import zope.interface
+import zope.i18n
+import zope.schema
+import zope.schema.interfaces
+import zope.location
+import zope.app.security.interfaces
+from zope.traversing import api
+from zope.location.interfaces import ILocation
+from zope.app.security.interfaces import IAuthentication
+from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.app.security.interfaces import IPrincipalSource
+
+from z3c.formui import form
+from z3c.form import field
+from z3c.form import button
+from z3c.form.i18n import MessageFactory as _
+from z3c.form.widget import SequenceWidget, FieldWidget
+from z3c.form.browser import widget
+from z3c.form.browser import text
+from z3c.form.browser.orderedselect import SequenceSelectFieldWidget
+from z3c.form import converter
+from z3c.form.interfaces import IFieldWidget
+from z3c.form.interfaces import IWidget
+from z3c.form.interfaces import ISequenceWidget
+from z3c.form.interfaces import ICheckBoxWidget
+from z3c.form.interfaces import IWidgets
+from z3c.form.interfaces import IFormLayer
+from z3c.form.interfaces import ITerms
+from z3c.template.template import getPageTemplate
+from z3c.template.template import getLayoutTemplate
+from z3c.authenticator import interfaces
+
+
+class IPrincipalSourceWidget(IFieldWidget):
+    """SourceWidget."""
+
+    def addValue(value):
+        """Add and render value as sequence item."""
+
+
+class ISourceResultWidget(ISequenceWidget):
+    """Search form result widget."""
+
+    def addValue(value):
+        """Add and render value as sequence item."""
+
+
+class ISourceSearchForm(zope.interface.Interface):
+    """Search schema."""
+
+
+# TODO: remove this if we have a fixed version of z3c.form
+class PrincipalSourceDataConverter(converter.CollectionSequenceDataConverter):
+    """A special converter between collections and sequence widgets."""
+
+    zope.component.adapts(zope.schema.interfaces.IList, IPrincipalSourceWidget)
+
+    def toWidgetValue(self, value):
+        widget = self.widget
+        if widget.terms is None:
+            widget.updateTerms()
+        return [widget.terms.getTerm(entry).token for entry in value]
+
+    def toFieldValue(self, value):
+        widget = self.widget
+        # bugfix, avoid to call lenght on terms
+        # if not widget.terms:
+        if widget.terms is None:
+            widget.updateTerms()
+        collectionType = self.field._type
+        if isinstance(collectionType, tuple):
+            collectionType = collectionType[-1]
+        return collectionType([widget.terms.getValue(token) for token in value])
+
+
+# TODO: remove this if we have a fixed version of z3c.form
+class SourceSearchDataConverter(converter.CollectionSequenceDataConverter):
+    """A special converter between collections and sequence widgets."""
+
+    zope.component.adapts(zope.schema.interfaces.IList, ISourceResultWidget)
+
+    def toWidgetValue(self, value):
+        widget = self.widget
+        if widget.terms is None:
+            widget.updateTerms()
+        return [widget.terms.getTerm(entry).token for entry in value]
+
+    def toFieldValue(self, value):
+        widget = self.widget
+        # bugfix, avoid to call lenght on terms
+        # if not widget.terms:
+        if widget.terms is None:
+            widget.updateTerms()
+        collectionType = self.field._type
+        if isinstance(collectionType, tuple):
+            collectionType = collectionType[-1]
+        return collectionType([widget.terms.getValue(token) for token in value])
+
+
+class PrincipalTerm(object):
+
+    def __init__(self, token, title):
+        self.token = token
+        self.title = title
+
+
+class PrincipalTerms(object):
+
+    zope.interface.implements(ITerms)
+    zope.component.adapts(
+        zope.interface.Interface,
+        IFormLayer,
+        zope.interface.Interface,
+        zope.schema.interfaces.IList,
+        IPrincipalSourceWidget)
+
+    def __init__(self, context, request, form, field, widget):
+        self.context = context
+        self.request = request
+        self.form = form
+        self.field = field
+        self.widget = widget
+        self.source = field.value_type.bind(self.context).vocabulary
+
+    def getTerm(self, pid):
+        if pid not in self.source:
+            raise LookupError(pid)
+
+        auth = zope.component.getUtility(IAuthentication)
+        principal = auth.getPrincipal(pid)
+
+        if principal is None:
+            raise LookupError(pid)
+
+        return PrincipalTerm(pid.encode('base64').strip().replace('=', '_'),
+                    principal.title)
+
+    def getTermByToken(self, token):
+        pid = token.replace('_', '=').decode('base64')
+        return self.getTerm(pid)
+
+    def getValue(self, token):
+        return token.replace('_', '=').decode('base64')
+
+    def __contains__(self, pid):
+        if pid in self.source:
+            return True
+        return False
+
+    def __iter__(self):
+        raise NotImplementedError('Source queriable is not iterable.')
+
+    def __len__(self):
+        raise NotImplementedError('Source queriable does not provide lenght.')
+
+
+class QueriableAuthenticator(object):
+    """Performs schema-based principal searches on behalf of a PAU.
+
+    Delegates the search to the adapted authenticator (which also provides
+    ISearchable)..
+    """
+    zope.component.adapts(interfaces.ISearchable, interfaces.IAuthenticator)
+
+    zope.interface.implements(interfaces.IQueriableAuthenticator, ILocation)
+
+    def __init__(self, authplugin, pau):
+        # locate them
+        if ILocation.providedBy(authplugin):
+            self.__parent__ = authplugin.__parent__
+            self.__name__ = authplugin.__name__
+        else:
+            self.__parent__ = pau
+            self.__name__ = ""
+        self.authplugin = authplugin
+        self.pau = pau
+
+    def search(self, query, start=None, batch_size=None):
+        for id in self.authplugin.search(query, start, batch_size):
+            yield id
+
+
+class ISearchFormResultsField(zope.schema.interfaces.IList):
+    """Search form results field.
+
+    Marker for the right widget.
+    """
+
+class SearchFormResultsField(zope.schema.List):
+    """Search form results field."""
+
+    zope.interface.implements(ISearchFormResultsField)
+
+
+class SourceResultWidget(widget.HTMLInputWidget, SequenceWidget):
+    """Knows how to catch the right terms."""
+
+    zope.interface.implements(ISourceResultWidget)
+
+    klass = u'search-form-widget checkbox-widget'
+    searchResults = []
+    value = []
+    items = []
+
+    def isChecked(self, term):
+        return term.token in self.value
+
+    def addValue(self, value):
+        term = self.terms.getTerm(value)
+        checked = self.isChecked(term)
+        label = zope.i18n.translate(term.title, context=self.request,
+                          default=term.title)
+        id = '%s-%s' % (self.id, term.token)
+        item = {'id':id, 'name':self.name + ':list', 'value':term.token,
+                'label':label, 'checked':checked}
+        if item not in self.items:
+            self.items.append(item)
+
+    def updateTerms(self):
+        self.terms = self.form.terms
+        return self.terms
+
+    def extract(self, default=[]):
+        """See z3c.form.interfaces.IWidget."""
+        tokens = super(SourceResultWidget, self).extract(default)
+        for value in self.searchResults:
+            token = self.terms.getTerm(value).token
+            if token not in tokens:
+                tokens.append(token)
+        return tokens
+
+    def update(self):
+        """See z3c.form.interfaces.IWidget."""
+        super(SourceResultWidget, self).update()
+        widget.addFieldClass(self)
+
+        # update search forms
+        self.items = []
+
+        # append existing items
+        for token in self.value:
+            value = self.terms.getValue(token)
+            self.addValue(value)
+
+
+def getSourceResultWidget(field, request):
+    """IFieldWidget factory for CheckBoxWidget."""
+    return FieldWidget(field, SourceResultWidget(request))
+
+
+class SourceSearchWidget(text.TextWidget):
+    """Source search widget."""
+
+    style = u'border-color: gray; width:100px;'
+
+    @apply
+    def label():
+        def get(self):
+            txt = _('search in: ')
+            prefix = zope.i18n.translate(txt, context=self.request, default=txt)
+            return '%s%s' % (prefix, self.form.title)
+        def set(self, value):
+            pass
+        return property(get, set)
+
+def getSourceSearchWidget(field, request):
+    """IFieldWidget factory for TextWidget."""
+    return FieldWidget(field, SourceSearchWidget(request))
+
+
+class ISearchResult(zope.interface.Interface):
+    """Search value."""
+
+    results = SearchFormResultsField(
+        title=_('Principals'),
+        description=_("Principal ids"),
+        default=[],
+        required=False
+        )
+
+# conditions
+def hasResults(form):
+    return bool(form.widgets['search'].value)
+
+
+class SearchFormMixin(form.Form):
+    """Source Query View search form."""
+
+    zope.interface.implements(ISourceSearchForm)
+
+    layout = getLayoutTemplate('subform')
+
+    formErrorsMessage = _('Search error')
+    ignoreContext = True
+    terms = None
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    @property
+    def title(self):
+        if hasattr(self.context, 'title'):
+            return self.context.title
+        return api.getName(self.context)
+
+    def search(self, data):
+        raise NotImplementedError('Subform must implement search')
+
+    @button.buttonAndHandler(_('Search'))
+    def handleSearch(self, action):
+        """Set search result"""
+        data, errors = self.extractData()
+        if errors:
+            self.status = self.formErrorsMessage
+            return
+        value = self.search(data)
+        self.widgets['results'].searchResults = value
+        self.widgets['results'].update()
+
+# TODO:add condition
+    @button.buttonAndHandler(_('Add'), condition=hasResults)
+    def handleAdd(self, action):
+        """Set search result"""
+        data, errors = self.extractData()
+        if errors:
+            self.status = self.formErrorsMessage
+            return
+        for value in data.get('results', []):
+            self.__parent__.addValue(value)
+
+
+class AuthenticatorSearchForm(SearchFormMixin):
+    """Source search form for ISourceSearchCriteria."""
+
+    fields = field.Fields(interfaces.ISourceSearchCriteria).select('search')
+    fields += field.Fields(ISearchResult)
+
+    fields['results'].widgetFactory = getSourceResultWidget
+    fields['search'].widgetFactory = getSourceSearchWidget
+
+    def search(self, data):
+        # avoid empty search strings
+        value = []
+        if data.get('search'):
+            value = self.context.search(data) or []
+        return value
+
+
+class PrincipalRegistrySearchForm(SearchFormMixin):
+    """Source Query View search form for global PrincipalRegistry."""
+
+    fields = field.Fields(interfaces.ISourceSearchCriteria).select('search')
+    fields += field.Fields(ISearchResult)
+
+    fields['results'].widgetFactory = getSourceResultWidget
+    fields['search'].widgetFactory = getSourceSearchWidget
+
+    @property
+    def title(self):
+        return 'principals.zcml'
+
+    def search(self, data):
+        # avoid empty search strings
+        if data.get('search'):
+            searchStr = data.get('search')
+            value = [principal.id
+                     for principal in self.context.getPrincipals(searchStr)]
+        return value
+
+
+class PrincipalSourceWidget(widget.HTMLInputWidget, SequenceWidget):
+    """Select widget implementation."""
+    zope.interface.implementsOnly(IPrincipalSourceWidget)
+    zope.component.adapts(zope.interface.Interface,
+        zope.app.security.interfaces.IPrincipalSource, zope.interface.Interface)
+
+    klass = u'principal-source-widget checkbox-widget'
+    value = []
+    items = []
+
+    def __init__(self, field, source, request):
+        self.field = field
+        self.source = source
+        self.request = request
+
+    def isChecked(self, term):
+        return term.token in self.value
+
+    def addValue(self, value):
+        term = self.terms.getTerm(value)
+        checked = self.isChecked(term)
+        label = zope.i18n.translate(term.title, context=self.request,
+            default=term.title)
+        id = '%s-%s' % (self.id, term.token)
+        item = {'id':id, 'name':self.name + ':list', 'value':term.token,
+                'label':label, 'checked':checked}
+        if item not in self.items:
+            self.items.append(item)
+
+    def update(self):
+        """See z3c.form.interfaces.IWidget."""
+        super(PrincipalSourceWidget, self).update()
+        widget.addFieldClass(self)
+
+        # update serach forms
+        self.items = []
+        self.updateSearchForms()
+
+        # append existing items
+        for token in self.value:
+            value = self.terms.getValue(token)
+            self.addValue(value)
+
+    def updateSearchForms(self):
+        queriables = zope.schema.interfaces.ISourceQueriables(self.source, None)
+        if queriables is None:
+            # treat the source itself as a queriable
+            queriables = ((self.name + '.query', self.source), )
+        else:
+            queriables = [
+                (self.name + '.' +
+                 unicode(i).encode('base64').strip().replace('=', '_'), s)
+                          for (i, s) in queriables.getQueriables()]
+
+        self.searchForms = []
+        append = self.searchForms.append
+        for (name, source) in queriables:
+            searchForm = zope.component.getMultiAdapter((source, self.request),
+                ISourceSearchForm)
+            # ignore views which do not follow the update/render pattern
+            if hasattr(searchForm, 'update'):
+                searchForm.prefix = name
+                searchForm.__parent__ = self
+                searchForm.__name__ = name
+                # set the same terms for this form
+                searchForm.terms = self.terms
+                searchForm.update()
+                append(searchForm)
+
+    def getSearchForms(self):
+        return self.searchForms
+
+
+def getSourceInputWidget(field, request):
+    """Sequence IFieldWidget factory for ISource."""
+    source = field.value_type.vocabulary
+    widget = zope.component.getMultiAdapter((field, source, request),
+        IFieldWidget)
+    return widget


Property changes on: z3c.authenticator/trunk/src/z3c/authenticator/widget.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.authenticator/trunk/src/z3c/authenticator/widget.zcml
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/widget.zcml	                        (rev 0)
+++ z3c.authenticator/trunk/src/z3c/authenticator/widget.zcml	2008-03-26 05:00:12 UTC (rev 84952)
@@ -0,0 +1,72 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:z3c="http://namespaces.zope.org/z3c"
+    i18n_domain="zope">
+
+  <adapter
+      for=".interfaces.ISearchable
+           .interfaces.IAuthenticator"
+      provides=".interfaces.IQueriableAuthenticator"
+      factory=".widget.QueriableAuthenticator"
+      />
+
+  <adapter
+      factory=".widget.PrincipalSourceDataConverter"
+      />
+  <adapter
+      factory=".widget.SourceSearchDataConverter"
+      />
+
+  <adapter
+      factory=".widget.PrincipalTerms"
+      />
+  <adapter
+      factory=".widget.PrincipalSourceWidget"
+      />
+
+
+  <!-- widget templates -->
+  <z3c:widgetTemplate
+      mode="input"
+      widget=".widget.ISourceResultWidget"
+      layer="z3c.form.interfaces.IFormLayer"
+      template="widget_source_search_input.pt"
+      />
+
+  <z3c:widgetTemplate
+      mode="input"
+      widget=".widget.IPrincipalSourceWidget"
+      layer="z3c.form.interfaces.IFormLayer"
+      template="widget.pt"
+      />
+
+
+  <!-- search forms -->
+  <adapter
+      for=".interfaces.ISearchable
+           zope.publisher.interfaces.browser.IBrowserRequest"
+      provides=".widget.ISourceSearchForm"
+      factory=".widget.AuthenticatorSearchForm"
+      />
+
+  <adapter
+      for="zope.app.security.interfaces.IAuthentication
+           zope.publisher.interfaces.browser.IBrowserRequest"
+      provides=".widget.ISourceSearchForm"
+      factory=".widget.PrincipalRegistrySearchForm"
+      />
+
+  <z3c:template
+      for=".widget.AuthenticatorSearchForm"
+      layer="z3c.form.interfaces.IFormLayer"
+      template="widget_search_form.pt"
+      />
+
+  <z3c:template
+      for=".widget.PrincipalRegistrySearchForm"
+      layer="z3c.form.interfaces.IFormLayer"
+      template="widget_search_form.pt"
+      />
+      
+
+</configure>


Property changes on: z3c.authenticator/trunk/src/z3c/authenticator/widget.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.authenticator/trunk/src/z3c/authenticator/widget_search_form.pt
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/widget_search_form.pt	                        (rev 0)
+++ z3c.authenticator/trunk/src/z3c/authenticator/widget_search_form.pt	2008-03-26 05:00:12 UTC (rev 84952)
@@ -0,0 +1,38 @@
+<table border="0" cellspacing="0" cellpadding="0">
+  <tr>
+    <td>
+      <div class="row">
+        <tal:block define="widget nocall:view/widgets/search">
+          <div class="label">
+            <label tal:attributes="for widget/id">
+              <span i18n:translate=""
+                  tal:content="widget/label">label</span>
+              <span class="required"
+                    tal:condition="widget/required">*</span>
+            </label>
+          </div>
+          <div class="widget">
+            <tal:block content="structure widget/render">
+              <input type="text" size="20" value="" />
+            </tal:block>
+            <input tal:replace="structure view/actions/search/render" />
+          </div>
+          <div class="error"
+               tal:condition="widget/error">
+            <span tal:replace="structure widget/error/render">error</span>
+          </div>
+        </tal:block>
+      </div>
+    </td>
+  </tr>
+  <tr>
+    <td tal:condition="python: view.actions.get('add')">
+      <div class="row" tal:define="widget nocall:view/widgets/results">
+        <div metal:use-macro="macro:widget-row" />
+      </div>
+      <div class="row">
+        <input tal:replace="structure view/actions/add/render" />
+      </div>
+    </td>
+  </tr>
+</table>


Property changes on: z3c.authenticator/trunk/src/z3c/authenticator/widget_search_form.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.authenticator/trunk/src/z3c/authenticator/widget_source_search_input.pt
===================================================================
--- z3c.authenticator/trunk/src/z3c/authenticator/widget_source_search_input.pt	                        (rev 0)
+++ z3c.authenticator/trunk/src/z3c/authenticator/widget_source_search_input.pt	2008-03-26 05:00:12 UTC (rev 84952)
@@ -0,0 +1,68 @@
+<div class="option"
+      tal:repeat="item view/items">
+  <input type="checkbox" id="" name="" class="" alt="" title=""
+         tabindex="" disabled="" readonly="" accesskey="" value=""
+         checked="checked"
+         tal:condition="item/checked"
+         tal:attributes="id item/id;
+                         name item/name;
+                         value item/value;
+                         class view/klass;
+                         style view/style;
+                         title view/title;
+                         lang view/lang;
+                         onclick view/onclick;
+                         ondblclick view/ondblclick;
+                         onmousedown view/onmousedown;
+                         onmouseup view/onmouseup;
+                         onmouseover view/onmouseover;
+                         onmousemove view/onmousemove;
+                         onmouseout view/onmouseout;
+                         onkeypress view/onkeypress;
+                         onkeydown view/onkeydown;
+                         onkeyup view/onkeyup;
+                         disabled view/disabled;
+                         tabindex view/tabindex;
+                         onfocus view/onfocus;
+                         onblur view/onblur;
+                         onchange view/onchange;
+                         readonly view/readonly;
+                         alt view/alt;
+                         accesskey view/accesskey;
+                         onselect view/onselect"
+  /><input type="checkbox" id="" name="" class="" alt="" title="" tabindex=""
+           disabled="" readonly="" accesskey="" value=""
+         tal:condition="not:item/checked"
+         tal:attributes="id item/id;
+                         name item/name;
+                         value item/value;
+                         class view/klass;
+                         style view/style;
+                         title view/title;
+                         lang view/lang;
+                         onclick view/onclick;
+                         ondblclick view/ondblclick;
+                         onmousedown view/onmousedown;
+                         onmouseup view/onmouseup;
+                         onmouseover view/onmouseover;
+                         onmousemove view/onmousemove;
+                         onmouseout view/onmouseout;
+                         onkeypress view/onkeypress;
+                         onkeydown view/onkeydown;
+                         onkeyup view/onkeyup;
+                         disabled view/disabled;
+                         tabindex view/tabindex;
+                         onfocus view/onfocus;
+                         onblur view/onblur;
+                         onchange view/onchange;
+                         readonly view/readonly;
+                         alt view/alt;
+                         accesskey view/accesskey;
+                         onselect view/onselect" />
+  <label for=""
+         tal:attributes="for item/id">
+    <span class="label" tal:content="item/label">Label</span>
+  </label>
+</div>
+<input name="field-empty-marker" type="hidden" value="1"
+       tal:attributes="name string:${view/name}-empty-marker" />


Property changes on: z3c.authenticator/trunk/src/z3c/authenticator/widget_source_search_input.pt
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Checkins mailing list