Skip to content
This repository
Browse code

Merge branch 'development' of https://github.com/TurboGears/tg2 into …

…development
  • Loading branch information...
commit e5d2ecf353d65b828cda5c094b7aace3581fc382 2 parents f649b34 + fcb2f3d
Alessandro Molina amol- authored
1  .gitignore
@@ -14,3 +14,4 @@ dist/
14 14 .project
15 15 .pydevproject
16 16 .settings
  17 +nosetests.xml
34 .hgignore
... ... @@ -1,34 +0,0 @@
1   -
2   -syntax: glob
3   -*~
4   -*.egg
5   -*.egg-info
6   -*.mak.py
7   -*.pyc
8   -*.pyo
9   -*.swp
10   -*.DS_Store
11   -.coverage
12   -.idea
13   -.noseids
14   -.project
15   -.pydevproject
16   -.settings
17   -
18   -syntax: regexp
19   -^build
20   -^chameleon
21   -^coverage
22   -^dist
23   -^Genshi
24   -^Jinja
25   -^kid
26   -^lib
27   -^lxml
28   -^pytz
29   -^repoze
30   -^source
31   -^SQL
32   -^Turbo
33   -^zope
34   -
7 .hgtags
... ... @@ -1,7 +0,0 @@
1   -1ed1e5d6eb72d173b0c079c8421c175e100ae517 2.1a2
2   -4feb4b5bb60eac893a3f2d2980daf240a3d5c47f 2.1b1
3   -7e5b0be5a387d304a6c75ab959c589edcf837957 2.1a3
4   -80d9b8cb2b431952c95aee736b28a2033eb0a1e6 2.1a1
5   -8708ef6132ecfd824cdf22c86e1ce480cb00c5fe 2.1b2
6   -996f80bffa8cf0998025aefbcde50e5774402ea0 tg2.0.3
7   -e81eb44876d033d8bc10b8ae07a6d81fec3fbedb 2.1rc1
2  CONTRIBUTING.txt
... ... @@ -0,0 +1,2 @@
  1 +Have a look at http://turbogears.org/en/resources
  2 +for how to contribute to the TurboGears project.
11 setup.cfg
@@ -6,21 +6,12 @@ tgdevelop = develop -i http://tg.gy/220
6 6 # Another alias for installing all possible requirements for testing
7 7 tgtesting = easy_install -i http://tg.gy/220 AddOns BytecodeAssembler Chameleon coverage DecoratorTools Extremes Genshi Jinja2 Kajiki kid multiprocessing nose PEAK_Rules repoze.tm2 repoze.who repoze.who_friendlyform repoze.who.plugins.sa simplegeneric sprox SQLAlchemy SymbolType tgext.admin tgext.crud ToscaWidgets transaction TurboJson TurboKid tw.forms zope.interface zope.sqlalchemy tw2.forms tw2.core speaklater
8 8 tgrelease = easy_install yolk basketweaver sphinx
9   -tgnose = nosetests --with-coverage --cover-erase --cover-package=turbogears --with-xunit --verbosity=2
  9 +tgnose = nosetests --with-coverage --cover-erase --cover-package=tg --with-xunit --verbosity=2
10 10
11 11 # A handy alias to run tests with a coverage report
12 12 cover = nosetests --with-coverage
13 13
14 14 [egg_info]
15   -#tag_build = dev
16   -#tag_svn_revision = true
17 15
18 16 [nosetests]
19 17 exclude=who_testutil|kajiki
20   -#verbose=True
21   -#verbosity=1
22   -#detailed-errors=1
23   -# Enable with-coverage manually in the CLI args to see coverage results
24   -#cover-package=tg
25   -#with-doctest=True
26   -#attr=!broken
17 tests/test_stack/test_authz.py
@@ -134,6 +134,10 @@ def index(self):
134 134 def commit(self):
135 135 return 'you can commit'
136 136
  137 + @expose()
  138 + @require(is_user('developer'), smart_denial=True)
  139 + def smartabort(self):
  140 + return {'key': 'value'}
137 141
138 142 class ControllerWithAllowOnlyAttributeAndAuthzDenialHandler(TGController):
139 143 """Mock TG2 protected controller using the .allow_only attribute"""
@@ -247,6 +251,19 @@ def test_authz_denied_in_sub_controller(self):
247 251 assert "was just registered" not in resp.body
248 252 self._check_flash(resp, r'The current user must be \"admin\"')
249 253
  254 + def test_smart_auth_json(self):
  255 + nouser = {'accept': 'application/json'}
  256 + baduser = {'accept': 'application/json',
  257 + 'REMOTE_USER': 'foobar'}
  258 + gooduser = {'accept': 'application/json',
  259 + 'REMOTE_USER': 'developer'}
  260 + resp = self.app.get('/smartabort', extra_environ=nouser, status=401)
  261 + assert resp.status == '401 Unauthorized', 'Expected 401, got %s' % (resp.status)
  262 + resp = self.app.get('/smartabort', extra_environ=baduser, status=403)
  263 + assert resp.status == '403 Forbidden', 'Expected 403, got %s' % (resp.status)
  264 + resp = self.app.get('/smartabort.json', extra_environ=gooduser, status=200)
  265 + assert resp.status == '200 OK', 'Expected 200, got %s' % (resp.body)
  266 +
250 267
251 268 class TestAllowOnlyDecoratorInSubController(BaseIntegrationTests):
252 269 """Test case for the @allow_only decorator in a sub-controller"""
21 tg/configuration/app_config.py
@@ -719,16 +719,29 @@ def add_auth_middleware(self, app, skip_authentication):
719 719 from tgming import setup_ming_auth
720 720 app = setup_ming_auth(app, skip_authentication=skip_authentication, **auth_args)
721 721 else:
722   - from tg.configuration.auth import setup_auth
723   - if 'authenticators' not in auth_args:
  722 + try:
  723 + pos = auth_args['authenticators'].index(('default', None))
  724 + except KeyError:
  725 + pos = None
  726 + except ValueError:
  727 + pos = -1
  728 + if pos is None or pos >= 0:
724 729 if self.auth_backend == "sqlalchemy":
725 730 from tg.configuration.sqla.auth import create_default_authenticator
726 731 auth_args, sqlauth = create_default_authenticator(**auth_args)
727   - auth_args['authenticators'] = [('sqlauth', sqlauth)]
  732 + authenticator = ('sqlauth', sqlauth)
728 733 elif self.auth_backend == "ming":
729 734 from tg.configuration.mongo.auth import create_default_authenticator
730 735 auth_args, mingauth = create_default_authenticator(**auth_args)
731   - auth_args['authenticators'] = [('mingauth', mingauth)]
  736 + authenticator = ('mingauth', mingauth)
  737 + else:
  738 + authenticator = None
  739 + if authenticator:
  740 + if pos is None:
  741 + auth_args['authenticators'] = [authenticator]
  742 + else:
  743 + auth_args['authenticators'][pos] = authenticator
  744 + from tg.configuration.auth import setup_auth
732 745 app = setup_auth(app, skip_authentication=skip_authentication, **auth_args)
733 746
734 747 return app
13 tg/decorators.py
@@ -700,7 +700,7 @@ def sample(self, *args):
700 700 class _BaseProtectionDecorator(object):
701 701 default_denial_handler = None
702 702
703   - def __init__(self, predicate, denial_handler=None):
  703 + def __init__(self, predicate, denial_handler=None, smart_denial=False):
704 704 """Verify that the predicate is met.
705 705
706 706 :param predicate: An object with a check_authorization(environ) method which
@@ -715,6 +715,7 @@ def __init__(self, predicate, denial_handler=None):
715 715
716 716 self.predicate = predicate
717 717 self.denial_handler = denial_handler or self.default_denial_handler
  718 + self.smart_denial = smart_denial
718 719
719 720
720 721 class require(_BaseProtectionDecorator):
@@ -752,12 +753,12 @@ def wrap_action(self, action_, *args, **kwargs):
752 753
753 754 def default_denial_handler(self, reason):
754 755 """Authorization denial handler for protectors."""
755   - if response.status_int == 401:
756   - status = 'warning'
  756 + status = 'warning' if response.status_int == 401 else 'error'
  757 + if not self.smart_denial:
  758 + flash(reason, status=status)
757 759 else:
758   - # Status is a 403
759   - status = 'error'
760   - flash(reason, status=status)
  760 + if response.content_type not in ['application/json', 'text/xml']:
  761 + flash(reason, status=status)
761 762 abort(response.status_int, reason)
762 763
763 764

0 comments on commit e5d2ecf

Please sign in to comment.
Something went wrong with that request. Please try again.