Mercurial > p > roundup > code
changeset 5166:232c74973a56
issue1408570: fix that form values are lost
.. on edit exceptions. This occured for example if editing an issue with
the classic template and setting 'superseder' to a non-existing issue
number. All changes to the form where the original field was non-empty
were lost.
| author | Ralf Schlatterbeck <rsc@runtux.com> |
|---|---|
| date | Mon, 22 Aug 2016 22:19:48 +0200 |
| parents | a86860224d80 |
| children | 984134ca9a55 |
| files | CHANGES.txt roundup/cgi/client.py roundup/cgi/templating.py test/test_cgi.py |
| diffstat | 4 files changed, 95 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGES.txt Mon Aug 15 20:53:37 2016 -0400 +++ b/CHANGES.txt Mon Aug 22 22:19:48 2016 +0200 @@ -317,10 +317,11 @@ %20. Fixes to allow a url_query method to be applied to HTMLStringProperty to properly quote string values passed as part of a url. -- issue2550755: exceptions.NotFound(msg) msg is not reported to user - in cgi. When an invalid column is specified return error code 400 - rather than 404. Make error code 400 also return an error message to - the user. Reported by: Bernhard Reiter, analysis, fix by John Rouillard. +- issue1408570: Finally fix that form values are lost on edit + exceptions. This occured for example if editing an issue with the + classic template and setting 'superseder' to a non-existing issue + number. All changes to the form where the original field was non-empty + were lost. 2016-01-11: 1.5.1
--- a/roundup/cgi/client.py Mon Aug 15 20:53:37 2016 -0400 +++ b/roundup/cgi/client.py Mon Aug 22 22:19:48 2016 +0200 @@ -295,6 +295,10 @@ self.env = env self.setTranslator(translator) self.mailer = Mailer(instance.config) + # If True the form contents wins over the database contents when + # rendering html properties. This is set when an error occurs so + # that we don't lose submitted form contents. + self.form_wins = False # save off the path self.path = env['PATH_INFO'] @@ -421,6 +425,9 @@ def add_error_message(self, msg, escape=True): add_message(self._error_message, msg, escape) + # Want to interpret form values when rendering when an error + # occurred: + self.form_wins = True def inner_main(self): """Process a request.
--- a/roundup/cgi/templating.py Mon Aug 15 20:53:37 2016 -0400 +++ b/roundup/cgi/templating.py Mon Aug 22 22:19:48 2016 +0200 @@ -1251,7 +1251,7 @@ is_in = form.has_key(self._formname) except TypeError: is_in = False - if not self._value and is_in: + if is_in and (not self._value or self._client.form_wins): if isinstance(prop, hyperdb.Multilink): value = lookupIds(self._db, prop, handleListCGIValue(form[self._formname]),
--- a/test/test_cgi.py Mon Aug 15 20:53:37 2016 -0400 +++ b/test/test_cgi.py Mon Aug 22 22:19:48 2016 +0200 @@ -13,9 +13,13 @@ from roundup.cgi import client, actions, exceptions from roundup.cgi.exceptions import FormError from roundup.cgi.templating import HTMLItem, HTMLRequest, NoTemplate +from roundup.cgi.templating import HTMLProperty, _HTMLItem from roundup.cgi.form_parser import FormParser from roundup import init, instance, password, hyperdb, date +# For testing very simple rendering +from roundup.cgi.engine_zopetal import RoundupPageTemplate + from mocknull import MockNull import db_test_base @@ -117,13 +121,20 @@ self.FV_SPECIAL = re.compile(FormParser.FV_LABELS%classes, re.VERBOSE) - def parseForm(self, form, classname='test', nodeid=None): + def setupClient(self, form, classname, nodeid=None, template='item'): cl = client.Client(self.instance, None, {'PATH_INFO':'/', 'REQUEST_METHOD':'POST'}, makeForm(form)) cl.classname = classname cl.nodeid = nodeid cl.language = ('en',) + cl.userid = '1' cl.db = self.db + cl.user = 'admin' + cl.template = template + return cl + + def parseForm(self, form, classname='test', nodeid=None): + cl = self.setupClient(form, classname, nodeid) return cl.parsePropsFromForm(create=1) def tearDown(self): @@ -772,6 +783,76 @@ 'name': 'foo.txt', 'type': 'text/plain'}}, [('issue', None, 'files', [('file', '-1')])])) + def testFormValuePreserveOnError(self): + page_template = """ + <html> + <body> + <p tal:condition="options/error_message|nothing" + tal:repeat="m options/error_message" + tal:content="structure m"/> + <p tal:content="context/title/plain"/> + <p tal:content="context/priority/plain"/> + <p tal:content="context/status/plain"/> + <p tal:content="context/nosy/plain"/> + <p tal:content="context/keyword/plain"/> + <p tal:content="structure context/superseder/field"/> + </body> + </html> + """.strip () + self.db.keyword.create (name = 'key1') + self.db.keyword.create (name = 'key2') + nodeid = self.db.issue.create (title = 'Title', priority = '1', + status = '1', nosy = ['1'], keyword = ['1']) + self.db.commit () + form = {':note': 'msg-content', 'title': 'New title', + 'priority': '2', 'status': '2', 'nosy': '1,2', 'keyword': '', + 'superseder': '5000', ':action': 'edit'} + cl = self.setupClient(form, 'issue', '1') + pt = RoundupPageTemplate() + pt.pt_edit(page_template, 'text/html') + out = [] + def wh(s): + out.append(s) + cl.write_html = wh + # Enable the following if we get a templating error: + #def send_error (*args, **kw): + # import pdb; pdb.set_trace() + #cl.send_error_to_admin = send_error + # Need to rollback the database on error -- this usually happens + # in web-interface (and for other databases) anyway, need it for + # testing that the form values are really used, not the database! + # We do this together with the setup of the easy template above + def load_template(x): + cl.db.rollback() + return pt + cl.instance.templates.load = load_template + cl.selectTemplate = MockNull() + cl.determine_context = MockNull () + def hasPermission(s, p, classname=None, d=None, e=None, **kw): + return True + actions.Action.hasPermission = hasPermission + e1 = _HTMLItem.is_edit_ok + _HTMLItem.is_edit_ok = lambda x : True + e2 = HTMLProperty.is_edit_ok + HTMLProperty.is_edit_ok = lambda x : True + cl.inner_main() + _HTMLItem.is_edit_ok = e1 + HTMLProperty.is_edit_ok = e2 + self.assertEqual(len(out), 1) + self.assertEqual(out [0].strip (), """ + <html> + <body> + <p>Edit Error: issue has no node 5000</p> + <p>New title</p> + <p>urgent</p> + <p>deferred</p> + <p>admin, anonymous</p> + <p></p> + <p><input type="text" name="superseder" value="5000" size="30"></p> + </body> + </html> + """.strip ()) + # # SECURITY #
