diff --git a/crc/models/file.py b/crc/models/file.py index 42cf336e..da59cff7 100644 --- a/crc/models/file.py +++ b/crc/models/file.py @@ -1,13 +1,15 @@ import enum - +import urllib +import flask from marshmallow import INCLUDE, EXCLUDE, Schema +from marshmallow.fields import Method from marshmallow_enum import EnumField from marshmallow_sqlalchemy import SQLAlchemyAutoSchema from sqlalchemy import func, Index from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import deferred, relationship -from crc import db, ma +from crc import db, ma, app from crc.models.data_store import DataStoreModel @@ -144,9 +146,17 @@ class FileSchema(Schema): fields = ["id", "name", "is_status", "is_reference", "content_type", "primary", "primary_process_id", "workflow_spec_id", "workflow_id", "irb_doc_code", "last_modified", "latest_version", "type", "size", "data_store", - "document", "user_uid"] + "document", "user_uid", "url"] unknown = INCLUDE type = EnumField(FileType) + url = Method("get_url") + + def get_url(self, obj): + token = 'not_available' + if hasattr(flask.g, 'user'): + token = flask.g.user.encode_auth_token() + return (app.config['APPLICATION_ROOT'] + 'file/' + + str(obj.id) + '/download?auth_token=' + urllib.parse.quote_plus(token)) class LookupFileModel(db.Model): diff --git a/crc/services/study_service.py b/crc/services/study_service.py index bb4ec86d..914eafd4 100755 --- a/crc/services/study_service.py +++ b/crc/services/study_service.py @@ -14,7 +14,7 @@ from crc import db, session, app from crc.api.common import ApiError from crc.models.data_store import DataStoreModel from crc.models.email import EmailModel -from crc.models.file import FileModel, File +from crc.models.file import FileModel, File, FileSchema from crc.models.ldap import LdapSchema from crc.models.protocol_builder import ProtocolBuilderStudy, ProtocolBuilderStatus @@ -294,15 +294,10 @@ class StudyService(object): token = 'not_available' if hasattr(flask.g, 'user'): token = flask.g.user.encode_auth_token() - for file in doc_files: - file_data = {'file_id': file.id, - 'name': file.name, - 'url': app.config['APPLICATION_ROOT'] + - 'file/' + str(file.id) + - '/download?auth_token=' + - urllib.parse.quote_plus(token), - 'workflow_id': file.workflow_id - } + for file_model in doc_files: + file = File.from_models(file_model, FileService.get_file_data(file_model.id), []) + file_data = FileSchema().dump(file) + del file_data['document'] data = db.session.query(DataStoreModel).filter(DataStoreModel.file_id == file.id).all() data_store_data = {} for d in data: diff --git a/tests/data/file_data_store/file_data_store.bpmn b/tests/data/file_data_store/file_data_store.bpmn index ddc9e987..91939c17 100644 --- a/tests/data/file_data_store/file_data_store.bpmn +++ b/tests/data/file_data_store/file_data_store.bpmn @@ -1,5 +1,5 @@ - + SequenceFlow_1pnq3kg @@ -16,7 +16,7 @@ Flow_0z7kamo filelist = list(documents.keys()) -fileid = documents['UVACompl_PRCAppr'].files[0]['file_id'] +fileid = documents['UVACompl_PRCAppr'].files[0]['id'] fileurl = documents['UVACompl_PRCAppr'].files[0]['url'] @@ -43,6 +43,22 @@ file_data_set(file_id=fileid,key='test',value='me') + + + + + + + + + + + + + + + + @@ -53,34 +69,18 @@ file_data_set(file_id=fileid,key='test',value='me') - - - - - - - - - - - - - - - - diff --git a/tests/study/test_study_service.py b/tests/study/test_study_service.py index 0c66d9b6..ed3b7fcb 100644 --- a/tests/study/test_study_service.py +++ b/tests/study/test_study_service.py @@ -156,7 +156,7 @@ class TestStudyService(BaseTest): self.assertEqual("not_started", docs["UVACompl_PRCAppr"]['status']) self.assertEqual(1, docs["UVACompl_PRCAppr"]['count']) self.assertIsNotNone(docs["UVACompl_PRCAppr"]['files'][0]) - self.assertIsNotNone(docs["UVACompl_PRCAppr"]['files'][0]['file_id']) + self.assertIsNotNone(docs["UVACompl_PRCAppr"]['files'][0]['id']) self.assertEqual(workflow.id, docs["UVACompl_PRCAppr"]['files'][0]['workflow_id']) def test_get_all_studies(self): diff --git a/tests/test_study_info_script.py b/tests/test_study_info_script.py index f5bd92c6..a78698e8 100644 --- a/tests/test_study_info_script.py +++ b/tests/test_study_info_script.py @@ -1,3 +1,6 @@ +import io +import json + from tests.base_test import BaseTest from crc.scripts.study_info import StudyInfo from crc import app @@ -13,15 +16,15 @@ class TestStudyInfoScript(BaseTest): def do_work(self, info_type): app.config['PB_ENABLED'] = True self.load_example_data() - workflow = self.create_workflow('study_info_script') - workflow_api = self.get_workflow_api(workflow) + self.workflow = self.create_workflow('study_info_script') + self.workflow_api = self.get_workflow_api(self.workflow) # grab study_info directly from script - study_info = StudyInfo().do_task(workflow_api.study_id, workflow.study.id, workflow.id, info_type) + study_info = StudyInfo().do_task(self.workflow_api.study_id, self.workflow.study.id, self.workflow.id, info_type) # grab study info through a workflow - first_task = workflow_api.next_task - self.complete_form(workflow, first_task, {'which': info_type}) - workflow_api = self.get_workflow_api(workflow) + first_task = self.workflow_api.next_task + self.complete_form(self.workflow, first_task, {'which': info_type}) + workflow_api = self.get_workflow_api(self.workflow) second_task = workflow_api.next_task return study_info, second_task @@ -81,9 +84,29 @@ class TestStudyInfoScript(BaseTest): self.assertEqual(response['IND_2'], second_task.data['info']['IND_2']) self.assertEqual(response['IND_3'], second_task.data['info']['IND_3']) - # def test_info_script_documents(self): - # study_info, second_task = self.do_work(info_type='documents') - # self.assertEqual(study_info, second_task.data['info']) + def test_info_script_documents(self): + study_info, second_task = self.do_work(info_type='documents') + self.assertEqual(study_info, second_task.data['info']) + self.assertEqual(0, len(study_info['Grant_App']['files']), "Grant_App has not files yet.") + # Add a grant app file + data = {'file': (io.BytesIO(b"abcdef"), 'random_fact.svg')} + rv = self.app.post('/v1.0/file?study_id=%i&workflow_id=%s&task_spec_name=%s&form_field_key=%s' % + (self.workflow.study_id, self.workflow.id, second_task.name, 'Grant_App'), data=data, follow_redirects=True, + content_type='multipart/form-data', headers=self.logged_in_headers()) + self.assert_success(rv) + file_data = json.loads(rv.get_data(as_text=True)) + + # Now get the study info again. + study_info = StudyInfo().do_task(self.workflow_api.study_id, self.workflow.study.id, self.workflow.id, + 'documents') + # The data should contain a file. + self.assertEqual(1, len(study_info['Grant_App']['files']), "Grant_App has exactly one file.") + + # This file data returned should be the same as what we get back about the file when we uploaded it, + # but the details on the document should be removed, because that would be recursive. + del file_data['document'] + self.assertEqual(file_data, study_info['Grant_App']['files'][0]) + @patch('crc.services.protocol_builder.requests.get') def test_info_script_sponsors(self, mock_get):