[Checkins] SVN: z3c.authentication/trunk/src/z3c/authentication/cookie/ Last try to implement a life time cookie login

Roger Ineichen roger at projekt01.ch
Sat Nov 4 20:23:36 EST 2006


Log message for revision 71076:
  Last try to implement a life time cookie login 
  with the option to select between auto login based 
  on a life time cookie or login for each browser session.
  
  Note:
  Don't add the default browser client id manager 
  and the life time session client id manager in 
  the same site manager. This will end in mess up 
  the cookie generation. See the configurator adapter
  for a sample setup.

Changed:
  U   z3c.authentication/trunk/src/z3c/authentication/cookie/BROWSER.txt
  U   z3c.authentication/trunk/src/z3c/authentication/cookie/README.txt
  U   z3c.authentication/trunk/src/z3c/authentication/cookie/configurator.py
  U   z3c.authentication/trunk/src/z3c/authentication/cookie/configure.zcml
  U   z3c.authentication/trunk/src/z3c/authentication/cookie/interfaces.py
  U   z3c.authentication/trunk/src/z3c/authentication/cookie/plugin.py
  U   z3c.authentication/trunk/src/z3c/authentication/cookie/session.py
  U   z3c.authentication/trunk/src/z3c/authentication/cookie/testing.py
  U   z3c.authentication/trunk/src/z3c/authentication/cookie/tests.py

-=-
Modified: z3c.authentication/trunk/src/z3c/authentication/cookie/BROWSER.txt
===================================================================
--- z3c.authentication/trunk/src/z3c/authentication/cookie/BROWSER.txt	2006-11-05 01:16:14 UTC (rev 71075)
+++ z3c.authentication/trunk/src/z3c/authentication/cookie/BROWSER.txt	2006-11-05 01:23:34 UTC (rev 71076)
@@ -30,8 +30,8 @@
 Let's test the different utilities:
 
   >>> tuple(default.keys())
-  (u'CookieClientIdManager', u'CookieCredentialSessionDataContainer',...
-  u'PluggableAuthentication')
+  (u'CookieCredentialSessionDataContainer', u'LifeTimeSessionClientIdManager', 
+   u'PluggableAuthentication')
 
 Check if the PAU contains a liftime cookie session credential:
 
@@ -45,10 +45,12 @@
   >>> pau.credentialsPlugins
   (u'Z3C Cookie Credentials',)
 
-We also need to check if we got a own CookieClientIdManager which the 
-liftime is set to o (zero) whichmeans it never will expire.
+We also need to check if we got a own ICookieClientIdManager which the 
+cookieLifetime is set to 0 (zero) which means it never will expire. This 
+cookie client id manager is called LifeTimeSessionClientIdManager:
 
-  >>> ccim = default['CookieClientIdManager']
+  >>> rootDefault = traverse(root, '++etc++site/default')
+  >>> ccim = default['LifeTimeSessionClientIdManager']
   >>> ccim.cookieLifetime
   0
 

Modified: z3c.authentication/trunk/src/z3c/authentication/cookie/README.txt
===================================================================
--- z3c.authentication/trunk/src/z3c/authentication/cookie/README.txt	2006-11-05 01:16:14 UTC (rev 71075)
+++ z3c.authentication/trunk/src/z3c/authentication/cookie/README.txt	2006-11-05 01:23:34 UTC (rev 71076)
@@ -42,8 +42,8 @@
   >>> sm = zope.component.getSiteManager(siteStub)
   >>> default = sm['default']
   >>> tuple(default.keys())
-  (u'CookieClientIdManager', u'CookieCredentialSessionDataContainer',...
-  u'PluggableAuthentication')
+  (u'CookieCredentialSessionDataContainer', u'LifeTimeSessionClientIdManager', 
+   u'PluggableAuthentication')
 
 Check if the PAU contains a liftime cookie session credential:
 
@@ -57,10 +57,11 @@
   >>> pau.credentialsPlugins
   (u'Z3C Cookie Credentials',)
 
-We also need to check if we got a own CookieClientIdManager which the 
-liftime is set to o (zero) whichmeans it never will expire.
+We also need to check if we got a own ICookieClientIdManager which the 
+cookieLifetime is set to 0 (zero) which means it never will expire. This 
+cookie client id manager is called LifeTimeSessionClientIdManager:
 
-  >>> ccim = default['CookieClientIdManager']
+  >>> ccim = default['LifeTimeSessionClientIdManager']
   >>> ccim.cookieLifetime
   0
 
@@ -82,4 +83,6 @@
   <z3c.authentication.cookie.session.CookieCredentialSessionDataContainer ...>
 
   >>> ccsdc.timeout
-  0
\ No newline at end of file
+  0
+
+See also BROWSER.txt for additional tests.

Modified: z3c.authentication/trunk/src/z3c/authentication/cookie/configurator.py
===================================================================
--- z3c.authentication/trunk/src/z3c/authentication/cookie/configurator.py	2006-11-05 01:16:14 UTC (rev 71075)
+++ z3c.authentication/trunk/src/z3c/authentication/cookie/configurator.py	2006-11-05 01:23:34 UTC (rev 71076)
@@ -80,10 +80,11 @@
         sm.registerUtility(ccsdc, ISessionDataContainer, 
             interfaces.SESSION_KEY)
 
-        # setup cookie client id manager
+        # setup lifetime session cookie client id manager
         ccim = CookieClientIdManager()
         # Expiry time of 0 means never (well - close enough)
         ccim.cookieLifetime = 0
         zope.event.notify(zope.lifecycleevent.ObjectCreatedEvent(ccim))
-        default['CookieClientIdManager'] = ccim
-        sm.registerUtility(ccim, IClientIdManager)
+        default['LifeTimeSessionClientIdManager'] = ccim
+        sm.registerUtility(ccim, IClientIdManager, 
+            name='LifeTimeSessionClientIdManager')

Modified: z3c.authentication/trunk/src/z3c/authentication/cookie/configure.zcml
===================================================================
--- z3c.authentication/trunk/src/z3c/authentication/cookie/configure.zcml	2006-11-05 01:16:14 UTC (rev 71075)
+++ z3c.authentication/trunk/src/z3c/authentication/cookie/configure.zcml	2006-11-05 01:23:34 UTC (rev 71076)
@@ -2,6 +2,11 @@
     xmlns="http://namespaces.zope.org/zope"
     i18n_domain="z3c">
 
+  <class class=".session.LifeTimeSession">
+    <allow interface="zope.app.session.interfaces.ISession" />
+    <implements interface="zope.traversing.interfaces.IPathAdapter" />
+  </class>
+
   <class class=".session.CookieCredentialSessionDataContainer">
     <require
         interface="zope.app.session.interfaces.ISessionDataContainer"
@@ -38,6 +43,17 @@
         />
   </class>
 
+  <adapter
+      factory=".session.LifeTimeClientId"
+      permission="zope.Public" 
+      />
+
+  <adapter
+      factory=".session.LifeTimeSession"
+      provides=".interfaces.ILifeTimeSession"
+      permission="zope.Public"
+      />
+
   <include package=".browser" />
 
 </configure>

Modified: z3c.authentication/trunk/src/z3c/authentication/cookie/interfaces.py
===================================================================
--- z3c.authentication/trunk/src/z3c/authentication/cookie/interfaces.py	2006-11-05 01:16:14 UTC (rev 71075)
+++ z3c.authentication/trunk/src/z3c/authentication/cookie/interfaces.py	2006-11-05 01:23:34 UTC (rev 71076)
@@ -19,13 +19,35 @@
 import zope.interface
 import zope.schema
 from zope.app.session.interfaces import ISessionDataContainer
+from zope.app.session.interfaces import ISession
+from zope.app.session.interfaces import IClientId
 from zope.app.authentication import interfaces
 from zope.app.authentication import session
+
 from z3c.i18n import MessageFactory as _
 
 SESSION_KEY = 'z3c.authentication.cookie.ICookieCredentialSessionDataContainer'
 
+# The BROWSER_SESSION_KEY is a optional session key on which you can register 
+# a own ISessionDataContainer, if there is no such named utility, the default 
+# unnamed ISessionDataContainer is used. This fallback pattern is provided in
+# ISession._sdc
+BROWSER_SESSION_KEY = 'z3c.authentication.cookie.IBrowserSession-DataContainer'
 
+
+class ILifeTimeClientId(IClientId):
+    """Life time session client id."""
+
+
+class ILifeTimeSession(ISession):
+    """Session valid over a long time.
+    
+    Note this session requires a IClientIdManager configured with a 
+    ``cookieLifetime = 0`` registered as a named utility with a 
+    ``name = LifeTimeSessionClientIdManager``.
+    """
+
+
 class ICookieCredentialSessionDataContainer(ISessionDataContainer):
     """A persistent cookie credential container."""
 

Modified: z3c.authentication/trunk/src/z3c/authentication/cookie/plugin.py
===================================================================
--- z3c.authentication/trunk/src/z3c/authentication/cookie/plugin.py	2006-11-05 01:16:14 UTC (rev 71075)
+++ z3c.authentication/trunk/src/z3c/authentication/cookie/plugin.py	2006-11-05 01:23:34 UTC (rev 71076)
@@ -99,9 +99,9 @@
 
     Check if we get the initial login session flag:
 
-    >>> session = ISession(request)
-    >>> sessionData = session[interfaces.SESSION_KEY]
-    >>> sessionData.get('initialLogin', False)
+    >>> browserSession = ISession(request)
+    >>> browserSessionData = browserSession[interfaces.BROWSER_SESSION_KEY]
+    >>> browserSessionData.get('initialLogin', False)
     True
 
     Subsequent requests now have access to the credentials even if they're
@@ -112,14 +112,14 @@
 
     See if the initial login session is still there:
 
-    >>> sessionData.get('initialLogin', False)
+    >>> browserSessionData.get('initialLogin', False)
     True
 
     The initial login session didn't get set because we didn't use the 
     autologin field. Let's try use the autologin field and check the session.
 
     >>> request = TestRequest(login='scott', password='tiger', autologin='on')
-    >>> sessionData.get('initialLogin', False)
+    >>> browserSessionData.get('initialLogin', False)
     True
 
     We can always provide new credentials explicitly in the request:
@@ -157,7 +157,7 @@
 
     After a logout the initial login session flag must be disabled:
     
-    >>> sessionData.get('initialLogin', False)
+    >>> browserSessionData.get('initialLogin', False)
     False
 
     """
@@ -172,8 +172,13 @@
         """Extracts credentials from a session if they exist."""
         if not IHTTPRequest.providedBy(request):
             return None
-        session = ISession(request, None)
-        sessionData = session.get(interfaces.SESSION_KEY)
+
+        lifeTimeSession = interfaces.ILifeTimeSession(request, None)
+        browserSession = ISession(request, None)
+        
+        lifeTimeSessionData = lifeTimeSession.get(interfaces.SESSION_KEY)
+        browserSessionData = browserSession.get(interfaces.BROWSER_SESSION_KEY)
+
         login = request.get(self.loginfield, None)
         password = request.get(self.passwordfield, None)
         autologin = request.get(self.autologinfield, None)
@@ -183,34 +188,38 @@
         if login and password:
             credentials = CookieCredentials(login, password)
             # first or relogin login
+            
             if autologin:
                 credentials.autologin = True
             else:
                 credentials.autologin = False
             initialLogin = True
-        elif not sessionData:
+        elif not lifeTimeSessionData:
             # go away if no available session and no login try
             return None
         # not first access on portal
-        sessionData = session[interfaces.SESSION_KEY]
+        browserSessionData = browserSession[interfaces.BROWSER_SESSION_KEY]
+        lifeTimeSessionData = lifeTimeSession[interfaces.SESSION_KEY]
+
         if credentials:
             # first login or relogin
-            sessionData['credentials'] = credentials
+            lifeTimeSessionData['credentials'] = credentials
         else:
             # already logged in or not
-            credentials = sessionData.get('credentials', None)
+            credentials = lifeTimeSessionData.get('credentials', None)
+
         if not credentials:
             # not already logged in
             return None
-        
         if initialLogin:
             # set a marker for the initial login in the session
-            sessionData['initialLogin'] = True
+            browserSessionData['initialLogin'] = True
             # and do login
             return self.__doLogin(credentials)
         
         # all below this is a ongoing login or a autologin
-        initialLoginSession = sessionData.get('initialLogin', False)
+        initialLoginSession = browserSessionData.get('initialLogin', False)
+        
         if credentials.autologin == False and not initialLoginSession:
             # do not login if autologin is disabled and first login session 
             # is not set. 
@@ -228,8 +237,14 @@
         if not IHTTPRequest.providedBy(request):
             return False
 
-        sessionData = ISession(request)[interfaces.SESSION_KEY]
-        sessionData['credentials'] = None
-        sessionData['initialLogin'] = False
+        lifeTimeSession = interfaces.ILifeTimeSession(request, None)
+        browserSession = ISession(request, None)
+
+        lifeTimeSessionData = lifeTimeSession.get(interfaces.SESSION_KEY)
+        browserSessionData = browserSession.get(interfaces.BROWSER_SESSION_KEY)
+
+        # reset the session data
+        lifeTimeSessionData['credentials'] = None
+        browserSessionData['initialLogin'] = False
         transaction.commit()
         return True

Modified: z3c.authentication/trunk/src/z3c/authentication/cookie/session.py
===================================================================
--- z3c.authentication/trunk/src/z3c/authentication/cookie/session.py	2006-11-05 01:16:14 UTC (rev 71075)
+++ z3c.authentication/trunk/src/z3c/authentication/cookie/session.py	2006-11-05 01:23:34 UTC (rev 71076)
@@ -16,10 +16,53 @@
 """
 
 import zope.interface
+import zope.component
+from zope.publisher.interfaces import IRequest
+from zope.app.session.interfaces import IClientId
+from zope.app.session.interfaces import IClientIdManager
 from zope.app.session.session import PersistentSessionDataContainer
+from zope.app.session.session import Session
 from z3c.authentication.cookie import interfaces
 
 
+class LifeTimeClientId(str):
+    """Client browser id for LifeTimeSession.
+
+    >>> from z3c.authentication.cookie import testing
+    >>> request = testing.clientIdSetUp()
+
+    >>> id1 = LifeTimeClientId(request)
+    >>> id2 = LifeTimeClientId(request)
+    >>> id1 == id2
+    True
+
+    >>> testing.clientIdTearDown()
+
+    """
+    zope.interface.implements(interfaces.ILifeTimeClientId)
+    zope.component.adapts(IRequest)
+
+    def __new__(cls, request):
+        name = 'LifeTimeSessionClientIdManager'
+        util = zope.component.getUtility(IClientIdManager, name=name)
+        id = util.getClientId(request)
+        return str.__new__(cls, id)
+
+
+class LifeTimeSession(Session):
+    """Session valid over a long time.
+    
+    Note this session requires a IClientIdManager configured with a 
+    ``cookieLifetime = 0`` registered as a named utility with a 
+    ``name = LifeTimeSessionClientIdManager``.
+    """
+    zope.interface.implements(interfaces.ILifeTimeSession)
+    zope.component.adapts(IRequest)
+
+    def __init__(self, request):
+        self.client_id = str(interfaces.ILifeTimeClientId(request))
+
+
 class CookieCredentialSessionDataContainer(PersistentSessionDataContainer):
     """A persistent cookie credential container."""
 

Modified: z3c.authentication/trunk/src/z3c/authentication/cookie/testing.py
===================================================================
--- z3c.authentication/trunk/src/z3c/authentication/cookie/testing.py	2006-11-05 01:16:14 UTC (rev 71075)
+++ z3c.authentication/trunk/src/z3c/authentication/cookie/testing.py	2006-11-05 01:23:34 UTC (rev 71076)
@@ -16,6 +16,7 @@
 """
 __docformat__ = "reStructuredText"
 
+from cStringIO import StringIO
 import unittest
 import zope.interface
 import zope.schema
@@ -24,13 +25,14 @@
 from zope.interface import implements
 from zope.component import provideUtility, provideAdapter
 from zope.publisher.interfaces import IRequest
+from zope.publisher.http import HTTPRequest
 from zope.testing import doctestunit
 
 from zope.app.component import hooks
 from zope.app.component.interfaces import ISite
 from zope.app.testing import functional
+from zope.app.testing import placelesssetup
 from zope.app.testing import setup
-from zope.app.testing import placelesssetup
 from zope.app.testing import ztapi
 from zope.app.session.interfaces import IClientId
 from zope.app.session.interfaces import IClientIdManager
@@ -43,8 +45,7 @@
 
 from z3c.configurator import configurator
 from z3c.authentication.cookie import interfaces
-from z3c.authentication.cookie.session import \
-    CookieCredentialSessionDataContainer
+from z3c.authentication.cookie import session
 
 
 ###############################################################################
@@ -139,17 +140,41 @@
 
 
 def sessionSetUp():
-    placelesssetup.setUp()
+    # setup client ids
     ztapi.provideAdapter(IRequest, IClientId, TestClientId)
+    ztapi.provideAdapter(IRequest, interfaces.ILifeTimeClientId, TestClientId)
+
+    # setup session adapters
     ztapi.provideAdapter(IRequest, ISession, Session)
+    ztapi.provideAdapter(IRequest, interfaces.ILifeTimeSession, 
+        session.LifeTimeSession)
+
+    # setup client id managers
     ztapi.provideUtility(IClientIdManager, CookieClientIdManager())
+    ccim = CookieClientIdManager()
+    ccim.cookieLifetime = 0
+    ztapi.provideUtility(IClientIdManager, ccim, 
+        name='LifeTimeSessionClientIdManager')
+
+    # setup session data containers
     defaultSDC = PersistentSessionDataContainer()
     ztapi.provideUtility(ISessionDataContainer, defaultSDC, '')
-    cookieSDC = CookieCredentialSessionDataContainer()
+    cookieSDC = session.CookieCredentialSessionDataContainer()
     ztapi.provideUtility(ISessionDataContainer, cookieSDC, 
         interfaces.SESSION_KEY)
 
 
+def clientIdSetUp():
+    placelesssetup.setUp()
+    sessionSetUp()
+    request = HTTPRequest(StringIO(), {}, None)
+    return request
+
+
+def clientIdTearDown():
+    placelesssetup.tearDown()
+
+
 def FunctionalDocFileSuite(path, **kw):
     """Including relative path setup."""
     globs = {'getRootFolder': getRootFolder}

Modified: z3c.authentication/trunk/src/z3c/authentication/cookie/tests.py
===================================================================
--- z3c.authentication/trunk/src/z3c/authentication/cookie/tests.py	2006-11-05 01:16:14 UTC (rev 71075)
+++ z3c.authentication/trunk/src/z3c/authentication/cookie/tests.py	2006-11-05 01:23:34 UTC (rev 71076)
@@ -26,6 +26,8 @@
 
 def test_suite():
     return unittest.TestSuite((
+        doctest.DocTestSuite('z3c.authentication.cookie.session',
+            setUp=testing.siteSetUp, tearDown=testing.siteTearDown),
         doctest.DocTestSuite('z3c.authentication.cookie.plugin',
             setUp=testing.siteSetUp, tearDown=testing.siteTearDown),
         doctestunit.DocFileSuite('README.txt',



More information about the Checkins mailing list