api: allow async mode on import-csv cards (#52137)

This commit is contained in:
Thomas NOËL 2021-03-17 15:28:09 +01:00
parent e5a12818e2
commit 748b70a535
3 changed files with 37 additions and 4 deletions

View File

@ -18,6 +18,7 @@ from wcs.api_utils import sign_url
from wcs.carddef import CardDef
from wcs.categories import CardDefCategory
from wcs.data_sources import NamedDataSource
from wcs.qommon.afterjobs import AfterJob
from wcs.qommon.form import PicklableUpload
from wcs.qommon.http_request import HTTPRequest
from wcs.workflows import Workflow, WorkflowBackofficeFieldsFormDef
@ -185,14 +186,32 @@ def test_cards_import_csv(pub, local_user):
get_app(pub).get(sign_uri('/api/cards/test/import-csv'), status=405)
get_app(pub).put(sign_uri('/api/cards/test/import-csv'), status=403)
get_app(pub).put(
resp = get_app(pub).put(
sign_uri('/api/cards/test/import-csv', user=local_user),
params=b'foobar;foobar2\nfirst entry;plop\nsecond entry;plop\n',
headers={'content-type': 'text/csv'},
)
assert resp.json == {'err': 0}
assert carddef.data_class().count() == 2
assert set([x.data['0'] for x in carddef.data_class().select()]) == {'first entry', 'second entry'}
# async mode
carddef.data_class().wipe()
assert carddef.data_class().count() == 0
resp = get_app(pub).put(
sign_uri('/api/cards/test/import-csv?async=on', user=local_user),
params=b'foobar;foobar2\nfirst entry;plop\nsecond entry;plop\n',
headers={'content-type': 'text/csv'},
)
# afterjobs are not async in tests: job is already completed during request
assert carddef.data_class().count() == 2
assert set([x.data['0'] for x in carddef.data_class().select()]) == {'first entry', 'second entry'}
assert resp.json['err'] == 0
assert 'job' in resp.json['data']
job_id = resp.json['data']['job']['id']
job = AfterJob.get(job_id)
assert AfterJob.get(job_id).status == 'completed'
def test_post_invalid_json(pub, local_user):
resp = get_app(pub).post(

View File

@ -339,12 +339,24 @@ class ApiCardPage(ApiFormPageMixin, BackofficeCardPage):
if not (get_request()._user and self.can_user_add_cards()):
raise AccessForbiddenError('cannot import cards')
afterjob = bool(get_request().form.get('async') == 'on')
get_response().set_content_type('application/json')
try:
self.import_csv_submit(get_request().stdin, afterjob=False)
job = self.import_csv_submit(get_request().stdin, afterjob=afterjob, api=True)
except ValueError as e:
return json.dumps({'err': 1, 'err_desc': str(e)})
return json.dumps({'err': 0})
if job is None:
return json.dumps({'err': 0})
return json.dumps(
{
'err': 0,
'data': {
'job': {
'id': job.id,
}
},
}
)
class ApiFormsDirectory(Directory):

View File

@ -229,7 +229,7 @@ class CardPage(FormPage):
templates=['wcs/backoffice/card-data-import-form.html'], context=context
)
def import_csv_submit(self, fd, afterjob=True):
def import_csv_submit(self, fd, afterjob=True, api=False):
content = fd.read()
if b'\0' in content:
raise ValueError(_('Invalid file format.'))
@ -286,6 +286,8 @@ class CardPage(FormPage):
job = ImportFromCsvAfterJob(carddef=self.formdef, data_lines=data_lines)
if afterjob:
get_response().add_after_job(job)
if api:
return job
return redirect(job.get_processing_url())
else:
job.execute()