[Checkins] SVN: Products.CMFDefault/branches/cookiecrumbler_with_views/ modernizing CookieCrumbler

Yvo Schubbe y.2010 at wcm-solutions.de
Fri Apr 23 12:27:25 EDT 2010


Log message for revision 111308:
  modernizing CookieCrumbler

Changed:
  A   Products.CMFDefault/branches/cookiecrumbler_with_views/
  U   Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/authentication.py
  U   Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/configure.zcml
  A   Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/templates/forbidden.pt
  U   Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/tests/authentication.txt

-=-
Modified: Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/authentication.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/authentication.py	2010-04-23 16:02:22 UTC (rev 111307)
+++ Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/authentication.py	2010-04-23 16:27:25 UTC (rev 111308)
@@ -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
@@ -27,11 +32,61 @@
 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 _
 
 
+class UnauthorizedView(BrowserView):
+
+    """Exception view for Unauthorized.
+    """
+
+    forbidden_template = ViewPageTemplateFile('templates/forbidden.pt')
+
+    def __call__(self):
+        try:
+            cctool = getToolByName(self, 'cookie_authentication')
+            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 == ATTEMPT_NONE:
+            # An anonymous user was denied access to something.
+            retry = ''
+        elif attempt == ATTEMPT_LOGIN:
+            # The login attempt failed.  Try again.
+            retry = '1'
+        else:
+            # 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())
+
+        if req.response.cookies.has_key(cctool.auth_cookie):
+            del req.response.cookies[cctool.auth_cookie]
+
+        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&retry=%s&disable_cookie_login__=1' % (
+            target, quote(came_from), retry)
+        raise Redirect(url)
+
+
 class NameSource(object):
 
     implements(ISource)

Modified: Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/configure.zcml
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml	2010-04-23 16:02:22 UTC (rev 111307)
+++ Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/configure.zcml	2010-04-23 16:27:25 UTC (rev 111308)
@@ -185,4 +185,12 @@
       permission="zope2.View"
       />
 
+  <browser:page
+      for="zExceptions.Unauthorized"
+      layer="..interfaces.ICMFDefaultSkin"
+      name="index.html"
+      class=".authentication.UnauthorizedView"
+      permission="zope.Public"
+      />
+
 </configure>

Added: Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/templates/forbidden.pt
===================================================================
--- Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/templates/forbidden.pt	                        (rev 0)
+++ Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/templates/forbidden.pt	2010-04-23 16:27:25 UTC (rev 111308)
@@ -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>


Property changes on: Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/templates/forbidden.pt
___________________________________________________________________
Added: svn:eol-style
   + native

Modified: Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/tests/authentication.txt
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/authentication.txt	2010-04-23 16:02:22 UTC (rev 111307)
+++ Products.CMFDefault/branches/cookiecrumbler_with_views/Products/CMFDefault/browser/tests/authentication.txt	2010-04-23 16:27:25 UTC (rev 111308)
@@ -3,15 +3,60 @@
 
 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.
 
-    >>> from Products.Five.testbrowser import Browser
+    >>> try:
+    ...     from Testing.testbrowser import Browser
+    ... except ImportError: # BBB: for Zope 2.12
+    ...     from Products.Five.testbrowser import Browser
     >>> browser = Browser()
-    >>> browser.handleErrors = False
+    >>> # 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&retry=&disable_cookie_login__=1'
+
+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&retry=&disable_cookie_login__=1'
+
+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()
+
 Use the login form without input.
 
     >>> browser.open('http://localhost/site/@@login.html')
@@ -34,22 +79,26 @@
 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()
     >>> '[[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.
 



More information about the checkins mailing list