Commit d2f0e9a9 authored by Jérome Perrin's avatar Jérome Perrin

Fixes for captcha field

 - fix "numeric" which was not working at all
 - remove the link to captchas.net
 - ~~partial workaround for the problem that sessions are not shared by zopes~~ dropped, because nexedi/erp5!1451 fixes the root cause 

See merge request nexedi/erp5!1450
parents f860e578 95182a5b
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
# TODO: Some tests from this file can be merged into Formulator # TODO: Some tests from this file can be merged into Formulator
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
import hashlib
import mock
import unittest import unittest
# Initialize ERP5Form Product to load monkey patches # Initialize ERP5Form Product to load monkey patches
...@@ -39,6 +41,7 @@ from Products.Formulator.Validator import ValidationError ...@@ -39,6 +41,7 @@ from Products.Formulator.Validator import ValidationError
from Products.Formulator.StandardFields import FloatField, StringField,\ from Products.Formulator.StandardFields import FloatField, StringField,\
DateTimeField, TextAreaField, CheckBoxField, ListField, LinesField, \ DateTimeField, TextAreaField, CheckBoxField, ListField, LinesField, \
MultiListField, IntegerField MultiListField, IntegerField
from Products.ERP5Form.CaptchaField import CaptchaField
from Products.Formulator.MethodField import Method from Products.Formulator.MethodField import Method
from Products.Formulator.TALESField import TALESMethod from Products.Formulator.TALESField import TALESMethod
...@@ -1084,6 +1087,110 @@ class TestFieldValueCache(ERP5TypeTestCase): ...@@ -1084,6 +1087,110 @@ class TestFieldValueCache(ERP5TypeTestCase):
self.assertEqual(True, cache_size == self._getCacheSize('ProxyField.get_value')) self.assertEqual(True, cache_size == self._getCacheSize('ProxyField.get_value'))
class TestCaptchaField(ERP5TypeTestCase):
"""Test Captcha field
"""
def afterSetUp(self):
self.field = CaptchaField('test_field').__of__(self.portal)
self.widget = self.field.widget
self.validator = self.field.validator
def beforeTearDown(self):
self.portal.portal_sessions.manage_delObjects(
[
hashlib.md5(b'1 + 1').hexdigest(),
hashlib.md5(b'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa').hexdigest(),
]
)
if 'Base_viewTestCaptcha' in self.portal.portal_skins.custom.objectIds():
self.portal.portal_skins.custom.manage_delObjects(['Base_viewTestCaptcha'])
self.tic()
def test_numeric_good_captcha(self):
self.field.values['captcha_type'] = 'numeric'
with mock.patch('Products.ERP5Form.CaptchaField.random.randint', return_value=1), \
mock.patch('Products.ERP5Form.CaptchaField.random.choice', side_effect=lambda seq: seq[0]):
field_html = self.field.render(REQUEST=self.portal.REQUEST)
self.assertIn('1 plus 1', field_html)
self.assertIn(hashlib.md5(b'1 + 1').hexdigest(), field_html)
self.assertEqual(
self.validator.validate(
self.field, 'field_test', {
'field_test': '2',
'__captcha_field_test__': hashlib.md5(b'1 + 1').hexdigest()
}),
'2',
)
def test_numeric_bad_captcha(self):
self.field.values['captcha_type'] = 'numeric'
with mock.patch('Products.ERP5Form.CaptchaField.random.randint', return_value=1), \
mock.patch('Products.ERP5Form.CaptchaField.random.choice', side_effect=lambda seq: seq[0]):
self.field.render(REQUEST=self.portal.REQUEST)
self.assertRaises(
ValidationError, self.validator.validate, self.field, 'field_test', {
'field_test': '3',
'__captcha_field_test__': hashlib.md5(b'1 + 1').hexdigest()
})
# once a reply was entered, the correct reply no longer work
self.assertRaises(
ValidationError, self.validator.validate, self.field, 'field_test', {
'field_test': '2',
'__captcha_field_test__': hashlib.md5(b'1 + 1').hexdigest()
})
def test_text_good_captcha(self):
self.field.values['captcha_type'] = 'text'
self.field.values['captcha_dot_net_client'] = 'demo'
self.field.values['captcha_dot_net_secret'] = 'secret'
self.field.values['captcha_dot_net_use_ssl'] = True
with mock.patch('Products.ERP5Form.CaptchasDotNet.random.choice',
side_effect=lambda seq: seq[0]):
field_html = self.field.render(REQUEST=self.portal.REQUEST)
self.assertIn(
'src="https://image.captchas.net/?client=demo&random=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&alphabet=abcdefghkmnopqrstuvwxyz"',
field_html)
self.assertIn(
hashlib.md5(b'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa').hexdigest(),
field_html)
self.assertEqual(
self.validator.validate(
self.field, 'field_test', {
'field_test': 'cbktzg',
'__captcha_field_test__': hashlib.md5(b'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa').hexdigest()
}),
'cbktzg',
)
def test_text_bad_captcha(self):
self.field.values['captcha_type'] = 'text'
self.field.values['captcha_dot_net_client'] = 'demo'
self.field.values['captcha_dot_net_secret'] = 'secret'
self.field.values['captcha_dot_net_use_ssl'] = True
with mock.patch('Products.ERP5Form.CaptchasDotNet.random.choice',
side_effect=lambda seq: seq[0]):
self.field.render(REQUEST=self.portal.REQUEST)
self.assertRaises(
ValidationError, self.validator.validate, self.field, 'field_test', {
'field_test': 'wrong',
'__captcha_field_test__': hashlib.md5(b'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa').hexdigest()
})
# once a reply was entered, the correct reply no longer work
self.assertRaises(
ValidationError, self.validator.validate, self.field, 'field_test', {
'field_test': 'cbktzg',
'__captcha_field_test__': hashlib.md5(b'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa').hexdigest()
})
def makeDummyOid(): def makeDummyOid():
import time, random import time, random
return '%s%s' % (time.time(), random.random()) return '%s%s' % (time.time(), random.random())
...@@ -1103,4 +1210,5 @@ def test_suite(): ...@@ -1103,4 +1210,5 @@ def test_suite():
suite.addTest(unittest.makeSuite(TestMultiListField)) suite.addTest(unittest.makeSuite(TestMultiListField))
suite.addTest(unittest.makeSuite(TestProxyField)) suite.addTest(unittest.makeSuite(TestProxyField))
suite.addTest(unittest.makeSuite(TestFieldValueCache)) suite.addTest(unittest.makeSuite(TestFieldValueCache))
suite.addTest(unittest.makeSuite(TestCaptchaField))
return suite return suite
...@@ -125,7 +125,7 @@ class NumericCaptchaProvider(object): ...@@ -125,7 +125,7 @@ class NumericCaptchaProvider(object):
calculus_text = " ".join(terms) calculus_text = " ".join(terms)
result = eval(calculus_text) result = eval(calculus_text)
return (calculus_text, result) return (calculus_text, str(result))
def getHTML(self, field, captcha_key): def getHTML(self, field, captcha_key):
# Make the text harder to parse for a computer # Make the text harder to parse for a computer
......
...@@ -85,10 +85,9 @@ class CaptchasDotNet: ...@@ -85,10 +85,9 @@ class CaptchasDotNet:
def image (self, random, id = 'captchas.net'): def image (self, random, id = 'captchas.net'):
return ''' return '''
<a href="http://captchas.net"><img <img class="captchas_dot_net"
class="captchas_dot_net"
id="%(id)s" src="%(source)s" width="%(width)d" height="%(height)d" id="%(id)s" src="%(source)s" width="%(width)d" height="%(height)d"
alt="The CAPTCHA image" /></a> alt="The CAPTCHA image" />
<script type="text/javascript"> <script type="text/javascript">
<!-- <!--
function captchas_image_error (image) function captchas_image_error (image)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment