Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

@require now provides smart behavior, and can be used to just abort, …

…rather than do redirect. Closes #27
  • Loading branch information...
commit bcb5e775f895fef8ec9d04f7aa2a0e545a3d41a9 1 parent d3016c6
@pedersen pedersen authored
Showing with 24 additions and 6 deletions.
  1. +17 −0 tests/test_stack/test_authz.py
  2. +7 −6 tg/decorators.py
View
17 tests/test_stack/test_authz.py
@@ -134,6 +134,10 @@ def index(self):
def commit(self):
return 'you can commit'
+ @expose()
+ @require(is_user('developer'), smart_denial=True)
+ def smartabort(self):
+ return {'key': 'value'}
class ControllerWithAllowOnlyAttributeAndAuthzDenialHandler(TGController):
"""Mock TG2 protected controller using the .allow_only attribute"""
@@ -247,6 +251,19 @@ def test_authz_denied_in_sub_controller(self):
assert "was just registered" not in resp.body
self._check_flash(resp, r'The current user must be \"admin\"')
+ def test_smart_auth_json(self):
+ nouser = {'accept': 'application/json'}
+ baduser = {'accept': 'application/json',
+ 'REMOTE_USER': 'foobar'}
+ gooduser = {'accept': 'application/json',
+ 'REMOTE_USER': 'developer'}
+ resp = self.app.get('/smartabort', extra_environ=nouser, status=401)
+ assert resp.status == '401 Unauthorized', 'Expected 401, got %s' % (resp.status)
+ resp = self.app.get('/smartabort', extra_environ=baduser, status=403)
+ assert resp.status == '403 Forbidden', 'Expected 403, got %s' % (resp.status)
+ resp = self.app.get('/smartabort.json', extra_environ=gooduser, status=200)
+ assert resp.status == '200 OK', 'Expected 200, got %s' % (resp.body)
+
class TestAllowOnlyDecoratorInSubController(BaseIntegrationTests):
"""Test case for the @allow_only decorator in a sub-controller"""
View
13 tg/decorators.py
@@ -698,7 +698,7 @@ def sample(self, *args):
class _BaseProtectionDecorator(object):
default_denial_handler = None
- def __init__(self, predicate, denial_handler=None):
+ def __init__(self, predicate, denial_handler=None, smart_denial=False):
"""Verify that the predicate is met.
:param predicate: An object with a check_authorization(environ) method which
@@ -713,6 +713,7 @@ def __init__(self, predicate, denial_handler=None):
self.predicate = predicate
self.denial_handler = denial_handler or self.default_denial_handler
+ self.smart_denial = smart_denial
class require(_BaseProtectionDecorator):
@@ -750,12 +751,12 @@ def wrap_action(self, action_, *args, **kwargs):
def default_denial_handler(self, reason):
"""Authorization denial handler for protectors."""
- if response.status_int == 401:
- status = 'warning'
+ status = 'warning' if response.status_int == 401 else 'error'
+ if not self.smart_denial:
+ flash(reason, status=status)
else:
- # Status is a 403
- status = 'error'
- flash(reason, status=status)
+ if response.content_type not in ['application/json', 'text/xml']:
+ flash(reason, status=status)
abort(response.status_int, reason)
Please sign in to comment.
Something went wrong with that request. Please try again.