Projet

Général

Profil

0001-misc-do-not-save-initial-draft-for-requests-from-app.patch

Frédéric Péters, 08 décembre 2020 20:02

Télécharger (5,27 ko)

Voir les différences:

Subject: [PATCH] misc: do not save initial draft for requests from
 applications (#49260)

 data/webbots                 |  1 -
 tests/form_pages/test_all.py | 30 ++++++++++++++++++++++++++++++
 wcs/forms/root.py            |  5 ++---
 wcs/qommon/http_request.py   | 12 ++++++++++++
 wcs/qommon/logger.py         |  8 +++++---
 5 files changed, 49 insertions(+), 7 deletions(-)
data/webbots
13 13
jan.gelin@av.com
14 14
FAST-WebCrawler
15 15
crawler@fast.no
16
Wget
17 16
Acoon Robot
18 17
antibot
19 18
Atomz
tests/form_pages/test_all.py
2148 2148
    assert '2012-02-12' in resp.text
2149 2149

  
2150 2150

  
2151
def test_form_draft_from_prefill(pub):
2152
    formdef = create_formdef()
2153
    formdef.fields = [
2154
        fields.StringField(id='0', label='string'),
2155
    ]
2156
    formdef.enable_tracking_codes = True
2157
    formdef.store()
2158
    formdef.data_class().wipe()
2159

  
2160
    # no draft
2161
    resp = get_app(pub).get('/test/')
2162
    assert formdef.data_class().count() == 0
2163
    formdef.data_class().wipe()
2164

  
2165
    # draft created if there's been some prefilled fields
2166
    formdef.fields[0].prefill = {'type': 'string', 'value': '{{request.GET.test|default:""}}'}
2167
    formdef.store()
2168
    resp = get_app(pub).get('/test/?test=hello')
2169
    assert formdef.data_class().count() == 1
2170
    formdef.data_class().wipe()
2171

  
2172
    # unless the call was made from an application
2173
    resp = get_app(pub).get('/test/?test=hello', headers={'User-agent': 'python-requests/0'})
2174
    assert formdef.data_class().count() == 0
2175

  
2176
    # or a bot
2177
    resp = get_app(pub).get('/test/?test=hello', headers={'User-agent': 'Googlebot'})
2178
    assert formdef.data_class().count() == 0
2179

  
2180

  
2151 2181
@pytest.mark.parametrize('tracking_code', [True, False])
2152 2182
def test_form_direct_draft_access(pub, tracking_code):
2153 2183
    user = create_user(pub)
wcs/forms/root.py
43 43
from ..qommon import misc, get_logger
44 44
from ..qommon import template
45 45
from ..qommon.form import *
46
from ..qommon.logger import BotFilter
47 46
from ..qommon import emails
48 47

  
49 48
from wcs.categories import Category
......
172 171
            raise errors.TraversalError()
173 172
        if formdata.formdef.enable_tracking_codes is False:
174 173
            raise errors.TraversalError()
175
        if BotFilter.is_bot():
174
        if get_request().is_from_bot():
176 175
            raise errors.AccessForbiddenError()
177 176
        get_session().mark_anonymous_formdata(formdata)
178 177
        return redirect(formdata.get_url())
......
466 465
                # include prefilled data
467 466
                transient_formdata = self.get_transient_formdata()
468 467
                transient_formdata.data.update(self.formdef.get_data(form))
469
                if self.has_draft_support():
468
                if self.has_draft_support() and not (req.is_from_application() or req.is_from_bot()):
470 469
                    # save to get prefilling data in database
471 470
                    self.save_draft(form_data)
472 471
            else:
wcs/qommon/http_request.py
184 184
    def is_in_frontoffice(self):
185 185
        return not (self.is_in_backoffice() or self.is_api_url())
186 186

  
187
    def is_from_bot(self):
188
        from .logger import BotFilter
189
        return BotFilter.is_bot(request=self)
190

  
191
    def is_from_application(self):
192
        # detect calls made from other applications or debug tools
193
        # this is not to detect bots (is_from_bot above)
194
        user_agent = self.get_environ('HTTP_USER_AGENT', '')
195
        return (user_agent.startswith('python-requests') or
196
                user_agent.startswith('curl') or
197
                user_agent.startswith('Wget'))
198

  
187 199
    @property
188 200
    def META(self):
189 201
        return self.environ
wcs/qommon/logger.py
52 52
        return 1
53 53

  
54 54
    @classmethod
55
    def is_bot(cls):
55
    def is_bot(cls, request=None):
56
        if request is None:
57
            request = get_request()
56 58
        botfile = os.path.join(get_publisher().data_dir, 'webbots')
57
        if os.path.exists(botfile) and get_request():
58
            user_agent = get_request().get_environ('HTTP_USER_AGENT', '')
59
        if request and os.path.exists(botfile):
60
            user_agent = request.get_environ('HTTP_USER_AGENT', '')
59 61
            with open(botfile) as fd:
60 62
                for bot_ua_string in [x.strip() for x in fd.readlines()]:
61 63
                    if bot_ua_string in user_agent:
62
-