From aae1c513c0a940c1c31c97b4d79fec3d09cbd01e Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Tue, 26 Feb 2019 17:49:36 -0800 Subject: Add `request.identity`. --- src/pyramid/request.py | 5 ++++- src/pyramid/security.py | 32 +++++++++++++++++++++++++++++--- src/pyramid/testing.py | 2 ++ tests/test_security.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/src/pyramid/request.py b/src/pyramid/request.py index b9bd7451a..726f485e7 100644 --- a/src/pyramid/request.py +++ b/src/pyramid/request.py @@ -15,7 +15,9 @@ from pyramid.interfaces import ( from pyramid.decorator import reify from pyramid.i18n import LocalizerRequestMixin from pyramid.response import Response, _get_response_factory -from pyramid.security import AuthenticationAPIMixin, AuthorizationAPIMixin +from pyramid.security import ( + SecurityAPIMixin, AuthenticationAPIMixin, AuthorizationAPIMixin, +) from pyramid.url import URLMethodsMixin from pyramid.util import ( InstancePropertyHelper, @@ -147,6 +149,7 @@ class Request( CallbackMethodsMixin, InstancePropertyMixin, LocalizerRequestMixin, + SecurityAPIMixin, AuthenticationAPIMixin, AuthorizationAPIMixin, ViewMethodsMixin, diff --git a/src/pyramid/security.py b/src/pyramid/security.py index abb9c7442..efc0c193c 100644 --- a/src/pyramid/security.py +++ b/src/pyramid/security.py @@ -44,6 +44,11 @@ def _get_registry(request): return reg +def _get_security_policy(request): + registry = _get_registry(request) + return registry.queryUtility(ISecurityPolicy) + + def _get_authentication_policy(request): registry = _get_registry(request) return registry.queryUtility(IAuthenticationPolicy) @@ -281,6 +286,20 @@ class ACLAllowed(ACLPermitsResult, Allowed): """ +class SecurityAPIMixin(object): + @property + def identity(self): + """ + Return an opaque object identifying the current user or ``None`` if no + user is authenticated or there is no :term:`security policy` in effect. + + """ + policy = _get_security_policy(self) + if policy is None: + return None + return policy.identify(self) + + class AuthenticationAPIMixin(object): @property def authenticated_userid(self): @@ -288,7 +307,10 @@ class AuthenticationAPIMixin(object): ``None`` if there is no :term:`authentication policy` in effect or there is no currently authenticated user. - .. versionadded:: 1.5 + .. deprecated:: 2.0 + + Use ``request.identity`` instead. + """ policy = _get_authentication_policy(self) if policy is None: @@ -305,7 +327,10 @@ class AuthenticationAPIMixin(object): effective authentication policy will not ensure that a record associated with the userid exists in persistent storage. - .. versionadded:: 1.5 + .. deprecated:: 2.0 + + Use ``request.identity`` instead. + """ policy = _get_authentication_policy(self) if policy is None: @@ -319,7 +344,8 @@ class AuthenticationAPIMixin(object): this will return a one-element list containing the :data:`pyramid.security.Everyone` principal. - .. versionadded:: 1.5 + .. deprecated:: 2.0 + """ policy = _get_authentication_policy(self) if policy is None: diff --git a/src/pyramid/testing.py b/src/pyramid/testing.py index ffddd233f..7a85aff85 100644 --- a/src/pyramid/testing.py +++ b/src/pyramid/testing.py @@ -17,6 +17,7 @@ from pyramid.registry import Registry from pyramid.security import ( Authenticated, Everyone, + SecurityAPIMixin, AuthenticationAPIMixin, AuthorizationAPIMixin, ) @@ -303,6 +304,7 @@ class DummyRequest( CallbackMethodsMixin, InstancePropertyMixin, LocalizerRequestMixin, + SecurityAPIMixin, AuthenticationAPIMixin, AuthorizationAPIMixin, ViewMethodsMixin, diff --git a/tests/test_security.py b/tests/test_security.py index ee4340ced..514175a92 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -338,6 +338,23 @@ class TestViewExecutionPermitted(unittest.TestCase): self.assertTrue(result) +class TestIdentity(unittest.TestCase): + def setUp(self): + testing.setUp() + + def tearDown(self): + testing.tearDown() + + def test_identity_no_security_policy(self): + request = _makeRequest() + self.assertEquals(request.identity, None) + + def test_identity(self): + request = _makeRequest() + _registerSecurityPolicy(request.registry, 'yo') + self.assertEqual(request.identity, 'yo') + + class TestAuthenticatedUserId(unittest.TestCase): def setUp(self): testing.setUp() @@ -533,6 +550,27 @@ class DummyContext: self.__dict__.update(kw) +class DummySecurityPolicy: + def __init__(self, result): + self.result = result + + def identify(self, request): + return self.result + + def permits(self, request, context, identity, permission): + return self.result + + def remember(self, request, userid, **kw): + headers = [(_TEST_HEADER, userid)] + self._header_remembered = headers[0] + return headers + + def forget(self, request): + headers = [(_TEST_HEADER, 'logout')] + self._header_forgotten = headers[0] + return headers + + class DummyAuthenticationPolicy: def __init__(self, result): self.result = result @@ -568,6 +606,14 @@ class DummyAuthorizationPolicy: return self.result +def _registerSecurityPolicy(reg, result): + from pyramid.interfaces import ISecurityPolicy + + policy = DummySecurityPolicy(result) + reg.registerUtility(policy, ISecurityPolicy) + return policy + + def _registerAuthenticationPolicy(reg, result): from pyramid.interfaces import IAuthenticationPolicy -- cgit v1.2.3