Projet

Général

Profil

0001-forms-force-authentication-if-anonymous-use-user-tra.patch

Nicolas Roche, 08 janvier 2020 15:12

Télécharger (8,08 ko)

Voir les différences:

Subject: [PATCH] forms: force authentication if anonymous use user tracking
 code (#38239)

 tests/test_form_pages.py    | 17 +++++++++++------
 tests/test_tracking_code.py | 30 ++++++++++++++++++++++++------
 wcs/forms/root.py           |  9 ++++++++-
 3 files changed, 43 insertions(+), 13 deletions(-)
tests/test_form_pages.py
1582 1582
    resp = resp.forms[0].submit()
1583 1583
    assert formdef.data_class().get(formdata_id).evolution[-1].comment == 'hello world'
1584 1584

  
1585
    # and check we can also get back to it as anonymous
1585
    # check we can't get back to it as anonymous
1586 1586
    app = get_app(pub)
1587 1587
    resp = app.get('/')
1588 1588
    resp.forms[0]['code'] = tracking_code
1589 1589
    resp = resp.forms[0].submit()
1590 1590
    assert resp.location == 'http://example.net/code/%s/load' % tracking_code
1591 1591
    resp = resp.follow()
1592
    assert resp.location == 'http://example.net/test/%s' % formdata_id
1593
    resp = resp.follow()
1594
    resp = resp.follow()
1595
    assert 'form_comment' in resp.text # makes sure user is treated as submitter
1592
    assert resp.location == 'http://example.net/login/?ReturnUrl=http://example.net/test/%s' % formdata_id
1596 1593

  
1597 1594
    # and check a bot is not allowed to get it
1598 1595
    app = get_app(pub)
......
6020 6017
    formdef.store()
6021 6018
    resp = app.get(formdata.get_url(), status=403)
6022 6019

  
6023
    # agent access via a tracking code (stays in frontoffice)
6020
    # agent access via a tracking code (redirected to login and next backoffice)
6024 6021
    formdef.workflow_roles = {'_receiver': role.id}
6025 6022
    formdef.enable_tracking_codes = True
6026 6023
    formdef.store()
......
6030 6027
    code.store()
6031 6028

  
6032 6029
    resp = app.get('/code/%s/load' % code.id)
6030
    resp = resp.follow() # -> /login/?ReturnUrl=.../test/1
6031
    assert '<title>wcs - Login</title>' in resp.text
6032
    resp.form['username'] = 'admin'
6033
    resp.form['password'] = 'admin'
6034
    resp = resp.form.submit()
6035
    assert resp.status_int == 302
6033 6036
    resp = resp.follow() # -> /test/1
6034 6037
    assert not 'backoffice' in resp.location
6035 6038
    resp = resp.follow() # -> /test/1/
6039
    assert 'backoffice' in resp.location
6040
    resp = resp.follow() # -> /test/1/
6036 6041
    assert 'The form has been recorded' in resp.text
6037 6042

  
6038 6043
    # authorized access but not backoffice access
tests/test_tracking_code.py
183 183
    | agent1 (submiter)   |  login    | deny  | deny  | deny   | back   | back   |
184 184
    | user1               |  login    | allow | deny  | deny   | back   | back   |
185 185

  
186
    2- New user on prefill fields when accessing using tracking code :
186
    2- Access using tracking code :
187

  
188
    | sumitter / accesser | anonymous | user1 | user2 | agent1 | agent2 | admin1 |
189
    +---------------------+-----------+-------+-------+--------+--------+--------+
190
    | anonymous           |  allow    | allow | allow | allow  | allow  | allow  |
191
    | agent1 (submiter))  |  allow    | allow | allow | allow  | allow  | allow  |
192
    | user1               |  login    | allow | login | login  | login  | login  |
193

  
194
    3- New user on prefill fields when accessing using tracking code :
187 195
     a-  Drafts
188 196

  
189 197
    | sumitter / accesser | anonymous | user1 | user2 | agent1 | agent2 | admin1 |
190 198
    +---------------------+-----------+-------+-------+--------+--------+--------+
191 199
    | anonymous           | anonymous | user1 | user2 | agent1 | agent2 | admin  |
192 200
    | agent1 (submiter)   | anonymous | user1 | user2 | agent1 | agent2 | admin  |
193
    | user1               | anonymous | user1 | user2 | agent1 | agent2 | admin  |
201
    | user1               |           | user1 | user2 | agent1 | agent2 | admin  |
194 202

  
195 203
     b-  Demands (evolving into Workflows forms)
196 204

  
......
198 206
    +---------------------+-----------+-------+-------+--------+--------+--------+
199 207
    | anonymous           | anonymous | user1 | user2 | agent1 | agent2 | admin  |
200 208
    | agent1 (submiter)   | anonymous | user1 | user2 | agent1 | agent2 | admin  |
201
    | user1               | anonymous | user1 | user2 | agent1 | agent2 | admin  |
209
    | user1               |           | user1 | user2 | agent1 | agent2 | admin  |
202 210
    """
203 211
    (anonymous, user1, user2, agent1, agent2, admin1) = users
204 212
    tracking_code = None
......
338 346
            else:
339 347
                assert access in ('login', 'deny', 'front',  'back')
340 348

  
341
    def check_tracking_code_access(user, owner=None, new_owner=None):
349
    def check_tracking_code_access(user, owner=None, new_owner=None, access='allow'):
342 350
        """
343 351
        load the formdata using the tracking code and prefill user name fields.
344 352
        new_owner is used to show that user fields change on drafts.
......
353 361
        resp.forms[0]['code'] = tracking_code
354 362
        resp = resp.forms[0].submit()
355 363
        resp = resp.follow()
364
        if access == 'login':
365
            assert resp.location == (
366
                'http://example.net/login/?ReturnUrl='
367
                + 'http://example.net/test/%s') % formdata_id
368
            return
356 369
        resp = resp.follow()
357 370
        resp = resp.follow()
358 371
        assert '<title>Forms - test</title>' in resp.text
......
434 447
            check_direct_access(users[i], access[i])
435 448

  
436 449
    # access to formdata using the tracking code
450
    access = ('login', 'allow', 'login', 'login', 'login', 'login')
437 451
    is_draft = True  # drafts
452
    i = 0
438 453
    for user in users:
439 454
        with submit(anonymous, is_front=True) as (tracking_code, formdata_id):
440 455
            check_tracking_code_access(user, owner=anonymous, new_owner=user)
441 456
        with submit(agent1, is_front=False) as (tracking_code, formdata_id):
442 457
            check_tracking_code_access(user, owner=anonymous, new_owner=user)
443 458
        with submit(user1, is_front=True) as (tracking_code, formdata_id):
444
            check_tracking_code_access(user, owner=user1, new_owner=user)
459
            check_tracking_code_access(user, owner=user1, new_owner=user, access=access[i])
460
        i += 1
445 461

  
446 462
    is_draft = False  # demands
463
    i = 0
447 464
    for user in users:
448 465
        with submit(anonymous, is_front=True) as (tracking_code, formdata_id):
449 466
            check_tracking_code_access(user, owner=anonymous, new_owner=user)
450 467
        with submit(agent1, is_front=False) as (tracking_code, formdata_id):
451 468
            check_tracking_code_access(user, owner=anonymous, new_owner=user)
452 469
        with submit(user1, is_front=True) as (tracking_code, formdata_id):
453
            check_tracking_code_access(user, owner=user1, new_owner=user)
470
            check_tracking_code_access(user, owner=user1, new_owner=user, access=access[i])
471
        i += 1
wcs/forms/root.py
174 174
            raise errors.TraversalError()
175 175
        if BotFilter.is_bot():
176 176
            raise errors.AccessForbiddenError()
177

  
178
        formdata_url = formdata.get_url().rstrip('/')
179
        if formdata.user_id and (not get_request().user
180
                or str(get_request().user.id) != str(formdata.user_id)):
181
            # asked to load a tracking code associated with another user
182
            # don't load, ask for authentication instead
183
            return redirect('/login/?ReturnUrl=%s' % formdata_url)
177 184
        get_session().mark_anonymous_formdata(formdata)
178
        return redirect(formdata.get_url().rstrip('/'))
185
        return redirect(formdata_url)
179 186

  
180 187

  
181 188
class TrackingCodesDirectory(Directory):
182
-