Пример #1
0
    def get_study(study_id, study_model: StudyModel = None):
        """Returns a study model that contains all the workflows organized by category.
        IMPORTANT:  This is intended to be a lightweight call, it should never involve
        loading up and executing all the workflows in a study to calculate information."""
        if not study_model:
            study_model = session.query(StudyModel).filter_by(id=study_id).first()
        study = Study.from_model(study_model)
        study.categories = StudyService.get_categories()
        workflow_metas = StudyService.__get_workflow_metas(study_id)
        study.approvals = ApprovalService.get_approvals_for_study(study.id)
        files = FileService.get_files_for_study(study.id)
        files = (File.from_models(model, FileService.get_file_data(model.id),
                         FileService.get_doc_dictionary()) for model in files)
        study.files = list(files)

        # Calling this line repeatedly is very very slow.  It creates the
        # master spec and runs it.  Don't execute this for Abandoned studies, as
        # we don't have the information to process them.
        if study.protocol_builder_status != ProtocolBuilderStatus.ABANDONED:
            status = StudyService.__get_study_status(study_model)
            study.warnings = StudyService.__update_status_of_workflow_meta(workflow_metas, status)

            # Group the workflows into their categories.
            for category in study.categories:
                category.workflows = {w for w in workflow_metas if w.category_id == category.id}

        return study
    def get_image_file_data(self, fields_str, task):
        image_file_data = []
        images_field_str = re.sub(r'[\[\]]', '', fields_str)
        images_field_keys = [
            v.strip() for v in images_field_str.strip().split(',')
        ]
        for field_key in images_field_keys:
            if field_key in task.data:
                v = task.data[field_key]
                file_ids = v if isinstance(v, list) else [v]

                for file_id in file_ids:
                    if isinstance(file_id, str) and file_id.isnumeric():
                        file_id = int(file_id)

                    if file_id is not None and isinstance(file_id, int):
                        if not task.workflow.data[
                                WorkflowProcessor.VALIDATION_PROCESS_KEY]:
                            # Get the actual image data
                            image_file_model = session.query(
                                FileModel).filter_by(id=file_id).first()
                            image_file_data_model = FileService.get_file_data(
                                file_id, image_file_model)
                            if image_file_data_model is not None:
                                image_file_data.append(image_file_data_model)

                    else:
                        raise ApiError(
                            code="not_a_file_id",
                            message=
                            "The CompleteTemplate script requires 2-3 arguments. The third argument should "
                            "be a comma-delimited list of File IDs")

        return image_file_data
Пример #3
0
def get_file_data(file_id, version=None):
    file_data = FileService.get_file_data(file_id, version)
    if file_data is None:
        raise ApiError('no_such_file', 'The file id you provided does not exist')
    return send_file(
        io.BytesIO(file_data.data),
        attachment_filename=file_data.file_model.name,
        mimetype=file_data.file_model.content_type,
        cache_timeout=-1,  # Don't cache these files on the browser.
        last_modified=file_data.date_created
    )
Пример #4
0
def to_file_api(file_model):
    """Converts a FileModel object to something we can return via the api"""
    if file_model.workflow_spec_id is not None:
        file_data_model = SpecFileService().get_spec_file_data(file_model.id)
    elif file_model.is_reference:
        file_data_model = ReferenceFileService().get_reference_file_data(
            file_model.name)
    else:
        file_data_model = FileService.get_file_data(file_model.id)
    return File.from_models(file_model, file_data_model,
                            DocumentService.get_dictionary())
Пример #5
0
def get_document_directory(study_id, workflow_id=None):
    """
    return a nested list of files arranged according to the category hierarchy
    defined in the doc dictionary
    """
    file_models = FileService.get_files_for_study(study_id=study_id)
    doc_dict = DocumentService.get_dictionary()
    files = (File.from_models(model, FileService.get_file_data(model.id),
                              doc_dict) for model in file_models)
    directory = DocumentService.get_directory(doc_dict, files, workflow_id)

    return DocumentDirectorySchema(many=True).dump(directory)
Пример #6
0
    def get_study(study_id, study_model: StudyModel = None, do_status=False):
        """Returns a study model that contains all the workflows organized by category.
        IMPORTANT:  This is intended to be a lightweight call, it should never involve
        loading up and executing all the workflows in a study to calculate information."""
        if not study_model:
            study_model = session.query(StudyModel).filter_by(
                id=study_id).first()

        study = Study.from_model(study_model)
        study.create_user_display = LdapService.user_info(
            study.user_uid).display_name
        last_event: TaskEventModel = session.query(TaskEventModel) \
            .filter_by(study_id=study_id, action='COMPLETE') \
            .order_by(TaskEventModel.date.desc()).first()
        if last_event is None:
            study.last_activity_user = '******'
            study.last_activity_date = ""
        else:
            study.last_activity_user = LdapService.user_info(
                last_event.user_uid).display_name
            study.last_activity_date = last_event.date
        study.categories = StudyService.get_categories()
        workflow_metas = StudyService._get_workflow_metas(study_id)
        files = FileService.get_files_for_study(study.id)
        files = (File.from_models(model, FileService.get_file_data(model.id),
                                  DocumentService.get_dictionary())
                 for model in files)
        study.files = list(files)
        # Calling this line repeatedly is very very slow.  It creates the
        # master spec and runs it.  Don't execute this for Abandoned studies, as
        # we don't have the information to process them.
        if study.status != StudyStatus.abandoned:
            # this line is taking 99% of the time that is used in get_study.
            # see ticket #196
            if do_status:
                # __get_study_status() runs the master workflow to generate the status dictionary
                status = StudyService._get_study_status(study_model)
                study.warnings = StudyService._update_status_of_workflow_meta(
                    workflow_metas, status)

            # Group the workflows into their categories.
            for category in study.categories:
                category.workflows = {
                    w
                    for w in workflow_metas if w.category_id == category.id
                }

        return study
Пример #7
0
def get_file_data(file_id, version=None):
    file_model = session.query(FileModel).filter(
        FileModel.id == file_id).first()
    if file_model is not None:
        file_data_model = FileService.get_file_data(file_id, version)
        if file_data_model is not None:
            return send_file(
                io.BytesIO(file_data_model.data),
                attachment_filename=file_model.name,
                mimetype=file_model.content_type,
                cache_timeout=-1  # Don't cache these files on the browser.
            )
        else:
            raise ApiError(
                'missing_data_model',
                f'The data model for file ({file_id}) does not exist')
    else:
        raise ApiError('missing_file_model',
                       f'The file id you provided ({file_id}) does not exist')
Пример #8
0
    def test_update_file_data(self):
        self.load_example_data()
        spec = session.query(WorkflowSpecModel).first()
        data = {}
        data['file'] = io.BytesIO(
            self.minimal_bpmn("abcdef")), 'my_new_file.bpmn'
        rv = self.app.post('/v1.0/file?workflow_spec_id=%s' % spec.id,
                           data=data,
                           follow_redirects=True,
                           content_type='multipart/form-data',
                           headers=self.logged_in_headers())
        json_data = json.loads(rv.get_data(as_text=True))
        file = FileModelSchema().load(json_data, session=session)

        data['file'] = io.BytesIO(
            self.minimal_bpmn("efghijk")), 'my_new_file.bpmn'
        rv = self.app.put('/v1.0/file/%i/data' % file.id,
                          data=data,
                          follow_redirects=True,
                          content_type='multipart/form-data',
                          headers=self.logged_in_headers())
        self.assert_success(rv)
        self.assertIsNotNone(rv.get_data())
        file_json = json.loads(rv.get_data(as_text=True))
        self.assertEqual(2, file_json['latest_version'])
        self.assertEqual(FileType.bpmn.value, file_json['type'])
        self.assertEqual("application/octet-stream", file_json['content_type'])
        self.assertEqual(spec.id, file.workflow_spec_id)

        # Assure it is updated in the database and properly persisted.
        file_model = session.query(FileModel).filter(
            FileModel.id == file.id).first()
        file_data = FileService.get_file_data(file_model.id)
        self.assertEqual(2, file_data.version)

        rv = self.app.get('/v1.0/file/%i/data' % file.id,
                          headers=self.logged_in_headers())
        self.assert_success(rv)
        data = rv.get_data()
        self.assertIsNotNone(data)
        self.assertEqual(self.minimal_bpmn("efghijk"), data)
Пример #9
0
def get_file_data_link(file_id, auth_token, version=None):
    if not verify_token(auth_token):
        raise ApiError(
            'not_authenticated',
            'You need to include an authorization token in the URL with this')
    file_model = session.query(FileModel).filter(
        FileModel.id == file_id).first()
    if file_model.workflow_spec_id is not None:
        file_data = SpecFileService().get_spec_file_data(file_id)
    elif file_model.is_reference:
        file_data = ReferenceFileService().get_reference_file_data(file_id)
    else:
        file_data = FileService.get_file_data(file_id, version)
    if file_data is None:
        raise ApiError('no_such_file',
                       f'The file id you provided ({file_id}) does not exist')
    return send_file(
        io.BytesIO(file_data.data),
        attachment_filename=file_model.name,
        mimetype=file_model.content_type,
        cache_timeout=-1,  # Don't cache these files on the browser.
        last_modified=file_data.date_created,
        as_attachment=True)
Пример #10
0
    def get_documents_status(study_id):
        """Returns a list of documents related to the study, and any file information
        that is available.."""

        # Get PB required docs, if Protocol Builder Service is enabled.
        if ProtocolBuilderService.is_enabled() and study_id is not None:
            try:
                pb_docs = ProtocolBuilderService.get_required_docs(
                    study_id=study_id)
            except requests.exceptions.ConnectionError as ce:
                app.logger.error(
                    f'Failed to connect to the Protocol Builder - {str(ce)}',
                    exc_info=True)
                pb_docs = []
        else:
            pb_docs = []

        # Loop through all known document types, get the counts for those files,
        # and use pb_docs to mark those as required.
        doc_dictionary = DocumentService.get_dictionary()

        documents = {}
        for code, doc in doc_dictionary.items():

            doc['required'] = False
            if ProtocolBuilderService.is_enabled() and doc['id'] != '':
                pb_data = next(
                    (item for item in pb_docs['AUXDOCS']
                     if int(item['SS_AUXILIARY_DOC_TYPE_ID']) == int(doc['id'])
                     ), None)
                if pb_data:
                    doc['required'] = True

            doc['study_id'] = study_id
            doc['code'] = code

            # Make a display name out of categories
            name_list = []
            for cat_key in ['category1', 'category2', 'category3']:
                if doc[cat_key] not in ['', 'NULL', None]:
                    name_list.append(doc[cat_key])
            doc['display_name'] = ' / '.join(name_list)

            # For each file, get associated workflow status
            doc_files = FileService.get_files_for_study(study_id=study_id,
                                                        irb_doc_code=code)
            doc['count'] = len(doc_files)
            doc['files'] = []

            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']
                doc['files'].append(Box(file_data))
                # update the document status to match the status of the workflow it is in.
                if 'status' not in doc or doc['status'] is None:
                    status = session.query(WorkflowModel.status).filter_by(
                        id=file.workflow_id).scalar()
                    doc['status'] = status.value

            documents[code] = doc
        return Box(documents)
Пример #11
0
def to_file_api(file_model):
    """Converts a FileModel object to something we can return via the api"""
    return File.from_models(file_model, FileService.get_file_data(file_model.id),
                            FileService.get_doc_dictionary())