summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-05-26 00:44:17 +0000
committerChris McDonough <chrism@agendaless.com>2009-05-26 00:44:17 +0000
commit08ead74d05e25f58c83712f6f8651484ddc983d0 (patch)
tree8a14ba839615678ab1eb4510782595af2d51f4d5
parent9b1876725d2268af42961e36dbccfdc990fa4dd1 (diff)
downloadpyramid-08ead74d05e25f58c83712f6f8651484ddc983d0.tar.gz
pyramid-08ead74d05e25f58c83712f6f8651484ddc983d0.tar.bz2
pyramid-08ead74d05e25f58c83712f6f8651484ddc983d0.zip
Revert all work towards creating a "forbidden" API on the security policy; I'll do this work on the authchanges branch first.
-rw-r--r--CHANGES.txt63
-rw-r--r--docs/narr/hooks.rst72
-rw-r--r--repoze/bfg/interfaces.py46
-rw-r--r--repoze/bfg/router.py78
-rw-r--r--repoze/bfg/security.py40
-rw-r--r--repoze/bfg/tests/test_router.py213
-rw-r--r--repoze/bfg/tests/test_security.py19
-rw-r--r--repoze/bfg/tests/test_wsgi.py4
-rw-r--r--repoze/bfg/wsgi.py2
9 files changed, 158 insertions, 379 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 6df0c8171..40a810305 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,66 +1,3 @@
-Next release
-============
-
-Features
---------
-
-- It is now possible to register a custom
- ``repoze.bfg.interfaces.IForbiddenResponseFactory`` for a given
- application. This feature replaces the
- ``repoze.bfg.interfaces.IUnauthorizedAppFactory`` feature previously
- described in the Hooks chapter. The IForbiddenResponseFactory will
- be called when the framework detects an authorization failure; it
- should accept a context object and a request object; it should
- return an IResponse object (a webob response, basically). Read the
- below point for more info and see the Hooks narrative chapter of the
- BFG docs for more info; this registration trumps the security policy
- ``forbidden`` feature when it is registered.
-
-- It is now possible to register a security policy that returns a
- customized ``Forbidden`` response when BFG cannot authorize an
- invocation of a view. To this end, ISecurityPolicy objects must now
- have a ``forbidden`` method that accepts two arguments: ``context``
- and ``request``. The ``context`` will be the context found by the
- router, the ``request`` will be the current request. This method
- should return an IResponse (a webob response). The returned
- response application should be appropriate when access to a view
- resource was forbidden by the security policy (e.g. perhaps a login
- page or a general "forbidden" page). ``repoze.bfg`` is willing to
- operate with a custom security policy that does not have a
- ``forbidden`` method, but it will issue a warning; eventually
- security policies without a ``forbidden`` method will cease to work
- under ``repoze.bfg``.
-
- Note that the ``forbidden`` method of a security policy is not used
- if a developer has registered an IForbiddenResponseFactory (see the
- "Hooks" narrative chapter); the explicitly registered
- IForbiddenResponseFactory will be preferred over the (more general)
- security policy forbidden method.
-
-- All default security policies now have a ``forbidden`` callable
- attached to them. This particular callable returns an IResponse (a
- webob response) with a ``401 Unauthorized`` status for backwards
- compatibility (had backwards compatibility not been an issue, this
- callable would have returned a WSGI app that generated a ``403
- Forbidden`` response).
-
-Backwards Incompatibilities
----------------------------
-
-- Custom NotFound and Forbidden (nee' Unauthorized) WSGI applications
- (registered as a utility for INotFoundAppFactory and
- IUnauthorizedAppFactory) could rely on an environment key named
- ``message`` describing the circumstance of the response. This key
- has been renamed to ``repoze.bfg.message`` (as per the WSGI spec,
- which requires environment extensions to contain dots).
-
-Deprecations
-------------
-
-- The ``repoze.bfg.interfaces.IUnauthorizedAppFactory`` interface has
- been deprecated in favor of using the new
- ``repoze.bfg.interfaces.IForbiddenResponseFactory`` mechanism.
-
0.8.1 (2009-05-21)
==================
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index 6428408e8..21906e466 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -88,7 +88,7 @@ an object that implements any particular interface; it simply needs
have a ``status`` attribute, a ``headerlist`` attribute, and and
``app_iter`` attribute.
-Changing the NotFound Application
+Changing the NotFound application
---------------------------------
When :mod:`repoze.bfg` can't map a URL to code, it creates and invokes
@@ -119,56 +119,54 @@ sample code that implements a minimal NotFound application factory:
.. note:: When a NotFound application factory is invoked, it is passed
the WSGI environ and the WSGI ``start_response`` handler by
:mod:`repoze.bfg`. Within the WSGI environ will be a key named
- ``repoze.bfg.message`` that has a value explaining why the not
- found error was raised. This error will be different when the
- ``debug_notfound`` environment setting is true than it is when it
- is false.
+ ``message`` that has a value explaining why the not found error was
+ raised. This error will be different when the ``debug_notfound``
+ environment setting is true than it is when it is false.
-Changing the Forbidden Response
--------------------------------
+Changing the Unauthorized application
+-------------------------------------
When :mod:`repoze.bfg` can't authorize execution of a view based on
-the security policy in use, it invokes a "forbidden response factory".
-Usually this forbidden response factory is serviced by the currently
-active :term:`security policy`, but it can be overridden as necessary
-by placing something like the following ZCML in your
-``configure.zcml`` file.
+the security policy in use, it creates and invokes an Unauthorized
+WSGI application. The application it invokes can be customized by
+placing something like the following ZCML in your ``configure.zcml``
+file.
.. code-block:: xml
:linenos:
- <utility provides="repoze.bfg.interfaces.IForbiddenResponseFactory"
- component="helloworld.factories.forbidden_response_factory"/>
+ <utility provides="repoze.bfg.interfaces.IUnauthorizedAppFactory"
+ component="helloworld.factories.unauthorized_app_factory"/>
-Replace ``helloworld.factories.forbidden_app_factory`` with the Python
-dotted name to the forbidden response factory you want to use. The
-response factory must accept two parameters: ``context`` and
-``request``. The ``context`` is the context found by the router when
-the view invocation was denied. The ``request`` is the current
-:term:`request` representing the denied action. Here's some sample
-code that implements a minimal forbidden response factory:
+Replace ``helloworld.factories.unauthorized_app_factory`` with the
+Python dotted name to the request factory you want to use. Here's
+some sample code that implements a minimal Unauthorized application
+factory:
.. code-block:: python
- from repoze.bfg.chameleon_zpt import render_template_to_response
+ from webob.exc import HTTPUnauthorized
- def forbidden_response_factory(context, request):
- return render_template_to_response('templates/login_form.pt')
+ class MyUnauthorized(HTTPUnauthorized):
+ pass
-.. note:: When an forbidden response factory is invoked, it is passed
- the request as the second argument. An attribute of the request is
- ``environ``, which is the WSGI environment. Within the WSGI
- environ will be a key named ``repoze.bfg.message`` that has a value
- explaining why the current view invocation was forbidden. This
- error will be different when the ``debug_authorization``
- environment setting is true than it is when it is false.
+ def notfound_app_factory():
+ return MyUnauthorized
-.. warning:: the default forbidden application factory sends a
- response with a ``401 Unauthorized`` status code for backwards
- compatibility reasons. You can influence the status code of
- Forbidden responses by using an alterate forbidden application
- factory. For example, it would make sense to return an forbidden
- application with a ``403 Forbidden`` status code.
+.. note:: When an Unauthorized application factory is invoked, it is
+ passed the WSGI environ and the WSGI ``start_response`` handler by
+ :mod:`repoze.bfg`. Within the WSGI environ will be a key named
+ ``message`` that has a value explaining why the action was not
+ authorized. This error will be different when the
+ ``debug_authorization`` environment setting is true than it is when
+ it is false.
+
+.. note:: You can influence the status code of Unauthorized responses
+ by using an alterate unauthorized application factory. For
+ example, you may return an unauthorized application with a ``403
+ Forbidden`` status code, rather than use the default unauthorized
+ application factory, which sends a response with a ``401
+ Unauthorized`` status code.
Changing the Default Routes Context Factory
-------------------------------------------
diff --git a/repoze/bfg/interfaces.py b/repoze/bfg/interfaces.py
index 78311962f..cecc3a397 100644
--- a/repoze/bfg/interfaces.py
+++ b/repoze/bfg/interfaces.py
@@ -131,27 +131,6 @@ class ISecurityPolicy(Interface):
implementation, in which case, it should raise a
``NotImplementedError`` exception."""
- def forbidden(context, request):
- """ This method should return an IResponse object (an object
- with the attributes ``status``, ``headerlist``, and
- ``app_iter``) as a result of a view invocation denial. The
- ``forbidden`` method of a security policy will be called by
- ``repoze.bfg`` when view invocation is denied (usually as a
- result of the ``permit`` method of the same security policy
- returning False to the Router).
-
- The ``forbidden`` method of a security will not be called when
- an ``IForbiddenResponseFactory`` utility is registered;
- instead the ``IForbiddenResponseFactory`` utility will serve
- the forbidden response.
-
- Note that the ``repoze.bfg.message`` key in the environ passed
- to the WSGI app will contain the 'raw' reason that view
- invocation was denied by repoze.bfg. The ``context`` object
- passed in will be the context found by ``repoze.bfg`` when the
- denial was found and the ``request`` will be the request which
- caused the denial."""
-
class IViewPermission(Interface):
def __call__(security_policy):
""" Return True if the permission allows, return False if it denies. """
@@ -218,26 +197,15 @@ class INotFoundAppFactory(Interface):
a``message`` key in the WSGI environ provides information
pertaining to the reason for the notfound."""
-class IForbiddenResponseFactory(Interface):
- """ A utility which returns an IResponse as the result of the
- denial of a view invocation by a security policy."""
- def __call__(context, request):
- """ Return an object implementing IResponse (an object with
- the status, headerlist, and app_iter attributes) as a result
- of a view invocation denial by a security policy.
-
- Note that the ``message`` key in the WSGI environ
- (request.environ) provides information pertaining to the
- reason for the view invocation denial. The ``context`` passed
- to the forbidden app factory will be the context found by the
- repoze.bfg router during traversal or url dispatch. The
- ``request`` will be the request object which caused the deny."""
-
class IUnauthorizedAppFactory(Interface):
""" A utility which returns an Unauthorized WSGI application
- factory (deprecated in repoze.bfg 0.8.2) in favor of
- IForbiddenResponseFactory """
-
+ factory"""
+ def __call__():
+ """ Return a callable which returns an unauthorized WSGI
+ application. When the WSGI application is invoked, a
+ ``message`` key in the WSGI environ provides information
+ pertaining to the reason for the unauthorized."""
+
class IContextURL(Interface):
""" An adapter which deals with URLs related to a context.
"""
diff --git a/repoze/bfg/router.py b/repoze/bfg/router.py
index ac3bd53cd..81bc6e4ef 100644
--- a/repoze/bfg/router.py
+++ b/repoze/bfg/router.py
@@ -17,7 +17,6 @@ from repoze.bfg.interfaces import IRouter
from repoze.bfg.interfaces import IRoutesMapper
from repoze.bfg.interfaces import ISecurityPolicy
from repoze.bfg.interfaces import ISettings
-from repoze.bfg.interfaces import IForbiddenResponseFactory
from repoze.bfg.interfaces import IUnauthorizedAppFactory
from repoze.bfg.interfaces import IView
from repoze.bfg.interfaces import IViewPermission
@@ -31,15 +30,13 @@ from repoze.bfg.registry import populateRegistry
from repoze.bfg.request import HTTP_METHOD_FACTORIES
from repoze.bfg.request import Request
-from repoze.bfg.security import _forbidden
-
from repoze.bfg.settings import Settings
from repoze.bfg.urldispatch import RoutesRootFactory
from repoze.bfg.traversal import _traverse
from repoze.bfg.view import _view_execution_permitted
-
+from repoze.bfg.wsgi import Unauthorized
from repoze.bfg.wsgi import NotFound
_marker = object()
@@ -53,65 +50,22 @@ class Router(object):
def __init__(self, registry):
self.registry = registry
- self.logger = registry.queryUtility(ILogger, 'repoze.bfg.debug')
self.request_factory = registry.queryUtility(IRequestFactory)
- security_policy = registry.queryUtility(ISecurityPolicy)
- self.security_policy = security_policy
-
- unauthorized_app_factory = registry.queryUtility(
- IUnauthorizedAppFactory)
-
- forbidden = None
-
- if unauthorized_app_factory is not None:
- warning = (
- 'Instead of registering a utility against the '
- 'repoze.bfg.interfaces.IUnauthorizedAppFactory interface '
- 'to return a custom forbidden response, you should now '
- 'register a "repoze.interfaces.IForbiddenResponseFactory". '
- 'The IUnauthorizedAppFactory interface was deprecated in '
- 'repoze.bfg 0.8.2 and will be removed in a subsequent version '
- 'of repoze.bfg. See the "Hooks" chapter of the repoze.bfg '
- 'documentation for more information about '
- 'IForbiddenResponseFactory.')
- self.logger and self.logger.warn(warning)
- def forbidden(context, request):
- app = unauthorized_app_factory()
- response = request.get_response(app)
- return response
-
- self.forbidden_resp_factory = registry.queryUtility(
- IForbiddenResponseFactory,
- default=forbidden)
-
- if security_policy is not None:
- if hasattr(security_policy, 'forbidden'):
- security_policy_forbidden = security_policy.forbidden
- else:
- security_policy_forbidden = _forbidden
- warning = ('You are running with a security policy (%s) which '
- 'does not have a "forbidden" method; in BFG 0.8.2+ '
- 'the ISecurityPolicy interface in the '
- 'repoze.bfg.interfaces module defines this method '
- 'as required; your application will not work under '
- 'a future release of BFG if you continue using a '
- 'security policy without a "forbidden" method.' %
- security_policy)
- self.logger and self.logger.warn(warning)
- # allow a specifically-registered IForbiddenResponseFactory to
- # override the security policy's forbidden
- self.forbidden_resp_factory = (self.forbidden_resp_factory or
- security_policy_forbidden)
-
- self.notfound_app_factory = registry.queryUtility(INotFoundAppFactory,
- default=NotFound)
-
+ self.security_policy = registry.queryUtility(ISecurityPolicy)
+ self.notfound_app_factory = registry.queryUtility(
+ INotFoundAppFactory,
+ default=NotFound)
+ self.unauth_app_factory = registry.queryUtility(
+ IUnauthorizedAppFactory,
+ default=Unauthorized)
+
settings = registry.queryUtility(ISettings)
if settings is not None:
self.debug_authorization = settings.debug_authorization
self.debug_notfound = settings.debug_notfound
+ self.logger = registry.queryUtility(ILogger, 'repoze.bfg.debug')
self.root_factory = registry.getUtility(IRootFactory)
self.root_policy = self.root_factory # b/w compat
self.traverser_warned = {}
@@ -190,18 +144,14 @@ class Router(object):
'context %r): %s' % (
request.url, view_name, context, permitted)
)
-
if not permitted:
if debug_authorization:
msg = str(permitted)
else:
msg = 'Unauthorized: failed security policy check'
-
- environ['repoze.bfg.message'] = msg
-
- response = self.forbidden_resp_factory(context, request)
- start_response(response.status, response.headerlist)
- return response.app_iter
+ environ['message'] = msg
+ unauth_app = self.unauth_app_factory()
+ return unauth_app(environ, start_response)
response = registry.queryMultiAdapter(
(context, request), IView, name=view_name)
@@ -218,7 +168,7 @@ class Router(object):
logger and logger.debug(msg)
else:
msg = request.url
- environ['repoze.bfg.message'] = msg
+ environ['message'] = msg
notfound_app = self.notfound_app_factory()
return notfound_app(environ, start_response)
diff --git a/repoze/bfg/security.py b/repoze/bfg/security.py
index 14423ffdc..90916bac2 100644
--- a/repoze/bfg/security.py
+++ b/repoze/bfg/security.py
@@ -1,6 +1,3 @@
-from cgi import escape
-from webob import Response
-
from zope.component import queryUtility
from zope.deprecation import deprecated
from zope.interface import implements
@@ -10,7 +7,6 @@ from repoze.bfg.location import lineage
from repoze.bfg.interfaces import ISecurityPolicy
from repoze.bfg.interfaces import IViewPermission
from repoze.bfg.interfaces import IViewPermissionFactory
-from repoze.bfg.interfaces import IResponseFactory
Everyone = 'system.Everyone'
Authenticated = 'system.Authenticated'
@@ -78,31 +74,9 @@ def principals_allowed_by_permission(context, permission):
return [Everyone]
return policy.principals_allowed_by_permission(context, permission)
-def _forbidden(context, request):
- status = '401 Unauthorized'
- try:
- msg = escape(request.environ['repoze.bfg.message'])
- except KeyError:
- msg = ''
- html = """
- <html>
- <title>%s</title>
- <body>
- <h1>%s</h1>
- <code>%s</code>
- </body>
- </html>
- """ % (status, status, msg)
- headers = [('Content-Length', str(len(html))),
- ('Content-Type', 'text/html')]
- response_factory = queryUtility(IResponseFactory, default=Response)
- return response_factory(status = status,
- headerlist = headers,
- app_iter = [html])
-
class ACLSecurityPolicy(object):
implements(ISecurityPolicy)
-
+
def __init__(self, get_principals):
self.get_principals = get_principals
@@ -171,9 +145,6 @@ class ACLSecurityPolicy(object):
return []
- def forbidden(self, context, request):
- return _forbidden(context, request)
-
class InheritingACLSecurityPolicy(object):
""" A security policy which uses ACLs in the following ways:
@@ -218,7 +189,7 @@ class InheritingACLSecurityPolicy(object):
``authenticated_userid``).
"""
implements(ISecurityPolicy)
-
+
def __init__(self, get_principals):
self.get_principals = get_principals
@@ -297,9 +268,6 @@ class InheritingACLSecurityPolicy(object):
return allowed
- def forbidden(self, context, request):
- return _forbidden(context, request)
-
def get_remoteuser(request):
user_id = request.environ.get('REMOTE_USER')
if user_id:
@@ -515,7 +483,6 @@ def WhoInheritingACLSecurityPolicy():
"""
return InheritingACLSecurityPolicy(get_who_principals)
-
class PermitsResult(int):
def __new__(cls, s, *args):
inst = int.__new__(cls, cls.boolval)
@@ -628,3 +595,6 @@ class ViewPermissionFactory(object):
class Unauthorized(Exception):
pass
+
+
+
diff --git a/repoze/bfg/tests/test_router.py b/repoze/bfg/tests/test_router.py
index 29ebf61d5..db47f832e 100644
--- a/repoze/bfg/tests/test_router.py
+++ b/repoze/bfg/tests/test_router.py
@@ -78,12 +78,9 @@ class RouterTests(unittest.TestCase):
from repoze.bfg.interfaces import IViewPermission
self.registry.registerAdapter(permission, for_, IViewPermission, name)
- def _registerSecurityPolicy(self, secpol=None):
- if secpol is None:
- secpol = DummySecurityPolicy()
+ def _registerSecurityPolicy(self, secpol):
from repoze.bfg.interfaces import ISecurityPolicy
self.registry.registerUtility(secpol, ISecurityPolicy)
- return secpol
def _registerEventListener(self, iface):
L = []
@@ -92,11 +89,9 @@ class RouterTests(unittest.TestCase):
self.registry.registerHandler(listener, (iface,))
return L
- def _registerRootFactory(self, val):
- rootfactory = make_rootfactory(val)
+ def _registerRootFactory(self, root_factory):
from repoze.bfg.interfaces import IRootFactory
- self.registry.registerUtility(rootfactory, IRootFactory)
- return rootfactory
+ self.registry.registerUtility(root_factory, IRootFactory)
def _getTargetClass(self):
from repoze.bfg.router import Router
@@ -118,93 +113,21 @@ class RouterTests(unittest.TestCase):
return environ
def test_root_policy(self):
+ rootfactory = make_rootfactory(None)
environ = self._makeEnviron()
context = DummyContext()
self._registerTraverserFactory(context)
- rootfactory = self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
self.assertEqual(router.root_policy, rootfactory)
- def test_secpol_no_forbidden(self):
- environ = self._makeEnviron()
- context = DummyContext()
- self._registerTraverserFactory(context)
- rootfactory = self._registerRootFactory(None)
- logger = self._registerLogger()
- class Dummy:
- pass
- self._registerSecurityPolicy(Dummy())
- router = self._makeOne()
- self.assertEqual(len(logger.messages), 1)
- self.failUnless('which does not have a "forbidden" method'
- in logger.messages[0])
- class DummyRequest:
- environ = {}
- req = DummyRequest()
- resp = router.forbidden_resp_factory(None, req)
- self.assertEqual(resp.status, '401 Unauthorized')
-
- def test_secpol_with_iunauthorized_appfactory(self):
- from repoze.bfg.interfaces import IUnauthorizedAppFactory
- environ = self._makeEnviron()
- context = DummyContext()
- self._registerTraverserFactory(context)
- rootfactory = self._registerRootFactory(None)
- logger = self._registerLogger()
- secpol = self._registerSecurityPolicy()
- def factory():
- return 'yo'
- self.registry.registerUtility(factory, IUnauthorizedAppFactory)
- router = self._makeOne()
- self.assertEqual(len(logger.messages), 1)
- self.failUnless('IForbiddenResponseFactory' in logger.messages[0])
- class DummyRequest:
- def get_response(self, app):
- return app
- req = DummyRequest()
- self.assertEqual(router.forbidden_resp_factory(None, req), 'yo')
-
- def test_inotfound_appfactory_override(self):
- from repoze.bfg.interfaces import INotFoundAppFactory
- def app():
- """ """
- self.registry.registerUtility(app, INotFoundAppFactory)
- self._registerRootFactory(None)
- router = self._makeOne()
- self.assertEqual(router.notfound_app_factory, app)
-
- def test_iforbidden_respfactory_override_withsecpol(self):
- from repoze.bfg.interfaces import IForbiddenResponseFactory
- def app():
- """ """
- self.registry.registerUtility(app, IForbiddenResponseFactory)
- self._registerSecurityPolicy()
- self._registerRootFactory(None)
- router = self._makeOne()
- self.assertEqual(router.forbidden_resp_factory, app)
-
- def test_iforbidden_responsefactory_override_nosecpol(self):
- from repoze.bfg.interfaces import IForbiddenResponseFactory
- def app():
- """ """
- self.registry.registerUtility(app, IForbiddenResponseFactory)
- self._registerRootFactory(None)
- router = self._makeOne()
- self.assertEqual(router.forbidden_resp_factory, app)
-
- def test_iforbidden_responsefactory_nooverride(self):
- secpol = self._registerSecurityPolicy()
- context = DummyContext()
- self._registerRootFactory(None)
- router = self._makeOne()
- self.assertEqual(router.forbidden_resp_factory, secpol.forbidden)
-
def test_call_no_view_registered_no_isettings(self):
+ rootfactory = make_rootfactory(None)
environ = self._makeEnviron()
context = DummyContext()
self._registerTraverserFactory(context)
logger = self._registerLogger()
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
@@ -225,7 +148,8 @@ class RouterTests(unittest.TestCase):
self._registerTraverserFactory(context)
environ = self._makeEnviron()
start_response = DummyStartResponse()
- self._registerRootFactory(NotFound())
+ rootfactory = make_rootfactory(NotFound())
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
result = router(environ, start_response)
status = start_response.status
@@ -233,12 +157,13 @@ class RouterTests(unittest.TestCase):
self.failUnless('http://localhost:8080' in result[0], result)
def test_call_no_view_registered_debug_notfound_false(self):
+ rootfactory = make_rootfactory(None)
environ = self._makeEnviron()
context = DummyContext()
self._registerTraverserFactory(context)
logger = self._registerLogger()
self._registerSettings(debug_notfound=False)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
@@ -251,12 +176,13 @@ class RouterTests(unittest.TestCase):
self.assertEqual(len(logger.messages), 0)
def test_call_no_view_registered_debug_notfound_true(self):
+ rootfactory = make_rootfactory(None)
environ = self._makeEnviron()
context = DummyContext()
self._registerTraverserFactory(context)
self._registerSettings(debug_notfound=True)
logger = self._registerLogger()
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
@@ -279,17 +205,19 @@ class RouterTests(unittest.TestCase):
self.failUnless("subpath: []" in message)
def test_call_view_returns_nonresponse(self):
+ rootfactory = make_rootfactory(None)
context = DummyContext()
self._registerTraverserFactory(context)
environ = self._makeEnviron()
view = make_view('abc')
self._registerView(view, '', None, None)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
self.assertRaises(ValueError, router, environ, start_response)
def test_call_view_registered_nonspecific_default_path(self):
+ rootfactory = make_rootfactory(None)
context = DummyContext()
self._registerTraverserFactory(context)
response = DummyResponse()
@@ -297,7 +225,7 @@ class RouterTests(unittest.TestCase):
view = make_view(response)
environ = self._makeEnviron()
self._registerView(view, '', None, None)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
@@ -310,6 +238,7 @@ class RouterTests(unittest.TestCase):
self.assertEqual(environ['webob.adhoc_attrs']['root'], None)
def test_call_deprecation_warning(self):
+ rootfactory = make_rootfactory(None)
context = DummyContext()
self._registerTraverserFactory(context, _deprecation_warning='abc')
response = DummyResponse()
@@ -317,7 +246,7 @@ class RouterTests(unittest.TestCase):
view = make_view(response)
environ = self._makeEnviron()
self._registerView(view, '', None, None)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
logger = self._registerLogger()
router.logger = logger
@@ -327,6 +256,7 @@ class RouterTests(unittest.TestCase):
self.assertEqual(logger.messages[0], 'abc')
def test_call_view_registered_nonspecific_nondefault_path_and_subpath(self):
+ rootfactory = make_rootfactory(None)
context = DummyContext()
self._registerTraverserFactory(context, view_name='foo',
subpath=['bar'],
@@ -336,7 +266,7 @@ class RouterTests(unittest.TestCase):
view = make_view(response)
environ = self._makeEnviron()
self._registerView(view, 'foo', None, None)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
@@ -349,6 +279,7 @@ class RouterTests(unittest.TestCase):
self.assertEqual(environ['webob.adhoc_attrs']['root'], None)
def test_call_view_registered_specific_success(self):
+ rootfactory = make_rootfactory(None)
from zope.interface import Interface
from zope.interface import directlyProvides
class IContext(Interface):
@@ -362,7 +293,7 @@ class RouterTests(unittest.TestCase):
view = make_view(response)
environ = self._makeEnviron()
self._registerView(view, '', IContext, IRequest)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
@@ -375,6 +306,7 @@ class RouterTests(unittest.TestCase):
self.assertEqual(environ['webob.adhoc_attrs']['root'], None)
def test_call_view_registered_specific_fail(self):
+ rootfactory = make_rootfactory(None)
from zope.interface import Interface
from zope.interface import directlyProvides
class IContext(Interface):
@@ -389,7 +321,7 @@ class RouterTests(unittest.TestCase):
view = make_view(response)
environ = self._makeEnviron()
self._registerView(view, '', IContext, IRequest)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
@@ -397,6 +329,7 @@ class RouterTests(unittest.TestCase):
self.failUnless('404' in result[0])
def test_call_view_registered_security_policy_permission_none(self):
+ rootfactory = make_rootfactory(None)
from zope.interface import Interface
from zope.interface import directlyProvides
class IContext(Interface):
@@ -409,14 +342,16 @@ class RouterTests(unittest.TestCase):
view = make_view(response)
environ = self._makeEnviron()
self._registerView(view, '', IContext, IRequest)
- self._registerSecurityPolicy()
- self._registerRootFactory(None)
+ secpol = DummySecurityPolicy()
+ self._registerSecurityPolicy(secpol)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
self.assertEqual(start_response.status, '200 OK')
def test_call_view_registered_security_policy_permission_succeeds(self):
+ rootfactory = make_rootfactory(None)
from zope.interface import Interface
from zope.interface import directlyProvides
class IContext(Interface):
@@ -427,12 +362,13 @@ class RouterTests(unittest.TestCase):
self._registerTraverserFactory(context, subpath=[''])
response = DummyResponse()
view = make_view(response)
+ secpol = DummySecurityPolicy()
permissionfactory = make_permission_factory(True)
environ = self._makeEnviron()
self._registerView(view, '', IContext, IRequest)
- secpol = self._registerSecurityPolicy()
+ self._registerSecurityPolicy(secpol)
self._registerPermission(permissionfactory, '', IContext, IRequest)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
@@ -440,6 +376,7 @@ class RouterTests(unittest.TestCase):
self.assertEqual(permissionfactory.checked_with, secpol)
def test_call_view_permission_fails_nosettings(self):
+ rootfactory = make_rootfactory(None)
from zope.interface import Interface
from zope.interface import directlyProvides
class IContext(Interface):
@@ -450,24 +387,26 @@ class RouterTests(unittest.TestCase):
self._registerTraverserFactory(context, subpath=[''])
response = DummyResponse()
view = make_view(response)
+ secpol = DummySecurityPolicy()
from repoze.bfg.security import ACLDenied
permissionfactory = make_permission_factory(
ACLDenied('ace', 'acl', 'permission', ['principals'], context)
)
environ = self._makeEnviron()
self._registerView(view, '', IContext, IRequest)
- secpol = self._registerSecurityPolicy()
+ self._registerSecurityPolicy(secpol)
self._registerPermission(permissionfactory, '', IContext, IRequest)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
self.assertEqual(start_response.status, '401 Unauthorized')
- message = environ['repoze.bfg.message']
- self.assertEqual(message, 'Unauthorized: failed security policy check')
+ message = result[0]
+ self.failUnless('failed security policy check' in message)
self.assertEqual(permissionfactory.checked_with, secpol)
def test_call_view_permission_fails_no_debug_auth(self):
+ rootfactory = make_rootfactory(None)
from zope.interface import Interface
from zope.interface import directlyProvides
class IContext(Interface):
@@ -478,25 +417,27 @@ class RouterTests(unittest.TestCase):
self._registerTraverserFactory(context, subpath=[''])
response = DummyResponse()
view = make_view(response)
+ secpol = DummySecurityPolicy()
from repoze.bfg.security import ACLDenied
permissionfactory = make_permission_factory(
ACLDenied('ace', 'acl', 'permission', ['principals'], context)
)
environ = self._makeEnviron()
self._registerView(view, '', IContext, IRequest)
- secpol = self._registerSecurityPolicy()
+ self._registerSecurityPolicy(secpol)
self._registerPermission(permissionfactory, '', IContext, IRequest)
self._registerSettings(debug_authorization=False)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
self.assertEqual(start_response.status, '401 Unauthorized')
- message = environ['repoze.bfg.message']
+ message = result[0]
self.failUnless('failed security policy check' in message)
self.assertEqual(permissionfactory.checked_with, secpol)
def test_call_view_permission_fails_with_debug_auth(self):
+ rootfactory = make_rootfactory(None)
from zope.interface import Interface
from zope.interface import directlyProvides
class IContext(Interface):
@@ -507,22 +448,23 @@ class RouterTests(unittest.TestCase):
self._registerTraverserFactory(context, subpath=[''])
response = DummyResponse()
view = make_view(response)
+ secpol = DummySecurityPolicy()
from repoze.bfg.security import ACLDenied
permissionfactory = make_permission_factory(
ACLDenied('ace', 'acl', 'permission', ['principals'], context)
)
environ = self._makeEnviron()
self._registerView(view, '', IContext, IRequest)
- secpol = self._registerSecurityPolicy()
+ self._registerSecurityPolicy(secpol)
self._registerPermission(permissionfactory, '', IContext, IRequest)
self._registerSettings(debug_authorization=True)
logger = self._registerLogger()
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
self.assertEqual(start_response.status, '401 Unauthorized')
- message = environ['repoze.bfg.message']
+ message = result[0]
self.failUnless(
"ACLDenied permission 'permission' via ACE 'ace' in ACL 'acl' "
"on context" in message)
@@ -540,6 +482,7 @@ class RouterTests(unittest.TestCase):
"for principals ['principals']" in logged)
def test_call_eventsends(self):
+ rootfactory = make_rootfactory(None)
context = DummyContext()
self._registerTraverserFactory(context)
response = DummyResponse()
@@ -551,7 +494,7 @@ class RouterTests(unittest.TestCase):
from repoze.bfg.interfaces import INewResponse
request_events = self._registerEventListener(INewRequest)
response_events = self._registerEventListener(INewResponse)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
result = router(environ, start_response)
@@ -565,6 +508,7 @@ class RouterTests(unittest.TestCase):
from repoze.bfg.interfaces import IPOSTRequest
from repoze.bfg.interfaces import IPUTRequest
from repoze.bfg.interfaces import IRequest
+ rootfactory = make_rootfactory(None)
context = DummyContext()
self._registerTraverserFactory(context)
response = DummyResponse()
@@ -572,7 +516,7 @@ class RouterTests(unittest.TestCase):
view = make_view(response)
environ = self._makeEnviron(REQUEST_METHOD='POST')
self._registerView(view, '', None, None)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
request_events = self._registerEventListener(INewRequest)
@@ -587,6 +531,7 @@ class RouterTests(unittest.TestCase):
from repoze.bfg.interfaces import IPUTRequest
from repoze.bfg.interfaces import IPOSTRequest
from repoze.bfg.interfaces import IRequest
+ rootfactory = make_rootfactory(None)
context = DummyContext()
self._registerTraverserFactory(context)
response = DummyResponse()
@@ -594,7 +539,7 @@ class RouterTests(unittest.TestCase):
view = make_view(response)
environ = self._makeEnviron(REQUEST_METHOD='PUT')
self._registerView(view, '', None, None)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
request_events = self._registerEventListener(INewRequest)
@@ -607,6 +552,7 @@ class RouterTests(unittest.TestCase):
def test_call_unknown_method(self):
from repoze.bfg.interfaces import INewRequest
from repoze.bfg.interfaces import IRequest
+ rootfactory = make_rootfactory(None)
context = DummyContext()
self._registerTraverserFactory(context)
response = DummyResponse()
@@ -614,7 +560,7 @@ class RouterTests(unittest.TestCase):
view = make_view(response)
environ = self._makeEnviron(REQUEST_METHOD='UNKNOWN')
self._registerView(view, '', None, None)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
request_events = self._registerEventListener(INewRequest)
@@ -627,6 +573,7 @@ class RouterTests(unittest.TestCase):
from repoze.bfg.interfaces import IRequestFactory
from repoze.bfg.testing import DummyRequest
self.registry.registerUtility(DummyRequest, IRequestFactory)
+ rootfactory = make_rootfactory(None)
context = DummyContext()
self._registerTraverserFactory(context)
response = DummyResponse()
@@ -634,7 +581,7 @@ class RouterTests(unittest.TestCase):
view = make_view(response)
environ = self._makeEnviron()
self._registerView(view, '', None, None)
- self._registerRootFactory(None)
+ self._registerRootFactory(rootfactory)
router = self._makeOne()
start_response = DummyStartResponse()
request_events = self._registerEventListener(INewRequest)
@@ -646,6 +593,40 @@ class RouterTests(unittest.TestCase):
self.assertEqual(request.view_name, '')
self.assertEqual(request.subpath, [])
+ def test_call_inotfound_appfactory_override(self):
+ from repoze.bfg.interfaces import INotFoundAppFactory
+ def app():
+ """ """
+ self.registry.registerUtility(app, INotFoundAppFactory)
+ rootfactory = make_rootfactory(None)
+ context = DummyContext()
+ self._registerTraverserFactory(context)
+ response = DummyResponse()
+ response.app_iter = ['Hello world']
+ view = make_view(response)
+ environ = self._makeEnviron()
+ self._registerView(view, '', None, None)
+ self._registerRootFactory(rootfactory)
+ router = self._makeOne()
+ self.assertEqual(router.notfound_app_factory, app)
+
+ def test_call_iunauth_appfactory_override(self):
+ from repoze.bfg.interfaces import IUnauthorizedAppFactory
+ def app():
+ """ """
+ self.registry.registerUtility(app, IUnauthorizedAppFactory)
+ rootfactory = make_rootfactory(None)
+ context = DummyContext()
+ self._registerTraverserFactory(context)
+ response = DummyResponse()
+ response.app_iter = ['Hello world']
+ view = make_view(response)
+ environ = self._makeEnviron()
+ self._registerView(view, '', None, None)
+ self._registerRootFactory(rootfactory)
+ router = self._makeOne()
+ self.assertEqual(router.unauth_app_factory, app)
+
class MakeAppTests(unittest.TestCase):
def setUp(self):
cleanUp()
@@ -793,11 +774,5 @@ class DummyResponse:
app_iter = ()
class DummySecurityPolicy:
- def forbidden(self, context, request):
- self.request = request
- ob = DummyResponse()
- ob.status = '401 Unauthorized'
- ob.app_iter = ['Unauthorized']
- ob.headerlist = ()
- return ob
+ pass
diff --git a/repoze/bfg/tests/test_security.py b/repoze/bfg/tests/test_security.py
index b9f9624d4..03a466e7c 100644
--- a/repoze/bfg/tests/test_security.py
+++ b/repoze/bfg/tests/test_security.py
@@ -243,16 +243,6 @@ class TestACLSecurityPolicy(unittest.TestCase):
result = policy.principals_allowed_by_permission(None, 'read')
self.assertEqual(result, [])
- def test_forbidden(self):
- policy = self._makeOne(lambda *arg: None)
- context = DummyContext()
- request = DummyRequest({})
- response = policy.forbidden(context, request)
- self.failUnless('401 Unauthorized' in response.app_iter[0])
- self.assertEqual(response.status, '401 Unauthorized')
- self.assertEqual(len(response.headerlist), 2)
-
-
class TestInheritingACLSecurityPolicy(unittest.TestCase):
def setUp(self):
cleanUp()
@@ -440,15 +430,6 @@ class TestInheritingACLSecurityPolicy(unittest.TestCase):
result = policy.authenticated_userid(request)
self.assertEqual(result, None)
- def test_forbidden(self):
- policy = self._makeOne(lambda *arg: None)
- context = DummyContext()
- request = DummyRequest({})
- response = policy.forbidden(context, request)
- self.failUnless('401 Unauthorized' in response.app_iter[0])
- self.assertEqual(response.status, '401 Unauthorized')
- self.assertEqual(len(response.headerlist), 2)
-
class TestAllPermissionsList(unittest.TestCase):
def setUp(self):
cleanUp()
diff --git a/repoze/bfg/tests/test_wsgi.py b/repoze/bfg/tests/test_wsgi.py
index 893364635..b9568eb82 100644
--- a/repoze/bfg/tests/test_wsgi.py
+++ b/repoze/bfg/tests/test_wsgi.py
@@ -131,7 +131,7 @@ class TestNotFound(unittest.TestCase):
('Content-Type', 'text/html')])
def test_with_message(self):
- environ = {'repoze.bfg.message':'<hi!>'}
+ environ = {'message':'<hi!>'}
L = []
def start_response(status, headers):
L.append((status, headers))
@@ -166,7 +166,7 @@ class TestUnauthorized(unittest.TestCase):
('Content-Type', 'text/html')])
def test_with_message(self):
- environ = {'repoze.bfg.message':'<hi!>'}
+ environ = {'message':'<hi!>'}
L = []
def start_response(status, headers):
L.append((status, headers))
diff --git a/repoze/bfg/wsgi.py b/repoze/bfg/wsgi.py
index 027345673..abe7ebead 100644
--- a/repoze/bfg/wsgi.py
+++ b/repoze/bfg/wsgi.py
@@ -105,7 +105,7 @@ def wsgiapp2(wrapped):
class HTTPException(object):
def __call__(self, environ, start_response, exc_info=False):
try:
- msg = escape(environ['repoze.bfg.message'])
+ msg = escape(environ['message'])
except KeyError:
msg = ''
html = """<body>