forms: prevent autosave from overwriting session's data (#58208)
This commit is contained in:
parent
827d7d4898
commit
d9f1f6e378
|
@ -4567,6 +4567,53 @@ def test_form_autosave_with_parameterized_datasource(pub):
|
|||
assert formdef.data_class().select()[0].data['3_display'] == 'barbar'
|
||||
|
||||
|
||||
def test_form_autosave_never_overwrite(mocker, pub, settings):
|
||||
create_user(pub)
|
||||
|
||||
formdef = create_formdef()
|
||||
formdef.data_class().wipe()
|
||||
|
||||
formdef.fields = [
|
||||
fields.PageField(id='0', label='1st page', type='page'),
|
||||
fields.StringField(id='1', label='string1'),
|
||||
fields.PageField(id='2', label='2nd page', type='page'),
|
||||
fields.StringField(id='3', label='string2'),
|
||||
]
|
||||
formdef.store()
|
||||
|
||||
app = get_app(pub)
|
||||
login(app, username='foo', password='foo')
|
||||
|
||||
resp = app.get('/test/')
|
||||
resp.form.set('f1', '1')
|
||||
# go to the second page
|
||||
resp = resp.form.submit('submit')
|
||||
resp.form.set('f3', '1')
|
||||
# autosave wrong data
|
||||
autosave_data = dict(resp.form.submit_fields())
|
||||
autosave_data['f3'] = 'wtf!'
|
||||
resp_autosave = app.post('/test/autosave', params=autosave_data)
|
||||
assert resp_autosave.json == {'result': 'success'}
|
||||
# check the draft is fucked
|
||||
data = formdef.data_class().select()[0].data
|
||||
assert data['3'] == 'wtf!'
|
||||
# now finish submitting
|
||||
resp = resp.form.submit('submit') # -> validation page
|
||||
# autosave wrong data
|
||||
# _ajax_form_token is just a form_token, so take the current one to
|
||||
# simulate a rogue autosave from the second page
|
||||
autosave_data['_ajax_form_token'] = resp.form['_form_id'].value
|
||||
resp_autosave = app.post('/test/autosave', params=autosave_data)
|
||||
assert resp_autosave.json == {'result': 'success'}
|
||||
data = formdef.data_class().select()[0].data
|
||||
assert data['3'] == 'wtf!'
|
||||
# validate
|
||||
resp = resp.form.submit('submit') # -> submit
|
||||
|
||||
# great everything is still fine in the end
|
||||
assert formdef.data_class().select()[0].data == {'1': '1', '3': '1'}
|
||||
|
||||
|
||||
def test_form_string_field_autocomplete(pub):
|
||||
formdef = create_formdef()
|
||||
formdef.fields = [fields.StringField(id='0', label='string', type='string', required=False)]
|
||||
|
|
|
@ -1354,9 +1354,9 @@ class FormPage(Directory, FormTemplateMixin):
|
|||
|
||||
def autosave(self):
|
||||
get_response().set_content_type('application/json')
|
||||
get_request().ignore_session = True
|
||||
|
||||
def result_error(reason):
|
||||
get_request().ignore_session = True
|
||||
return json.dumps({'result': 'error', 'reason': reason})
|
||||
|
||||
ajax_form_token = get_request().form.get('_ajax_form_token')
|
||||
|
@ -1418,6 +1418,7 @@ class FormPage(Directory, FormTemplateMixin):
|
|||
|
||||
def save_draft(self, data, page_no=None):
|
||||
filled = self.get_current_draft() or self.formdef.data_class()()
|
||||
new_draft = bool(filled.id is None)
|
||||
if filled.id and filled.status != 'draft':
|
||||
raise SubmittedDraftException()
|
||||
filled.data = data
|
||||
|
@ -1436,9 +1437,12 @@ class FormPage(Directory, FormTemplateMixin):
|
|||
filled.store()
|
||||
|
||||
if not filled.user_id:
|
||||
get_session().mark_anonymous_formdata(filled)
|
||||
if get_session().mark_anonymous_formdata(filled):
|
||||
get_session().store()
|
||||
|
||||
data['draft_formdata_id'] = filled.id
|
||||
if new_draft:
|
||||
data['draft_formdata_id'] = filled.id
|
||||
get_session().store()
|
||||
self.set_tracking_code(filled, data)
|
||||
|
||||
get_logger().info('form %s - saving draft (id: %s)' % (self.formdef.name, filled.id))
|
||||
|
|
|
@ -59,7 +59,11 @@ class BasicSession(Session):
|
|||
def mark_anonymous_formdata(self, formdata):
|
||||
if not self.anonymous_formdata_keys:
|
||||
self.anonymous_formdata_keys = {}
|
||||
self.anonymous_formdata_keys[formdata.get_object_key()] = True
|
||||
key = formdata.get_object_key()
|
||||
if key not in self.anonymous_formdata_keys:
|
||||
self.anonymous_formdata_keys[key] = True
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_anonymous_submitter(self, formdata):
|
||||
if not self.anonymous_formdata_keys:
|
||||
|
|
Loading…
Reference in New Issue