Projet

Général

Profil

0001-forms-prevent-autosave-from-overwriting-session-s-da.patch

Benjamin Dauvergne, 23 décembre 2021 09:06

Télécharger (4,86 ko)

Voir les différences:

Subject: [PATCH] forms: prevent autosave from overwriting session's data
 (#58208)

 tests/form_pages/test_all.py | 47 ++++++++++++++++++++++++++++++++++++
 wcs/forms/root.py            | 10 +++++---
 wcs/sessions.py              |  6 ++++-
 3 files changed, 59 insertions(+), 4 deletions(-)
tests/form_pages/test_all.py
4567 4567
    assert formdef.data_class().select()[0].data['3_display'] == 'barbar'
4568 4568

  
4569 4569

  
4570
def test_form_autosave_never_overwrite(mocker, pub, settings):
4571
    create_user(pub)
4572

  
4573
    formdef = create_formdef()
4574
    formdef.data_class().wipe()
4575

  
4576
    formdef.fields = [
4577
        fields.PageField(id='0', label='1st page', type='page'),
4578
        fields.StringField(id='1', label='string1'),
4579
        fields.PageField(id='2', label='2nd page', type='page'),
4580
        fields.StringField(id='3', label='string2'),
4581
    ]
4582
    formdef.store()
4583

  
4584
    app = get_app(pub)
4585
    login(app, username='foo', password='foo')
4586

  
4587
    resp = app.get('/test/')
4588
    resp.form.set('f1', '1')
4589
    # go to the second page
4590
    resp = resp.form.submit('submit')
4591
    resp.form.set('f3', '1')
4592
    # autosave wrong data
4593
    autosave_data = dict(resp.form.submit_fields())
4594
    autosave_data['f3'] = 'wtf!'
4595
    resp_autosave = app.post('/test/autosave', params=autosave_data)
4596
    assert resp_autosave.json == {'result': 'success'}
4597
    # check the draft is fucked
4598
    data = formdef.data_class().select()[0].data
4599
    assert data['3'] == 'wtf!'
4600
    # now finish submitting
4601
    resp = resp.form.submit('submit')  # -> validation page
4602
    # autosave wrong data
4603
    # _ajax_form_token is just a form_token, so take the current one to
4604
    # simulate a rogue autosave from the second page
4605
    autosave_data['_ajax_form_token'] = resp.form['_form_id'].value
4606
    resp_autosave = app.post('/test/autosave', params=autosave_data)
4607
    assert resp_autosave.json == {'result': 'success'}
4608
    data = formdef.data_class().select()[0].data
4609
    assert data['3'] == 'wtf!'
4610
    # validate
4611
    resp = resp.form.submit('submit')  # -> submit
4612

  
4613
    # great everything is still fine in the end
4614
    assert formdef.data_class().select()[0].data == {'1': '1', '3': '1'}
4615

  
4616

  
4570 4617
def test_form_string_field_autocomplete(pub):
4571 4618
    formdef = create_formdef()
4572 4619
    formdef.fields = [fields.StringField(id='0', label='string', type='string', required=False)]
wcs/forms/root.py
1354 1354

  
1355 1355
    def autosave(self):
1356 1356
        get_response().set_content_type('application/json')
1357
        get_request().ignore_session = True
1357 1358

  
1358 1359
        def result_error(reason):
1359
            get_request().ignore_session = True
1360 1360
            return json.dumps({'result': 'error', 'reason': reason})
1361 1361

  
1362 1362
        ajax_form_token = get_request().form.get('_ajax_form_token')
......
1418 1418

  
1419 1419
    def save_draft(self, data, page_no=None):
1420 1420
        filled = self.get_current_draft() or self.formdef.data_class()()
1421
        new_draft = bool(filled.id is None)
1421 1422
        if filled.id and filled.status != 'draft':
1422 1423
            raise SubmittedDraftException()
1423 1424
        filled.data = data
......
1436 1437
            filled.store()
1437 1438

  
1438 1439
            if not filled.user_id:
1439
                get_session().mark_anonymous_formdata(filled)
1440
                if get_session().mark_anonymous_formdata(filled):
1441
                    get_session().store()
1440 1442

  
1441
        data['draft_formdata_id'] = filled.id
1443
        if new_draft:
1444
            data['draft_formdata_id'] = filled.id
1445
            get_session().store()
1442 1446
        self.set_tracking_code(filled, data)
1443 1447

  
1444 1448
        get_logger().info('form %s - saving draft (id: %s)' % (self.formdef.name, filled.id))
wcs/sessions.py
59 59
    def mark_anonymous_formdata(self, formdata):
60 60
        if not self.anonymous_formdata_keys:
61 61
            self.anonymous_formdata_keys = {}
62
        self.anonymous_formdata_keys[formdata.get_object_key()] = True
62
        key = formdata.get_object_key()
63
        if key not in self.anonymous_formdata_keys:
64
            self.anonymous_formdata_keys[key] = True
65
            return True
66
        return False
63 67

  
64 68
    def is_anonymous_submitter(self, formdata):
65 69
        if not self.anonymous_formdata_keys:
66
-