From 6e552c3fffb633cf7a076bde1440a2a63c097f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Tue, 30 May 2023 17:50:39 +0200 Subject: [PATCH] misc: handle ajax-uploaded files in mass actions (#78026) --- tests/backoffice_pages/test_all.py | 10 +++++++++- wcs/forms/actions.py | 2 ++ wcs/qommon/form.py | 11 ++--------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/tests/backoffice_pages/test_all.py b/tests/backoffice_pages/test_all.py index b927c0699..cc2e4d393 100644 --- a/tests/backoffice_pages/test_all.py +++ b/tests/backoffice_pages/test_all.py @@ -1244,7 +1244,8 @@ def test_backoffice_multi_actions_interactive_create_carddata(pub): } -def test_backoffice_multi_actions_interactive_file_field(pub): +@pytest.mark.parametrize('upload_mode', ['no_ajax', 'ajax']) +def test_backoffice_multi_actions_interactive_file_field(pub, upload_mode): user = create_superuser(pub) workflow = Workflow.get_default_workflow() @@ -1290,6 +1291,13 @@ def test_backoffice_multi_actions_interactive_file_field(pub): resp = resp.follow() assert '5 selected forms' in resp.text resp.form['fblah_1$file'] = Upload('test3.txt', b'foobar3', 'text/plain') + if upload_mode == 'ajax': + # this part is actually done in javascript + upload_url = resp.form['fblah_1$file'].attrs['data-url'] + upload_resp = app.post(upload_url, params=resp.form.submit_fields()) + resp.form['fblah_1$file'] = None + resp.form['fblah_1$token'] = upload_resp.json[0]['token'] + resp = resp.form.submit('submit') assert '?job=' in resp.location diff --git a/wcs/forms/actions.py b/wcs/forms/actions.py index 5f3c07ee6..7671f9880 100644 --- a/wcs/forms/actions.py +++ b/wcs/forms/actions.py @@ -180,6 +180,7 @@ class GlobalInteractiveActionDirectory(Directory, FormTemplateMixin): user_id=get_request().user.id, action_id=self.action.id, item_ids=self.token.context['form_ids'], + session_id=get_session().id, return_url=self.token.context['return_url'], ) ) @@ -221,6 +222,7 @@ class GlobalInteractiveMassActionAfterJob(AfterJob): user = publisher.user_class.get(self.kwargs['user_id']) for item_id in self.kwargs['item_ids']: publisher._set_request(req) + req.session = publisher.session_class.get(self.kwargs['session_id']) formdata = data_class.get(item_id) self.execute_one(publisher, formdata, action, user) self.increment_count() diff --git a/wcs/qommon/form.py b/wcs/qommon/form.py index f4f73f909..2bd0e7c4b 100644 --- a/wcs/qommon/form.py +++ b/wcs/qommon/form.py @@ -933,19 +933,15 @@ class FileWithPreviewWidget(CompositeWidget): def set_value_from_token(self, request): self.value = None - if self.get('token') and get_session(): + if self.get('token'): token = self.get('token') - elif self.get('file') and get_session(): + elif self.get('file'): try: token = get_session().add_tempfile(self.get('file'), storage=self.storage)['token'] except UploadStorageError: self.set_error(_('failed to store file (system error)')) return request.form[self.get_widget('token').get_name()] = token - elif self.get('file') and not get_session(): - # a file field in a global interactive form being run in an afterjob - self.value = self.get('file') - return else: token = None @@ -981,9 +977,6 @@ class FileWithPreviewWidget(CompositeWidget): if isinstance(self.value.fp, io.BufferedRandom): # internally recreated file, trust supplied MIME type filetype = self.value.content_type - elif not get_session() and isinstance(self.value.fp, io.BytesIO): - # a file field in a global interactive form being run in an afterjob - filetype = self.value.content_type elif magic and self.value.fp: mime = magic.Magic(mime=True) filetype = mime.from_file(self.value.fp.name)