diff options
| author | Éric Araujo <merwok@netwok.org> | 2020-06-22 16:33:13 -0400 |
|---|---|---|
| committer | Éric Araujo <merwok@netwok.org> | 2020-06-22 16:33:13 -0400 |
| commit | baa59284e1ee26284ecb68d957d5607e40ed786f (patch) | |
| tree | f41bff89b8c65ea4bcdc557a4e1dd4c35ddb4f1c | |
| parent | 48a04855ad4f1f1ae6af934090f35a4ad035ed67 (diff) | |
| download | pyramid-baa59284e1ee26284ecb68d957d5607e40ed786f.tar.gz pyramid-baa59284e1ee26284ecb68d957d5607e40ed786f.tar.bz2 pyramid-baa59284e1ee26284ecb68d957d5607e40ed786f.zip | |
first shot for #1602
| -rw-r--r-- | docs/narr/advanced-features.rst | 2 | ||||
| -rw-r--r-- | docs/narr/viewconfig.rst | 8 | ||||
| -rw-r--r-- | src/pyramid/config/routes.py | 7 | ||||
| -rw-r--r-- | src/pyramid/config/views.py | 7 | ||||
| -rw-r--r-- | src/pyramid/interfaces.py | 12 | ||||
| -rw-r--r-- | src/pyramid/predicates.py | 13 | ||||
| -rw-r--r-- | src/pyramid/security.py | 5 | ||||
| -rw-r--r-- | tests/test_config/test_predicates.py | 38 |
8 files changed, 86 insertions, 6 deletions
diff --git a/docs/narr/advanced-features.rst b/docs/narr/advanced-features.rst index 6e819ff5b..6f3b4e11b 100644 --- a/docs/narr/advanced-features.rst +++ b/docs/narr/advanced-features.rst @@ -34,7 +34,7 @@ For our example above, you can do this instead: .. code-block:: python :linenos: - @view_config(route_name="items", effective_principals=pyramid.authorization.Authenticated) + @view_config(route_name="items", is_authenticated=True) def auth_view(request): # do one thing diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index b43ebb93e..c60b7b50d 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -494,6 +494,12 @@ configured view. .. versionadded:: 1.4a3 +``is_authenticated`` + + XXX doc doc + + .. versionadded:: 2.0 + ``effective_principals`` If specified, this value should be a :term:`principal` identifier or a sequence of principal identifiers. If the @@ -505,6 +511,8 @@ configured view. .. versionadded:: 1.4a4 + .. deprecated:: TODO add + ``custom_predicates`` If ``custom_predicates`` is specified, it must be a sequence of references to custom predicate callables. Custom predicates can be combined with diff --git a/src/pyramid/config/routes.py b/src/pyramid/config/routes.py index a12e18fa8..0fbfcca0c 100644 --- a/src/pyramid/config/routes.py +++ b/src/pyramid/config/routes.py @@ -268,6 +268,12 @@ class RoutesConfiguratorMixin: Removed support for media ranges. + is_authenticated + + XXX doc doc + + .. versionadded:: 2.0 + effective_principals If specified, this value should be a :term:`principal` identifier or @@ -537,6 +543,7 @@ class RoutesConfiguratorMixin: ('request_param', p.RequestParamPredicate), ('header', p.HeaderPredicate), ('accept', p.AcceptPredicate), + ('is_authenticated', p.IsAuthenticatedPredicate), ('effective_principals', p.EffectivePrincipalsPredicate), ('custom', p.CustomPredicate), ('traverse', p.TraversePredicate), diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py index a064ebd05..87f2cbcd7 100644 --- a/src/pyramid/config/views.py +++ b/src/pyramid/config/views.py @@ -712,6 +712,12 @@ class ViewsConfiguratorMixin: .. versionadded:: 1.4a3 + is_authenticated + + XXX doc doc + + ..versionadded:: 2.0 + effective_principals If specified, this value should be a :term:`principal` identifier or @@ -1205,6 +1211,7 @@ class ViewsConfiguratorMixin: ('request_type', p.RequestTypePredicate), ('match_param', p.MatchParamPredicate), ('physical_path', p.PhysicalPathPredicate), + ('is_authenticated', p.IsAuthenticatedPredicate), ('effective_principals', p.EffectivePrincipalsPredicate), ('custom', p.CustomPredicate), ): diff --git a/src/pyramid/interfaces.py b/src/pyramid/interfaces.py index e92662f11..85539c2f2 100644 --- a/src/pyramid/interfaces.py +++ b/src/pyramid/interfaces.py @@ -113,6 +113,14 @@ class IResponse(Interface): """ Return a new app_iter built from the response app_iter that serves up only the given start:stop range. """ + authenticated_identity = Attribute( + """XXX Doc doc""" + ) + + authenticated_userid = Attribute( + """XXX Doc doc""" + ) + body = Attribute( """The body of the response, as a str. This will read in the entire app_iter if necessary.""" @@ -233,6 +241,10 @@ class IResponse(Interface): headers = Attribute(""" The headers in a dictionary-like object """) + is_authenticated = Attribute( + """XXX doc doc""" + ) + last_modified = Attribute( """ Gets and sets and deletes the Last-Modified header. For more information on Last-Modified see RFC 2616 section 14.29. Converts diff --git a/src/pyramid/predicates.py b/src/pyramid/predicates.py index 576bbbce6..fe8bc228c 100644 --- a/src/pyramid/predicates.py +++ b/src/pyramid/predicates.py @@ -276,6 +276,19 @@ class PhysicalPathPredicate: return False +class IsAuthenticatedPredicate: + def __init__(self, val, config): + self.val = val + + def text(self): + return "is_authenticated = %r" % (self.val,) + + phash = text + + def __call__(self, context, request): + return request.is_authenticated == self.val + + class EffectivePrincipalsPredicate: def __init__(self, val, config): if is_nonstr_iter(val): diff --git a/src/pyramid/security.py b/src/pyramid/security.py index 58bc72116..356286407 100644 --- a/src/pyramid/security.py +++ b/src/pyramid/security.py @@ -244,6 +244,11 @@ class SecurityAPIMixin: return None return policy.authenticated_userid(self) + @property + def is_authenticated(self): + """Return True if a user is authenticated for this request.""" + return self.authenticated_identity is not None + def has_permission(self, permission, context=None): """ Given a permission and an optional context, returns an instance of :data:`pyramid.security.Allowed` if the permission is granted to this diff --git a/tests/test_config/test_predicates.py b/tests/test_config/test_predicates.py index 8017fc898..6797e71bc 100644 --- a/tests/test_config/test_predicates.py +++ b/tests/test_config/test_predicates.py @@ -19,6 +19,7 @@ class TestPredicateList(unittest.TestCase): ('containment', predicates.ContainmentPredicate), ('request_type', predicates.RequestTypePredicate), ('match_param', predicates.MatchParamPredicate), + ('is_authenticated', predicates.IsAuthenticatedPredicate), ('custom', predicates.CustomPredicate), ('traverse', predicates.TraversePredicate), ): @@ -38,6 +39,19 @@ class TestPredicateList(unittest.TestCase): def test_ordering_number_of_predicates(self): from pyramid.config.predicates import predvalseq + order0, _, _ = self._callFUT( + xhr='xhr', + request_method='request_method', + path_info='path_info', + request_param='param', + match_param='foo=bar', + header='header', + accept='accept', + is_authenticated=True, + containment='containment', + request_type='request_type', + custom=predvalseq([DummyCustomPredicate()]), + ) order1, _, _ = self._callFUT( xhr='xhr', request_method='request_method', @@ -121,6 +135,7 @@ class TestPredicateList(unittest.TestCase): ) order11, _, _ = self._callFUT(xhr='xhr') order12, _, _ = self._callFUT() + self.assertTrue(order1 > order0) self.assertEqual(order1, order2) self.assertTrue(order3 > order2) self.assertTrue(order4 > order3) @@ -131,7 +146,7 @@ class TestPredicateList(unittest.TestCase): self.assertTrue(order9 > order8) self.assertTrue(order10 > order9) self.assertTrue(order11 > order10) - self.assertTrue(order12 > order10) + self.assertTrue(order12 > order11) def test_ordering_importance_of_predicates(self): from pyramid.config.predicates import predvalseq @@ -145,7 +160,8 @@ class TestPredicateList(unittest.TestCase): order7, _, _ = self._callFUT(containment='containment') order8, _, _ = self._callFUT(request_type='request_type') order9, _, _ = self._callFUT(match_param='foo=bar') - order10, _, _ = self._callFUT( + order10, _, _ = self._callFUT(is_authenticated=True) + order11, _, _ = self._callFUT( custom=predvalseq([DummyCustomPredicate()]) ) self.assertTrue(order1 > order2) @@ -157,6 +173,7 @@ class TestPredicateList(unittest.TestCase): self.assertTrue(order7 > order8) self.assertTrue(order8 > order9) self.assertTrue(order9 > order10) + self.assertTrue(order10 > order11) def test_ordering_importance_and_number(self): from pyramid.config.predicates import predvalseq @@ -296,6 +313,7 @@ class TestPredicateList(unittest.TestCase): ] ), match_param='foo=bar', + is_authenticated=False, ) self.assertEqual(predicates[0].text(), 'xhr = True') self.assertEqual( @@ -308,9 +326,10 @@ class TestPredicateList(unittest.TestCase): self.assertEqual(predicates[6].text(), 'containment = containment') self.assertEqual(predicates[7].text(), 'request_type = request_type') self.assertEqual(predicates[8].text(), "match_param foo=bar") - self.assertEqual(predicates[9].text(), 'custom predicate') - self.assertEqual(predicates[10].text(), 'classmethod predicate') - self.assertTrue(predicates[11].text().startswith('custom predicate')) + self.assertEqual(predicates[9].text(), "is_authenticated = False") + self.assertEqual(predicates[10].text(), 'custom predicate') + self.assertEqual(predicates[11].text(), 'classmethod predicate') + self.assertTrue(predicates[12].text().startswith('custom predicate')) def test_predicate_text_is_correct_when_multiple(self): _, predicates, _ = self._callFUT( @@ -434,6 +453,15 @@ class TestPredicateList(unittest.TestCase): request.headers = {'foo': 'nobar', 'spamme': 'ham'} self.assertFalse(predicates[0](Dummy(), request)) + def test_is_authenticated_true_matches(self): + ... + def test_is_authenticated_true_fails(self): + ... + def test_is_authenticated_false_matches(self): + ... + def test_is_authenticated_false_fails(self): + ... + def test_unknown_predicate(self): from pyramid.exceptions import ConfigurationError |
