summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pyramid/config/views.py18
-rw-r--r--pyramid/interfaces.py4
-rw-r--r--pyramid/tests/test_viewderivers.py57
-rw-r--r--pyramid/viewderivers.py21
4 files changed, 88 insertions, 12 deletions
diff --git a/pyramid/config/views.py b/pyramid/config/views.py
index 34f289fcc..9e46ba155 100644
--- a/pyramid/config/views.py
+++ b/pyramid/config/views.py
@@ -13,7 +13,6 @@ from zope.interface import (
from zope.interface.interfaces import IInterface
from pyramid.interfaces import (
- IDefaultPermission,
IException,
IExceptionViewClassifier,
IMultiView,
@@ -878,11 +877,6 @@ class ViewsConfiguratorMixin(object):
registry=self.registry
)
- if permission is None:
- # intent: will be None if no default permission is registered
- # (reg'd in phase 1)
- permission = self.registry.queryUtility(IDefaultPermission)
-
# added by discrim_func above during conflict resolving
preds = view_intr['predicates']
order = view_intr['order']
@@ -1436,7 +1430,10 @@ class ViewsConfiguratorMixin(object):
.. versionadded:: 1.3
"""
- for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):
+ for arg in (
+ 'name', 'permission', 'context', 'for_', 'http_cache',
+ 'require_csrf',
+ ):
if arg in view_options:
raise ConfigurationError(
'%s may not be used as an argument to add_forbidden_view'
@@ -1464,6 +1461,7 @@ class ViewsConfiguratorMixin(object):
match_param=match_param,
route_name=route_name,
permission=NO_PERMISSION_REQUIRED,
+ require_csrf=False,
attr=attr,
renderer=renderer,
)
@@ -1548,7 +1546,10 @@ class ViewsConfiguratorMixin(object):
.. versionchanged:: 1.6
.. versionadded:: 1.3
"""
- for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):
+ for arg in (
+ 'name', 'permission', 'context', 'for_', 'http_cache',
+ 'require_csrf',
+ ):
if arg in view_options:
raise ConfigurationError(
'%s may not be used as an argument to add_notfound_view'
@@ -1576,6 +1577,7 @@ class ViewsConfiguratorMixin(object):
match_param=match_param,
route_name=route_name,
permission=NO_PERMISSION_REQUIRED,
+ require_csrf=False,
)
settings.update(view_options)
if append_slash:
diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py
index c03afbd39..b252d0f4a 100644
--- a/pyramid/interfaces.py
+++ b/pyramid/interfaces.py
@@ -1224,9 +1224,9 @@ class IViewDeriver(Interface):
class IViewDeriverInfo(Interface):
""" An object implementing this interface is passed to every
:term:`view deriver` during configuration."""
- registry = Attribute('The "current" application registry when the '
+ registry = Attribute('The "current" application registry where the '
'view was created')
- package = Attribute('The "current package" when the view '
+ package = Attribute('The "current package" where the view '
'configuration statement was found')
settings = Attribute('The deployment settings dictionary related '
'to the current application')
diff --git a/pyramid/tests/test_viewderivers.py b/pyramid/tests/test_viewderivers.py
index e84863d69..79fcd6e71 100644
--- a/pyramid/tests/test_viewderivers.py
+++ b/pyramid/tests/test_viewderivers.py
@@ -628,6 +628,63 @@ class TestDeriveView(unittest.TestCase):
else: # pragma: no cover
raise AssertionError
+ def test_secured_view_skipped_by_default_on_exception_view(self):
+ from pyramid.request import Request
+ from pyramid.security import NO_PERMISSION_REQUIRED
+ def view(request):
+ raise ValueError
+ def excview(request):
+ return 'hello'
+ self._registerSecurityPolicy(False)
+ self.config.add_settings({'debug_authorization': True})
+ self.config.set_default_permission('view')
+ self.config.add_view(view, name='foo', permission=NO_PERMISSION_REQUIRED)
+ self.config.add_view(excview, context=ValueError, renderer='string')
+ app = self.config.make_wsgi_app()
+ request = Request.blank('/foo', base_url='http://example.com')
+ request.method = 'POST'
+ response = request.get_response(app)
+ self.assertTrue(b'hello' in response.body)
+
+ def test_secured_view_failed_on_explicit_exception_view(self):
+ from pyramid.httpexceptions import HTTPForbidden
+ from pyramid.request import Request
+ from pyramid.security import NO_PERMISSION_REQUIRED
+ def view(request):
+ raise ValueError
+ def excview(request): pass
+ self._registerSecurityPolicy(False)
+ self.config.add_view(view, name='foo', permission=NO_PERMISSION_REQUIRED)
+ self.config.add_view(excview, context=ValueError, renderer='string',
+ permission='view')
+ app = self.config.make_wsgi_app()
+ request = Request.blank('/foo', base_url='http://example.com')
+ request.method = 'POST'
+ try:
+ request.get_response(app)
+ except HTTPForbidden:
+ pass
+ else: # pragma: no cover
+ raise AssertionError
+
+ def test_secured_view_passed_on_explicit_exception_view(self):
+ from pyramid.request import Request
+ from pyramid.security import NO_PERMISSION_REQUIRED
+ def view(request):
+ raise ValueError
+ def excview(request):
+ return 'hello'
+ self._registerSecurityPolicy(True)
+ self.config.add_view(view, name='foo', permission=NO_PERMISSION_REQUIRED)
+ self.config.add_view(excview, context=ValueError, renderer='string',
+ permission='view')
+ app = self.config.make_wsgi_app()
+ request = Request.blank('/foo', base_url='http://example.com')
+ request.method = 'POST'
+ request.headers['X-CSRF-Token'] = 'foo'
+ response = request.get_response(app)
+ self.assertTrue(b'hello' in response.body)
+
def test_predicate_mismatch_view_has_no_name(self):
from pyramid.exceptions import PredicateMismatch
response = DummyResponse()
diff --git a/pyramid/viewderivers.py b/pyramid/viewderivers.py
index 1b922b89e..5d138a02a 100644
--- a/pyramid/viewderivers.py
+++ b/pyramid/viewderivers.py
@@ -16,6 +16,7 @@ from pyramid.interfaces import (
IAuthenticationPolicy,
IAuthorizationPolicy,
IDefaultCSRFOptions,
+ IDefaultPermission,
IDebugLogger,
IResponse,
IViewMapper,
@@ -272,7 +273,9 @@ def secured_view(view, info):
secured_view.options = ('permission',)
def _secured_view(view, info):
- permission = info.options.get('permission')
+ permission = explicit_val = info.options.get('permission')
+ if permission is None:
+ permission = info.registry.queryUtility(IDefaultPermission)
if permission == NO_PERMISSION_REQUIRED:
# allow views registered within configurations that have a
# default permission to explicitly override the default
@@ -288,6 +291,12 @@ def _secured_view(view, info):
principals = authn_policy.effective_principals(request)
return authz_policy.permits(context, principals, permission)
def _secured_view(context, request):
+ if (
+ getattr(request, 'exception', None) is not None and
+ explicit_val is None
+ ):
+ return view(context, request)
+
result = _permitted(context, request)
if result:
return view(context, request)
@@ -306,12 +315,20 @@ def _secured_view(view, info):
def _authdebug_view(view, info):
wrapped_view = view
settings = info.settings
- permission = info.options.get('permission')
+ permission = explicit_val = info.options.get('permission')
+ if permission is None:
+ permission = info.registry.queryUtility(IDefaultPermission)
authn_policy = info.registry.queryUtility(IAuthenticationPolicy)
authz_policy = info.registry.queryUtility(IAuthorizationPolicy)
logger = info.registry.queryUtility(IDebugLogger)
if settings and settings.get('debug_authorization', False):
def _authdebug_view(context, request):
+ if (
+ getattr(request, 'exception', None) is not None and
+ explicit_val is None
+ ):
+ return view(context, request)
+
view_name = getattr(request, 'view_name', None)
if authn_policy and authz_policy: