summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/narr/advanced-features.rst2
-rw-r--r--docs/narr/viewconfig.rst8
-rw-r--r--src/pyramid/config/routes.py7
-rw-r--r--src/pyramid/config/views.py7
-rw-r--r--src/pyramid/interfaces.py12
-rw-r--r--src/pyramid/predicates.py13
-rw-r--r--src/pyramid/security.py5
-rw-r--r--tests/test_config/test_predicates.py38
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