forms: move captcha to the validation page (#10222)

This commit is contained in:
Frédéric Péters 2016-03-25 10:10:55 +01:00
parent 561bc2d7fd
commit 35c1211f4b
2 changed files with 56 additions and 49 deletions

View File

@ -1374,56 +1374,65 @@ def test_form_captcha(pub):
formdef.data_class().wipe()
formdef.fields = [fields.StringField(id='0', label='Some field')]
formdef.has_captcha = True
formdef.enable_tracking_codes = True
formdef.store()
# test authentic users are not presented with a captcha
# test authenticated users are not presented with a captcha
resp = login(get_app(pub), username='foo', password='foo').get('/')
resp = resp.click('test')
assert 'Some field' in resp.body
resp.form['f0'] = 'test'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.body
assert not 'form_captcha' in resp.body
# check anonymous user gets the captcha
app = get_app(pub)
resp = app.get('/')
resp = resp.click('test')
resp.form['f0'] = 'test'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.body
assert 'form_captcha' in resp.body
session_id = app.cookies.values()[0].strip('"')
session = BasicSession.get(session_id)
resp.forms[0]['captcha$q'] = session.get_captcha_token(resp.forms[0]['captcha$token'].value)['answer']
resp = resp.forms[0].submit()
assert 'Some field' in resp.body
resp.form['captcha$q'] = session.get_captcha_token(resp.forms[0]['captcha$token'].value)['answer']
resp = resp.form.submit('submit')
assert resp.status_code == 302 # redirect when formdata is created
# and check it gets it only once
resp = app.get('/')
resp = resp.click('test')
assert 'Some field' in resp.body
resp.form['f0'] = 'test'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.body
assert not 'form_captcha' in resp.body
def test_form_captcha_and_tracking_code(pub):
def test_form_captcha_and_no_validation_page(pub):
user = create_user(pub)
formdef = create_formdef()
formdef.data_class().wipe()
formdef.fields = [fields.StringField(id='0', label='Some field')]
formdef.has_captcha = True
formdef.enable_tracking_codes = True
formdef.confirmation = False
formdef.store()
# check the captcha is not given as being an error
# test authenticated users are not stopped on a confirmation page
resp = login(get_app(pub), username='foo', password='foo').get('/')
resp = resp.click('test')
resp.form['f0'] = 'test'
resp = resp.form.submit('submit')
assert resp.status_code == 302 # redirect when formdata is created
# check anonymous user gets the captcha
app = get_app(pub)
resp = app.get('/')
resp = resp.click('test')
resp.form['f0'] = 'test'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.body
assert 'form_captcha' in resp.body
assert not 'wrong answer' in resp.body
resp.form['captcha$q'] = 'az' # wrong answer
resp = resp.form.submit()
assert 'form_captcha' in resp.body
assert 'wrong answer' in resp.body
session_id = app.cookies.values()[0].strip('"')
session = BasicSession.get(session_id)
resp.form['captcha$q'] = session.get_captcha_token(resp.forms[0]['captcha$token'].value)['answer']
resp = resp.form.submit()
assert 'f0' in resp.form.fields
def test_form_file_field_submit(pub):
formdef = create_formdef()

View File

@ -258,6 +258,15 @@ class FormPage(Directory):
if not user_roles.intersection(other_roles):
raise errors.AccessForbiddenError()
def has_confirmation_page(self):
if self.formdef.confirmation:
return True
if self.formdef.has_captcha:
session = get_session()
if not (session.get_user() or session.won_captcha):
return True
return False
def step(self, step_no, page_no=0, log_detail=None, data=None):
if step_no == 0:
self.substvars['current_page_no'] = str(page_no + 1)
@ -285,7 +294,7 @@ class FormPage(Directory):
if step_no > 0:
current_position = len(page_labels) + step_no
if self.formdef.confirmation and not self.edit_mode:
if self.has_confirmation_page() and not self.edit_mode:
page_labels.append(_('Validating'))
r = TemplateIO(html=True)
@ -312,34 +321,12 @@ class FormPage(Directory):
r += htmltext('</ol></div>')
return r.getvalue()
def initial_captcha_page(self):
form = Form()
form.add_captcha(hint='')
form.add_submit('submit', _('Next'))
form.add_submit('cancel', _('Cancel'))
if form.get_submit() == 'cancel':
return redirect(get_publisher().get_root_url())
if not form.is_submitted() or form.has_errors():
html_top(self.formdef.name)
r = TemplateIO(html=True)
r += TextsDirectory.get_html_text('captcha-page')
r += form.render()
return r.getvalue()
return self.page(0)
def page(self, page_no, page_change=True, log_detail=None, page_error_messages=None):
r = TemplateIO(html=True)
displayed_fields = []
session = get_session()
if page_no == 0 and self.formdef.has_captcha:
if not session.get_user() and not session.won_captcha:
return self.initial_captcha_page()
if page_no > 0:
magictoken = get_request().form['magictoken']
self.feed_current_data(magictoken)
@ -375,7 +362,7 @@ class FormPage(Directory):
if self.edit_mode and page_no == self.page_number - 1:
form.add_submit('submit', _('Save Changes'))
elif not self.formdef.confirmation and page_no == self.page_number - 1:
elif not self.has_confirmation_page() and page_no == self.page_number - 1:
form.add_submit('submit', _('Submit'))
else:
form.add_submit('submit', _('Next'))
@ -738,7 +725,7 @@ class FormPage(Directory):
if self.edit_mode:
form = self.formdef.create_view_form(form_data, use_tokens=False)
return self.submitted_existing(form)
if self.formdef.confirmation:
if self.has_confirmation_page():
return self.validating(form_data)
else:
step = 1 # so it will flow to submit
@ -793,7 +780,11 @@ class FormPage(Directory):
# so it gets FakeFileWidget in preview mode
form = self.formdef.create_view_form(form_data,
use_tokens = self.formdef.confirmation)
use_tokens=self.has_confirmation_page())
if self.formdef.has_captcha and not (get_session().get_user() or get_session().won_captcha):
form.add_captcha(hint='')
if form.captcha.has_error():
return self.validating(form_data)
if form.has_errors():
# the only possible error here is a token error if the form is
@ -1034,8 +1025,15 @@ class FormPage(Directory):
form = self.formdef.create_view_form(data)
token_widget = form.get_widget(form.TOKEN_NAME)
token_widget._parsed = True
form.add_submit('previous', _('Previous'))
if self.formdef.has_captcha and not (get_session().get_user() or get_session().won_captcha):
get_request().form['captcha$q'] = ''
captcha_text = TextsDirectory.get_html_text('captcha-page')
if captcha_text:
form.widgets.append(HtmlWidget(captcha_text))
form.add_captcha(hint='')
form.captcha.has_error = lambda request: False
form.add_submit('submit', _('Submit'))
form.add_submit('previous', _('Previous'))
form.add_submit('cancel', _('Cancel'), css_class = 'cancel')
session = get_session()
if self.formdef.enable_tracking_codes:
@ -1476,11 +1474,11 @@ TextsDirectory.register('welcome-unlogged',
N_('Welcome text on home page for unlogged users'))
TextsDirectory.register('captcha-page',
N_('Explanation text on the CAPTCHA page'),
N_('Explanation text before the CAPTCHA'),
default = N_('''<h3>Verification</h3>
<p>
In order to proceed you need to complete this simple question.
In order to submit the form you need to complete this simple question.
</p>'''))