diff options
| author | Chris McDonough <chrism@plope.com> | 2011-08-15 03:01:51 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-08-15 03:01:51 -0400 |
| commit | 1a42bd45ad6dd066078d6d4997d33208b1bd0c63 (patch) | |
| tree | a6b647e692576e4131f0dd883343233e4d1e033b | |
| parent | b2533554bb8816d412615595f4d7947f7779bf47 (diff) | |
| download | pyramid-1a42bd45ad6dd066078d6d4997d33208b1bd0c63.tar.gz pyramid-1a42bd45ad6dd066078d6d4997d33208b1bd0c63.tar.bz2 pyramid-1a42bd45ad6dd066078d6d4997d33208b1bd0c63.zip | |
- New methods of the ``pyramid.config.Configurator`` class:
``set_authentication_policy`` and ``set_authorization_policy``. These are
meant to be consumed mostly by add-on authors.
| -rw-r--r-- | CHANGES.txt | 4 | ||||
| -rw-r--r-- | TODO.txt | 8 | ||||
| -rw-r--r-- | docs/api/config.rst | 4 | ||||
| -rw-r--r-- | pyramid/config.py | 67 | ||||
| -rw-r--r-- | pyramid/tests/permbugapp/__init__.py | 4 | ||||
| -rw-r--r-- | pyramid/tests/test_config.py | 69 | ||||
| -rw-r--r-- | pyramid/tests/test_integration.py | 12 |
7 files changed, 135 insertions, 33 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 1e7abc153..54a39b614 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -55,6 +55,10 @@ Features - ``pyramid.testing.DummyRequest`` now implements the ``add_finished_callback`` and ``add_response_callback`` methods. +- New methods of the ``pyramid.config.Configurator`` class: + ``set_authentication_policy`` and ``set_authorization_policy``. These are + meant to be consumed mostly by add-on authors. + Internal -------- @@ -6,18 +6,14 @@ Should-Have - Name WSGI app "main" instead of pipeline in scaffold configs? -- Turn off debugtoolbar redirect catcher in scaffolding (makes tutorials - weird). +- Make another release of debug toolbar (has now redirects turned off by + default so tutorials aren't weird). - Mention debug toolbar in tutorials. - Make it possible to use tween aliases in explicit tween config? If not, the tween factories of all add-ons must be APIs. -- Provide a way to set the authentication policy and the authorization policy - during a config.include (they are related, so just exposing the currently - underscored-private _set_auth* methods won't cut it). - - Merge Michael's route group work. - Deprecate pyramid.security.view_execution_permitted (it only works for diff --git a/docs/api/config.rst b/docs/api/config.rst index 30c541905..de054d7ce 100644 --- a/docs/api/config.rst +++ b/docs/api/config.rst @@ -78,6 +78,10 @@ .. automethod:: set_view_mapper + .. automethod:: set_authentication_policy + + .. automethod:: set_authorization_policy + .. automethod:: add_tween .. automethod:: testing_securitypolicy diff --git a/pyramid/config.py b/pyramid/config.py index fc00e2ffa..950c90f00 100644 --- a/pyramid/config.py +++ b/pyramid/config.py @@ -353,22 +353,61 @@ class Configurator(object): self.action(IRootFactory, register) @action_method + def set_authentication_policy(self, policy): + """ Override the :app:`Pyramid` :term:`authentication policy` in the + current configuration. The ``policy`` argument must be an instance + of an authentication policy or a :term:`dotted Python name` + that points at an instance of an authentication policy. + """ + self._set_authentication_policy(policy) + def ensure(): + if self.autocommit: + return + if self.registry.queryUtility(IAuthorizationPolicy) is None: + raise ConfigurationError( + 'Cannot configure an authentication policy without ' + 'also configuring an authorization policy ' + '(see the set_authorization_policy method)') + self.action(IAuthenticationPolicy, callable=ensure) + + @action_method def _set_authentication_policy(self, policy): - """ Add a :app:`Pyramid` :term:`authentication policy` to - the current configuration.""" policy = self.maybe_dotted(policy) self.registry.registerUtility(policy, IAuthenticationPolicy) - self.action(IAuthenticationPolicy) + + @action_method + def set_authorization_policy(self, policy): + """ Override the :app:`Pyramid` :term:`authorization policy` in the + current configuration. The ``policy`` argument must be an instance + of an authorization policy or a :term:`dotted Python name` that points + at an instance of an authorization policy. + """ + self._set_authorization_policy(policy) + def ensure(): + if self.registry.queryUtility(IAuthenticationPolicy) is None: + raise ConfigurationError( + 'Cannot configure an authorization policy without also ' + 'configuring an authentication policy ' + '(see the set_authentication_policy method)') + self.action(IAuthorizationPolicy, callable=ensure) @action_method def _set_authorization_policy(self, policy): - """ Add a :app:`Pyramid` :term:`authorization policy` to - the current configuration state (also accepts a :term:`dotted - Python name`.""" policy = self.maybe_dotted(policy) self.registry.registerUtility(policy, IAuthorizationPolicy) - self.action(IAuthorizationPolicy, None) - + + @action_method + def _set_security_policies(self, authentication, authorization=None): + if (authorization is not None) and (not authentication): + raise ConfigurationError( + 'If the "authorization" is passed a value, ' + 'the "authentication" argument must also be ' + 'passed a value; authorization requires authentication.') + if authorization is None: + authorization = ACLAuthorizationPolicy() # default + self._set_authentication_policy(authentication) + self._set_authorization_policy(authorization) + def _make_spec(self, path_or_spec): package, filename = resolve_asset_spec(path_or_spec, self.package_name) @@ -414,18 +453,6 @@ class Configurator(object): return deriver(view) - @action_method - def _set_security_policies(self, authentication, authorization=None): - if (authorization is not None) and (not authentication): - raise ConfigurationError( - 'If the "authorization" is passed a value, ' - 'the "authentication" argument must also be ' - 'passed a value; authorization requires authentication.') - if authorization is None: - authorization = ACLAuthorizationPolicy() # default - self._set_authentication_policy(authentication) - self._set_authorization_policy(authorization) - def _fix_registry(self): """ Fix up a ZCA component registry that is not a pyramid.registry.Registry by adding analogues of ``has_listeners``, diff --git a/pyramid/tests/permbugapp/__init__.py b/pyramid/tests/permbugapp/__init__.py index fe90c716d..10a244f3b 100644 --- a/pyramid/tests/permbugapp/__init__.py +++ b/pyramid/tests/permbugapp/__init__.py @@ -16,7 +16,7 @@ def includeme(config): from pyramid.authorization import ACLAuthorizationPolicy authn_policy = AuthTktAuthenticationPolicy('seekt1t') authz_policy = ACLAuthorizationPolicy() - config._set_authentication_policy(authn_policy) - config._set_authorization_policy(authz_policy) + config.set_authentication_policy(authn_policy) + config.set_authorization_policy(authz_policy) config.add_view(test, name='test') config.add_view(x_view, name='x', permission='private') diff --git a/pyramid/tests/test_config.py b/pyramid/tests/test_config.py index 921f5ec84..b222a398a 100644 --- a/pyramid/tests/test_config.py +++ b/pyramid/tests/test_config.py @@ -2730,21 +2730,80 @@ pyramid.tests.test_config.dummy_include2""", config.end() self.assertTrue('div' in result.body) - def test__set_authentication_policy(self): + def test_set_authentication_policy_no_authz_policy(self): + from zope.configuration.config import ConfigurationExecutionError + config = self._makeOne() + policy = object() + config.set_authentication_policy(policy) + self.assertRaises(ConfigurationExecutionError, config.commit) + + def test_set_authentication_policy_no_authz_policy_autocommit(self): from pyramid.interfaces import IAuthenticationPolicy config = self._makeOne(autocommit=True) policy = object() - config._set_authentication_policy(policy) + config.set_authentication_policy(policy) self.assertEqual( config.registry.getUtility(IAuthenticationPolicy), policy) - def test__set_authorization_policy(self): + def test_set_authentication_policy_with_authz_policy(self): + from pyramid.interfaces import IAuthenticationPolicy + from pyramid.interfaces import IAuthorizationPolicy + config = self._makeOne() + authn_policy = object() + authz_policy = object() + config.registry.registerUtility(authz_policy, IAuthorizationPolicy) + config.set_authentication_policy(authn_policy) + config.commit() + self.assertEqual( + config.registry.getUtility(IAuthenticationPolicy), authn_policy) + + def test_set_authentication_policy_with_authz_policy_autocommit(self): + from pyramid.interfaces import IAuthenticationPolicy from pyramid.interfaces import IAuthorizationPolicy config = self._makeOne(autocommit=True) + authn_policy = object() + authz_policy = object() + config.registry.registerUtility(authz_policy, IAuthorizationPolicy) + config.set_authentication_policy(authn_policy) + config.commit() + self.assertEqual( + config.registry.getUtility(IAuthenticationPolicy), authn_policy) + + def test_set_authorization_policy_no_authn_policy(self): + from zope.configuration.config import ConfigurationExecutionError + config = self._makeOne() + policy = object() + config.set_authorization_policy(policy) + self.assertRaises(ConfigurationExecutionError, config.commit) + + def test_set_authorization_policy_no_authn_policy_autocommit(self): + from pyramid.exceptions import ConfigurationError + config = self._makeOne(autocommit=True) policy = object() - config._set_authorization_policy(policy) + self.assertRaises(ConfigurationError, + config.set_authorization_policy, policy) + + def test_set_authorization_policy_with_authn_policy(self): + from pyramid.interfaces import IAuthorizationPolicy + from pyramid.interfaces import IAuthenticationPolicy + config = self._makeOne() + authn_policy = object() + authz_policy = object() + config.registry.registerUtility(authn_policy, IAuthenticationPolicy) + config.set_authorization_policy(authz_policy) + self.assertEqual( + config.registry.getUtility(IAuthorizationPolicy), authz_policy) + + def test_set_authorization_policy_with_authn_policy_autocommit(self): + from pyramid.interfaces import IAuthorizationPolicy + from pyramid.interfaces import IAuthenticationPolicy + config = self._makeOne(autocommit=True) + authn_policy = object() + authz_policy = object() + config.registry.registerUtility(authn_policy, IAuthenticationPolicy) + config.set_authorization_policy(authz_policy) self.assertEqual( - config.registry.getUtility(IAuthorizationPolicy), policy) + config.registry.getUtility(IAuthorizationPolicy), authz_policy) def test_set_locale_negotiator(self): from pyramid.interfaces import ILocaleNegotiator diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index 1ebf83062..a9fb80d6f 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -297,6 +297,18 @@ class TestViewPermissionBug(IntegrationBase): class TestDefaultViewPermissionBug(IntegrationBase): # default_view_permission bug as reported by Wiggy at http://lists.repoze.org/pipermail/repoze-dev/2010-October/003602.html package = 'pyramid.tests.defpermbugapp' + def setUp(self): + from pyramid.config import Configurator + config = Configurator(root_factory=self.root_factory, + package=self.package) + config.begin() + config.include(self.package) + config.commit() + app = config.make_wsgi_app() + from webtest import TestApp + self.testapp = TestApp(app) + self.config = config + def test_x(self): res = self.testapp.get('/x', status=403) self.assertTrue('failed permission check' in res.body) |
