[Zope-CVS] CVS: Products/PluggableAuthService - __init__.py:1.4 PluggableAuthService.py:1.19

Zachery Bir zbir at urbanape.com
Sat Oct 16 16:15:47 EDT 2004


Update of /cvs-repository/Products/PluggableAuthService
In directory cvs.zope.org:/tmp/cvs-serv25732

Modified Files:
	__init__.py PluggableAuthService.py 
Log Message:
Merging pre-1_0_3-zbir-challenge-branch to the head.


=== Products/PluggableAuthService/__init__.py 1.3 => 1.4 ===
--- Products/PluggableAuthService/__init__.py:1.3	Thu Aug 12 11:15:53 2004
+++ Products/PluggableAuthService/__init__.py	Sat Oct 16 16:15:47 2004
@@ -30,6 +30,7 @@
 from permissions import ManageGroups
 
 from plugins import HTTPBasicAuthHelper as HBAH
+from plugins import InlineAuthHelper as IAH
 from plugins import CookieAuthHelper as CAH
 from plugins import SessionAuthHelper as SAH
 from plugins import DomainAuthHelper as DAH
@@ -44,6 +45,7 @@
 from plugins import DynamicGroupsPlugin as DGP
 
 registerMultiPlugin(HBAH.HTTPBasicAuthHelper.meta_type)
+registerMultiPlugin(IAH.InlineAuthHelper.meta_type)
 registerMultiPlugin(DAH.DomainAuthHelper.meta_type)
 registerMultiPlugin(SAH.SessionAuthHelper.meta_type)
 registerMultiPlugin(CAH.CookieAuthHelper.meta_type)
@@ -73,6 +75,15 @@
                             HBAH.addHTTPBasicAuthHelper, )
                          , visibility=None
                          , icon='plugins/www/HTTPBasicAuthHelper.png'
+                         )
+
+    context.registerClass( IAH.InlineAuthHelper
+                         , permission=ManageUsers
+                         , constructors=(
+                            IAH.manage_addInlineAuthHelperForm,
+                            IAH.addInlineAuthHelper, )
+                         , visibility=None
+                         , icon='plugins/www/InlineAuthHelper.png'
                          )
 
     context.registerClass( CAH.CookieAuthHelper


=== Products/PluggableAuthService/PluggableAuthService.py 1.18 => 1.19 ===
--- Products/PluggableAuthService/PluggableAuthService.py:1.18	Thu Oct  7 12:44:30 2004
+++ Products/PluggableAuthService/PluggableAuthService.py	Sat Oct 16 16:15:47 2004
@@ -79,7 +79,7 @@
                                  , KeyError
                                  , TypeError
                                  , ValueError
-                                 ) 
+                                 )
 
 security.declarePublic( 'MANGLE_DELIMITER' )
 MANGLE_DELIMITER = '__'
@@ -196,7 +196,7 @@
         if not user_id:
             return None
 
-        return self._findUser( plugins, user_id, name 
+        return self._findUser( plugins, user_id, name
                            # , cache=self._getUserCache()
                              )
 
@@ -221,7 +221,7 @@
                                                      , exact_match=True )
                     assert( len( user_info ) in [ 0, 1 ] )
                 except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-                    LOG('PluggableAuthService', WARNING, 
+                    LOG('PluggableAuthService', WARNING,
                         'UserEnumerationPlugin %s error' % plugin_id,
                         error=sys.exc_info())
                 else:
@@ -252,7 +252,7 @@
         , name
         , value
         ) = self._getObjectContext( request[ 'PUBLISHED' ], request )
-        
+
         for user_id, login in user_ids:
 
             user = self._findUser( plugins, user_id, login
@@ -323,7 +323,7 @@
                     else:
                         return ()
                 except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-                    LOG('PluggableAuthService', WARNING, 
+                    LOG('PluggableAuthService', WARNING,
                         'UserEnumerationPlugin %s error' % plugin_id,
                         error=sys.exc_info())
                     return ()
@@ -332,7 +332,7 @@
         max_results = kw.get('max_results', '')
         sort_by = kw.get('sort_by', '')
 
-        # We apply sorting and slicing here across all sets, so don't 
+        # We apply sorting and slicing here across all sets, so don't
         # make the plugin do it
         if sort_by:
             del kw['sort_by']
@@ -359,7 +359,7 @@
                     result.append(info)
 
             except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-                LOG('PluggableAuthService', WARNING, 
+                LOG('PluggableAuthService', WARNING,
                     'UserEnumerationPlugin %s error' % enumerator_id,
                     error=sys.exc_info())
 
@@ -405,7 +405,7 @@
                     else:
                         return ()
                 except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-                    LOG('PluggableAuthService', WARNING, 
+                    LOG('PluggableAuthService', WARNING,
                         'GroupEnumerationPlugin %s error' % plugin_id,
                         error=sys.exc_info())
                     return ()
@@ -414,7 +414,7 @@
         max_results = kw.get('max_results', '')
         sort_by = kw.get('sort_by', '')
 
-        # We apply sorting and slicing here across all sets, so don't 
+        # We apply sorting and slicing here across all sets, so don't
         # make the plugin do it
         if sort_by:
             del kw['sort_by']
@@ -440,7 +440,7 @@
                     info[ 'title' ] = "(Group) %s" % info[ 'groupid' ]
                     result.append(info)
             except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-                LOG('PluggableAuthService', WARNING, 
+                LOG('PluggableAuthService', WARNING,
                     'GroupEnumerationPlugin %s error' % enumerator_id,
                     error=sys.exc_info())
 
@@ -508,7 +508,7 @@
                     else:
                         return ()
                 except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-                    LOG('PluggableAuthService', WARNING, 
+                    LOG('PluggableAuthService', WARNING,
                         'UserEnumeratePlugin %s error' % plugin_id,
                         error=sys.exc_info())
                     return ()
@@ -650,7 +650,7 @@
         try:
             extractors = plugins.listPlugins( IExtractionPlugin )
         except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-            LOG('PluggableAuthService', WARNING, 
+            LOG('PluggableAuthService', WARNING,
                 'Plugin listing error',
                 error=sys.exc_info())
             extractors = ()
@@ -661,7 +661,7 @@
         try:
             authenticators = plugins.listPlugins( IAuthenticationPlugin )
         except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-            LOG('PluggableAuthService', WARNING, 
+            LOG('PluggableAuthService', WARNING,
                 'Plugin listing error',
                 error=sys.exc_info())
             authenticators = ()
@@ -671,7 +671,7 @@
             try:
                 credentials = extractor.extractCredentials( request )
             except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-                LOG('PluggableAuthService', WARNING, 
+                LOG('PluggableAuthService', WARNING,
                     'ExtractionPlugin %s error' % extractor_id,
                     error=sys.exc_info())
                 continue
@@ -685,7 +685,7 @@
                     items.sort()
                     cache_key = tuple( items )
                 except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-                    LOG('PluggableAuthService', WARNING, 
+                    LOG('PluggableAuthService', WARNING,
                         'Credentials error: %s' % credentials,
                         error=sys.exc_info())
                     cache_key = None
@@ -696,7 +696,7 @@
 
                     # first try to authenticate against the emergency
                     # user, and return immediately if authenticated
-                    user_id, name = self._tryEmergencyUserAuthentication( 
+                    user_id, name = self._tryEmergencyUserAuthentication(
                                                                 credentials )
 
                     if user_id is not None:
@@ -705,12 +705,12 @@
                     for authenticator_id, auth in authenticators:
 
                         try:
-                            user_id, name = auth.authenticateCredentials( 
-                                                                credentials ) 
+                            user_id, name = auth.authenticateCredentials(
+                                                                credentials )
                         except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-                            LOG('PluggableAuthService', WARNING, 
-                                'AuthenticationPlugin %s error' % authenticator_id,
-                                error=sys.exc_info())
+                            LOG('PluggableAuthService', WARNING,
+                                'AuthenticationPlugin %s error' %
+                                authenticator_id, error=sys.exc_info())
                             continue
 
                         if user_id is not None:
@@ -725,7 +725,7 @@
                 result.extend( user_ids )
 
         if not user_ids:
-            user_id, name = self._tryEmergencyUserAuthentication( 
+            user_id, name = self._tryEmergencyUserAuthentication(
                     DumbHTTPExtractor().extractCredentials( request ) )
 
             if user_id is not None:
@@ -760,7 +760,7 @@
             eua = EmergencyUserAuthenticator()
             user_id, name = eua.authenticateCredentials( credentials )
         except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-            LOG('PluggableAuthService', WARNING, 
+            LOG('PluggableAuthService', WARNING,
                 'Credentials error: %s' % credentials,
                 error=sys.exc_info())
             user_id, name = ( None, None )
@@ -906,7 +906,7 @@
                         return self._computeMangledId( info[0] )
 
                 except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-                    LOG('PluggableAuthService', WARNING, 
+                    LOG('PluggableAuthService', WARNING,
                         'UserEnumerationPlugin %s error' % enumerator_id,
                         error=sys.exc_info())
 
@@ -1058,7 +1058,7 @@
                 try:
                     roleassigner.doAssignRoleToPrincipal( user.getId(), role )
                 except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
-                    LOG('PluggableAuthService', WARNING, 
+                    LOG('PluggableAuthService', WARNING,
                         'RoleAssigner %s error' % roleassigner_id,
                         error=sys.exc_info())
                     pass
@@ -1093,51 +1093,68 @@
             BeforeTraverse.registerBeforeTraverse(container, nc, handle)
 
     def __call__(self, container, req):
-        """ The __before_publishing_traverse__ hook. 
+        """ The __before_publishing_traverse__ hook.
         """
         resp = req['RESPONSE']
-        resp.exception = self.exception
+        req._hold(ResponseCleanup(resp))
+        stack = getattr(resp, '_unauthorized_stack', [])
+        stack.append(resp._unauthorized)
+        resp._unauthorized_stack = stack
         resp._unauthorized = self._unauthorized
+        resp._has_challenged = False
 
     #
-    # Response overrides
+    # Response override
     #
     def _unauthorized(self):
-        pass
-    
-    def exception(self, fatal=0, info=None,
-                  absuri_match=re.compile(r'\w+://[\w\.]+').match,
-                  tag_search=re.compile('[a-zA-Z]>').search,
-                  abort=1
-                  ):
         req = self.REQUEST
         resp = req['RESPONSE']
-        try: del resp.exception
-        except: pass
-        try: del resp._unauthorized
-        except: pass
-        
-        if type(info) is type(()) and len(info) == 3:
-            t, v, tb = info
+        if resp._has_challenged: # Been here already
+            return
+        if not self.challenge(req, resp):
+            # Need to fall back here
+            resp = self._cleanupResponse()
+            resp._unauthorized()
         else:
-            t, v, tb = sys.exc_info()
-        
-        if t == 'Unauthorized' or t == Unauthorized or (
-            isinstance(t, types.ClassType) and issubclass(t, Unauthorized)):
-            t = 'Unauthorized'
-            self.challenge(req, resp)
-            return resp
-        
-        return resp.exception(fatal, info, absuri_match, tag_search, abort)
-    
+            resp._has_challenged = True
+
     def challenge(self, request, response):
         # Go through all challenge plugins
         plugins = self._getOb('plugins')
         challengers = plugins.listPlugins( IChallengePlugin )
+
+        protocol = None
+
         for challenger_id, challenger in challengers:
-            if challenger.challenge(request, response):
-                break
-                                
+            challenger_protocol = getattr(challenger, 'protocol',
+                                          challenger_id)
+            if protocol is None or protocol == challenger_protocol:
+                if challenger.challenge(request, response):
+                    protocol = challenger_protocol
+
+        if protocol is not None:
+            # something fired, so it was a successful PAS challenge
+            return True
+
+        # nothing fired, so trigger the fallback
+        return False
+
+    def _cleanupResponse(self):
+        resp = self.REQUEST['RESPONSE']
+        # No errors of any sort may propagate, and we don't care *what*
+        # they are, even to log them.
+        stack = getattr(resp, '_unauthorized_stack', [])
+
+        if stack:
+            resp._unauthorized = stack.pop()
+        else:
+            try:
+                del resp._unauthorized
+            except:
+                pass
+
+        return resp
+
     security.declarePublic( 'hasUsers' )
     def hasUsers(self):
         """Zope quick start sacrifice.
@@ -1152,7 +1169,7 @@
     ( IExtractionPlugin
     , 'IExtractionPlugin'
     , 'extraction'
-    , "Extraction plugins are responsible for extracting credentials " 
+    , "Extraction plugins are responsible for extracting credentials "
       "from the request."
     )
   , ( IAuthenticationPlugin
@@ -1260,4 +1277,33 @@
                                 '%s/manage_workspace'
                                 '?manage_tabs_message='
                                 'PluggableAuthService+added.'
-                              % dispatcher.absolute_url() ) 
+                              % dispatcher.absolute_url() )
+
+class ResponseCleanup:
+    def __init__(self, resp):
+        self.resp = resp
+
+    def __del__(self):
+        # Free the references.
+        #
+        # No errors of any sort may propagate, and we don't care *what*
+        # they are, even to log them.
+        stack = getattr(self.resp, '_unauthorized_stack', [])
+        old = None
+
+        while stack:
+            old = stack.pop()
+
+        if old is not None:
+            self.resp._unauthorized = old
+        else:
+            try:
+                del self.resp._unauthorized
+            except:
+                pass
+
+        try:
+            del self.resp
+        except:
+            pass
+



More information about the Zope-CVS mailing list