diff options
| -rw-r--r-- | CONTRIBUTORS.txt | 2 | ||||
| -rw-r--r-- | docs/api/authentication.rst | 2 | ||||
| -rw-r--r-- | pyramid/authentication.py | 42 | ||||
| -rw-r--r-- | pyramid/tests/test_authentication.py | 98 | ||||
| -rw-r--r-- | pyramid/url.py | 8 |
5 files changed, 145 insertions, 7 deletions
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index f2195de70..2873ce1b6 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -138,3 +138,5 @@ Contributors - Juliusz Gonera, 2011/04/17 - Philip Jenvey, 2011/04/24 + +- Michael Merickel, 2011/5/25 diff --git a/docs/api/authentication.rst b/docs/api/authentication.rst index bf7f8f8d5..5d4dbd9e3 100644 --- a/docs/api/authentication.rst +++ b/docs/api/authentication.rst @@ -14,6 +14,8 @@ Authentication Policies .. autoclass:: RemoteUserAuthenticationPolicy + .. autoclass:: SessionAuthenticationPolicy + Helper Classes ~~~~~~~~~~~~~~ diff --git a/pyramid/authentication.py b/pyramid/authentication.py index a6c74e549..e1384e0b8 100644 --- a/pyramid/authentication.py +++ b/pyramid/authentication.py @@ -524,4 +524,44 @@ class AuthTktCookieHelper(object): cookie_value = ticket.cookie_value() return self._get_cookies(environ, cookie_value, max_age) - + +class SessionAuthenticationPolicy(CallbackAuthenticationPolicy): + """ A :app:`Pyramid` authentication policy which gets its data from + the configured session. + + Constructor Arguments + + ``prefix`` + + A prefix used when storing the authentication parameters in the + session. Defaults to 'auth.'. Optional. + + ``callback`` + + Default: ``None``. A callback passed the userid and the + request, expected to return ``None`` if the userid doesn't + exist or a sequence of principal identifiers (possibly empty) if + the user does exist. If ``callback`` is ``None``, the userid + will be assumed to exist with no principals. Optional. + """ + implements(IAuthenticationPolicy) + + def __init__(self, prefix='auth.', callback=None): + self.callback = callback + self.prefix = prefix or '' + self.userid_key = prefix + 'userid' + + def remember(self, request, principal, **kw): + """ Store a principal in the session.""" + request.session[self.userid_key] = principal + return [] + + def forget(self, request): + """ Remove the stored principal from the session.""" + if self.userid_key in request.session: + del request.session[self.userid_key] + return [] + + def unauthenticated_userid(self, request): + return request.session.get(self.userid_key) + diff --git a/pyramid/tests/test_authentication.py b/pyramid/tests/test_authentication.py index ecd76a71c..8acc2b31c 100644 --- a/pyramid/tests/test_authentication.py +++ b/pyramid/tests/test_authentication.py @@ -751,12 +751,106 @@ class TestAuthTktCookieHelper(unittest.TestCase): 'auth_tkt=""; Path=/; Domain=.localhost; Max-Age=0; ' 'Expires=Wed, 31-Dec-97 23:59:59 GMT') + +class TestSessionAuthenticationPolicy(unittest.TestCase): + def _getTargetClass(self): + from pyramid.authentication import SessionAuthenticationPolicy + return SessionAuthenticationPolicy + + def _makeOne(self, callback=None, prefix=''): + return self._getTargetClass()(prefix=prefix, callback=callback) + + def test_class_implements_IAuthenticationPolicy(self): + from zope.interface.verify import verifyClass + from pyramid.interfaces import IAuthenticationPolicy + verifyClass(IAuthenticationPolicy, self._getTargetClass()) + + def test_instance_implements_IAuthenticationPolicy(self): + from zope.interface.verify import verifyObject + from pyramid.interfaces import IAuthenticationPolicy + verifyObject(IAuthenticationPolicy, self._makeOne()) + + def test_unauthenticated_userid_returns_None(self): + request = DummyRequest() + policy = self._makeOne() + self.assertEqual(policy.unauthenticated_userid(request), None) + + def test_unauthenticated_userid(self): + request = DummyRequest(session={'userid':'fred'}) + policy = self._makeOne() + self.assertEqual(policy.unauthenticated_userid(request), 'fred') + + def test_authenticated_userid_no_cookie_identity(self): + request = DummyRequest() + policy = self._makeOne() + self.assertEqual(policy.authenticated_userid(request), None) + + def test_authenticated_userid_callback_returns_None(self): + request = DummyRequest(session={'userid':'fred'}) + def callback(userid, request): + return None + policy = self._makeOne(callback) + self.assertEqual(policy.authenticated_userid(request), None) + + def test_authenticated_userid(self): + request = DummyRequest(session={'userid':'fred'}) + def callback(userid, request): + return True + policy = self._makeOne(callback) + self.assertEqual(policy.authenticated_userid(request), 'fred') + + def test_effective_principals_no_identity(self): + from pyramid.security import Everyone + request = DummyRequest() + policy = self._makeOne() + self.assertEqual(policy.effective_principals(request), [Everyone]) + + def test_effective_principals_callback_returns_None(self): + from pyramid.security import Everyone + request = DummyRequest(session={'userid':'fred'}) + def callback(userid, request): + return None + policy = self._makeOne(callback) + self.assertEqual(policy.effective_principals(request), [Everyone]) + + def test_effective_principals(self): + from pyramid.security import Everyone + from pyramid.security import Authenticated + request = DummyRequest(session={'userid':'fred'}) + def callback(userid, request): + return ['group.foo'] + policy = self._makeOne(callback) + self.assertEqual(policy.effective_principals(request), + [Everyone, Authenticated, 'fred', 'group.foo']) + + def test_remember(self): + request = DummyRequest() + policy = self._makeOne() + result = policy.remember(request, 'fred') + self.assertEqual(request.session.get('userid'), 'fred') + self.assertEqual(result, []) + + def test_forget(self): + request = DummyRequest(session={'userid':'fred'}) + policy = self._makeOne() + result = policy.forget(request) + self.assertEqual(request.session.get('userid'), None) + self.assertEqual(result, []) + + def test_forget_no_identity(self): + request = DummyRequest() + policy = self._makeOne() + result = policy.forget(request) + self.assertEqual(request.session.get('userid'), None) + self.assertEqual(result, []) + class DummyContext: pass class DummyRequest: - def __init__(self, environ): - self.environ = environ + def __init__(self, environ=None, session=None): + self.environ = environ or {} + self.session = session or {} self.callbacks = [] def add_response_callback(self, callback): diff --git a/pyramid/url.py b/pyramid/url.py index 2a6fda89a..a9d7862fd 100644 --- a/pyramid/url.py +++ b/pyramid/url.py @@ -20,7 +20,7 @@ def route_url(route_name, request, *elements, **kw): """Generates a fully qualified URL for a named :app:`Pyramid` :term:`route configuration`. - .. note:: Calling :meth:`pyramid.Request.route_url` can be used to + .. note:: Calling :meth:`pyramid.request.Request.route_url` can be used to achieve the same result as :func:`pyramid.url.route_url`. Use the route's ``name`` as the first positional argument. Use a @@ -159,7 +159,7 @@ def route_path(route_name, request, *elements, **kw): """Generates a path (aka a 'relative URL', a URL minus the host, scheme, and port) for a named :app:`Pyramid` :term:`route configuration`. - .. note:: Calling :meth:`pyramid.Request.route_path` can be used to + .. note:: Calling :meth:`pyramid.request.Request.route_path` can be used to achieve the same result as :func:`pyramid.url.route_path`. This function accepts the same argument as :func:`pyramid.url.route_url` @@ -191,7 +191,7 @@ def resource_url(resource, request, *elements, **kw): overall result of this function is always a UTF-8 encoded string (never Unicode). - .. note:: Calling :meth:`pyramid.Request.resource_url` can be used to + .. note:: Calling :meth:`pyramid.request.Request.resource_url` can be used to achieve the same result as :func:`pyramid.url.resource_url`. Examples:: @@ -325,7 +325,7 @@ def static_url(path, request, **kw): :meth:`pyramid.config.Configurator.add_static_view` :term:`configuration declaration` (see :ref:`static_assets_section`). - .. note:: Calling :meth:`pyramid.Request.static_url` can be used to + .. note:: Calling :meth:`pyramid.request.Request.static_url` can be used to achieve the same result as :func:`pyramid.url.static_url`. Example:: |
