[Checkins] SVN: Products.CMFDefault/trunk/Products/CMFDefault/ - merged cookiecrumbler_with_views branch

Yvo Schubbe y.2010 at wcm-solutions.de
Tue Jun 15 06:19:43 EDT 2010


Log message for revision 113478:
  - merged cookiecrumbler_with_views branch

Changed:
  U   Products.CMFDefault/trunk/Products/CMFDefault/CHANGES.txt
  U   Products.CMFDefault/trunk/Products/CMFDefault/browser/authentication.py
  U   Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml
  A   Products.CMFDefault/trunk/Products/CMFDefault/browser/templates/forbidden.pt
  A   Products.CMFDefault/trunk/Products/CMFDefault/browser/templates/logged_out.pt
  U   Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/authentication.txt
  U   Products.CMFDefault/trunk/Products/CMFDefault/profiles/default/cookieauth.xml
  U   Products.CMFDefault/trunk/Products/CMFDefault/profiles/default/metadata.xml
  U   Products.CMFDefault/trunk/Products/CMFDefault/skins/zpt_control/logout.py
  U   Products.CMFDefault/trunk/Products/CMFDefault/upgrade/configure.zcml
  U   Products.CMFDefault/trunk/Products/CMFDefault/upgrade/tests/test_upgrade.py
  A   Products.CMFDefault/trunk/Products/CMFDefault/upgrade/to23.py

-=-
Modified: Products.CMFDefault/trunk/Products/CMFDefault/CHANGES.txt
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/CHANGES.txt	2010-06-15 10:16:49 UTC (rev 113477)
+++ Products.CMFDefault/trunk/Products/CMFDefault/CHANGES.txt	2010-06-15 10:19:43 UTC (rev 113478)
@@ -4,6 +4,9 @@
 2.3.0-alpha (unreleased)
 ------------------------
 
+- views: Added Unauthorized exception view.
+  This replaces CookieCrumbler's old redirect support.
+
 - Deal with deprecation warnings for Zope 2.13.
 
 - Use the standard libraries doctest module.

Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/authentication.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/authentication.py	2010-06-15 10:16:49 UTC (rev 113477)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/authentication.py	2010-06-15 10:19:43 UTC (rev 113478)
@@ -15,7 +15,12 @@
 $Id$
 """
 
+from urllib import quote
+
+from Products.Five import BrowserView
 from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+from zExceptions import Forbidden
+from zExceptions import Redirect
 from zope.app.form.browser import TextWidget
 from zope.formlib import form
 from zope.interface import implements
@@ -23,15 +28,67 @@
 from zope.schema import Bool
 from zope.schema import Choice
 from zope.schema import Password
+from zope.schema import TextLine
 from zope.schema import URI
 from zope.schema.interfaces import ISource
 from zope.site.hooks import getSite
 
+from Products.CMFCore.CookieCrumbler import ATTEMPT_LOGIN
+from Products.CMFCore.CookieCrumbler import ATTEMPT_NONE
 from Products.CMFCore.utils import getToolByName
 from Products.CMFDefault.formlib.form import EditFormBase
 from Products.CMFDefault.utils import Message as _
+from Products.CMFDefault.browser.utils import ViewBase, memoize
 
 
+def _expireAuthCookie(view):
+    try:
+        cctool = getToolByName(view, 'cookie_authentication')
+        method = cctool.getCookieMethod('expireAuthCookie',
+                                        cctool.defaultExpireAuthCookie)
+        method(view.request.response, cctool.auth_cookie)
+    except AttributeError:
+        view.request.response.expireCookie('__ac', path='/')
+
+
+class UnauthorizedView(BrowserView):
+
+    """Exception view for Unauthorized.
+    """
+
+    forbidden_template = ViewPageTemplateFile('templates/forbidden.pt')
+
+    def __call__(self):
+        try:
+            atool = getToolByName(self, 'portal_actions')
+            target = atool.getActionInfo('user/login')['url']
+        except (AttributeError, ValueError):
+            # re-raise the unhandled exception
+            raise self.context
+
+        req = self.request
+        attempt = getattr(req, '_cookie_auth', ATTEMPT_NONE)
+        if attempt not in (ATTEMPT_NONE, ATTEMPT_LOGIN):
+            # An authenticated user was denied access to something.
+            # XXX: hack context to get the right @@standard_macros/page
+            #      why do we get the wrong without this hack?
+            self.context = self.__parent__
+            raise Forbidden(self.forbidden_template())
+
+        _expireAuthCookie(self)
+        came_from = req.get('came_from', None)
+        if came_from is None:
+            came_from = req.get('ACTUAL_URL')
+            query = req.get('QUERY_STRING')
+            if query:
+                # Include the query string in came_from
+                if not query.startswith('?'):
+                    query = '?' + query
+                came_from = came_from + query
+        url = '%s?came_from=%s' % (target, quote(came_from))
+        raise Redirect(url)
+
+
 class NameSource(object):
 
     implements(ISource)
@@ -58,10 +115,9 @@
     came_from = URI(
         required=False)
 
-    name = Choice(
+    name = TextLine(
         title=_(u'Member ID'),
-        description=_(u'Member ID or email address'),
-        source=available_names)
+        description=_(u'Case sensitive'))
 
     password = Password(
         title=_(u'Password'),
@@ -92,43 +148,55 @@
     base_template = EditFormBase.template
     template = ViewPageTemplateFile('templates/login.pt')
     label = _(u'Log in')
+    prefix = ''
 
     form_fields = form.FormFields(ILoginSchema)
-    form_fields['name'].custom_widget = TextWidget
 
     actions = form.Actions(
         form.Action(
             name='login',
             label=_(u'Login'),
+            validator='handle_login_validate',
             success='handle_login_success',
             failure='handle_failure'))
 
     def setUpWidgets(self, ignore_request=False):
-        cctool = self._getTool('cookie_authentication')
-        ac_name = self.request.get(cctool.name_cookie)
-        if ac_name and not self.request.has_key('%s.name' % self.prefix):
-            self.request.form['%s.name' % self.prefix] = ac_name
+        try:
+            cctool = self._getTool('cookie_authentication')
+            ac_name_id = cctool.name_cookie
+            ac_password_id = cctool.pw_cookie
+            ac_persistent_id = cctool.persist_cookie
+        except AttributeError:
+            ac_name_id = '__ac_name'
+            ac_password_id = '__ac_password'
+            ac_persistent_id = '__ac_persistent'
+        ac_name = self.request.get(ac_name_id)
+        if ac_name is not None:
+            self.request.form['name'] = ac_name
+            self.request.form[ac_name_id] = ac_name
+        ac_persistent = self.request.get(ac_persistent_id)
+        if ac_persistent is not None:
+            self.request.form['persistent'] = ac_persistent
+        ac_persistent_used = self.request.get("%s.used" % ac_persistent_id)
+        if ac_persistent_used is not None:
+            self.request.form['persistent.used'] = ac_persistent_used
         super(LoginFormView,
               self).setUpWidgets(ignore_request=ignore_request)
         self.widgets['came_from'].hide = True
+        self.widgets['name'].name = ac_name_id
+        self.widgets['password'].name = ac_password_id
+        self.widgets['persistent'].name = ac_persistent_id
 
+    def handle_login_validate(self, action, data):
+        mtool = self._getTool('portal_membership')
+        if mtool.isAnonymousUser():
+            _expireAuthCookie(self)
+            return (_(u'Login failure'),)
+        return None
+
     def handle_login_success(self, action, data):
-        mtool = self._getTool('portal_membership')
-        if not mtool.getMemberById(data['name']):
-            candidates = mtool.searchMembers('email', data['name'])
-            for candidate in candidates:
-                if candidate['email'].lower() == data['name'].lower():
-                    data['name'] = candidate['username']
-                    break
-        cctool = self._getTool('cookie_authentication')
-        # logged_in uses default charset for decoding
-        charset = self._getDefaultCharset()
-        self.request.form[cctool.name_cookie] = data['name'].encode(charset)
-        self.request.form[cctool.pw_cookie] = data['password'].encode(charset)
-        self.request.form[cctool.persist_cookie] = data['persistent']
-        cctool(self.context, self.request)
         return self._setRedirect('portal_actions', 'user/logged_in',
-                                 '%s.came_from' % self.prefix)
+                                 'came_from')
 
 
 class MailPasswordFormView(EditFormBase):
@@ -154,8 +222,12 @@
             failure='handle_failure'))
 
     def setUpWidgets(self, ignore_request=False):
-        cctool = self._getTool('cookie_authentication')
-        ac_name = self.request.get(cctool.name_cookie)
+        try:
+            cctool = self._getTool('cookie_authentication')
+            ac_name_id = cctool.name_cookie
+        except AttributeError:
+            ac_name_id = '__ac_name'
+        ac_name = self.request.get(ac_name_id)
         if ac_name and not self.request.has_key('%s.name' % self.prefix):
             self.request.form['%s.name' % self.prefix] = ac_name
         super(MailPasswordFormView,
@@ -173,3 +245,32 @@
         rtool.mailPassword(data['name'], self.request)
         self.status = _(u'Your password has been mailed to you.')
         return self._setRedirect('portal_actions', 'user/login')
+
+
+class Logout(ViewBase):
+    """Log the user out"""
+    
+    @memoize
+    def logged_in(self):
+        """Check whether the user is (still logged in)"""
+        mtool = self._getTool('portal_membership')
+        return mtool.isAnonymousUser()
+        
+    @memoize
+    def logout(self):
+        """Log the user out"""
+        _expireAuthCookie(self)
+    
+    @memoize
+    def clear_skin_cookie(self):
+        """Remove skin cookie"""
+        stool = self._getTool('portal_skins')
+        stool.clearSkinCookie()
+    
+    def __call__(self):
+        """Clear cookies and return the template"""
+        if not self.logged_in():
+            self.clear_skin_cookie()
+            self.logout()
+            return self.request.response.redirect(self.request.URL)
+        return super(Logout, self).__call__()

Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml	2010-06-15 10:16:49 UTC (rev 113477)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml	2010-06-15 10:19:43 UTC (rev 113478)
@@ -180,9 +180,26 @@
   <browser:page
       for="Products.CMFCore.interfaces.ISiteRoot"
       layer="..interfaces.ICMFDefaultSkin"
+      name="logout.html"
+      class=".authentication.Logout"
+      template="templates/logged_out.pt"
+      permission="zope2.View"
+      />
+
+  <browser:page
+      for="Products.CMFCore.interfaces.ISiteRoot"
+      layer="..interfaces.ICMFDefaultSkin"
       name="mail_password.html"
       class=".authentication.MailPasswordFormView"
       permission="zope2.View"
       />
 
+  <browser:page
+      for="zExceptions.Unauthorized"
+      layer="..interfaces.ICMFDefaultSkin"
+      name="index.html"
+      class=".authentication.UnauthorizedView"
+      permission="zope.Public"
+      />
+
 </configure>

Copied: Products.CMFDefault/trunk/Products/CMFDefault/browser/templates/forbidden.pt (from rev 113475, Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/templates/forbidden.pt)
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/templates/forbidden.pt	                        (rev 0)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/templates/forbidden.pt	2010-06-15 10:19:43 UTC (rev 113478)
@@ -0,0 +1,18 @@
+<html metal:use-macro="context/@@standard_macros/page">
+<body>
+
+<metal:slot metal:fill-slot="body" i18n:domain="cmf_default">
+<h1 id="DesktopTitle">Site Error</h1>
+
+<p id="DesktopDescription" i18n:translate="">An error was encountered while
+ publishing this resource.</p>
+
+<p><strong><tal:span i18n:translate="">Error Type:</tal:span>
+ <tal:span i18n:translate="">Forbidden</tal:span></strong><br />
+ <strong><tal:span i18n:translate="">Error Value:</tal:span>
+ <tal:span i18n:translate="">You don't have all the permissions necessary
+  to see the requested page.</tal:span></strong></p>
+</metal:slot>
+
+</body>
+</html>

Copied: Products.CMFDefault/trunk/Products/CMFDefault/browser/templates/logged_out.pt (from rev 113475, Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/templates/logged_out.pt)
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/templates/logged_out.pt	                        (rev 0)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/templates/logged_out.pt	2010-06-15 10:19:43 UTC (rev 113478)
@@ -0,0 +1,13 @@
+<html metal:use-macro="context/@@standard_macros/page">
+<body>
+
+<metal:slot metal:fill-slot="body" i18n:domain="cmf_default">
+<p tal:condition="view/logged_in"
+   i18n:translate="">You have been logged out.</p>
+<p tal:condition="not: view/logged_in"
+   i18n:translate="">You are logged in outside the portal. You may need to
+<a href="/manage_zmi_logout">log out of the Zope management interface</a>.</p>
+</metal:slot>
+
+</body>
+</html>

Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/authentication.txt
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/authentication.txt	2010-06-15 10:16:49 UTC (rev 113477)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/authentication.txt	2010-06-15 10:19:43 UTC (rev 113478)
@@ -3,8 +3,10 @@
 
 Set up user.
 
+    >>> from urllib import quote
     >>> uf = app.site.acl_users
-    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
+    >>> uf._doAddUser('mbr', 'mbrpw', ['Member'], [])
+    >>> mbr_credentials = quote('mbr:mbrpw'.encode('base64').rstrip())
 
 Create the browser object we'll be using.
 
@@ -13,9 +15,73 @@
     ...     from Testing.testbrowser import Browser
     ... except ImportError:
     ...     from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+    >>> # XXX: browser has no API for disabling redirects
+    >>> browser.mech_browser.set_handle_redirect(False)
 
+The view for zExceptions.Unauthorized redirects anonymous requests to the
+login_form. This works if raised by the object (here by the reconfig_form).
+
+    >>> browser.open('http://localhost/site/reconfig_form')
+    Traceback (most recent call last):
+    ...
+    HTTPError: HTTP Error 302: Moved Temporarily
+    >>> browser.contents
+    ''
+    >>> browser.headers['Location']
+    'http://localhost/site/login_form?came_from=http%3A//localhost/site/reconfig_form'
+
+And it works if raised by BaseRequest.traverse (here caused by manage_main).
+
+    >>> browser.open('http://localhost/site/manage_main')
+    Traceback (most recent call last):
+    ...
+    HTTPError: HTTP Error 302: Moved Temporarily
+    >>> browser.contents
+    ''
+    >>> browser.headers['Location']
+    'http://localhost/site/login_form?came_from=http%3A//localhost/site/manage_main'
+
+Same redirect with a query string. The query string is preserved.
+
+    >>> browser.open('http://localhost/site/manage_main?a:int=1&x:string=y')
+    Traceback (most recent call last):
+    ...
+    HTTPError: HTTP Error 302: Moved Temporarily
+    >>> browser.contents
+    ''
+    >>> browser.headers['Location']
+    'http://localhost/site/login_form?came_from=http%3A//localhost/site/manage_main%3Fa%3Aint%3D1%26x%3Astring%3Dy'
+    >>> quote('manage_main?a:int=1&x:string=y') in browser.headers['Location']
+    True
+
+And requests are redirected to the login_form if a login attempt fails.
+
+    >>> browser.post('http://localhost/site/manage_main',
+    ...              '__ac_name=mbr&__ac_password=wrong')
+    Traceback (most recent call last):
+    ...
+    HTTPError: HTTP Error 302: Moved Temporarily
+    >>> browser.contents
+    ''
+    >>> browser.headers['Location']
+    'http://localhost/site/login_form?came_from=http%3A//localhost/site/manage_main'
+
+The view for zExceptions.Unauthorized shows a Forbidden error if logged in.
+
+    >>> browser.cookies['__ac'] = '%s' % mbr_credentials
+    >>> browser.open('http://localhost/site/manage_main')
+    Traceback (most recent call last):
+    ...
+    HTTPError: HTTP Error 403: Forbidden
+    >>> 'zpt_stylesheet.css' in browser.contents
+    True
+    >>> '[[cmf_default][Forbidden]]' in browser.contents
+    True
+
+For the following examples we have to reset the browser object.
+
     >>> browser = Browser()
-    >>> browser.handleErrors = False
 
 Use the login form without input.
 
@@ -33,28 +99,34 @@
     >>> browser.getControl('[[cmf_default][Login]]').click()
     >>> '[[zope][There were errors]]' in browser.contents
     True
-    >>> '[[zope][Constraint not satisfied]]' in browser.contents
+    >>> '[[cmf_default][Login failure]]' in browser.contents
     True
 
 Use the login form with valid input but wrong password.
 
     >>> browser.open('http://localhost/site/@@login.html')
-    >>> browser.getControl('[[cmf_default][Member ID]]').value = 'mgr'
+    >>> browser.getControl('[[cmf_default][Member ID]]').value = 'mbr'
     >>> browser.getControl('[[cmf_default][Password]]').value = 'wrong'
     >>> browser.getControl('[[cmf_default][Remember my ID.]]').selected = False
     >>> browser.getControl('[[cmf_default][Login]]').click()
+    >>> '[[zope][There were errors]]' in browser.contents
+    True
     >>> '[[cmf_default][Login failure]]' in browser.contents
     True
+    >>> '__ac' not in browser.cookies
+    True
 
 Use the login form with valid input and correct password.
 
     >>> browser.open('http://localhost/site/@@login.html')
-    >>> browser.getControl('[[cmf_default][Member ID]]').value = 'mgr'
-    >>> browser.getControl('[[cmf_default][Password]]').value = 'mgrpw'
+    >>> browser.getControl('[[cmf_default][Member ID]]').value = 'mbr'
+    >>> browser.getControl('[[cmf_default][Password]]').value = 'mbrpw'
     >>> browser.getControl('[[cmf_default][Remember my ID.]]').selected = False
     >>> browser.getControl('[[cmf_default][Login]]').click()
     >>> '[[cmf_default][Login success]]' in browser.contents
     True
+    >>> browser.cookies['__ac'] == '"%s"' % mbr_credentials
+    True
 
 Use the mail password form without input.
 
@@ -74,3 +146,14 @@
     True
     >>> '[[zope][Constraint not satisfied]]' in browser.contents
     True
+
+Log the user in and then out
+    >>> browser.open('http://localhost/site/@@login.html')
+    >>> browser.getControl('[[cmf_default][Member ID]]').value = 'mbr'
+    >>> browser.getControl('[[cmf_default][Password]]').value = 'mbrpw'
+    >>> browser.getControl('[[cmf_default][Login]]').click()
+    >>> '[[cmf_default][Login success]]' in browser.contents
+    True
+    >>> browser.open('http://localhost/site/@@logout.html')
+    >>> '[cmf_default][You have been logged out.' in browser.contents
+    True
\ No newline at end of file

Modified: Products.CMFDefault/trunk/Products/CMFDefault/profiles/default/cookieauth.xml
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/profiles/default/cookieauth.xml	2010-06-15 10:16:49 UTC (rev 113477)
+++ Products.CMFDefault/trunk/Products/CMFDefault/profiles/default/cookieauth.xml	2010-06-15 10:19:43 UTC (rev 113478)
@@ -4,9 +4,6 @@
  <property name="name_cookie">__ac_name</property>
  <property name="pw_cookie">__ac_password</property>
  <property name="persist_cookie">__ac_persistent</property>
- <property name="auto_login_page">login_form</property>
- <property name="logout_page">logged_out</property>
- <property name="unauth_page"></property>
  <property name="local_cookie_path">False</property>
  <property name="cache_header_value">private</property>
  <property name="log_username">True</property>

Modified: Products.CMFDefault/trunk/Products/CMFDefault/profiles/default/metadata.xml
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/profiles/default/metadata.xml	2010-06-15 10:16:49 UTC (rev 113477)
+++ Products.CMFDefault/trunk/Products/CMFDefault/profiles/default/metadata.xml	2010-06-15 10:19:43 UTC (rev 113478)
@@ -1,4 +1,4 @@
 <?xml version="1.0"?>
 <metadata>
-  <version>2.2</version>
+  <version>2.3</version>
 </metadata>

Modified: Products.CMFDefault/trunk/Products/CMFDefault/skins/zpt_control/logout.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/skins/zpt_control/logout.py	2010-06-15 10:16:49 UTC (rev 113477)
+++ Products.CMFDefault/trunk/Products/CMFDefault/skins/zpt_control/logout.py	2010-06-15 10:19:43 UTC (rev 113478)
@@ -1,8 +1,17 @@
 ## Script (Python) "logout"
 ##title=Logout handler
 ##parameters=
+from Products.CMFCore.utils import getToolByName
+
+stool = getToolByName(context, 'portal_skins')
+utool = getToolByName(context, 'portal_url')
 REQUEST = context.REQUEST
-if REQUEST.has_key('portal_skin'):
-   context.portal_skins.clearSkinCookie()
-REQUEST.RESPONSE.expireCookie('__ac', path='/')
-return REQUEST.RESPONSE.redirect(REQUEST.URL1+'/logged_out')
+
+stool.clearSkinCookie()
+try:
+    cctool = getToolByName(context, 'cookie_authentication')
+    cctool.logout(REQUEST.RESPONSE)
+except AttributeError:
+    REQUEST.RESPONSE.expireCookie('__ac', path='/')
+
+return REQUEST.RESPONSE.redirect(utool() + '/logged_out')

Modified: Products.CMFDefault/trunk/Products/CMFDefault/upgrade/configure.zcml
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/upgrade/configure.zcml	2010-06-15 10:16:49 UTC (rev 113477)
+++ Products.CMFDefault/trunk/Products/CMFDefault/upgrade/configure.zcml	2010-06-15 10:19:43 UTC (rev 113478)
@@ -181,4 +181,28 @@
       sortkey="6"
       />
 
+  <genericsetup:upgradeSteps
+      source="2.2"
+      destination="2.3"
+      profile="Products.CMFDefault:default"
+      sortkey="7">
+
+    <genericsetup:upgradeStep
+        title="Upgrade cookie crumbler"
+        description="Remove obsolete cookie crumbler properties."
+        handler=".to23.upgrade_cookie_crumbler"
+        checker=".to23.check_cookie_crumbler"
+        />
+
+  </genericsetup:upgradeSteps>
+
+  <genericsetup:upgradeStep
+      title="Mark 2.3 upgrade as finished"
+      source="2.2"
+      destination="2.3"
+      profile="Products.CMFDefault:default"
+      handler=".mark_as_finished"
+      sortkey="8"
+      />
+
 </configure>

Modified: Products.CMFDefault/trunk/Products/CMFDefault/upgrade/tests/test_upgrade.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/upgrade/tests/test_upgrade.py	2010-06-15 10:16:49 UTC (rev 113477)
+++ Products.CMFDefault/trunk/Products/CMFDefault/upgrade/tests/test_upgrade.py	2010-06-15 10:19:43 UTC (rev 113478)
@@ -70,7 +70,7 @@
         stool.manage_doUpgrades(request)
 
         self.assertEqual(stool.getLastVersionForProfile(profile_id),
-                         ('2', '2'))
+                         ('2', '3'))
 
         newSecurityManager(None, UnrestrictedUser('god', '', ['Manager'], ''))
         setSite(self.app.site)

Copied: Products.CMFDefault/trunk/Products/CMFDefault/upgrade/to23.py (from rev 113475, Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/upgrade/to23.py)
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/upgrade/to23.py	                        (rev 0)
+++ Products.CMFDefault/trunk/Products/CMFDefault/upgrade/to23.py	2010-06-15 10:19:43 UTC (rev 113478)
@@ -0,0 +1,47 @@
+##############################################################################
+#
+# Copyright (c) 2010 Zope Foundation and Contributors.
+#
+# 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.
+#
+##############################################################################
+"""Upgrade steps to CMFDefault 2.3.
+
+$Id$
+"""
+import logging
+
+from Acquisition import aq_base
+from Products.CMFCore.utils import getToolByName
+
+_MARKER = object()
+
+def check_cookie_crumbler(tool):
+    """2.2.x to 2.3.0 upgrade step checker
+    """
+    cctool = getToolByName(tool, 'cookie_authentication', None)
+    if cctool is None:
+        return False
+    cctool = aq_base(cctool)
+    for name in ('auto_login_page', 'unauth_page', 'logout_page'):
+        if getattr(cctool, name, _MARKER) is not _MARKER:
+            return True
+    return False
+
+def upgrade_cookie_crumbler(tool):
+    """2.2.x to 2.3.0 upgrade step handler
+    """
+    logger = logging.getLogger('GenericSetup.upgrade')
+    cctool = getToolByName(tool, 'cookie_authentication', None)
+    if cctool is None:
+        return
+    cctool = aq_base(cctool)
+    for name in ('auto_login_page', 'unauth_page', 'logout_page'):
+        if getattr(cctool, name, _MARKER) is not _MARKER:
+            delattr(cctool, name)
+            logger.info("Cookie crumbler property '%s' removed." % name)



More information about the checkins mailing list