[Checkins] SVN: zmi.core/trunk/src/zmi/core/authentication/ Copy browser code from zope.app.authentication.

Yusei Tahara yusei at domen.cx
Sun Jun 7 11:23:11 EDT 2009


Log message for revision 100688:
  Copy browser code from zope.app.authentication.
  

Changed:
  A   zmi.core/trunk/src/zmi/core/authentication/__init__.py
  A   zmi.core/trunk/src/zmi/core/authentication/adding.py
  A   zmi.core/trunk/src/zmi/core/authentication/configure.zcml
  A   zmi.core/trunk/src/zmi/core/authentication/group_searching_with_empty_string.txt
  A   zmi.core/trunk/src/zmi/core/authentication/groupfolder.txt
  A   zmi.core/trunk/src/zmi/core/authentication/groupfolder.zcml
  A   zmi.core/trunk/src/zmi/core/authentication/httpplugins.zcml
  A   zmi.core/trunk/src/zmi/core/authentication/issue663.txt
  A   zmi.core/trunk/src/zmi/core/authentication/loginform.pt
  A   zmi.core/trunk/src/zmi/core/authentication/loginform.py
  A   zmi.core/trunk/src/zmi/core/authentication/pau_prefix_and_searching.txt
  A   zmi.core/trunk/src/zmi/core/authentication/principalfolder.txt
  A   zmi.core/trunk/src/zmi/core/authentication/principalfolder.zcml
  A   zmi.core/trunk/src/zmi/core/authentication/register.py
  A   zmi.core/trunk/src/zmi/core/authentication/schemasearch.py
  A   zmi.core/trunk/src/zmi/core/authentication/schemasearch.txt
  A   zmi.core/trunk/src/zmi/core/authentication/session.zcml
  A   zmi.core/trunk/src/zmi/core/authentication/special-groups.txt
  A   zmi.core/trunk/src/zmi/core/authentication/tests.py

-=-
Added: zmi.core/trunk/src/zmi/core/authentication/__init__.py
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/__init__.py	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/__init__.py	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,17 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation 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.
+#
+##############################################################################
+"""Pluggable Authentication Views
+
+$Id: __init__.py 28947 2005-01-24 19:56:54Z jim $
+"""

Added: zmi.core/trunk/src/zmi/core/authentication/adding.py
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/adding.py	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/adding.py	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,26 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation 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.
+#
+##############################################################################
+"""Adding that redirects to plugins.html.
+
+$Id: adding.py 85500 2008-04-20 09:56:11Z lgs $
+"""
+
+import zope.app.container.browser.adding
+
+from zope.traversing.browser.absoluteurl import absoluteURL
+
+class Adding(zope.app.container.browser.adding.Adding):
+
+    def nextURL(self):
+        return absoluteURL(self.context, self.request) + '/@@contents.html'

Added: zmi.core/trunk/src/zmi/core/authentication/configure.zcml
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/configure.zcml	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/configure.zcml	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,91 @@
+<configure
+    xmlns:zope="http://namespaces.zope.org/zope"
+    xmlns="http://namespaces.zope.org/browser"
+    i18n_domain="zope"
+    >
+
+  <addform
+      schema="zope.app.authentication.interfaces.IPluggableAuthentication"
+      label="Add Pluggable Authentication"
+      content_factory="zope.app.authentication.authentication.PluggableAuthentication"
+      fields="prefix"
+      keyword_arguments="prefix"
+      name="AddPluggableAuthentication.html"
+      permission="zope.ManageServices"
+      >
+
+    <widget
+        field="prefix"
+        class="zope.app.form.browser.TextWidget"
+        required="False"
+        convert_missing_value="False"
+        />
+
+  </addform>
+
+  <addMenuItem
+      class="zope.app.authentication.authentication.PluggableAuthentication"
+      view="AddPluggableAuthentication.html"
+      title="Pluggable Authentication Utility"
+      description="New-style pluggable authentication utility"
+      permission="zope.ManageServices"
+      />
+
+  <page
+      for="zope.app.authentication.interfaces.IPluggableAuthentication"
+      name="addRegistration.html"
+      permission="zope.ManageSite"
+      class=".register.AddAuthenticationRegistration" 
+      />
+
+  <editform
+      schema="zope.app.authentication.interfaces.IPluggableAuthentication"
+      label="Edit Pluggable Authentication Utility"
+      name="configure.html"
+      fields="prefix credentialsPlugins authenticatorPlugins"
+      menu="zmi_views" title="Configure"
+      permission="zope.ManageServices"
+      />
+
+  <page
+      name="contents.html"
+      for="zope.app.authentication.interfaces.IPluggableAuthentication"
+      menu="zmi_views" title="Plugins"
+      permission="zope.ManageSite"
+      class="zmi.core.container.contents.Contents"
+      attribute="contents"
+      />
+
+  <view
+      name="+"
+      menu="zmi_actions" title="Add"
+      for="zope.app.authentication.interfaces.IPluggableAuthentication"
+      permission="zope.ManageSite"
+      class=".adding.Adding"
+      >
+    <page
+        name="index.html"
+        attribute="index"
+        />
+    <page
+        name="action.html"
+        attribute="action"
+        />
+  </view>
+
+  <menuItem
+      menu="zmi_views"
+      for="zope.app.authentication.interfaces.IPluggableAuthentication"
+      title="Contents"
+      action=""
+      filter="python:False"
+      />
+
+  <zope:adapter
+      for="zope.app.authentication.interfaces.IQuerySchemaSearch
+           zope.publisher.interfaces.browser.IBrowserRequest"
+      provides="zope.app.form.browser.interfaces.ISourceQueryView"
+      factory=".schemasearch.QuerySchemaSearchView"
+      />
+
+</configure>

Added: zmi.core/trunk/src/zmi/core/authentication/group_searching_with_empty_string.txt
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/group_searching_with_empty_string.txt	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/group_searching_with_empty_string.txt	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,190 @@
+We can search group folder with an empty string.
+
+We'll add a  pluggable authentication utility:
+
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/@@contents.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 98
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Referer: http://localhost:8081/++etc++site/default/@@contents.html?type_name=BrowserAdd__zope.app.authentication.authentication.PluggableAuthentication
+  ... 
+  ... type_name=BrowserAdd__zope.app.authentication.authentication.PluggableAuthentication&new_value=PAU""")
+  HTTP/1.1 303 See Other
+  ...
+
+
+And register it:
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/addRegistration.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 699
+  ... Content-Type: multipart/form-data; boundary=---------------------------191720529414243436931796477300
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/addRegistration.html
+  ... 
+  ... -----------------------------191720529414243436931796477300
+  ... Content-Disposition: form-data; name="field.comment"
+  ... 
+  ... 
+  ... -----------------------------191720529414243436931796477300
+  ... Content-Disposition: form-data; name="field.actions.register"
+  ... 
+  ... Register
+  ... -----------------------------191720529414243436931796477300--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+Next, we'll add the group folder:
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/+/AddGroupFolder.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 427
+  ... Content-Type: multipart/form-data; boundary=---------------------------4150524541658557772058105275
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/+/AddGroupFolder.html=
+  ... 
+  ... -----------------------------4150524541658557772058105275
+  ... Content-Disposition: form-data; name="field.prefix"
+  ... 
+  ... groups
+  ... -----------------------------4150524541658557772058105275
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ... 
+  ... Add
+  ... -----------------------------4150524541658557772058105275
+  ... Content-Disposition: form-data; name="add_input_name"
+  ... 
+  ... groups
+  ... -----------------------------4150524541658557772058105275--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+And add some groups:
+
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/groups/+/AddGroupInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 550
+  ... Content-Type: multipart/form-data; boundary=---------------------------12719796373012316301953477158
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/groups/+/AddGroupInformation.html=
+  ... 
+  ... -----------------------------12719796373012316301953477158
+  ... Content-Disposition: form-data; name="field.title"
+  ... 
+  ... Test1
+  ... -----------------------------12719796373012316301953477158
+  ... Content-Disposition: form-data; name="field.description"
+  ... 
+  ... 
+  ... -----------------------------12719796373012316301953477158
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ... 
+  ... Add
+  ... -----------------------------12719796373012316301953477158
+  ... Content-Disposition: form-data; name="add_input_name"
+  ... 
+  ... Test1
+  ... -----------------------------12719796373012316301953477158--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/groups/+/AddGroupInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 550
+  ... Content-Type: multipart/form-data; boundary=---------------------------10816732208483809451400699513
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/groups/+/AddGroupInformation.html=
+  ... 
+  ... -----------------------------10816732208483809451400699513
+  ... Content-Disposition: form-data; name="field.title"
+  ... 
+  ... Test2
+  ... -----------------------------10816732208483809451400699513
+  ... Content-Disposition: form-data; name="field.description"
+  ... 
+  ... 
+  ... -----------------------------10816732208483809451400699513
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ... 
+  ... Add
+  ... -----------------------------10816732208483809451400699513
+  ... Content-Disposition: form-data; name="add_input_name"
+  ... 
+  ... Test2
+  ... -----------------------------10816732208483809451400699513--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+Now we'll configure our pluggable-authentication utility to use the
+group folder:
+
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/@@configure.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 1040
+  ... Content-Type: multipart/form-data; boundary=---------------------------1786480431902757372789659730
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/@@configure.html
+  ... 
+  ... -----------------------------1786480431902757372789659730
+  ... Content-Disposition: form-data; name="field.credentialsPlugins.to"
+  ... 
+  ... U2Vzc2lvbiBDcmVkZW50aWFscw==
+  ... -----------------------------1786480431902757372789659730
+  ... Content-Disposition: form-data; name="field.credentialsPlugins-empty-marker"
+  ... 
+  ... 
+  ... -----------------------------1786480431902757372789659730
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins.to"
+  ... 
+  ... Z3JvdXBz
+  ... -----------------------------1786480431902757372789659730
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins-empty-marker"
+  ... 
+  ... 
+  ... -----------------------------1786480431902757372789659730
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ... 
+  ... Change
+  ... -----------------------------1786480431902757372789659730
+  ... Content-Disposition: form-data; name="field.credentialsPlugins"
+  ... 
+  ... U2Vzc2lvbiBDcmVkZW50aWFscw==
+  ... -----------------------------1786480431902757372789659730
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins"
+  ... 
+  ... Z3JvdXBz
+  ... -----------------------------1786480431902757372789659730--
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+
+Now, if we search for a group, but don't supply a string:
+
+  >>> print http(r"""
+  ... POST /@@grant.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 166
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Referer: http://localhost:8081/@@grant.html
+  ... 
+  ... field.principal.displayed=y&"""
+  ... "field.principal.MC5ncm91cHM_.field.search=&"
+  ... "field.principal.MC5ncm91cHM_.search=Search&"
+  ... "field.principal.MQ__.searchstring=")
+  HTTP/1.1 200 OK
+  ...Test1...Test2...
+
+We get both of our groups in the result.


Property changes on: zmi.core/trunk/src/zmi/core/authentication/group_searching_with_empty_string.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zmi.core/trunk/src/zmi/core/authentication/groupfolder.txt
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/groupfolder.txt	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/groupfolder.txt	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,659 @@
+Using Group Folders
+===================
+
+Group folders are used to define groups.  Before you can define
+groups, you have to create a group folder and configure it in a
+pluggable authentication utility. The group folder has to be
+registered with a pluggable authentication utility before defining any
+groups.  This is because the groups folder needs to use the pluggable
+authentication utility to find all of the groups containing a given
+group so that it can check for group cycles. Not all of a group's
+groups need to be defined in it's group folder. Other groups folders
+or group-defining plugins could define groups for a group.
+
+Let's walk through an example.
+
+First, We need to create and register a pluggable authentication utility.
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/@@contents.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 98
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/@@contents.html?type_name=BrowserAdd__zope.app.authentication.authentication.PluggableAuthentication
+  ...
+  ... type_name=BrowserAdd__zope.app.authentication.authentication.PluggableAuthentication&new_value=PAU""")
+  HTTP/1.1 303 See Other
+  ...
+
+  >>> print http(r"""
+  ... GET /++etc++site/default/PAU/@@registration.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/@@contents.html?type_name=BrowserAdd__zope.app.authentication.authentication.PluggableAuthentication
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+Register PAU.
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/addRegistration.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 687
+  ... Content-Type: multipart/form-data; boundary=---------------------------5559795404609280911441883437
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/addRegistration.html
+  ...
+  ... -----------------------------5559795404609280911441883437
+  ... Content-Disposition: form-data; name="field.comment"
+  ...
+  ... 
+  ... -----------------------------5559795404609280911441883437
+  ... Content-Disposition: form-data; name="field.actions.register"
+  ...
+  ... Register
+  ... -----------------------------5559795404609280911441883437--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+Add a Principal folder plugin `users` to PAU.
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/+/AddPrincipalFolder.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 429
+  ... Content-Type: multipart/form-data; boundary=---------------------------95449631112274213651507932125
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/+/AddPrincipalFolder.html=
+  ...
+  ... -----------------------------95449631112274213651507932125
+  ... Content-Disposition: form-data; name="field.prefix"
+  ...
+  ... users
+  ... -----------------------------95449631112274213651507932125
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------95449631112274213651507932125
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ... users
+  ... -----------------------------95449631112274213651507932125--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+Next we will add some users.
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 780
+  ... Content-Type: multipart/form-data; boundary=---------------------------5110544421083023415453147877
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.login"
+  ...
+  ... bob
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.passwordManagerName"
+  ...
+  ... Plain Text
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.password"
+  ...
+  ... 123
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... Bob
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 780
+  ... Content-Type: multipart/form-data; boundary=---------------------------5110544421083023415453147877
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.login"
+  ...
+  ... bill
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.passwordManagerName"
+  ...
+  ... Plain Text
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.password"
+  ...
+  ... 123
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... Bill
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 780
+  ... Content-Type: multipart/form-data; boundary=---------------------------5110544421083023415453147877
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.login"
+  ...
+  ... betty
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.passwordManagerName"
+  ...
+  ... Plain Text
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.password"
+  ...
+  ... 123
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... Betty
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 780
+  ... Content-Type: multipart/form-data; boundary=---------------------------5110544421083023415453147877
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.login"
+  ...
+  ... sally
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.passwordManagerName"
+  ...
+  ... Plain Text
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.password"
+  ...
+  ... 123
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... Sally
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 780
+  ... Content-Type: multipart/form-data; boundary=---------------------------5110544421083023415453147877
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.login"
+  ...
+  ... george
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.passwordManagerName"
+  ...
+  ... Plain Text
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.password"
+  ...
+  ... 123
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... George
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 780
+  ... Content-Type: multipart/form-data; boundary=---------------------------5110544421083023415453147877
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.login"
+  ...
+  ... mike
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.passwordManagerName"
+  ...
+  ... Plain Text
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.password"
+  ...
+  ... 123
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... Mike
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 780
+  ... Content-Type: multipart/form-data; boundary=---------------------------5110544421083023415453147877
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.login"
+  ...
+  ... mary
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.passwordManagerName"
+  ...
+  ... Plain Text
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.password"
+  ...
+  ... 123
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... Mary
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ...
+  ... -----------------------------5110544421083023415453147877--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+Next, We'll add out group folder plugin in PAU.
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/+/AddGroupFolder.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 427
+  ... Content-Type: multipart/form-data; boundary=---------------------------4150524541658557772058105275
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/+/AddGroupFolder.html=
+  ...
+  ... -----------------------------4150524541658557772058105275
+  ... Content-Disposition: form-data; name="field.prefix"
+  ...
+  ... groups
+  ... -----------------------------4150524541658557772058105275
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------4150524541658557772058105275
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ... groups
+  ... -----------------------------4150524541658557772058105275--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+Next we'll select the credentials and authenticators for the PAU:
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/@@configure.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 1313
+  ... Content-Type: multipart/form-data; boundary=---------------------------2026736768606413562109112352
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/@@configure.html
+  ...
+  ... -----------------------------2026736768606413562109112352
+  ... Content-Disposition: form-data; name="field.credentialsPlugins.to"
+  ...
+  ... U2Vzc2lvbiBDcmVkZW50aWFscw==
+  ... -----------------------------2026736768606413562109112352
+  ... Content-Disposition: form-data; name="field.credentialsPlugins-empty-marker"
+  ...
+  ...
+  ... -----------------------------2026736768606413562109112352
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins.to"
+  ...
+  ... dXNlcnM=
+  ... -----------------------------2026736768606413562109112352
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins.to"
+  ...
+  ... Z3JvdXBz
+  ... -----------------------------2026736768606413562109112352
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins-empty-marker"
+  ...
+  ...
+  ... -----------------------------2026736768606413562109112352
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Change
+  ... -----------------------------2026736768606413562109112352
+  ... Content-Disposition: form-data; name="field.credentialsPlugins"
+  ...
+  ... U2Vzc2lvbiBDcmVkZW50aWFscw==
+  ... -----------------------------2026736768606413562109112352
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins"
+  ...
+  ... dXNlcnM=
+  ... -----------------------------2026736768606413562109112352
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins"
+  ...
+  ... Z3JvdXBz
+  ... -----------------------------2026736768606413562109112352--
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+
+
+Now, we can define some groups.  Let's start with a group named "Admin":
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/groups/+/AddGroupInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 550
+  ... Content-Type: multipart/form-data; boundary=---------------------------20619400354342370301249668954
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/groups/+/AddGroupInformation.html=
+  ...
+  ... -----------------------------20619400354342370301249668954
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... Admin
+  ... -----------------------------20619400354342370301249668954
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------20619400354342370301249668954
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------20619400354342370301249668954
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ... admin
+  ... -----------------------------20619400354342370301249668954--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+That includes Betty, Mary and Mike:
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/groups/admin/@@edit.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 1509
+  ... Content-Type: multipart/form-data; boundary=---------------------------6981402699601872602121555350
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/groups/admin/@@edit.html
+  ...
+  ... -----------------------------6981402699601872602121555350
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... Admin
+  ... -----------------------------6981402699601872602121555350
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------6981402699601872602121555350
+  ... Content-Disposition: form-data; name="field.principals.displayed"
+  ...
+  ... y
+  ... -----------------------------6981402699601872602121555350
+  ... Content-Disposition: form-data; name="field.principals.MC51c2Vycw__.query.field.search"
+  ...
+  ...
+  ... -----------------------------6981402699601872602121555350
+  ... Content-Disposition: form-data; name="field.principals:list"
+  ...
+  ... dXNlcnMz
+  ... -----------------------------6981402699601872602121555350
+  ... Content-Disposition: form-data; name="field.principals:list"
+  ...
+  ... dXNlcnM3
+  ... -----------------------------6981402699601872602121555350
+  ... Content-Disposition: form-data; name="field.principals:list"
+  ...
+  ... dXNlcnM2
+  ... -----------------------------6981402699601872602121555350
+  ... Content-Disposition: form-data; name="field.principals.MC51c2Vycw__.apply"
+  ...
+  ... Apply
+  ... -----------------------------6981402699601872602121555350
+  ... Content-Disposition: form-data; name="field.principals.MC5ncm91cHM_.query.field.search"
+  ...
+  ...
+  ... -----------------------------6981402699601872602121555350
+  ... Content-Disposition: form-data; name="field.principals.MQ__.query.searchstring"
+  ...
+  ...
+  ... -----------------------------6981402699601872602121555350--
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+
+and a group "Power Users"
+
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/groups/+/AddGroupInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 561
+  ... Content-Type: multipart/form-data; boundary=---------------------------168380148515549442351132560943
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/groups/+/AddGroupInformation.html=
+  ...
+  ... -----------------------------168380148515549442351132560943
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... Power Users
+  ... -----------------------------168380148515549442351132560943
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------168380148515549442351132560943
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------168380148515549442351132560943
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ... power
+  ... -----------------------------168380148515549442351132560943--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+with Bill and Betty as members:
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/groups/power/@@edit.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 1729
+  ... Content-Type: multipart/form-data; boundary=---------------------------181944013812647128322134918391
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/groups/power/@@edit.html
+  ...
+  ... -----------------------------181944013812647128322134918391
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... Power Users
+  ... -----------------------------181944013812647128322134918391
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------181944013812647128322134918391
+  ... Content-Disposition: form-data; name="field.principals:list"
+  ...
+  ... dXNlcnMz
+  ... -----------------------------181944013812647128322134918391
+  ... Content-Disposition: form-data; name="field.principals:list"
+  ...
+  ... dXNlcnMy
+  ... -----------------------------181944013812647128322134918391
+  ... Content-Disposition: form-data; name="field.principals.displayed"
+  ...
+  ... y
+  ... -----------------------------181944013812647128322134918391
+  ... Content-Disposition: form-data; name="field.principals.MC51c2Vycw__.query.field.search"
+  ...
+  ...
+  ... -----------------------------181944013812647128322134918391
+  ... Content-Disposition: form-data; name="field.principals.MC5ncm91cHM_.query.field.search"
+  ...
+  ...
+  ... -----------------------------181944013812647128322134918391
+  ... Content-Disposition: form-data; name="field.principals.MQ__.query.searchstring"
+  ...
+  ...
+  ... -----------------------------181944013812647128322134918391
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Change
+  ... -----------------------------181944013812647128322134918391--
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+Now, with these groups set up, we should see these groups on the
+affected principals.  First, we'll make the root folder the
+thread-local site:
+
+  >>> from zope.site.hooks import setSite
+  >>> setSite(getRootFolder())
+
+and we'll get the pluggable authentication utility:
+
+  >>> from zope.authentication.interfaces import IAuthentication
+  >>> from zope.component import getUtility
+  >>> principals = getUtility(IAuthentication)
+
+Finally we'll get Betty and see that she is in the admin and
+power-user groups:
+
+  >>> betty = principals.getPrincipal(u'users3')
+  >>> betty.groups.sort()
+  >>> betty.groups
+  [u'groupspower', 'zope.Authenticated', 'zope.Everybody']
+
+
+And we'll get Bill, and see that he is only in the power-user group:
+
+  >>> bill = principals.getPrincipal(u'users2')
+  >>> bill.groups
+  ['zope.Everybody', 'zope.Authenticated', u'groupspower']


Property changes on: zmi.core/trunk/src/zmi/core/authentication/groupfolder.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zmi.core/trunk/src/zmi/core/authentication/groupfolder.zcml
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/groupfolder.zcml	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/groupfolder.zcml	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,55 @@
+<configure 
+    xmlns="http://namespaces.zope.org/browser"
+    i18n_domain="zope"
+    >
+
+<editform
+    schema="..groupfolder.IGroupInformation"
+    label="Change group information"
+    name="edit.html"
+    menu="zmi_views" title="Edit"
+    permission="zope.ManageServices"
+    />
+
+<addform
+    schema="..groupfolder.IGroupInformation"
+    content_factory="..groupfolder.GroupInformation"
+    label="Add group information"
+    name="AddGroupInformation.html"
+    permission="zope.ManageServices"
+    fields="title description"
+    />
+
+<addMenuItem
+    title="Group"
+    description="A principals group"
+    class="..groupfolder.GroupInformation"
+    permission="zope.ManageServices"
+    view="AddGroupInformation.html"
+    />
+
+<addform
+    schema="..groupfolder.IGroupFolder"
+    content_factory="..groupfolder.GroupFolder"
+    arguments="prefix"
+    label="Add group folder"
+    name="AddGroupFolder.html"
+    permission="zope.ManageServices"
+    />
+
+<addMenuItem
+    title="Group Folder"
+    description="A Group folder"
+    class="..groupfolder.GroupFolder"
+    permission="zope.ManageServices"
+    view="AddGroupFolder.html"
+    />
+
+<containerViews
+    for="..groupfolder.IGroupFolder"
+    contents="zope.ManageServices"
+    index="zope.ManageServices"
+    add="zope.ManageServices"
+    />
+
+</configure> 

Added: zmi.core/trunk/src/zmi/core/authentication/httpplugins.zcml
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/httpplugins.zcml	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/httpplugins.zcml	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,20 @@
+<configure 
+    xmlns="http://namespaces.zope.org/browser"
+    i18n_domain="zope"
+    >
+
+  <addMenuItem
+      title="HTTP Basic-Auth Plugin"
+      class="..httpplugins.HTTPBasicAuthCredentialsPlugin"
+      permission="zope.ManageServices"
+      />
+
+  <editform
+      schema="..httpplugins.IHTTPBasicAuthRealm"
+      label="Realm"
+      name="edit.html"
+      permission="zope.ManageServices"
+      menu="zmi_views" title="Edit"
+      />
+
+</configure>

Added: zmi.core/trunk/src/zmi/core/authentication/issue663.txt
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/issue663.txt	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/issue663.txt	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,54 @@
+http://www.zope.org/Collectors/Zope3-dev/663
+============================================
+
+Two plugins(basic-auth and session credentials) link
+on PAU add menu are broken and can't add them.
+
+For IPluggableAuthentication, "plugins.html" is a correct
+view name but "contents.html" is used.
+
+because menu implementation supporsing that all view
+uses "zope.app.container.browser.contents.Contents" are
+named "contents.html".
+
+In Zope3.2, PluggableAuthentication inherits
+SiteManagementFolder that provides "contents.html" view.
+
+    >>> from zope.testbrowser.testing import Browser
+    >>> browser = Browser()
+
+Create a pau
+
+    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+    >>> browser.open('http://localhost/@@contents.html')
+    >>> browser.getLink('Pluggable Authentication Utility').click()
+    >>> browser.getControl(name='add_input_name').value = 'auth'
+    >>> browser.getControl('Add').click()
+    >>> browser.getLink('auth').click()
+
+Go to the plugins view
+
+    >>> browser.getLink('Plugins').click()
+
+Add aa basic auth plugin
+
+    >>> browser.getLink('HTTP Basic-Auth Plugin').click()
+    >>> browser.getControl(name='new_value').value = 'basic'
+    >>> browser.getControl('Apply').click()
+
+Add a session-credential plugin
+
+    >>> browser.getLink('Session Credentials Plugin').click()
+    >>> browser.getControl(name='new_value').value = 'session'
+    >>> browser.getControl('Apply').click()
+
+Make sure we can use them:
+
+    >>> browser.getLink('Configure').click()
+    >>> browser.getControl(name='field.credentialsPlugins.from').value = [
+    ...     'Wm9wZSBSZWFsbSBCYXNpYy1BdXRo']
+    >>> browser.getControl(name='field.credentialsPlugins.from').value = [
+    ...     'YmFzaWM=']
+    >>> browser.getControl(name='field.credentialsPlugins.from').value = [
+    ...     'U2Vzc2lvbiBDcmVkZW50aWFscw==']
+    >>> browser.getControl('Change').click()


Property changes on: zmi.core/trunk/src/zmi/core/authentication/issue663.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zmi.core/trunk/src/zmi/core/authentication/loginform.pt
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/loginform.pt	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/loginform.pt	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,46 @@
+<html metal:use-macro="context/@@standard_macros/page" i18n:domain="zope">
+<head>
+  <title metal:fill-slot="title" i18n:translate="">Sign in</title>
+</head>
+<body>
+  <div metal:fill-slot="body">
+
+    <p i18n:translate="" tal:condition="view/unauthenticated">
+      Please provide Login Information
+    </p>
+
+    <p i18n:translate="" tal:condition="not:view/unauthenticated">
+      You are not authorized to perform this action. However, you may login as a 
+      different user who is authorized.
+    </p>
+
+    <form action="" method="post">
+
+      <div class="row">
+        <div class="label"><label for="login" i18n:translate="">User Name</label></div>
+          <div class="field">
+            <input type="text" name="login" id="login" />
+          </div>
+      </div>
+
+      <div class="row">
+        <div class="label"><label for="password" i18n:translate="">Password</label></div>
+        <div class="field">
+          <input type="password" name="password" id="password" />
+        </div>
+      </div>
+    
+      <div class="row">
+        <input class="form-element" type="submit" 
+               name="SUBMIT" value="Log in" i18n:attributes="value login-button" />
+      </div>
+
+      <input type="hidden" name="camefrom"
+             tal:condition="view/camefrom" 
+             tal:attributes="value view/camefrom" />
+
+    </form>
+
+  </div>
+</body>
+</html>

Added: zmi.core/trunk/src/zmi/core/authentication/loginform.py
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/loginform.py	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/loginform.py	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,42 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+"""Login Form
+
+$Id$
+"""
+from zope.authentication.interfaces import IUnauthenticatedPrincipal
+
+class LoginForm(object):
+    """Mix-in class to implement login form logic"""
+    
+    def __call__(self):
+        request = self.request
+        principal = request.principal
+
+        unauthenticated = IUnauthenticatedPrincipal.providedBy(principal)
+        self.unauthenticated = unauthenticated
+        
+        camefrom = request.get('camefrom')
+        if isinstance(camefrom, list):
+            # this can happen on python2.6, as it changed the
+            # behaviour of cgi.FieldStorage a bit.
+            camefrom = camefrom[0]
+        self.camefrom = camefrom
+        
+        if (not unauthenticated) and ('SUBMIT' in request):
+            # authenticated by submitting
+            request.response.redirect(camefrom or '.')
+            return ''
+        
+        return self.index() # call template

Added: zmi.core/trunk/src/zmi/core/authentication/pau_prefix_and_searching.txt
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/pau_prefix_and_searching.txt	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/pau_prefix_and_searching.txt	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,263 @@
+================================
+Using a PAU Prefix and Searching
+================================
+
+This test confirms that both principals and groups can be searched for in
+PAUs that have prefixes.
+
+First we'll create a PAU with a prefix of `pau1_` and and register:
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/+/AddPluggableAuthentication.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 372
+  ... Content-Type: multipart/form-data; boundary=---------------------------318183180122653
+  ...
+  ... -----------------------------318183180122653
+  ... Content-Disposition: form-data; name="field.prefix"
+  ...
+  ... pau1_
+  ... -----------------------------318183180122653
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------318183180122653
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ... PAU1
+  ... -----------------------------318183180122653--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU1/addRegistration.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 591
+  ... Content-Type: multipart/form-data; boundary=---------------------------516441125097
+  ...
+  ... -----------------------------516441125097
+  ... Content-Disposition: form-data; name="field.comment"
+  ...
+  ... 
+  ... -----------------------------516441125097
+  ... Content-Disposition: form-data; name="field.actions.register"
+  ...
+  ... Register
+  ... -----------------------------516441125097--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+Next we'll create and register a principal folder:
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU1/+/AddPrincipalFolder.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 374
+  ... Content-Type: multipart/form-data; boundary=---------------------------266241536215161
+  ...
+  ... -----------------------------266241536215161
+  ... Content-Disposition: form-data; name="field.prefix"
+  ...
+  ... users_
+  ... -----------------------------266241536215161
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------266241536215161
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ... Users
+  ... -----------------------------266241536215161--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+and add a principal that we'll later search for:
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU1/Users/+/AddPrincipalInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 686
+  ... Content-Type: multipart/form-data; boundary=---------------------------300171485226567
+  ...
+  ... -----------------------------300171485226567
+  ... Content-Disposition: form-data; name="field.login"
+  ...
+  ... bob
+  ... -----------------------------300171485226567
+  ... Content-Disposition: form-data; name="field.passwordManagerName"
+  ...
+  ... Plain Text
+  ... -----------------------------300171485226567
+  ... Content-Disposition: form-data; name="field.password"
+  ...
+  ... bob
+  ... -----------------------------300171485226567
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... Bob
+  ... -----------------------------300171485226567
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------300171485226567
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------300171485226567
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ...
+  ... -----------------------------300171485226567--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+Next, we'll add and register a group folder:
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU1/+/AddGroupFolder.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 372
+  ... Content-Type: multipart/form-data; boundary=---------------------------17420126702455
+  ...
+  ... -----------------------------17420126702455
+  ... Content-Disposition: form-data; name="field.prefix"
+  ...
+  ... groups_
+  ... -----------------------------17420126702455
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------17420126702455
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ... Groups
+  ... -----------------------------17420126702455--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+and add a group to search for:
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU1/Groups/+/AddGroupInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 485
+  ... Content-Type: multipart/form-data; boundary=---------------------------323081358415654
+  ...
+  ... -----------------------------323081358415654
+  ... Content-Disposition: form-data; name="field.title"
+  ...
+  ... Nice People
+  ... -----------------------------323081358415654
+  ... Content-Disposition: form-data; name="field.description"
+  ...
+  ...
+  ... -----------------------------323081358415654
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Add
+  ... -----------------------------323081358415654
+  ... Content-Disposition: form-data; name="add_input_name"
+  ...
+  ... nice
+  ... -----------------------------323081358415654--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+Since we're only searching in this test, we won't bother to add anyone to the
+group.
+
+Before we search, we need to register the two authenticator plugins with the
+PAU:
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU1/@@configure.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 888
+  ... Content-Type: multipart/form-data; boundary=---------------------------610310492754
+  ...
+  ... -----------------------------610310492754
+  ... Content-Disposition: form-data; name="field.credentialsPlugins-empty-marker"
+  ...
+  ...
+  ... -----------------------------610310492754
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins.to"
+  ...
+  ... R3JvdXBz
+  ... -----------------------------610310492754
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins.to"
+  ...
+  ... VXNlcnM=
+  ... -----------------------------610310492754
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins-empty-marker"
+  ...
+  ...
+  ... -----------------------------610310492754
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ...
+  ... Change
+  ... -----------------------------610310492754
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins"
+  ...
+  ... R3JvdXBz
+  ... -----------------------------610310492754
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins"
+  ...
+  ... VXNlcnM=
+  ... -----------------------------610310492754--
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+Now we'll use the 'grant' interface of the root folder to search for all of
+the available groups:
+
+  >>> print http(r"""
+  ... POST /@@grant.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 191
+  ... Content-Type: application/x-www-form-urlencoded
+  ... 
+  ... field.principal.displayed=y&"""
+  ... "field.principal.MC5Hcm91cHM_.field.search=&"
+  ... "field.principal.MC5Hcm91cHM_.search=Search&"
+  ... "field.principal.MC5Vc2Vycw__.field.search=&"
+  ... "field.principal.MQ__.searchstring=")
+  HTTP/1.1 200 OK
+  ...
+  <select name="field.principal.MC5Hcm91cHM_.selection">
+  <option value="cGF1MV9ncm91cHNfbmljZQ__">Nice People</option>
+  </select>
+  ...
+
+Note in the results that the dropdown box (i.e. the select element) has the
+single group 'Nice People' that we added earlier.
+
+Next, we'll use the same 'grant' interface to search for all of the available
+principals:
+
+  >>> print http(r"""
+  ... POST /@@grant.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 255
+  ... Content-Type: application/x-www-form-urlencoded
+  ...
+  ... field.principal.displayed=y&"""
+  ... "field.principal.MC5Hcm91cHM_.field.search=&"
+  ... "field.principal.MC5Hcm91cHM_.selection=cGF1MV9ncm91cHNfbmljZQ__&"
+  ... "field.principal.MC5Vc2Vycw__.field.search=&"
+  ... "field.principal.MC5Vc2Vycw__.search=Search&"
+  ... "field.principal.MQ__.searchstring=")
+  HTTP/1.1 200 OK
+  ...
+  <select name="field.principal.MC5Vc2Vycw__.selection">
+  <option value="cGF1MV91c2Vyc18x">Bob</option>
+  </select>
+  ...
+
+Note here the dropdown contains Bob, the principal we added earlier.


Property changes on: zmi.core/trunk/src/zmi/core/authentication/pau_prefix_and_searching.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zmi.core/trunk/src/zmi/core/authentication/principalfolder.txt
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/principalfolder.txt	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/principalfolder.txt	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,308 @@
+Using Principal Folders
+=======================
+
+Principal folders are Pluggable-Authentication plugins that manage
+principal information, especially authentication credentials.  To use
+a principal folder, you need add a principal folder plugin to the PAU
+and to configure the PAU to use plugin.
+
+Let's look at an example, in which we'll define a new manager named
+Bob.  Initially, attempts to log in as Bob fail:
+
+  >>> print http(r"""
+  ... GET /manage HTTP/1.1
+  ... Authorization: Basic Ym9iOjEyMw==
+  ... """)
+  HTTP/1.1 401 Unauthorized
+  ...
+
+To allow Bob to log in, we'll start by adding a principal folder to PAU:
+
+We need to create and register a pluggable authentication utility.
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/@@contents.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 98
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/@@contents.html?type_name=BrowserAdd__zope.app.authentication.authentication.PluggableAuthentication
+  ... 
+  ... type_name=BrowserAdd__zope.app.authentication.authentication.PluggableAuthentication&new_value=PAU""",
+  ... handle_errors=False)
+  HTTP/1.1 303 See Other
+  ...
+
+  >>> print http(r"""
+  ... GET /++etc++site/default/PAU/@@registration.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/@@contents.html?type_name=BrowserAdd__zope.app.authentication.authentication.PluggableAuthentication
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+Register PAU.
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/addRegistration.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 687
+  ... Content-Type: multipart/form-data; boundary=---------------------------5559795404609280911441883437
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/addRegistration.html
+  ... 
+  ... -----------------------------5559795404609280911441883437
+  ... Content-Disposition: form-data; name="field.comment"
+  ... 
+  ... 
+  ... -----------------------------5559795404609280911441883437
+  ... Content-Disposition: form-data; name="field.actions.register"
+  ... 
+  ... Register
+  ... -----------------------------5559795404609280911441883437--
+  ... """, handle_errors=False)
+  HTTP/1.1 303 See Other
+  ...
+
+Add a Principal folder plugin to PAU.
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/+/AddPrincipalFolder.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 429
+  ... Content-Type: multipart/form-data; boundary=---------------------------95449631112274213651507932125
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/+/AddPrincipalFolder.html=
+  ... 
+  ... -----------------------------95449631112274213651507932125
+  ... Content-Disposition: form-data; name="field.prefix"
+  ... 
+  ... users
+  ... -----------------------------95449631112274213651507932125
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ... 
+  ... Add
+  ... -----------------------------95449631112274213651507932125
+  ... Content-Disposition: form-data; name="add_input_name"
+  ... 
+  ... users
+  ... -----------------------------95449631112274213651507932125--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+We specify a prefix, `users.`.  This is used to make sure that ids
+used by this plugin don't conflict with ids of other plugins.  We also
+name ths plugin `users`.  This is the name we'll use when we configure
+the pluggable authentiaction service.
+
+Next we'll view the contents page of the principal folder:
+
+  >>> print http(r"""
+  ... GET /++etc++site/default/PAU/users/@@contents.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/users/addRegistration.html
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+
+And we'll add a principal, Bob:
+
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 780
+  ... Content-Type: multipart/form-data; boundary=---------------------------5110544421083023415453147877
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D
+  ... 
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.login"
+  ... 
+  ... bob
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.passwordManagerName"
+  ... 
+  ... SHA1
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.password"
+  ... 
+  ... bob
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.title"
+  ... 
+  ... bob
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.description"
+  ... 
+  ... 
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ... 
+  ... Add
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="add_input_name"
+  ... 
+  ... bob
+  ... -----------------------------5110544421083023415453147877--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+Note that we didn't pick a name.  The name, together with the folder
+prefix. If we don't choose a name, a numeric id is chosen.
+
+
+Now we have a principal folder with a principal. 
+
+Configure PAU, with registered principal folder plugin and 
+select any one credentials.
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/@@configure.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 1038
+  ... Content-Type: multipart/form-data; boundary=---------------------------6519411471194050603270010787
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/@@configure.html
+  ... 
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="field.credentialsPlugins.to"
+  ... 
+  ... U2Vzc2lvbiBDcmVkZW50aWFscw==
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="field.credentialsPlugins-empty-marker"
+  ... 
+  ... 
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins.to"
+  ... 
+  ... dXNlcnM=
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins-empty-marker"
+  ... 
+  ... 
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ... 
+  ... Change
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="field.credentialsPlugins"
+  ... 
+  ... U2Vzc2lvbiBDcmVkZW50aWFscw==
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins"
+  ... 
+  ... dXNlcnM=
+  ... -----------------------------6519411471194050603270010787--
+  ... """, handle_errors=False)
+  HTTP/1.1 200 OK
+  ... 
+
+Now, with this in place, Bob can log in, but he isn't allowed to
+access the management interface. When he attempts to do so, the PAU 
+issues a challenge to let bob login as a different user
+
+  >>> print http(r"""
+  ... POST /@@loginForm.html?camefrom=http%3A%2F%2Flocalhost%3A8081%2F%40%40login.html HTTP/1.1
+  ... Content-Length: 94
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Cookie: zope3_cs_6a58ae0=zt1tvSi4JRxMD4bggPyUqMA70iE3bgAqvQB.y.ZeOhMmkfbens3-pU
+  ... Referer: http://localhost:8081/@@loginForm.html?camefrom=http%3A%2F%2Flocalhost%3A8081%2F%40%40login.html
+  ... 
+  ... login=bob&password=bob&SUBMIT=Log+in&camefrom=http%3A%2F%2Flocalhost%3A8081%2F%40%40login.html""")
+  HTTP/1.1 303 See Other
+  ...
+
+When he attempts to do so, the PAU issues a challenge to let bob login 
+as a different user
+
+  >>> print http(r"""
+  ... GET /+ HTTP/1.1
+  ... Cookie: zope3_cs_6a58ae0=zt1tvSi4JRxMD4bggPyUqMA70iE3bgAqvQB.y.ZeOhMmkfbens3-pU
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+We go to the granting interface and search for and find a principal named Bob:
+  >>> print http(r"""
+  ... GET /@@grant.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Cookie: zope3_cs_6a58ae0=zt1tvSi4JRxMD4bggPyUqMA70iE3bgAqvQB.y.ZeOhMmkfbens3-pU
+  ... Referer: http://localhost:8081/@@contents.html
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+  >>> print http(r"""
+  ... POST /@@grant.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 210
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Cookie: zope3_cs_6a58ae0=zt1tvSi4JRxMD4bggPyUqMA70iE3bgAqvQB.y.ZeOhMmkfbens3-pU
+  ... Referer: http://localhost:8081/@@grant.html
+  ... 
+  ... field.principal.displayed=y&field.principal.MC51c2Vycw__.query.field.search=&field.principal.MC51c2Vycw__.selection=dXNlcnNib2I_&field.principal.MC51c2Vycw__.apply=Apply&field.principal.MQ__.query.searchstring=""")
+  HTTP/1.1 200 OK
+  ...
+
+
+  >>> print http(r"""
+  ... POST /@@grant.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 210
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Cookie: zope3_cs_6a58ae0=zt1tvSi4JRxMD4bggPyUqMA70iE3bgAqvQB.y.ZeOhMmkfbens3-pU
+  ... Referer: http://localhost:8081/@@grant.html
+  ... 
+  ... field.principal.displayed=y&field.principal.MC51c2Vycw__.query.field.search=&field.principal.MC51c2Vycw__.selection=dXNlcnNib2I_&field.principal.MC51c2Vycw__.apply=Apply&field.principal.MQ__.query.searchstring=""")
+  HTTP/1.1 200 OK
+  ...
+
+
+We select Bob and grant him the Manager role:
+
+  >>> print http(r"""
+  ... POST /@@grant.html HTTP/1.1
+  ... Authorization: Basic mgr:mgrpw
+  ... Content-Length: 5316
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Referer: http://localhost:8081/@@grant.html
+  ... 
+  ... field.principal=dXNlcnMuMQ__"""
+  ... """&field.principal.displayed=y"""
+  ... """&field.principal.MC51c2Vycw__.query.field.search=bob"""
+  ... """&field.principal.MA__.query.searchstring="""
+  ... """&GRANT_SUBMIT=Change"""
+  ... """&field.dXNlcnMuMQ__.role.zope.Manager=allow"""
+  ... """&field.dXNlcnMuMQ__.role.zope.Manager-empty-marker=1""")
+  HTTP/1.1 200 OK
+  ...
+
+
+  >>> print http(r"""
+  ... POST /@@grant.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 2598
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Cookie: zope3_cs_6a58ae0=zt1tvSi4JRxMD4bggPyUqMA70iE3bgAqvQB.y.ZeOhMmkfbens3-pU
+  ... Referer: http://localhost:8081/@@grant.html
+  ... 
+  ... field.principal=dXNlcnNib2I_&field.principal.displayed=y&field.principal.MC51c2Vycw__.query.field.search=&field.principal.MQ__.query.searchstring=&GRANT_SUBMIT=Change&field.dXNlcnNib2I_.role.bugtracker.Admin=unset&field.dXNlcnNib2I_.role.bugtracker.Editor=unset&field.dXNlcnNib2I_.role.bugtracker.User=unset&field.dXNlcnNib2I_.role.zope.Anonymous=unset&field.dXNlcnNib2I_.role.zope.Manager=allow&field.dXNlcnNib2I_.role.zope.Member=unset&field.dXNlcnNib2I_.role.zwiki.Admin=unset&field.dXNlcnNib2I_.role.zwiki.Editor=unset&field.dXNlcnNib2I_.role.zwiki.User=unset&field.dXNlcnNib2I_.permission.bugtracker.AddBug=unset&field.dXNlcnNib2I_.permission.bugtracker.AddAttachment=unset&field.dXNlcnNib2I_.permission.bugtracker.AddComment=unset&field.dXNlcnNib2I_.permission.zwiki.AddWikiPage=unset&field.dXNlcnNib2I_.permission.zwiki.CommentWikiPage=unset&field.dXNlcnNib2I_.permission.zwiki.DeleteWikiPage=unset&field.dXNlcnNib2I_.permission.bugtracker.EditBug=unset&field.dXNlcnNib2I_.per
 mission.zwiki.EditWikiPage=unset&field.dXNlcnNib2I_.permission.bugtracker.ManageBugTracker=unset&field.dXNlcnNib2I_.permission.zwiki.ReparentWikiPage=unset&field.dXNlcnNib2I_.permission.bugtracker.ViewBug=unset&field.dXNlcnNib2I_.permission.bugtracker.ViewBugTracker=unset&field.dXNlcnNib2I_.permission.zwiki.ViewWikiPage=unset&field.dXNlcnNib2I_.permission.zope.AddImages=unset&field.dXNlcnNib2I_.permission.zope.AddSQLScripts=unset&field.dXNlcnNib2I_.permission.zope.Security=unset&field.dXNlcnNib2I_.permission.zope.workflow.CreateProcessInstances=unset&field.dXNlcnNib2I_.permission.zope.ManageApplication=unset&field.dXNlcnNib2I_.permission.zope.ManageCode=unset&field.dXNlcnNib2I_.permission.zope.ManageContent=unset&field.dXNlcnNib2I_.permission.zope.ManagePrincipals=unset&field.dXNlcnNib2I_.permission.zope.ManageBindings=unset&field.dXNlcnNib2I_.permission.zope.ManageServices=unset&field.dXNlcnNib2I_.permission.zope.ManageSite=unset&field.dXNlcnNib2I_.permission.zope.workflow.
 ManageProcessDefinitions=unset&field.dXNlcnNib2I_.permission.zope.SendMail=unset&field.dXNlcnNib2I_.permission.zope.UndoAllTransactions=unset&field.dXNlcnNib2I_.permission.zope.UndoOwnTransactions=unset&field.dXNlcnNib2I_.permission.zope.workflow.UseProcessInstances=unset&field.dXNlcnNib2I_.permission.zope.View=unset&field.dXNlcnNib2I_.permission.zope.app.apidoc.UseAPIDoc=unset&field.dXNlcnNib2I_.permission.zope.app.dublincore.change=unset&field.dXNlcnNib2I_.permission.zope.app.dublincore.view=unset&field.dXNlcnNib2I_.permission.zope.app.introspector.Introspect=unset&field.dXNlcnNib2I_.permission.zope.app.rdb.Use=unset""")
+  HTTP/1.1 200 OK
+  ...
+
+
+At which point, Bob can access the management interface:
+
+  >>> print http(r"""
+  ... GET /@@contents.html HTTP/1.1
+  ... Authorization: Basic Ym9iOjEyMw==
+  ... """)
+  HTTP/1.1 200 OK
+  ...


Property changes on: zmi.core/trunk/src/zmi/core/authentication/principalfolder.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zmi.core/trunk/src/zmi/core/authentication/principalfolder.zcml
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/principalfolder.zcml	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/principalfolder.zcml	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,65 @@
+<configure
+    xmlns="http://namespaces.zope.org/browser"
+    >
+
+  <addform
+      schema="..principalfolder.IInternalPrincipalContainer"
+      label="Add Principal Folder"
+      content_factory="..principalfolder.PrincipalFolder"
+      keyword_arguments="prefix"
+      name="AddPrincipalFolder.html"
+      permission="zope.ManageServices"
+      />
+
+  <addMenuItem
+      title="Principal Folder"
+      description="A Pluggable Persistent Authentication Plugin"
+      class="..principalfolder.PrincipalFolder"
+      permission="zope.ManageServices"
+      view="AddPrincipalFolder.html"
+      />
+
+  <addform
+      schema="..principalfolder.IInternalPrincipal"
+      label="Add Principal Information"
+      content_factory="..principalfolder.InternalPrincipal"
+      arguments="login password title"
+      keyword_arguments="passwordManagerName description"
+      fields="login passwordManagerName password title description"
+      name="AddPrincipalInformation.html"
+      permission="zope.ManageServices"
+      />
+
+  <addMenuItem
+      title="Principal Information"
+      class="..principalfolder.InternalPrincipal"
+      permission="zope.ManageServices"
+      view="AddPrincipalInformation.html"
+      />
+
+  <editform
+      schema="..principalfolder.IInternalPrincipal"
+      label="Change Internal Principal"
+      name="edit.html"
+      fields="login passwordManagerName password title description"
+      permission="zope.ManageServices"
+      menu="zmi_views" title="Edit"
+      />
+
+  <containerViews
+      for="..principalfolder.IInternalPrincipalContainer"
+      add="zope.ManageServices"
+      contents="zope.ManageServices"
+      index="zope.ManageServices"
+      />
+
+  <schemadisplay
+      schema="..principalfolder.IInternalPrincipalContainer"
+      label="Principal Folder Prefix"
+      name="prefix.html"
+      fields="prefix"
+      permission="zope.ManageServices"
+      menu="zmi_views" title="Prefix"
+      />
+
+</configure>

Added: zmi.core/trunk/src/zmi/core/authentication/register.py
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/register.py	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/register.py	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,28 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation 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.
+#
+##############################################################################
+"""Improved registration UI for registering pluggable authentication utilities
+
+$Id: register.py 97982 2009-03-12 13:32:48Z nadako $
+"""
+
+from zope.app.authentication.i18n import ZopeMessageFactory as _
+import zope.app.component.browser.registration
+import zope.authentication.interfaces
+
+class AddAuthenticationRegistration(
+    zope.app.component.browser.registration.AddUtilityRegistration,
+    ):
+    label = _("Register a pluggable authentication utility")
+    name = ''
+    provided = zope.authentication.interfaces.IAuthentication

Added: zmi.core/trunk/src/zmi/core/authentication/schemasearch.py
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/schemasearch.py	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/schemasearch.py	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,110 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation 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.
+#
+##############################################################################
+"""Search interface for queriables.
+
+$Id: schemasearch.py 85500 2008-04-20 09:56:11Z lgs $
+"""
+__docformat__ = "reStructuredText"
+
+from zope.interface import implements
+from zope.i18n import translate
+from zope.schema import getFieldsInOrder
+from zope.app.form.utility import setUpWidgets, getWidgetsData
+from zope.app.form.interfaces import IInputWidget
+from zope.app.form.browser.interfaces import ISourceQueryView
+from zope.app.authentication.i18n import ZopeMessageFactory as _
+from zope.traversing.api import getName, getPath
+
+
+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)

Added: zmi.core/trunk/src/zmi/core/authentication/schemasearch.txt
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/schemasearch.txt	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/schemasearch.txt	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,104 @@
+The Query View for Schema Search Plugins
+========================================
+
+Placefull setup for making the search plugin IPhysicallyLocatable::
+
+  >>> from zope.app.testing import ztapi
+  >>> from zope.schema.interfaces import ITextLine
+  >>> from zope.app.form.browser import TextWidget
+  >>> from zope.app.form.interfaces import IInputWidget
+  >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
+  >>> site = placefulSetUp(True)
+  >>> ztapi.browserView(ITextLine, '', TextWidget, providing=IInputWidget)
+
+If a plugin supports `IQuerySchemaSearch`::
+
+  >>> from zope.interface import Interface
+  >>> import zope.schema
+  >>> class ISearchCriteria(Interface):
+  ...     search = zope.schema.TextLine(title=u"Search String")
+
+  >>> from zope.interface import implements
+  >>> class MySearchPlugin:
+  ...     __name__ = 'searchplugin'
+  ...     __parent__ = site
+  ...     schema = ISearchCriteria
+  ...     data = ['foo', 'bar', 'blah']
+  ...
+  ...     def get(self, id):
+  ...         if id in self.data:
+  ...             return {}
+  ...
+  ...     def search(self, query, start=None, batch_size=None):
+  ...         search = query.get('search')
+  ...         if search is not None:
+  ...             i = 0
+  ...             n = 0
+  ...             for value in self.data:
+  ...                 if search in value:
+  ...                     if not ((start is not None and i < start)
+  ...                             or
+  ...                             (batch_size is not None and n > batch_size)):
+  ...                         yield value
+
+then we can get a view::
+
+  >>> from zope.app.authentication.browser.schemasearch \
+  ...     import QuerySchemaSearchView 
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> view = QuerySchemaSearchView(MySearchPlugin(), request)
+
+This allows us to render a search form::
+
+  >>> print view.render('test') # doctest: +NORMALIZE_WHITESPACE
+  <h4>searchplugin</h4>
+  <div class="row">
+    <div class="label">
+      <label for="searchplugin" title="Path to the source utility">
+        Source path
+      </label>
+    </div>
+    <div class="field">
+        /searchplugin
+    </div>
+  </div>
+  <div class="row">
+    <div class="label">
+      <label for="test.field.search" title="">
+        Search String
+      </label>
+    </div>
+    <div class="field">
+      <input class="textType" id="test.field.search" name="test.field.search"
+         size="20" type="text" value=""  />
+    </div>
+  </div>
+  <div class="row">
+    <div class="field">
+      <input type="submit" name="test.search" value="Search" />
+    </div>
+  </div>
+
+If we ask for results::
+
+  >>> view.results('test')
+
+We don't get any, since we did not provide any. But if we give input::
+
+  >>> request.form['test.field.search'] = 'a'
+
+we still don't get any::
+
+  >>> view.results('test')
+
+because we did not press the button. So let's press the button::
+
+  >>> request.form['test.search'] = 'Search'
+
+so that we now get results (!)::
+
+  >>> list(view.results('test'))
+  ['bar', 'blah']
+
+  >>> placefulTearDown()


Property changes on: zmi.core/trunk/src/zmi/core/authentication/schemasearch.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zmi.core/trunk/src/zmi/core/authentication/session.zcml
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/session.zcml	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/session.zcml	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,27 @@
+<configure 
+    xmlns="http://namespaces.zope.org/browser"
+    >
+
+  <addMenuItem
+      title="Session Credentials Plugin"
+      class="..session.SessionCredentialsPlugin"
+      permission="zope.ManageServices"
+      />
+
+  <editform
+      schema="..session.IBrowserFormChallenger"
+      label="Browser Form Challenger"
+      name="edit.html"
+      permission="zope.ManageServices"
+      menu="zmi_views" title="Edit"
+      />
+
+  <page
+      name="loginForm.html" 
+      for="*"
+      template="loginform.pt"
+      class=".loginform.LoginForm"
+      permission="zope.Public" 
+      />
+
+</configure>

Added: zmi.core/trunk/src/zmi/core/authentication/special-groups.txt
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/special-groups.txt	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/special-groups.txt	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,376 @@
+Granting to unauthenticated
+===========================
+
+There are 3 special groups:
+
+- Everybody, that everybody belongs to,
+
+- Unauthenticated, that unauthenticated users belong to, and
+
+- Authenticating, that authenticated users belong to.
+
+Here's an example:
+
+First, we'll set up a pluggable authentication utility containing a
+principal folder, which we'll create first.
+
+
+
+Create pluggable authentication utility and register it.
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/@@contents.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 98
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/@@contents.html?type_name=BrowserAdd__zope.app.authentication.authentication.PluggableAuthentication
+  ... 
+  ... type_name=BrowserAdd__zope.app.authentication.authentication.PluggableAuthentication&new_value=PAU""")
+  HTTP/1.1 303 See Other
+  ...
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/addRegistration.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 687
+  ... Content-Type: multipart/form-data; boundary=---------------------------5559795404609280911441883437
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/addRegistration.html
+  ... 
+  ... -----------------------------5559795404609280911441883437
+  ... Content-Disposition: form-data; name="field.comment"
+  ... 
+  ... 
+  ... -----------------------------5559795404609280911441883437
+  ... Content-Disposition: form-data; name="field.actions.register"
+  ... 
+  ... Register
+  ... -----------------------------5559795404609280911441883437--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+Add a Principal folder plugin to PAU.
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/+/AddPrincipalFolder.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 429
+  ... Content-Type: multipart/form-data; boundary=---------------------------95449631112274213651507932125
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/+/AddPrincipalFolder.html=
+  ... 
+  ... -----------------------------95449631112274213651507932125
+  ... Content-Disposition: form-data; name="field.prefix"
+  ... 
+  ... users
+  ... -----------------------------95449631112274213651507932125
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ... 
+  ... Add
+  ... -----------------------------95449631112274213651507932125
+  ... Content-Disposition: form-data; name="add_input_name"
+  ... 
+  ... users
+  ... -----------------------------95449631112274213651507932125--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+Add a principal to it:
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 780
+  ... Content-Type: multipart/form-data; boundary=---------------------------5110544421083023415453147877
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/users/+/AddPrincipalInformation.html%3D
+  ... 
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.login"
+  ... 
+  ... bob
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.passwordManagerName"
+  ... 
+  ... Plain Text
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.password"
+  ... 
+  ... bob
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.title"
+  ... 
+  ... bob
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="field.description"
+  ... 
+  ... 
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ... 
+  ... Add
+  ... -----------------------------5110544421083023415453147877
+  ... Content-Disposition: form-data; name="add_input_name"
+  ... 
+  ... bob
+  ... -----------------------------5110544421083023415453147877--
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+Configure PAU, with registered principal folder plugin.
+
+  >>> print http(r"""
+  ... POST /++etc++site/default/PAU/@@configure.html HTTP/1.1
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 1038
+  ... Content-Type: multipart/form-data; boundary=---------------------------6519411471194050603270010787
+  ... Cookie: zope3_cs_6a553b3=-j7C3CdeW9sUK8BP5x97u2d9o242xMJDzJd8HCQ5AAi9xeFcGTFkAs
+  ... Referer: http://localhost:8081/++etc++site/default/PAU/@@configure.html
+  ... 
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="field.credentialsPlugins.to"
+  ... 
+  ... U2Vzc2lvbiBDcmVkZW50aWFscw==
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="field.credentialsPlugins-empty-marker"
+  ... 
+  ... 
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins.to"
+  ... 
+  ... dXNlcnM=
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins-empty-marker"
+  ... 
+  ... 
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ... 
+  ... Change
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="field.credentialsPlugins"
+  ... 
+  ... U2Vzc2lvbiBDcmVkZW50aWFscw==
+  ... -----------------------------6519411471194050603270010787
+  ... Content-Disposition: form-data; name="field.authenticatorPlugins"
+  ... 
+  ... dXNlcnM=
+  ... -----------------------------6519411471194050603270010787--
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+Normally, the anonymous role has view, we'll deny it:
+
+  >>> print http(r"""
+  ... POST /++etc++site/AllRolePermissions.html HTTP/1.1
+  ... Authorization: Basic mgr:mgrpw
+  ... Content-Type: application/x-www-form-urlencoded
+  ... 
+  ... role_id=zope.Anonymous""" 
+  ... """&Deny%3Alist=zope.View""" 
+  ... """&Deny%3Alist=zope.app.dublincore.view""" 
+  ... """&SUBMIT_ROLE=Save+Changes""")
+  HTTP/1.1 200 OK
+  ...
+
+Now, if we try to access the main page as an anonymous user, 
+we'll be unauthorized:
+
+
+  >>> print http(r"""
+  ... GET / HTTP/1.1
+  ... """)
+  ...
+  HTTP/1.1 303 See Other
+  ...
+
+
+
+We'll even be unauthorized if we try to access it as bob:
+
+  >>> print http(r"""
+  ... POST /@@loginForm.html?camefrom=http%3A%2F%2Flocalhost%3A8081%2F%40%40index.html HTTP/1.1
+  ... Content-Length: 94
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Cookie: zope3_cs_6a60902=cxcKJetHJjB2Px2umkzvTjeVI1E3aOpirHSjOYlxUPF.VX9DNjybrE
+  ... Referer: http://localhost:8081/@@loginForm.html?camefrom=http%3A%2F%2Flocalhost%3A8081%2F%40%40index.html
+  ... 
+  ... login=bob&password=bob&SUBMIT=Log+in&camefrom=http%3A%2F%2Flocalhost%3A8081%2F%40%40index.html""")
+  ...
+  HTTP/1.1 303 See Other
+  ...
+
+
+No, let's grant view to the authenticated group:
+
+  >>> print http(r"""
+  ... POST /@@grant.html HTTP/1.1
+  ... Authorization: Basic mgr:mgrpw
+  ... Content-Type: application/x-www-form-urlencoded
+  ... 
+  ... field.principal=em9wZS5BdXRoZW50aWNhdGVk&field.principal.displayed=y"""
+  ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.View=allow"""
+  ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.app.dublincore.view=allow"""
+  ... """&GRANT_SUBMIT=Change""")
+  HTTP/1.1 200 OK
+  ...
+
+Now, with this, we can access the main page as bob, but not as an
+anonymous user:
+
+  >>> print http(r"""
+  ... GET / HTTP/1.1
+  ... Authorization: Basic bob:123
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+  >>> print http(r"""
+  ... GET / HTTP/1.1
+  ... """)
+  HTTP/1.1 200 OK 
+  ...
+
+###401 Unauthorized
+
+
+Now, we'll grant to unauthenticated:
+
+  >>> print http(r"""
+  ... POST /@@grant.html HTTP/1.1
+  ... Authorization: Basic mgr:mgrpw
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Referer: http://localhost:8081/@@grant.html
+  ... 
+  ... field.principal=em9wZS5Bbnlib2R5"""
+  ... """&field.em9wZS5Bbnlib2R5.permission.zope.View=allow"""
+  ... """&field.em9wZS5Bbnlib2R5.permission.zope.app.dublincore.view=allow"""
+  ... """&GRANT_SUBMIT=Change""")
+  HTTP/1.1 200 OK
+  ...
+
+With this, we can access the page as either bob or anonymous:
+
+  >>> print http(r"""
+  ... GET / HTTP/1.1
+  ... Authorization: Basic bob:123
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+  >>> print http(r"""
+  ... GET / HTTP/1.1
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+
+Now, we'll remove the authenticated group grant:
+
+  >>> print http(r"""
+  ... POST /@@grant.html HTTP/1.1
+  ... Authorization: Basic mgr:mgrpw
+  ... Content-Type: application/x-www-form-urlencoded
+  ... 
+  ... field.principal=em9wZS5BdXRoZW50aWNhdGVk"""
+  ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.View=unset"""
+  ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.app.dublincore.view=unset"""
+  ... """&GRANT_SUBMIT=Change""")
+  HTTP/1.1 200 OK
+  ...
+
+And anonymous people will be able to access the page, but bob won't be able to:
+
+  >>> print http(r"""
+  ... POST /@@loginForm.html?camefrom=http%3A%2F%2Flocalhost%3A8081%2F%40%40index.html HTTP/1.1
+  ... Content-Length: 94
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Cookie: zope3_cs_6a60902=cxcKJetHJjB2Px2umkzvTjeVI1E3aOpirHSjOYlxUPF.VX9DNjybrE
+  ... Referer: http://localhost:8081/@@loginForm.html?camefrom=http%3A%2F%2Flocalhost%3A8081%2F%40%40index.html
+  ... 
+  ... login=bob&password=bob&SUBMIT=Log+in&camefrom=http%3A%2F%2Flocalhost%3A8081%2F%40%40index.html""")
+  ...
+  HTTP/1.1 303 See Other
+  ...
+
+
+
+  >>> print http(r"""
+  ... GET / HTTP/1.1
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+
+
+Now, we'll remove the unauthenticated group grant:
+
+  >>> print http(r"""
+  ... POST /@@grant.html HTTP/1.1
+  ... Authorization: Basic mgr:mgrpw
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Referer: http://localhost:8081/@@grant.html
+  ... 
+  ... field.principal=em9wZS5Bbnlib2R5"""
+  ... """&field.em9wZS5Bbnlib2R5.permission.zope.View=unset"""
+  ... """&field.em9wZS5Bbnlib2R5.permission.zope.app.dublincore.view=unset"""
+  ... """&GRANT_SUBMIT=Change""")
+  HTTP/1.1 200 OK
+  ...
+
+  >>> print http(r"""
+  ... POST /@@loginForm.html?camefrom=http%3A%2F%2Flocalhost%3A8081%2F%40%40index.html HTTP/1.1
+  ... Content-Length: 94
+  ... Content-Type: application/x-www-form-urlencoded
+  ... Cookie: zope3_cs_6a60902=cxcKJetHJjB2Px2umkzvTjeVI1E3aOpirHSjOYlxUPF.VX9DNjybrE
+  ... Referer: http://localhost:8081/@@loginForm.html?camefrom=http%3A%2F%2Flocalhost%3A8081%2F%40%40index.html
+  ... 
+  ... login=bob&password=bob&SUBMIT=Log+in&camefrom=http%3A%2F%2Flocalhost%3A8081%2F%40%40index.html""")
+  ...
+  HTTP/1.1 303 See Other
+  ...
+
+
+  >>> print http(r"""
+  ... GET / HTTP/1.1
+  ... """)
+  HTTP/1.1 303 See Other
+  ...
+
+
+
+Finally, we'll grant to everybody:
+
+  >>> print http(r"""
+  ... POST /@@grant.html HTTP/1.1
+  ... Authorization: Basic mgr:mgrpw
+  ... Content-Type: application/x-www-form-urlencoded
+  ... 
+  ... field.principal=em9wZS5FdmVyeWJvZHk_"""
+  ... """&field.em9wZS5FdmVyeWJvZHk_.permission.zope.View=allow"""
+  ... """&field.em9wZS5FdmVyeWJvZHk_.permission.zope.app.dublincore.view=allow"""
+  ... """&GRANT_SUBMIT=Change""", handle_errors = False)
+  HTTP/1.1 200 OK
+  ...
+
+and both bob nor anonymous can access:
+
+  >>> print http(r"""
+  ... GET / HTTP/1.1
+  ... Authorization: Basic bob:123
+  ... """)
+  HTTP/1.1 200 OK
+  ...
+
+  >>> print http(r"""
+  ... GET / HTTP/1.1
+  ... """)
+  HTTP/1.1 200 OK
+  ...


Property changes on: zmi.core/trunk/src/zmi/core/authentication/special-groups.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zmi.core/trunk/src/zmi/core/authentication/tests.py
===================================================================
--- zmi.core/trunk/src/zmi/core/authentication/tests.py	                        (rev 0)
+++ zmi.core/trunk/src/zmi/core/authentication/tests.py	2009-06-07 15:23:10 UTC (rev 100688)
@@ -0,0 +1,161 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation 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.
+#
+##############################################################################
+"""Pluggable Authentication Service Tests
+
+$Id: tests.py 75772 2007-05-15 18:21:29Z hdima $
+"""
+
+__docformat__ = "reStructuredText"
+
+import re
+import unittest
+from zope.testing import renormalizing, doctest
+from zope.app.testing.setup import placefulSetUp, placefulTearDown
+import transaction
+from zope.interface import directlyProvides
+from zope.exceptions.interfaces import UserError
+from zope.app.testing import functional
+from zope.app.authentication.principalfolder import PrincipalFolder
+from zope.app.authentication.principalfolder import Principal
+from zope.app.authentication.principalfolder import IInternalPrincipal
+from zope.app.authentication.testing import AppAuthenticationLayer
+
+
+def schemaSearchSetUp(self):
+    placefulSetUp(site=True)
+
+def schemaSearchTearDown(self):
+    placefulTearDown()
+
+class FunkTest(functional.BrowserTestCase):
+
+    def test_copypaste_duplicated_id_object(self):
+
+        root = self.getRootFolder()
+
+        # Create a principal Folder
+        root['pf'] = PrincipalFolder()
+        pf = root['pf']
+
+        # Create a principal with p1 as login
+        principal = Principal('p1')
+        principal.login = 'p1'
+        directlyProvides(principal, IInternalPrincipal)
+
+        pf['p1'] = principal
+
+        transaction.commit()
+        self.assertEqual(len(pf.keys()), 1)
+        #raise str([x for x in pf.keys()])
+
+        response = self.publish('/pf/@@contents.html',
+                                basic='mgr:mgrpw',
+                                form={'ids': [u'p1'],
+                                      'container_copy_button': u'Copy'})
+        self.assertEqual(response.getStatus(), 302)
+
+
+        # Try to paste the file
+        try:
+            response = self.publish('/pf/@@contents.html',
+                                    basic='mgr:mgrpw',
+                                    form={'container_paste_button': ''})
+        except UserError, e:
+            self.assertEqual(
+                str(e),
+                "The given name(s) [u'p1'] is / are already being used")
+        else:
+            # test failed !
+            self.asserEqual(1, 0)
+
+    def test_cutpaste_duplicated_id_object(self):
+
+        root = self.getRootFolder()
+
+        # Create a principal Folder
+        root['pf'] = PrincipalFolder()
+        pf = root['pf']
+
+        # Create a principal with p1 as login
+        principal = Principal('p1')
+        principal.login = 'p1'
+        directlyProvides(principal, IInternalPrincipal)
+
+        pf['p1'] = principal
+
+        transaction.commit()
+        self.assertEqual(len(pf.keys()), 1)
+        #raise str([x for x in pf.keys()])
+
+        response = self.publish('/pf/@@contents.html',
+                                basic='mgr:mgrpw',
+                                form={'ids': [u'p1'],
+                                      'container_cut_button': u'Cut'})
+        self.assertEqual(response.getStatus(), 302)
+
+
+        # Try to paste the file
+        try:
+            response = self.publish('/pf/@@contents.html',
+                                    basic='mgr:mgrpw',
+                                    form={'container_paste_button': ''})
+        except UserError, e:
+            self.assertEqual(
+                str(e),
+                "The given name(s) [u'p1'] is / are already being used")
+        else:
+            # test failed !
+            self.asserEqual(1, 0)
+
+
+checker = renormalizing.RENormalizing([
+    (re.compile(r"HTTP/1\.1 200 .*"), "HTTP/1.1 200 OK"),
+    (re.compile(r"HTTP/1\.1 303 .*"), "HTTP/1.1 303 See Other"),
+    (re.compile(r"HTTP/1\.1 401 .*"), "HTTP/1.1 401 Unauthorized"),
+    ])
+
+
+def test_suite():
+    FunkTest.layer = AppAuthenticationLayer
+    principalfolder = functional.FunctionalDocFileSuite(
+        'principalfolder.txt', checker=checker)
+    principalfolder.layer = AppAuthenticationLayer
+    groupfolder = functional.FunctionalDocFileSuite(
+        'groupfolder.txt', checker=checker)
+    groupfolder.layer = AppAuthenticationLayer
+    pau_prefix_and_searching = functional.FunctionalDocFileSuite(
+        'pau_prefix_and_searching.txt', checker=checker)
+    pau_prefix_and_searching.layer = AppAuthenticationLayer
+    group_searching_with_empty_string = functional.FunctionalDocFileSuite(
+        'group_searching_with_empty_string.txt', checker=checker)
+    group_searching_with_empty_string.layer = AppAuthenticationLayer
+    special_groups = functional.FunctionalDocFileSuite(
+        'special-groups.txt', checker=checker)
+    special_groups.layer = AppAuthenticationLayer
+    issue663 = functional.FunctionalDocFileSuite('issue663.txt')
+    issue663.layer = AppAuthenticationLayer
+    return unittest.TestSuite((
+        principalfolder,
+        groupfolder,
+        pau_prefix_and_searching,
+        group_searching_with_empty_string,
+        special_groups,
+        unittest.makeSuite(FunkTest),
+        issue663,
+        doctest.DocFileSuite('schemasearch.txt'),
+        ))
+
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')



More information about the Checkins mailing list