From 14f863d9b5c323303155c79901f22c5d0e1dbe69 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 8 Jan 2011 00:02:41 -0500 Subject: - ``pyramid.interfaces.ISession.get_csrf_token`` now mandates that an implementation should return a *new* token if one doesn't already exist in the session (previously it would return None). The internal sessioning implementation has been changed. --- CHANGES.txt | 5 +++++ TODO.txt | 3 --- pyramid/interfaces.py | 9 ++++++--- pyramid/session.py | 5 ++++- pyramid/tests/test_session.py | 7 +++++++ 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 6157e3426..b7be0aea0 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -83,6 +83,11 @@ Backwards Incompatibilities when the global function named ``pyramid.security.unauthenticated_userid`` is invoked, so if you're not invoking that, you will not notice any issues. +- ``pyramid.interfaces.ISession.get_csrf_token`` now mandates that an + implementation should return a *new* token if one doesn't already exist in + the session (previously it would return None). The internal sessioning + implementation has been changed. + Documentation ------------- diff --git a/TODO.txt b/TODO.txt index a61da36b8..745b4abe4 100644 --- a/TODO.txt +++ b/TODO.txt @@ -16,9 +16,6 @@ Must-Have (before 1.0) - Use a commit veto when configuring repoze.tm2 in paster templates for non-1X, 2X, or 3X responses. -- Make ``get_csrf_token`` call ``new_csrf_token`` (session timeout is - probably fine for the token). - - Consider passing two callables to CallbackAuthenticationPolicy: one for validating/obtaining the userid, the other for returning groups. diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index b109df77e..14ff100b1 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -517,9 +517,12 @@ class ISession(Interface): forgery protection token. Return the token. It will be a string.""" def get_csrf_token(): - """ Get the CSRF token previously added to the session via - ``new_csrf_token``, and return the token. If no CSRF token exists, - the value returned will be ``None``. + """ Return a random cross-site request forgery protection token. It + will be a string. If a token was previously added to the session via + ``new_csrf_token``, that token will be returned. If no CSRF token + was previously set into the session, ``new_csrf_token`` will be + called, which will create and set a token, and this token will be + returned. """ # mapping methods diff --git a/pyramid/session.py b/pyramid/session.py index 516815d99..9fbb79bf7 100644 --- a/pyramid/session.py +++ b/pyramid/session.py @@ -194,7 +194,10 @@ def UnencryptedCookieSessionFactoryConfig( @manage_accessed def get_csrf_token(self): - return self.get('_csrft_', None) + token = self.get('_csrft_', None) + if token is None: + token = self.new_csrf_token() + return token # non-API methods def _set_cookie(self, response): diff --git a/pyramid/tests/test_session.py b/pyramid/tests/test_session.py index 0e88b28cd..251d92c23 100644 --- a/pyramid/tests/test_session.py +++ b/pyramid/tests/test_session.py @@ -178,6 +178,13 @@ class TestUnencryptedCookieSession(unittest.TestCase): self.assertEqual(token, 'token') self.failUnless('_csrft_' in session) + def test_get_csrf_token_new(self): + request = testing.DummyRequest() + session = self._makeOne(request) + token = session.get_csrf_token() + self.failUnless(token) + self.failUnless('_csrft_' in session) + class Test_manage_accessed(unittest.TestCase): def _makeOne(self, wrapped): from pyramid.session import manage_accessed -- cgit v1.2.3