Skip to content

Commit

Permalink
first shot for #1602
Browse files Browse the repository at this point in the history
  • Loading branch information
merwok committed Jun 22, 2020
1 parent 48a0485 commit baa5928
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 6 deletions.
2 changes: 1 addition & 1 deletion docs/narr/advanced-features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions docs/narr/viewconfig.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
7 changes: 7 additions & 0 deletions src/pyramid/config/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,12 @@ def add_route(
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
Expand Down Expand Up @@ -537,6 +543,7 @@ def add_default_route_predicates(self):
('request_param', p.RequestParamPredicate),
('header', p.HeaderPredicate),
('accept', p.AcceptPredicate),
('is_authenticated', p.IsAuthenticatedPredicate),
('effective_principals', p.EffectivePrincipalsPredicate),
('custom', p.CustomPredicate),
('traverse', p.TraversePredicate),
Expand Down
7 changes: 7 additions & 0 deletions src/pyramid/config/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,12 @@ def wrapper(context, request):
.. versionadded:: 1.4a3
is_authenticated
XXX doc doc
..versionadded:: 2.0
effective_principals
If specified, this value should be a :term:`principal` identifier or
Expand Down Expand Up @@ -1205,6 +1211,7 @@ def add_default_view_predicates(self):
('request_type', p.RequestTypePredicate),
('match_param', p.MatchParamPredicate),
('physical_path', p.PhysicalPathPredicate),
('is_authenticated', p.IsAuthenticatedPredicate),
('effective_principals', p.EffectivePrincipalsPredicate),
('custom', p.CustomPredicate),
):
Expand Down
12 changes: 12 additions & 0 deletions src/pyramid/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ def app_iter_range(start, stop):
""" 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."""
Expand Down Expand Up @@ -233,6 +241,10 @@ def encode_content(encoding='gzip', lazy=False):

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
Expand Down
13 changes: 13 additions & 0 deletions src/pyramid/predicates.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,19 @@ def __call__(self, context, request):
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):
Expand Down
5 changes: 5 additions & 0 deletions src/pyramid/security.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ def authenticated_userid(self):
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
Expand Down
38 changes: 33 additions & 5 deletions tests/test_config/test_predicates.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def _makeOne(self):
('containment', predicates.ContainmentPredicate),
('request_type', predicates.RequestTypePredicate),
('match_param', predicates.MatchParamPredicate),
('is_authenticated', predicates.IsAuthenticatedPredicate),
('custom', predicates.CustomPredicate),
('traverse', predicates.TraversePredicate),
):
Expand All @@ -38,6 +39,19 @@ def test_ordering_xhr_and_request_method_trump_only_containment(self):
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',
Expand Down Expand Up @@ -121,6 +135,7 @@ def test_ordering_number_of_predicates(self):
)
order11, _, _ = self._callFUT(xhr='xhr')
order12, _, _ = self._callFUT()
self.assertTrue(order1 > order0)
self.assertEqual(order1, order2)
self.assertTrue(order3 > order2)
self.assertTrue(order4 > order3)
Expand All @@ -131,7 +146,7 @@ def test_ordering_number_of_predicates(self):
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
Expand All @@ -145,7 +160,8 @@ def test_ordering_importance_of_predicates(self):
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)
Expand All @@ -157,6 +173,7 @@ def test_ordering_importance_of_predicates(self):
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
Expand Down Expand Up @@ -296,6 +313,7 @@ def test_predicate_text_is_correct(self):
]
),
match_param='foo=bar',
is_authenticated=False,
)
self.assertEqual(predicates[0].text(), 'xhr = True')
self.assertEqual(
Expand All @@ -308,9 +326,10 @@ def test_predicate_text_is_correct(self):
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(
Expand Down Expand Up @@ -434,6 +453,15 @@ def test_header_multiple_mixed_fails(self):
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

Expand Down

0 comments on commit baa5928

Please sign in to comment.