Projet

Général

Profil

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

Benjamin Dauvergne, 23 novembre 2021 11:21

Télécharger (4,85 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
4376 4376
    assert formdef.data_class().select()[0].data['3_display'] == 'barbar'
4377 4377

  
4378 4378

  
4379
def test_form_autosave_never_overwrite(mocker, pub, settings):
4380
    create_user(pub)
4381

  
4382
    formdef = create_formdef()
4383
    formdef.data_class().wipe()
4384

  
4385
    formdef.fields = [
4386
        fields.PageField(id='0', label='1st page', type='page'),
4387
        fields.StringField(id='1', label='string1'),
4388
        fields.PageField(id='2', label='2nd page', type='page'),
4389
        fields.StringField(id='3', label='string2'),
4390
    ]
4391
    formdef.store()
4392

  
4393
    app = get_app(pub)
4394
    login(app, username='foo', password='foo')
4395

  
4396
    resp = app.get('/test/')
4397
    resp.form.set('f1', '1')
4398
    # go to the second page
4399
    resp = resp.form.submit('submit')
4400
    resp.form.set('f3', '1')
4401
    # autosave wrong data
4402
    autosave_data = dict(resp.form.submit_fields())
4403
    autosave_data['f3'] = 'wtf!'
4404
    resp_autosave = app.post('/test/autosave', params=autosave_data)
4405
    assert resp_autosave.json == {'result': 'success'}
4406
    # check the draft is fucked
4407
    data = formdef.data_class().select()[0].data
4408
    assert data['3'] == 'wtf!'
4409
    # now finish submitting
4410
    resp = resp.form.submit('submit')  # -> validation page
4411
    # autosave wrong data
4412
    # _ajax_form_token is just a form_token, so take the current one to
4413
    # simulate a rogue autosave from the second page
4414
    autosave_data['_ajax_form_token'] = resp.form['_form_id'].value
4415
    resp_autosave = app.post('/test/autosave', params=autosave_data)
4416
    assert resp_autosave.json == {'result': 'success'}
4417
    data = formdef.data_class().select()[0].data
4418
    assert data['3'] == 'wtf!'
4419
    # validate
4420
    resp = resp.form.submit('submit')  # -> submit
4421

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

  
4425

  
4379 4426
def test_form_string_field_autocomplete(pub):
4380 4427
    formdef = create_formdef()
4381 4428
    formdef.fields = [fields.StringField(id='0', label='string', type='string', required=False)]
wcs/forms/root.py
1299 1299

  
1300 1300
    def autosave(self):
1301 1301
        get_response().set_content_type('application/json')
1302
        get_request().ignore_session = True
1302 1303

  
1303 1304
        def result_error(reason):
1304
            get_request().ignore_session = True
1305 1305
            return json.dumps({'result': 'error', 'reason': reason})
1306 1306

  
1307 1307
        ajax_form_token = get_request().form.get('_ajax_form_token')
......
1360 1360

  
1361 1361
    def save_draft(self, data, page_no=None):
1362 1362
        filled = self.get_current_draft() or self.formdef.data_class()()
1363
        new_draft = bool(filled.id is None)
1363 1364
        if filled.id and filled.status != 'draft':
1364 1365
            raise SubmittedDraftException()
1365 1366
        filled.data = data
......
1378 1379
            filled.store()
1379 1380

  
1380 1381
            if not filled.user_id:
1381
                get_session().mark_anonymous_formdata(filled)
1382
                if get_session().mark_anonymous_formdata(filled):
1383
                    get_session().store()
1382 1384

  
1383
        data['draft_formdata_id'] = filled.id
1385
        if new_draft:
1386
            data['draft_formdata_id'] = filled.id
1387
            get_session().store()
1384 1388
        self.set_tracking_code(filled, data)
1385 1389

  
1386 1390
        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
-