diff --git a/tests/api/test_formdata.py b/tests/api/test_formdata.py index b2e8af642..bef2e18ca 100644 --- a/tests/api/test_formdata.py +++ b/tests/api/test_formdata.py @@ -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') diff --git a/wcs/formdata.py b/wcs/formdata.py index 8fea86fac..59fcf1b04 100644 --- a/wcs/formdata.py +++ b/wcs/formdata.py @@ -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'] = {} diff --git a/wcs/wf/register_comment.py b/wcs/wf/register_comment.py index 8549713ec..655b936dc 100644 --- a/wcs/wf/register_comment.py +++ b/wcs/wf/register_comment.py @@ -69,7 +69,7 @@ class JournalEvolutionPart: + htmltext('

') ) - 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, diff --git a/wcs/wf/wscall.py b/wcs/wf/wscall.py index 6fd8d792c..b22a5c722 100644 --- a/wcs/wf/wscall.py +++ b/wcs/wf/wscall.py @@ -94,7 +94,7 @@ class JournalWsCallErrorPart: r += htmltext('') 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', } diff --git a/wcs/workflows.py b/wcs/workflows.py index 4b6416c0d..677d406f4 100644 --- a/wcs/workflows.py +++ b/wcs/workflows.py @@ -271,6 +271,18 @@ class AttachmentEvolutionPart: else: return htmltext('

%s

' % 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 {