diff options
| author | Chris McDonough <chrism@agendaless.com> | 2009-05-24 23:12:59 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2009-05-24 23:12:59 +0000 |
| commit | 86ed4016ea6a681d4f579ace62cea032a679544d (patch) | |
| tree | 697f67bbcb9e55e45db5d9aae52f0c3280e9b1e2 /repoze/bfg/router.py | |
| parent | ab5959d3d4e4603a61b3559096da30d2adfdcf4b (diff) | |
| download | pyramid-86ed4016ea6a681d4f579ace62cea032a679544d.tar.gz pyramid-86ed4016ea6a681d4f579ace62cea032a679544d.tar.bz2 pyramid-86ed4016ea6a681d4f579ace62cea032a679544d.zip | |
Features
--------
- It is now possible to write a custom security policy that returns a
customized ``Forbidden`` WSGI application when BFG cannot authorize
an invocation of a view. To this end, ISecurityPolicy objects must
now have a ``forbidden`` method. This method should return a WSGI
application. The returned WSGI application should generate a
response which is appropriate when access to a view resource was
forbidden by the security policy (e.g. perhaps a login 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`` WSGI application returned by the
security policy is not used if a developer has registered an
IForbiddenAppFactory (see the "Hooks" narrative chapter); the
explicitly registered IForbiddenAppFactory will be preferred over
the (more general) security policy forbidden app factory.
- All default security policies now have a ``forbidden`` callable
attached to them. This particular callable returns a WSGI
application which generates a ``401 Unauthorized`` response 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 a 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 renamed to ``repoze.bfg.interfaces.IForbiddenAppFactory``.
Diffstat (limited to 'repoze/bfg/router.py')
| -rw-r--r-- | repoze/bfg/router.py | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/repoze/bfg/router.py b/repoze/bfg/router.py index 81bc6e4ef..885a08184 100644 --- a/repoze/bfg/router.py +++ b/repoze/bfg/router.py @@ -17,7 +17,7 @@ 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 IUnauthorizedAppFactory +from repoze.bfg.interfaces import IForbiddenAppFactory from repoze.bfg.interfaces import IView from repoze.bfg.interfaces import IViewPermission @@ -50,22 +50,40 @@ class Router(object): def __init__(self, registry): self.registry = registry + self.logger = registry.queryUtility(ILogger, 'repoze.bfg.debug') self.request_factory = registry.queryUtility(IRequestFactory) - self.security_policy = registry.queryUtility(ISecurityPolicy) - self.notfound_app_factory = registry.queryUtility( - INotFoundAppFactory, - default=NotFound) - self.unauth_app_factory = registry.queryUtility( - IUnauthorizedAppFactory, - default=Unauthorized) + security_policy = registry.queryUtility(ISecurityPolicy) + + self.forbidden_app_factory = registry.queryUtility(IForbiddenAppFactory) + if security_policy is not None: + if hasattr(security_policy, 'forbidden'): + security_policy_forbidden = security_policy.forbidden + else: + security_policy_forbidden = Unauthorized + 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 IForbiddenAppFactory to + # override the security policy's forbidden + self.forbidden_app_factory = (self.forbidden_app_factory or + security_policy_forbidden) + + self.security_policy = security_policy + self.notfound_app_factory = registry.queryUtility(INotFoundAppFactory, + default=NotFound) 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 = {} @@ -144,14 +162,16 @@ 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['message'] = msg - unauth_app = self.unauth_app_factory() - return unauth_app(environ, start_response) + + environ['repoze.bfg.message'] = msg + + return self.forbidden_app_factory()(environ, start_response) response = registry.queryMultiAdapter( (context, request), IView, name=view_name) @@ -168,7 +188,7 @@ class Router(object): logger and logger.debug(msg) else: msg = request.url - environ['message'] = msg + environ['repoze.bfg.message'] = msg notfound_app = self.notfound_app_factory() return notfound_app(environ, start_response) |
