[Checkins] SVN: z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/ added viewlet manager for html head containing JavaScript basic auth logout and redirect

Michael Howitz mh at gocept.com
Fri Mar 13 17:16:22 EDT 2009


Log message for revision 98050:
  added viewlet manager for html head containing JavaScript basic auth logout and redirect
  

Changed:
  U   z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/auth.py
  A   z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/logout_head.pt
  A   z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/redirect_head.pt
  U   z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/zope.app.security.browser.zcml
  U   z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/login.txt
  U   z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/tests/__init__.py
  U   z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/tests/ftesting.zcml
  U   z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/tests/login-logout-template.pt

-=-
Modified: z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/auth.py
===================================================================
--- z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/auth.py	2009-03-13 20:51:24 UTC (rev 98049)
+++ z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/auth.py	2009-03-13 21:16:22 UTC (rev 98050)
@@ -33,6 +33,14 @@
 _ = zope.i18nmessageid.MessageFactory("z3c")
 
 
+class ILoginLogoutHeadViewletManager(zope.viewlet.interfaces.IViewletManager):
+    """ViewletManager for supporting header contents (e. g. JavaScript)."""
+
+
+LoginLogoutHeadViewletManager = zope.viewlet.manager.ViewletManager(
+    'login-logout-head', ILoginLogoutHeadViewletManager)
+
+
 class ILoginLogoutViewletManager(zope.viewlet.interfaces.IViewletManager):
     """ViewletManager for login and logout viewlets."""
 

Added: z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/logout_head.pt
===================================================================
--- z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/logout_head.pt	                        (rev 0)
+++ z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/logout_head.pt	2009-03-13 21:16:22 UTC (rev 98050)
@@ -0,0 +1,16 @@
+<script type="text/javascript"><!--
+  // clear HTTP Authentication
+  try {
+    if (window.XMLHttpRequest) {
+      var xmlhttp = new XMLHttpRequest();
+      // Send invalid credentials, then abort
+      xmlhttp.open("GET", "@@", true, "logout", "logout");
+      xmlhttp.send("");
+      xmlhttp.abort();
+    } else if (document.execCommand) {
+      // IE specific command
+      document.execCommand("ClearAuthenticationCache");
+    }
+  } catch(e) { }
+  //-->
+</script>


Property changes on: z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/logout_head.pt
___________________________________________________________________
Added: svn:keywords
   + Id Rev Date
Added: svn:eol-style
   + native

Added: z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/redirect_head.pt
===================================================================
--- z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/redirect_head.pt	                        (rev 0)
+++ z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/redirect_head.pt	2009-03-13 21:16:22 UTC (rev 98050)
@@ -0,0 +1,2 @@
+<meta http-equiv="refresh" content="0;url=./"
+      tal:attributes="content string:0;;url=${request/nextURL}" />


Property changes on: z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/redirect_head.pt
___________________________________________________________________
Added: svn:keywords
   + Id Rev Date
Added: svn:eol-style
   + native

Modified: z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/zope.app.security.browser.zcml
===================================================================
--- z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/zope.app.security.browser.zcml	2009-03-13 20:51:24 UTC (rev 98049)
+++ z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/browser/zope.app.security.browser.zcml	2009-03-13 21:16:22 UTC (rev 98050)
@@ -4,122 +4,167 @@
    xmlns:z3c="http://namespaces.zope.org/z3c"
    i18n_domain="z3c">
 
-  <!-- viewlets for login and logout links -->
+  <!-- viewlets in head tag supporting login and logout
+       (viewlets are defined together with the pagelets below) -->
   <browser:viewletManager
+     provides=".auth.ILoginLogoutHeadViewletManager"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
+     name="login-logout-head"
+     class=".auth.LoginLogoutHeadViewletManager"
+     permission="zope.Public"
+     />
+
+  <!-- viewlet manager and viewlets for login and logout links -->
+  <browser:viewletManager
+     provides=".auth.ILoginLogoutViewletManager"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      name="login-logout"
-     provides=".auth.ILoginLogoutViewletManager"
      class=".auth.LoginLogoutViewletManager"
-     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      permission="zope.Public"
      />
 
   <browser:viewlet
      manager=".auth.ILoginLogoutViewletManager"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      name="Login"
-     for="*"
      class=".auth.LoginViewlet"
      permission="zope.Public"
-     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      weight="1"
      viewName="@@login.html"
      />
 
   <browser:viewlet
      manager=".auth.ILoginLogoutViewletManager"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      name="Logout"
-     for="*"
      class=".auth.LogoutViewlet"
      permission="zope.Public"
-     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      weight="2"
      viewName="@@logout.html"
      />
 
+  <!-- login page (executing login and redirecting user) -->
   <browser:page
-     name="logout.html"
      for="*"
-     class=".auth.HTTPAuthenticationLogout"
-     attribute="logout"
-     permission="zope.Public"
-     allowed_interface="zope.app.publisher.interfaces.http.ILogout"
      layer="z3c.layer.pagelet.IPageletBrowserLayer"
-     />
-
-  <browser:page
      name="login.html"
-     for="*"
      class=".auth.HTTPAuthenticationLogin"
      attribute="login"
+     allowed_interface="zope.app.publisher.interfaces.http.ILogin"
      permission="zope.Public"
-     allowed_interface="zope.app.publisher.interfaces.http.ILogin"
+     />
+
+  <!-- login form for session credentials  -->
+  <z3c:pagelet
+     for="*"
      layer="z3c.layer.pagelet.IPageletBrowserLayer"
+     name="loginForm.html"
+     class=".auth.SessionCredentialsLoginForm"
+     permission="zope.Public"
      />
 
+  <z3c:template
+     for=".auth.SessionCredentialsLoginForm"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
+     template="session_cred_loginform.pt"
+     />
+
+  <!-- login failed -->
   <z3c:pagelet
+     for=".auth.HTTPAuthenticationLogin"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      name="login_failed.html"
      class=".auth.LoginFailedPagelet"
      permission="zope.Public"
-     for=".auth.HTTPAuthenticationLogin"
      />
 
   <z3c:template
      for=".auth.LoginFailedPagelet"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      template="login_failed.pt"
-     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      />
 
+  <!-- login success confirmation -->
   <z3c:pagelet
+     for=".auth.HTTPAuthenticationLogin"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      name="login_success.html"
      class=".auth.LoginSuccessfulPagelet"
      permission="zope.Public"
-     for=".auth.HTTPAuthenticationLogin"
      />
 
   <z3c:template
      for=".auth.LoginSuccessfulPagelet"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      template="login_success.pt"
+     />
+
+  <!-- logout page (executing logout and redirecting user) -->
+  <browser:page
+     for="*"
      layer="z3c.layer.pagelet.IPageletBrowserLayer"
+     name="logout.html"
+     class=".auth.HTTPAuthenticationLogout"
+     attribute="logout"
+     allowed_interface="zope.app.publisher.interfaces.http.ILogout"
+     permission="zope.Public"
      />
 
+  <!-- redirecting logout confirmation -->
   <z3c:pagelet
+     for=".auth.HTTPAuthenticationLogout"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      name="redirect.html"
      class=".auth.LogoutRedirectPagelet"
      permission="zope.Public"
-     for=".auth.HTTPAuthenticationLogout"
      />
 
   <z3c:template
      for=".auth.LogoutRedirectPagelet"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      template="redirect.pt"
+     />
+
+  <browser:viewlet
+     manager=".auth.ILoginLogoutHeadViewletManager"
      layer="z3c.layer.pagelet.IPageletBrowserLayer"
+     view=".auth.LogoutRedirectPagelet"
+     name="Redirect"
+     template="redirect_head.pt"
+     permission="zope.Public"
      />
 
+  <browser:viewlet
+     manager=".auth.ILoginLogoutHeadViewletManager"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
+     view=".auth.LogoutRedirectPagelet"
+     name="Logout"
+     template="logout_head.pt"
+     permission="zope.Public"
+     />
+
+  <!-- not redirecting logout confirmation -->
   <z3c:pagelet
+     for=".auth.HTTPAuthenticationLogout"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      name="logout_success.html"
      class=".auth.LogoutSuccessPagelet"
      permission="zope.Public"
-     for=".auth.HTTPAuthenticationLogout"
      />
 
   <z3c:template
      for=".auth.LogoutSuccessPagelet"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      template="logout.pt"
-     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      />
 
-  <!-- login form for session credentials  -->
-  <z3c:pagelet
-     name="loginForm.html"
-     for="*"
-     class=".auth.SessionCredentialsLoginForm"
+  <browser:viewlet
+     manager=".auth.ILoginLogoutHeadViewletManager"
+     layer="z3c.layer.pagelet.IPageletBrowserLayer"
+     view=".auth.LogoutSuccessPagelet"
+     name="Logout"
+     template="logout_head.pt"
      permission="zope.Public"
-     layer="z3c.layer.pagelet.IPageletBrowserLayer"
      />
 
-  <z3c:template
-     for=".auth.SessionCredentialsLoginForm"
-     layer="z3c.layer.pagelet.IPageletBrowserLayer"
-     template="session_cred_loginform.pt"
-     />
-
 </configure>

Modified: z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/login.txt
===================================================================
--- z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/login.txt	2009-03-13 20:51:24 UTC (rev 98049)
+++ z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/login.txt	2009-03-13 21:16:22 UTC (rev 98050)
@@ -7,10 +7,17 @@
 Setup
 ~~~~~
 
-To get login resp. logout links, the layout page template has to
-include the login-logout viewlet manger. Our sample template looks
-like this:
+The layout page template has to include two content providers (viewlet
+mangers):
 
+  - ``login-logout-head`` inside the head tag to get automatic
+    redirects and JavaScript code which does the logout for basic
+    auth and
+
+  - ``login-logout`` inside the body tag to get login and logout links.
+
+The sample template looks like this:
+
   >>> import os.path
   >>> template_path = os.path.join(os.path.dirname(__file__), "tests",
   ...     "login-logout-template.pt")
@@ -19,14 +26,16 @@
   <html ...>
     <head>
       <title>PageletTest</title>
+      <tal:block replace="structure provider:login-logout-head" />
     </head>
     <body>
       <tal:block replace="structure provider:login-logout" />
+      <tal:block replace="structure provider:pagelet" />
     </body>
   </html>
 
-This template is registered for the ``IContainer`` interface in the
-``ftesting.zcml`` file. After creating a container the template is
+This template is registered for the ``IContainer`` interface in
+``ftesting.zcml``. After creating a container the template is
 used when browsing the container:
 
   >>> from zope.container.btree import BTreeContainer
@@ -40,6 +49,7 @@
   >>> from zope.testbrowser.testing import Browser
   >>> skinURL = 'http://localhost/++skin++PageletTestSkin/'
   >>> browser = Browser()
+  >>> browser.handleErrors = False
   >>> browser.open(skinURL + 'container/@@default.html')
   >>> browser.url
   'http://localhost/++skin++PageletTestSkin/container/@@default.html'
@@ -163,21 +173,36 @@
     </body>
   </html>
 
-Logout is done using JavaScript and a redirect. As testbrowser is not
-able to execute JavaScript the user remains authenticated:
+Logout is done using JavaScript and a redirect. zope.testbrowser
+follows the redirects even if they use the meta tag instead of the
+status code. So I have to use a non API call to change this behavior
+to show the file contents:
 
+  >>> browser.mech_browser.set_handle_refresh(False)
+
+As testbrowser is not able to execute JavaScript the user remains
+authenticated:
+
+  >>> logout_url = browser.getLink('Logout').url
   >>> browser.getLink('Logout').click()
-  >>> logout_url = browser.url
-  >>> logout_url
+  >>> browser.url
   'http://localhost/++skin++PageletTestSkin/container/@@logout.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40default.html'
   >>> print browser.contents
   <!DOCTYPE ...>
   <html ...>
-  <head>
-  <title>PageletTestLayout</title>
-  </head>
-  <body>
-    <div>
+    <head>
+      <title>PageletTest</title>
+      <script type="text/javascript"><!--
+    // clear HTTP Authentication
+    ...
+    //-->
+  </script>
+  <meta http-equiv="refresh"
+        content="0;url=http://localhost/++skin++PageletTestSkin/container/@@default.html" />
+    </head>
+    <body>
+      <a href="http://localhost/++skin++PageletTestSkin/container/@@logout.html/@@logout.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40logout.html">Logout</a>
+      <div>
     <h1>You are being redirected!</h1>
     <p style="font-size: 150%">
       <a href="http://localhost/++skin++PageletTestSkin/container/@@default.html">
@@ -185,7 +210,7 @@
       </a>
     </p>
   </div>
-  </body>
+    </body>
   </html>
 
 Calling the logout URL again after logout (simulated using a new
@@ -214,16 +239,24 @@
   >>> print browser2.contents
   <!DOCTYPE ...>
   <html ...>
-  <head>
-  <title>PageletTestLayout</title>
-  </head>
-  <body>
-    <div>
-      <h1>Logout successful!</h1>
-      <p style="font-size: 200%"> You are now logged out. </p>
-      <a href=".">Back to the main page.</a>
-    </div>
-  </body>
+    <head>
+      <title>PageletTest</title>
+      <script type="text/javascript"><!--
+    // clear HTTP Authentication
+    ...
+    //-->
+  </script>
+    </head>
+    <body>
+      <a href="http://localhost/++skin++PageletTestSkin/container/logout.html/@@login.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40logout.html">Login</a>
+      <div>
+    <h1>Logout successful!</h1>
+    <p style="font-size: 200%">
+      You are now logged out.
+    </p>
+    <a href=".">Back to the main page.</a>
+  </div>
+    </body>
   </html>
 
 
@@ -482,26 +515,38 @@
 
 Selecting the displayed logout link drops authentication information
 and displays a confirmation page, which redirects to the default page
-where the login link is displayed again:
+where the login link is displayed again (as redirection is done
+automatically by testbrowser I have to use the non API call trick
+again to show the displayed page):
 
+  >>> browser.mech_browser.set_handle_refresh(False)
   >>> logout_url = browser.getLink('Logout').url
   >>> browser.getLink('Logout').click()
   >>> print browser.contents
   <!DOCTYPE ...>
   <html ...>
-  <head>
-  <title>PageletTestLayout</title>
-  </head>
-  <body>
-    <div>
+    <head>
+      <title>PageletTest</title>
+      <script type="text/javascript"><!--
+    // clear HTTP Authentication
+    ...
+    //-->
+  </script>
+  <meta http-equiv="refresh"
+        content="0;url=http://localhost/++skin++PageletTestSkin/container/@@default.html" />
+    </head>
+    <body>
+      <a href="http://localhost/++skin++PageletTestSkin/container/@@logout.html/@@logout.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40logout.html">Logout</a>
+      <div>
     <h1>You are being redirected!</h1>
+  <BLANKLINE>
     <p style="font-size: 150%">
       <a href="http://localhost/++skin++PageletTestSkin/container/@@default.html">
         If you see this screen for more than 5 seconds, click here.
       </a>
     </p>
   </div>
-  </body>
+    </body>
   </html>
   >>> browser.getLink('If you see this screen for more than 5 seconds').click()
   >>> print browser.contents
@@ -514,6 +559,7 @@
       <a href="http://localhost/++skin++PageletTestSkin/container/@@login.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40default.html">Login</a>
     </body>
   </html>
+  >>> browser.mech_browser.set_handle_refresh(True)
 
 Calling the logout URL again after logout leads directly to the page
 referred in nextURL:
@@ -541,14 +587,22 @@
   >>> print browser.contents
   <!DOCTYPE ...>
   <html ...>
-  <head>
-  <title>PageletTestLayout</title>
-  </head>
-  <body>
-    <div>
-      <h1>Logout successful!</h1>
-      <p style="font-size: 200%"> You are now logged out. </p>
-      <a href=".">Back to the main page.</a>
-    </div>
-  </body>
+    <head>
+      <title>PageletTest</title>
+      <script type="text/javascript"><!--
+    // clear HTTP Authentication
+    ...
+    //-->
+  </script>
+    </head>
+    <body>
+      <a href="http://localhost/++skin++PageletTestSkin/container/logout.html/@@login.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40logout.html">Login</a>
+      <div>
+    <h1>Logout successful!</h1>
+    <p style="font-size: 200%">
+      You are now logged out.
+    </p>
+    <a href=".">Back to the main page.</a>
+  </div>
+    </body>
   </html>

Modified: z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/tests/__init__.py
===================================================================
--- z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/tests/__init__.py	2009-03-13 20:51:24 UTC (rev 98049)
+++ z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/tests/__init__.py	2009-03-13 21:16:22 UTC (rev 98050)
@@ -58,5 +58,10 @@
     def __call__(self):
         return str([type(x) for x in self.context.values()])
 
+
 class LoginLogoutPage(browser.BrowserPagelet):
     """Login and logout page."""
+
+    # make sure the pagelet renders no content, as this is not what we
+    # want to show with this pagelet
+    template = lambda self: ''

Modified: z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/tests/ftesting.zcml
===================================================================
--- z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/tests/ftesting.zcml	2009-03-13 20:51:24 UTC (rev 98049)
+++ z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/tests/ftesting.zcml	2009-03-13 21:16:22 UTC (rev 98050)
@@ -149,6 +149,19 @@
        layer="z3c.layer.pagelet.IPageletBrowserLayer"
        />
 
+    <!-- use tempate with head slot for logout pagelets -->
+    <z3c:layout
+        for="..browser.auth.LogoutRedirectPagelet"
+        layer="z3c.layer.pagelet.IPageletBrowserLayer"
+        template="login-logout-template.pt"
+        />
+
+    <z3c:layout
+        for="..browser.auth.LogoutSuccessPagelet"
+        layer="z3c.layer.pagelet.IPageletBrowserLayer"
+        template="login-logout-template.pt"
+        />
+
   </configure>
 
 

Modified: z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/tests/login-logout-template.pt
===================================================================
--- z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/tests/login-logout-template.pt	2009-03-13 20:51:24 UTC (rev 98049)
+++ z3c.layer.pagelet/branches/icemac_login_support/src/z3c/layer/pagelet/tests/login-logout-template.pt	2009-03-13 21:16:22 UTC (rev 98050)
@@ -2,8 +2,10 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   <head>
     <title>PageletTest</title>
+    <tal:block replace="structure provider:login-logout-head" />
   </head>
   <body>
     <tal:block replace="structure provider:login-logout" />
+    <tal:block replace="structure provider:pagelet" />
   </body>
 </html>



More information about the Checkins mailing list