misc: create session substitution variables from query string (#7858)
This commit is contained in:
parent
e5b689bc99
commit
d367031503
|
@ -213,4 +213,50 @@ champs, etc.
|
|||
|
||||
</section>
|
||||
|
||||
<section id="session-variables">
|
||||
<title>Variables de session</title>
|
||||
|
||||
<p>
|
||||
La session de l'usager contient une série d'informations fixes (par exemple
|
||||
le <code>session_user_display_name</code> décrit en haut de page), il est
|
||||
aussi possible d'y ajouter de nouvelles données par l'intermédiaire de
|
||||
liens contenant des paramètres. Cela permet par exemple d'inclure une URL
|
||||
personnalisée dans un courriel vers l'usager qui assurera le
|
||||
préremplissage automatique de champs.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Le fonctionnement est simple, si le site reçoit une adresse avec des
|
||||
paramètres de la forme <code>session_var_<var>nom</var></code>, une
|
||||
variable du même nom (<code>session_var_<var>nom</var></code>) est rendue
|
||||
disponible.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Un autre exemple pourrait être de faire varier le thème en fonction du site
|
||||
extérieur ayant pointé vers le formulaire, une URL serait par exemple
|
||||
<code>https://www.example.net/?session_var_departement=42</code> et le
|
||||
squelette du site pourrait avoir le code suivant :
|
||||
</p>
|
||||
|
||||
<example>
|
||||
[if-any session_var_departement]
|
||||
<link rel="stylesheet" type="text/css" href="extra/[session_var_departement].css"/>
|
||||
[end]
|
||||
</example>
|
||||
|
||||
<note style="important">
|
||||
<p>
|
||||
Ce fonctionnement doit explicitement être autorisé par
|
||||
l'administrateur système, la liste des variables permises doit être ajoutée
|
||||
au fichier <code>site_options.cfg</code>, dans la section
|
||||
<code>[options]</code>, par exemple :
|
||||
</p>
|
||||
<example>
|
||||
<code>query_string_allowed_vars = departement,une_autre_variable</code>
|
||||
</example>
|
||||
</note>
|
||||
|
||||
</section>
|
||||
|
||||
</page>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import pytest
|
||||
import hashlib
|
||||
import os
|
||||
|
||||
from wcs.qommon.ident.password_accounts import PasswordAccount
|
||||
from wcs.formdef import FormDef
|
||||
|
@ -884,3 +885,59 @@ def test_form_items_data_source_field_submit(pub):
|
|||
'0_structured': [
|
||||
{'id': '1', 'more': 'foo', 'text': 'un'},
|
||||
{'id': '3', 'more': 'baz', 'text': 'trois'}]}
|
||||
|
||||
def test_form_page_query_string_prefill(pub):
|
||||
user = create_user(pub)
|
||||
formdef = create_formdef()
|
||||
formdef.data_class().wipe()
|
||||
formdef.fields = [fields.StringField(id='0', label='string',
|
||||
prefill={'type': 'formula', 'value': 'session_var_foo'})]
|
||||
formdef.store()
|
||||
|
||||
# check it's empty if it doesn't exist
|
||||
resp = get_app(pub).get('/test/')
|
||||
assert resp.forms[0]['f0'].value == ''
|
||||
|
||||
# check it's not set if it's not whitelisted
|
||||
resp = get_app(pub).get('/?session_var_foo=hello')
|
||||
assert resp.location == 'http://example.net/'
|
||||
resp = resp.follow()
|
||||
resp = resp.click('test')
|
||||
assert resp.forms[0]['f0'].value == ''
|
||||
|
||||
# check it works
|
||||
open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w').write('''[options]
|
||||
query_string_allowed_vars = foo,bar
|
||||
''')
|
||||
|
||||
resp = get_app(pub).get('/?session_var_foo=hello')
|
||||
assert resp.location == 'http://example.net/'
|
||||
resp = resp.follow()
|
||||
resp = resp.click('test')
|
||||
assert resp.forms[0]['f0'].value == 'hello'
|
||||
|
||||
# check it survives a login
|
||||
resp = get_app(pub).get('/?session_var_foo=hello2')
|
||||
assert resp.location == 'http://example.net/'
|
||||
resp = resp.follow()
|
||||
resp = resp.click('Login')
|
||||
resp = resp.follow()
|
||||
resp.forms[0]['username'] = 'foo'
|
||||
resp.forms[0]['password'] = 'foo'
|
||||
resp = resp.forms[0].submit()
|
||||
resp = resp.follow()
|
||||
resp = resp.click('test')
|
||||
assert resp.forms[0]['f0'].value == 'hello2'
|
||||
|
||||
# check repeated options are ignored
|
||||
resp = get_app(pub).get('/?session_var_foo=hello&session_var_foo=hello2')
|
||||
assert resp.location == 'http://example.net/'
|
||||
resp = resp.follow()
|
||||
resp = resp.click('test')
|
||||
assert resp.forms[0]['f0'].value == ''
|
||||
|
||||
# check extra query string parameters are not lost
|
||||
resp = get_app(pub).get('/?session_var_foo=hello&foo=bar')
|
||||
assert resp.location == 'http://example.net/?foo=bar'
|
||||
|
||||
os.unlink(os.path.join(pub.app_dir, 'site-options.cfg'))
|
||||
|
|
|
@ -578,6 +578,35 @@ class QommonPublisher(Publisher):
|
|||
if request.get_environ('QOMMON_PAGE_TEMPLATE_KEY'):
|
||||
request.response.page_template_key = request.get_environ('QOMMON_PAGE_TEMPLATE_KEY')
|
||||
|
||||
# handle session_var_<xxx> in query strings, add them to session and
|
||||
# redirect to same URL without the parameters
|
||||
if request.get_method() == 'GET' and request.form:
|
||||
query_string_allowed_vars = self.get_site_option(
|
||||
'query_string_allowed_vars') or ''
|
||||
query_string_allowed_vars = [x.strip() for x in
|
||||
query_string_allowed_vars.split(',')]
|
||||
had_session_variables = False
|
||||
session_variables = {}
|
||||
for k, v in request.form.items():
|
||||
if k.startswith('session_var_'):
|
||||
had_session_variables = True
|
||||
session_variable = str(k[len('session_var_'):])
|
||||
# only add variable to session if it's a string, this
|
||||
# handles the case of repeated parameters producing a
|
||||
# list of values (by ignoring those parameters altogether).
|
||||
if session_variable in query_string_allowed_vars and (
|
||||
isinstance(v, str)):
|
||||
session_variables[session_variable] = v
|
||||
del request.form[k]
|
||||
if had_session_variables:
|
||||
self.start_request() # creates session
|
||||
request.session.add_extra_variables(**session_variables)
|
||||
self.finish_successful_request() # commits session
|
||||
new_query_string = ''
|
||||
if request.form:
|
||||
new_query_string = '?' + urllib.urlencode(request.form)
|
||||
return redirect(request.get_path() + new_query_string)
|
||||
|
||||
request.language = self.get_site_language()
|
||||
self.install_lang(request.language)
|
||||
self.substitutions.feed(self)
|
||||
|
|
|
@ -80,6 +80,7 @@ class Session(QommonSession, CaptchaSession, StorableObject):
|
|||
ident_idp_token = None
|
||||
tempfiles = None
|
||||
jsonp_display_values = None
|
||||
extra_variables = None
|
||||
|
||||
username = None # only set on password authentication
|
||||
|
||||
|
@ -92,6 +93,7 @@ class Session(QommonSession, CaptchaSession, StorableObject):
|
|||
self.ident_idp_token or \
|
||||
self.tempfiles or \
|
||||
self.jsonp_display_values or \
|
||||
self.extra_variables or \
|
||||
CaptchaSession.has_info(self) or \
|
||||
QuixoteSession.has_info(self)
|
||||
is_dirty = has_info
|
||||
|
@ -205,6 +207,18 @@ class Session(QommonSession, CaptchaSession, StorableObject):
|
|||
value.fp = open(filename)
|
||||
return value
|
||||
|
||||
def add_extra_variables(self, **kwargs):
|
||||
if not self.extra_variables:
|
||||
self.extra_variables = {}
|
||||
self.extra_variables.update(kwargs)
|
||||
|
||||
def get_substitution_variables(self, prefix='session_var_'):
|
||||
d = {}
|
||||
if self.extra_variables:
|
||||
for k, v in self.extra_variables.items():
|
||||
d[prefix + k] = v
|
||||
return d
|
||||
|
||||
|
||||
class QommonSessionManager(QuixoteSessionManager):
|
||||
def start_request(self):
|
||||
|
|
|
@ -283,6 +283,7 @@ class RootDirectory(Directory):
|
|||
if not hasattr(response, 'breadcrumb'):
|
||||
response.breadcrumb = [ ('', _('Home')) ]
|
||||
|
||||
get_publisher().substitutions.feed(get_session())
|
||||
get_publisher().substitutions.feed(get_request().user)
|
||||
get_publisher().substitutions.feed(NamedDataSource)
|
||||
|
||||
|
|
Loading…
Reference in New Issue