[Repoze-checkins] r782 - in repoze.pam/trunk: . repoze/pam

Chris McDonough chrism at agendaless.com
Sat Mar 8 02:59:25 UTC 2008


Author: Chris McDonough <chrism at agendaless.com>
Date: Fri Mar  7 21:59:25 2008
New Revision: 782

Log:
0.4 (03-07-2008)

 - Allow plugins to specify a classifiers list per interface (instead
   of a single classifiers list per plugin).



Modified:
   repoze.pam/trunk/CHANGES.txt
   repoze.pam/trunk/TODO.txt
   repoze.pam/trunk/repoze/pam/middleware.py
   repoze.pam/trunk/repoze/pam/tests.py
   repoze.pam/trunk/setup.py

Modified: repoze.pam/trunk/CHANGES.txt
==============================================================================
--- repoze.pam/trunk/CHANGES.txt	(original)
+++ repoze.pam/trunk/CHANGES.txt	Fri Mar  7 21:59:25 2008
@@ -1,3 +1,8 @@
+0.4 (03-07-2008)
+
+ - Allow plugins to specify a classifiers list per interface (instead
+   of a single classifiers list per plugin).
+
 0.3 (03-05-2008)
 
   - Make SQLAuthenticatorPlugin's default_password_compare use

Modified: repoze.pam/trunk/TODO.txt
==============================================================================
--- repoze.pam/trunk/TODO.txt	(original)
+++ repoze.pam/trunk/TODO.txt	Fri Mar  7 21:59:25 2008
@@ -1,5 +1,2 @@
-- Fix so each plugin has a classifiers attr per-plugin-type (as
-  opposed to a single classifiers attr as it has now).
-
 - Config file parser.
 

Modified: repoze.pam/trunk/repoze/pam/middleware.py
==============================================================================
--- repoze.pam/trunk/repoze/pam/middleware.py	(original)
+++ repoze.pam/trunk/repoze/pam/middleware.py	Fri Mar  7 21:59:25 2008
@@ -58,8 +58,7 @@
         if ids:
             auth_ids = self.authenticate(environ, classification, ids)
             # auth_ids will be a list of four-tuples; when sorted,
-            # its first element will be the "best" identity.  The fourth
-            # element in the tuple is the user_id.
+            # its first element will be the "best" identity.
             if auth_ids:
                 auth_ids.sort()
                 best = auth_ids[0]
@@ -111,7 +110,7 @@
         candidates = self.registry.get(IIdentifier, ())
         logger and self.logger.info('identifier plugins registered %s' %
                                     candidates)
-        plugins = self._match_classification(candidates, classification)
+        plugins = match_classification(IIdentifier, candidates, classification)
         logger and self.logger.info(
             'identifier plugins matched for '
             'classification "%s": %s' % (classification, plugins))
@@ -135,7 +134,8 @@
         candidates = self.registry.get(IAuthenticator, ())
         logger and self.logger.info('authenticator plugins registered %s' %
                                     candidates)
-        plugins = self._match_classification(candidates, classification)
+        plugins = match_classification(IAuthenticator, candidates,
+                                       classification)
         logger and self.logger.info(
             'authenticator plugins matched for '
             'classification "%s": %s' % (classification, plugins))
@@ -182,7 +182,8 @@
 
         candidates = self.registry.get(IChallenger, ())
         logger and logger.info('challengers registered: %s' % candidates)
-        plugins = self._match_classification(candidates, classification)
+        plugins = match_classification(IChallenger,
+                                       candidates, classification)
         logger and logger.info('challengers matched for '
                                'classification "%s": %s' % (classification,
                                                             plugins))
@@ -200,17 +201,19 @@
         logger and logger.info('no challenge app returned')
         return None
 
-    def _match_classification(self, plugins, classification):
-        result = []
-        for plugin in plugins:
-            plugin_classifications = getattr(plugin, 'classifications', None)
-            if not plugin_classifications: # good for any
-                result.append(plugin)
-                continue
-            if classification in plugin_classifications:
-                result.append(plugin)
-                    
-        return result
+def match_classification(iface, plugins, classification):
+    result = []
+    for plugin in plugins:
+        
+        plugin_classifications = getattr(plugin, 'classifications', {})
+        iface_classifications = plugin_classifications.get(iface)
+        if not iface_classifications: # good for any
+            result.append(plugin)
+            continue
+        if classification in iface_classifications:
+            result.append(plugin)
+
+    return result
 
 class StartResponseWrapper(object):
     def __init__(self, start_response):
@@ -284,8 +287,6 @@
     from repoze.pam.plugins.cookie import InsecureCookiePlugin
     from repoze.pam.plugins.form import FormPlugin
     basicauth = BasicAuthPlugin('repoze.pam')
-    any = None # means good for any classification
-    basicauth.classifications = any
     from StringIO import StringIO
     from repoze.pam.plugins.htpasswd import crypt_check
     io = StringIO()
@@ -295,11 +296,10 @@
         io.write('%s:%s\n' % (name, crypt.crypt(password, salt)))
     io.seek(0)
     htpasswd = HTPasswdPlugin(io, crypt_check)
-    htpasswd.classifications = any
     cookie = InsecureCookiePlugin('oatmeal')
-    cookie.classifications = any
     form = FormPlugin('__do_login', rememberer_name='cookie')
-    form.classifications = set(('browser',)) # only for for browser requests
+    form.classifications = { IIdentifier:['browser'],
+                             IChallenger:['browser'] } # only for browser
     identifiers = [('form', form),('cookie',cookie),('basicauth',basicauth) ]
     authenticators = [('htpasswd', htpasswd)]
     challengers = [('form',form), ('basicauth',basicauth)]

Modified: repoze.pam/trunk/repoze/pam/tests.py
==============================================================================
--- repoze.pam/trunk/repoze/pam/tests.py	(original)
+++ repoze.pam/trunk/repoze/pam/tests.py	Fri Mar  7 21:59:25 2008
@@ -105,7 +105,8 @@
         environ = self._makeEnviron()
         mw = self._makeOne()
         plugin1 = DummyIdentifier({'login':'fred','password':'fred'})
-        plugin1.classifications = set(['nomatch'])
+        from repoze.pam.interfaces import IIdentifier
+        plugin1.classifications = {IIdentifier:['nomatch']}
         plugin2 = DummyIdentifier({'login':'bob','password':'bob'})
         plugins = [ ('identifier1', plugin1),  ('identifier2', plugin2) ]
         mw = self._makeOne(identifiers=plugins)
@@ -118,10 +119,11 @@
 
     def test_identify_find_explicit_classifier(self):
         environ = self._makeEnviron()
+        from repoze.pam.interfaces import IIdentifier
         plugin1 = DummyIdentifier({'login':'fred','password':'fred'})
-        plugin1.classifications = set(['nomatch'])
+        plugin1.classifications = {IIdentifier:['nomatch']}
         plugin2 = DummyIdentifier({'login':'bob','password':'bob'})
-        plugin2.classifications = set(['match'])
+        plugin2.classifications = {IIdentifier:['match']}
         plugins= [ ('identifier1', plugin1), ('identifier2', plugin2) ]
         mw = self._makeOne(identifiers=plugins)
         results = mw.identify(environ, 'match')
@@ -203,7 +205,8 @@
         environ = self._makeEnviron()
         mw = self._makeOne()
         plugin1 = DummyAuthenticator('chris_id1')
-        plugin1.classifications = set(['nomatch'])
+        from repoze.pam.interfaces import IAuthenticator
+        plugin1.classifications = {IAuthenticator:['nomatch']}
         plugin2 = DummyAuthenticator('chris_id2')
         plugins = [ ('auth1', plugin1), ('auth2', plugin2) ]
         mw = self._makeOne(authenticators = plugins)
@@ -221,10 +224,11 @@
     def test_authenticate_find_explicit_classifier(self):
         environ = self._makeEnviron()
         mw = self._makeOne()
+        from repoze.pam.interfaces import IAuthenticator
         plugin1 = DummyAuthenticator('chris_id1')
-        plugin1.classifications = set(['nomatch'])
+        plugin1.classifications = {IAuthenticator:['nomatch']}
         plugin2 = DummyAuthenticator('chris_id2')
-        plugin2.classificationans = set(['match']) # game
+        plugin2.classifications = {IAuthenticator:['match']}
         plugins = [ ('auth1', plugin1), ('auth2', plugin2) ]
         mw = self._makeOne(authenticators = plugins)
         identities = [ (None, {'login':'chris', 'password':'password'}) ]
@@ -241,12 +245,11 @@
     def test_challenge_noidentifier_noapp(self):
         environ = self._makeEnviron()
         challenger = DummyChallenger()
-        challenger.classifications = None
         plugins = [ ('challenge', challenger) ]
         mw = self._makeOne(challengers = plugins)
         identity = {'login':'chris', 'password':'password'}
         app = mw.challenge(environ, 'match', '401 Unauthorized',
-                               [], None, identity)
+                           [], None, identity)
         self.assertEqual(app, None)
         self.assertEqual(environ['challenged'], app)
 
@@ -254,7 +257,6 @@
         environ = self._makeEnviron()
         app = DummyApp()
         challenger = DummyChallenger(app)
-        challenger.classifications = None
         plugins = [ ('challenge', challenger) ]
         mw = self._makeOne(challengers = plugins)
         identity = {'login':'chris', 'password':'password'}
@@ -266,7 +268,6 @@
     def test_challenge_identifier_noapp(self):
         environ = self._makeEnviron()
         challenger = DummyChallenger()
-        challenger.classifications = None
         identifier = DummyIdentifier()
         plugins = [ ('challenge', challenger) ]
         mw = self._makeOne(challengers = plugins)
@@ -281,7 +282,6 @@
         environ = self._makeEnviron()
         app = DummyApp()
         challenger = DummyChallenger(app)
-        challenger.classifications = None
         identifier = DummyIdentifier()
         plugins = [ ('challenge', challenger) ]
         mw = self._makeOne(challengers = plugins)
@@ -297,9 +297,7 @@
         app1 = DummyApp()
         app2 = DummyApp()
         challenger1 = DummyChallenger(app1)
-        challenger1.classifications = None
         challenger2 = DummyChallenger(app2)
-        challenger2.classifications = None
         identifier = DummyIdentifier()
         plugins = [ ('challenge1', challenger1), ('challenge2', challenger2) ]
         mw = self._makeOne(challengers = plugins)
@@ -314,10 +312,11 @@
         environ = self._makeEnviron()
         app1 = DummyApp()
         app2 = DummyApp()
+        from repoze.pam.interfaces import IChallenger
         challenger1 = DummyChallenger(app1)
-        challenger1.classifications = ['nomatch']
+        challenger1.classifications = {IChallenger:['nomatch']}
         challenger2 = DummyChallenger(app2)
-        challenger2.classifications = None
+        challenger2.classifications = {IChallenger:None}
         identifier = DummyIdentifier()
         plugins = [ ('challenge1', challenger1), ('challenge2', challenger2) ]
         mw = self._makeOne(challengers = plugins)
@@ -332,10 +331,11 @@
         environ = self._makeEnviron()
         app1 = DummyApp()
         app2 = DummyApp()
+        from repoze.pam.interfaces import IChallenger
         challenger1 = DummyChallenger(app1)
-        challenger1.classifications = ['nomatch']
+        challenger1.classifications = {IChallenger:['nomatch']}
         challenger2 = DummyChallenger(app2)
-        challenger2.classifications = ['match']
+        challenger2.classifications = {IChallenger:['match']}
         identifier = DummyIdentifier()
         plugins = [ ('challenge1', challenger1), ('challenge2', challenger2) ]
         mw = self._makeOne(challengers = plugins)
@@ -464,9 +464,37 @@
         self.assertEqual(identifier.remembered, True)
         self.assertEqual(environ['REMOTE_USER'], 'chris')
 
+
+
     # XXX need more call tests:
     #  - auth_id sorting
 
+class TestMatchClassification(unittest.TestCase):
+    def _getFUT(self):
+        from repoze.pam.middleware import match_classification
+        return match_classification
+
+    def test_match_classification(self):
+        f = self._getFUT()
+        from repoze.pam.interfaces import IIdentifier
+        from repoze.pam.interfaces import IChallenger
+        from repoze.pam.interfaces import IAuthenticator
+        multi1 = DummyMultiPlugin()
+        multi2 = DummyMultiPlugin()
+        multi1.classifications = {IIdentifier:('foo', 'bar'),
+                                  IChallenger:('buz',),
+                                  IAuthenticator:None}
+        multi2.classifications = {IIdentifier:('foo', 'baz', 'biz')}
+        plugins = (multi1, multi2)
+        # specific
+        self.assertEqual(f(IIdentifier, plugins, 'foo'), [multi1, multi2])
+        self.assertEqual(f(IIdentifier, plugins, 'bar'), [multi1])
+        self.assertEqual(f(IIdentifier, plugins, 'biz'), [multi2])
+        # any for multi2
+        self.assertEqual(f(IChallenger, plugins, 'buz'), [multi1, multi2])
+        # any for either
+        self.assertEqual(f(IAuthenticator, plugins, 'buz'), [multi1, multi2])
+
 class TestStartResponseWrapper(unittest.TestCase):
     def _getTargetClass(self):
         from repoze.pam.middleware import StartResponseWrapper
@@ -1159,6 +1187,9 @@
             return credentials['login']
         return self.userid
 
+class DummyMultiPlugin:
+    pass
+
 class DummyFailAuthenticator:
     def authenticate(self, environ, credentials):
         return None

Modified: repoze.pam/trunk/setup.py
==============================================================================
--- repoze.pam/trunk/setup.py	(original)
+++ repoze.pam/trunk/setup.py	Fri Mar  7 21:59:25 2008
@@ -12,7 +12,7 @@
 #
 ##############################################################################
 
-__version__ = '0.3'
+__version__ = '0.4'
 
 import os
 


More information about the Repoze-checkins mailing list