misc: expose session identifier in substitution variables (#24778)

This commit is contained in:
Frédéric Péters 2018-06-26 16:29:04 +02:00
parent 82ff638ffe
commit 6d243cb198
4 changed files with 58 additions and 5 deletions

View File

@ -4239,14 +4239,12 @@ def test_session_cookie_flags(pub):
formdef = create_formdef()
app = get_app(pub)
resp = app.get('/test/', status=200)
resp = resp.form.submit('submit')
assert resp.headers['Set-Cookie'].startswith('wcs-')
assert 'httponly' in resp.headers['Set-Cookie']
assert not 'secure' in resp.headers['Set-Cookie']
app = get_app(pub, https=True)
resp = app.get('/test/', status=200)
resp = resp.form.submit('submit')
assert resp.headers['Set-Cookie'].startswith('wcs-')
assert 'httponly' in resp.headers['Set-Cookie']
assert 'secure' in resp.headers['Set-Cookie']

View File

@ -7,6 +7,8 @@ from quixote import cleanup
from wcs.qommon.ident.password_accounts import PasswordAccount
from wcs.qommon.http_request import HTTPRequest
from wcs.formdef import FormDef
from wcs import fields
from utilities import create_temporary_pub, clean_temporary_pub, get_app, login
@ -159,3 +161,41 @@ def test_session_do_not_reuse_id(pub, user, app):
resp = login_form.submit()
assert resp.status_int == 302
assert pub.session_manager.session_class.count() == 2
def test_session_substitution_variables(pub, user, app):
pub.session_manager.session_class.wipe()
resp = app.get('/')
formdef = FormDef()
formdef.name = 'foobar'
formdef.fields = [fields.CommentField(id='7', label='Hello [session_id]', type='comment')]
formdef.store()
resp = app.get('/foobar/')
assert pub.session_manager.session_class.count() == 1
session_id = pub.session_manager.session_class.select()[0].id
assert 'Hello %s' % session_id in resp.body
login(app, username='foo', password='foo')
assert pub.session_manager.session_class.count() == 2
session_id = [x for x in pub.session_manager.session_class.select() if x.id != session_id][0].id
resp = app.get('/foobar/')
assert 'Hello %s' % session_id in resp.body
def test_session_substitution_variables_1st_page_condition(pub, user, app):
pub.session_manager.session_class.wipe()
resp = app.get('/')
formdef = FormDef()
formdef.name = 'foobar'
formdef.fields = [fields.PageField(id='0', label='1st PAGE', type='page',
condition={'type': 'python', 'value': 'vars().get("session_id") is not None'}),
fields.CommentField(id='7', label='COM1 [session_id]', type='comment'),
fields.PageField(id='8', label='2nd PAGE', type='page'),
fields.CommentField(id='9', label='COM2 [session_id]', type='comment')]
formdef.store()
resp = app.get('/foobar/')
assert pub.session_manager.session_class.count() == 1
session_id = pub.session_manager.session_class.select()[0].id
assert 'COM1' in resp.body

View File

@ -516,6 +516,11 @@ class FormPage(Directory, FormTemplateMixin):
return redirect(self.check_disabled())
session = get_session()
if not session.id:
# force session to be written down, this is required so
# [session_var_id] is available on the first page.
session.force()
if self.formdef.enable_tracking_codes:
if get_request().form.get('_ajax_form_token'):
# _ajax_form_token is immediately removed, this prevents

View File

@ -89,11 +89,19 @@ class Session(QommonSession, CaptchaSession, StorableObject):
jsonp_display_values = None
extra_variables = None
expire = None
forced = False
# should only be overwritten by authentication methods
extra_user_variables = None
username = None # only set on password authentication
def force(self):
# add some data in the session, it will force a cookie to be set, this
# is used so we get a session identifier fixed even on the first page
# of a form.
self.forced = True
get_session_manager().maintain_session(self)
def set_expire(self, expire):
self.expire = expire
@ -126,6 +134,7 @@ class Session(QommonSession, CaptchaSession, StorableObject):
CaptchaSession.has_info(self) or \
self.expire or \
self.extra_user_variables or \
self.forced or \
QuixoteSession.has_info(self)
is_dirty = has_info
@ -313,14 +322,15 @@ class Session(QommonSession, CaptchaSession, StorableObject):
self.extra_variables = {}
self.extra_variables.update(kwargs)
def get_substitution_variables(self, prefix='session_var_'):
def get_substitution_variables(self, prefix='session_'):
d = {}
d[prefix + 'id'] = self.id
if self.extra_variables:
for k, v in self.extra_variables.items():
d[prefix + k] = v
d[prefix + 'var_' + k] = v
if self.extra_user_variables:
for k, v in self.extra_user_variables.items():
d[prefix + 'user_' + k] = v
d[prefix + 'var_user_' + k] = v
return d
@classmethod