api: include attachment evolution parts in {card,form}data fetch API (#53253)

This commit is contained in:
Nicolas Roche 2021-04-27 11:15:01 +02:00 committed by Frédéric Péters
parent 07e14d9126
commit 51d935656a
5 changed files with 82 additions and 6 deletions

View File

@ -24,7 +24,12 @@ from wcs.qommon import ods
from wcs.qommon.http_request import HTTPRequest
from wcs.qommon.ident.password_accounts import PasswordAccount
from wcs.qommon.upload_storage import PicklableUpload
from wcs.workflows import EditableWorkflowStatusItem, Workflow, WorkflowBackofficeFieldsFormDef
from wcs.workflows import (
AttachmentEvolutionPart,
EditableWorkflowStatusItem,
Workflow,
WorkflowBackofficeFieldsFormDef,
)
from ..utilities import clean_temporary_pub, create_temporary_pub, get_app, login
from .utils import sign_uri
@ -464,6 +469,56 @@ def test_formdata_with_workflow_data(pub, local_user):
assert base64.decodebytes(force_bytes(resp.json['workflow']['data']['blah2']['content'])) == b'test'
def test_formdata_with_evolution_part_attachment(pub, local_user):
pub.role_class.wipe()
role = pub.role_class(name='test')
role.id = '123'
role.store()
local_user.roles = [role.id]
local_user.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'test'
formdef.fields = []
workflow = Workflow.get_default_workflow()
workflow.id = '2'
workflow.store()
formdef.workflow_id = workflow.id
formdef.workflow_roles = {'_receiver': role.id}
formdef.store()
formdef.data_class().wipe()
formdata = formdef.data_class()()
formdata.just_created()
formdata.status = 'wf-new'
formdata.evolution[-1].status = 'wf-new'
formdata.evolution[-1].parts = [
AttachmentEvolutionPart(
'hello.txt', fp=io.BytesIO(b'test'), content_type='text/plain', varname='testfile'
)
]
formdata.store()
resp = get_app(pub).get(sign_uri('/api/forms/test/%s/' % formdata.id, user=local_user))
assert len(resp.json['evolution']) == 1
assert len(resp.json['evolution'][0]['parts']) == 1
part = resp.json['evolution'][0]['parts'][0]
assert part['filename'] == 'hello.txt'
assert part['content_type'] == 'text/plain'
assert 'content' in part
assert base64.decodebytes(force_bytes(part['content'])) == b'test'
resp = get_app(pub).get(sign_uri('/api/forms/test/%s/?anonymise' % formdata.id, user=local_user))
assert len(resp.json['evolution']) == 1
assert 'parts' not in resp.json['evolution']
# check this doesn't get into list of forms API
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on', user=local_user))
assert 'hello.txt' not in resp.text
def test_api_list_formdata(pub, local_user):
pub.role_class.wipe()
role = pub.role_class(name='test')

View File

@ -159,7 +159,7 @@ class Evolution:
self._display_parts = l
return self._display_parts
def get_json_export_dict(self, user, anonymise=False):
def get_json_export_dict(self, user, anonymise=False, include_files=True):
data = {
'time': datetime.datetime(*self.time[:6]) if self.time else None,
'last_jump_datetime': self.last_jump_datetime,
@ -180,7 +180,10 @@ class Evolution:
parts = []
for part in self.parts or []:
if hasattr(part, 'get_json_export_dict'):
parts.append(part.get_json_export_dict(anonymise=anonymise))
d = part.get_json_export_dict(anonymise=anonymise, include_files=include_files)
if d:
parts.append(d)
if parts:
data['parts'] = parts
return data
@ -1213,7 +1216,13 @@ class FormData(StorableObject):
if self.evolution:
evolution = data['evolution'] = []
for evo in self.evolution:
evolution.append(evo.get_json_export_dict(None if anonymise else user, anonymise=anonymise))
evolution.append(
evo.get_json_export_dict(
user=None if anonymise else user,
anonymise=anonymise,
include_files=include_files,
)
)
if self.geolocations:
data['geolocations'] = {}

View File

@ -69,7 +69,7 @@ class JournalEvolutionPart:
+ htmltext('</p>')
)
def get_json_export_dict(self, anonymise=False):
def get_json_export_dict(self, anonymise=False, include_files=True):
d = {
'type': 'workflow-comment',
'to': self.to,

View File

@ -94,7 +94,7 @@ class JournalWsCallErrorPart:
r += htmltext('</div>')
return r.getvalue()
def get_json_export_dict(self, anonymise=False):
def get_json_export_dict(self, anonymise=False, include_files=True):
d = {
'type': 'wscall-error',
}

View File

@ -271,6 +271,18 @@ class AttachmentEvolutionPart:
else:
return htmltext('<p class="wf-attachment">%s</p>' % self.orig_filename)
def get_json_export_dict(self, anonymise=False, include_files=True):
if not include_files or anonymise:
return None
d = {
'type': 'workflow-attachment',
'content_type': self.content_type,
'filename': self.base_filename,
}
with open(self.filename, 'rb') as fd:
d['content'] = base64.encodebytes(fd.read())
return d
@classmethod
def get_substitution_variables(cls, formdata):
return {