Ejemplo n.º 1
0
def sample_in_sample_group(user: User, sample: Sample, sample_group: SampleGroup) -> bool:
    """
    Determine if a sample belongs to a sample group. NotFoundException,
    :param user:
    :param sample:
    :param sample_group:
    :return:
    """
    if is_read_permitted(user, sample_group) and is_read_permitted(user, sample):
        return sample in sample_group.samples
    raise AuthException(f'User {user.email} not permitted to check the attachment of {sample.id} to sample group {sample_group.id}')
Ejemplo n.º 2
0
def create_collection(user: User,
                      samples: List[Sample],
                      data: Dict[str, Any],
                      sort_by: str = 'base_sample_id') -> Collection:
    """
    Create a new collection by concatenating samples. Collection metadata is set with new_data
    :param user:
    :param samples:
    :param data: Collection attributes
    :param sort_by:
    :return:
    """
    data['owner_id'] = user.id
    data['creator_id'] = user.id
    if 'id' in data:  # cannot create with specified id
        del data['id']
    for sample in samples:
        if not is_read_permitted(user, sample):
            raise AuthException(f'User {user.id} is not permitted to access sample {sample.id}')
    filenames = [sample.filename for sample in samples]
    new_collection = Collection(owner=user, creator=user, last_editor=user, name=data['name'])
    db.session.add(new_collection)
    db.session.commit()
    new_collection.filename = f'{DATADIR}/collections/{new_collection.id}.h5'
    db.session.commit()
    if len(filenames):
        new_collection.merge_samples(samples, sort_by)
    else:
        new_collection.create_empty_file()
    update_collection(user, new_collection, data)
    return new_collection
Ejemplo n.º 3
0
def attach_collection(user: User, analysis: Analysis,
                      collection: Collection) -> Dict[str, Any]:
    """
    Add a collection to the list of collections belonging to an analysis
    :param user:
    :param analysis:
    :param collection:
    :return:
    """
    # check read permissions on analysis and collection
    if is_read_permitted(user, collection) and is_write_permitted(
            user, analysis):
        if collection not in analysis.collections:
            analysis.collections.append(collection)
            db.session.commit()
            return {
                'message':
                f'collection {collection.id} attached to analysis {analysis.id}'
            }
        return {
            'message':
            f'Collection {collection.id} already attached to analysis {analysis.id}'
        }
    raise AuthException(
        f'User {user.email} is not permitted to attach collection {collection.id} '
        f'to analysis {analysis.id}')
Ejemplo n.º 4
0
def download_external_file(user: User,
                           external_file: ExternalFile) -> Dict[str, str]:
    if is_read_permitted(user, external_file):
        return {'filename': os.path.basename(external_file.filename)}
    raise AuthException(
        f'User {user.id} is not permitted to access external file {external_file.id}'
    )
Ejemplo n.º 5
0
def list_collection_paths(user: User, collection: Collection) -> List[str]:
    """
    List the paths corresponding to datasets in the collection
    :param user:
    :param collection:
    :return:
    """
    if is_read_permitted(user, collection):
        return mdt.get_dataset_paths(collection.filename)
    raise AuthException(f'User {user.email} is not permitted to access collection {collection.id}')
Ejemplo n.º 6
0
def get_sample_group_members(user: User, sample_group: SampleGroup) -> List[Sample]:
    """
    Get a list of samples which belong to this group.
    :param user:
    :param sample_group:
    :return:
    """
    if is_read_permitted(user, sample_group):
        return get_read_permitted_records(user, sample_group.samples)
    raise AuthException(f'User {user.email} not permitted to view sample group {sample_group.id}')
Ejemplo n.º 7
0
def get_included_sample_groups(user: User, sample: Sample) -> List[SampleGroup]:
    """
    Get a list of sample groups that a sample is found in
    :param user:
    :param sample:
    :return:
    """
    if is_read_permitted(user, sample):
        return get_read_permitted_records(user, sample.sample_groups)
    raise AuthException(f'User {user.email} not permitted to view sample {sample.id}')
Ejemplo n.º 8
0
def download_collection(user: User, collection: Collection) -> Dict[str, str]:
    """
    If the user is permitted to read this collection, get the path to the collection, else throw.
    The file is sent via the send_from_directory flask method
    :param user:
    :param collection:
    :return:
    """
    if is_read_permitted(user, collection):
        return {'filename': os.path.basename(collection.filename)}
    raise AuthException(f'User {user.email} is not permitted to access collection {collection.id}')
Ejemplo n.º 9
0
def list_sample_paths(user: User, sample: Sample) -> List[str]:
    """
    List all the paths to datasets within the sample file
    :param user:
    :param sample:
    :return:
    """
    if is_read_permitted(user, sample):
        return mdt.get_dataset_paths(sample.filename)
    raise AuthException(
        f'User {user.email} is not permitted to access sample {sample.id}')
Ejemplo n.º 10
0
def get_analysis(user: User, analysis_id: int) -> Analysis:
    """
    Get analysis information
    :param user:
    :param analysis_id:
    :return:
    """
    analysis = Analysis.query.filter_by(id=analysis_id).first()
    if is_read_permitted(user, analysis):
        return analysis
    raise AuthException(
        f'User {user.email} is not permitted to access analysis {analysis_id}')
Ejemplo n.º 11
0
def download_sample(user: User, sample: Sample) -> Dict[str, str]:
    """
    If the user with user_id is permitted to access sample_id, present the filename for the sample with sample_id
    :param user:
    :param sample:
    :return:
    """

    if is_read_permitted(user, sample):
        return {'filename': f'{sample.id}.h5'}
    raise AuthException(
        f'User {user.email} is not permitted to access sample {sample.id}')
Ejemplo n.º 12
0
def get_attached_collections(user: User,
                             analysis: Analysis) -> List[Collection]:
    """
    Get all collections which belong to an analysis
    :param user:
    :param analysis:
    :return:
    """
    if is_read_permitted(user, analysis):
        return analysis.collections
    raise AuthException(
        f'User {user.email} is not permitted to access analysis {analysis.id}')
Ejemplo n.º 13
0
def get_sample_group(user: User, group_id: int) -> SampleGroup:
    """
    Get a sample group.
    :param user:
    :param group_id:
    :return:
    """
    sample_group = SampleGroup.query.filter_by(id=group_id).first()
    if sample_group is None:
        raise NotFoundException(f'Sample group with id {group_id} not found.')
    if is_read_permitted(user, sample_group):
        return sample_group
    raise AuthException(f'User {user.email} is not authorized to view sample group {group_id}')
Ejemplo n.º 14
0
def get_attached_analyses(user: User,
                          collection: Collection) -> List[Analysis]:
    """
    Get all analysis that a collection belongs to
    :param user:
    :param collection:
    :return:
    """
    if is_read_permitted(user, collection):
        return get_all_read_permitted_records(user, collection.analyses)
    raise AuthException(
        f'User {user.email} not permitted to access collection {collection.id}'
    )
Ejemplo n.º 15
0
def download_collection_dataset(user: User, collection: Collection, path: str) -> Dict[str,  str]:
    """
    If the user is allowed to read a collection, get the contents required to send a file containing a dataset
    as CSV
    :param user:
    :param collection:
    :param path:
    :return:
    """
    csv_filename = f'{os.path.basename(os.path.normpath(path))}.csv'
    if is_read_permitted(user, collection):
        return {'csv': mdt.get_csv(collection.filename, path), 'cd': f'attachment; filename={csv_filename}'}
    raise AuthException(f'User {user.email} is not permitted to access collection {collection.id}')
Ejemplo n.º 16
0
def get_collection(user: User, collection_id: int) -> Collection:
    """
    Get the attributes and dataset information of a collection
    :param user:
    :param collection_id:
    :return:
    """
    collection = Collection.query.filter_by(id=collection_id).first()
    if collection is None:
        raise NotFoundException(f'No collection with id {collection_id}')
    if is_read_permitted(user, collection):
        return collection
    raise AuthException(f'User {user.email} is not authorized to view collection {collection.id}')
Ejemplo n.º 17
0
def update_sample_group_attachments(user: User, sample_group: SampleGroup, samples: List[Sample]) -> SampleGroup:
    """
    Make the only samples attached to a group those in sample_ids
    :param user:
    :param sample_group:
    :param samples:
    :return:
    """
    if is_write_permitted(user, sample_group) and all([is_read_permitted(user, sample) for sample in samples]):
        sample_group.samples = samples
        sample_group.last_editor = user
        db.session.commit()
        return sample_group
    raise AuthException(f'User {user.email} not authorized to modify group {sample_group.id}')
Ejemplo n.º 18
0
def get_workflow(user: User, workflow_id: int) -> Workflow:
    """
    Get workflow metadata.
    :param user:
    :param workflow_id:
    :return:
    """
    workflow = Workflow.query.filter_by(id=workflow_id).first()
    if workflow is None:
        raise NotFoundException(f'No workflow with id {workflow_id}.')
    if is_read_permitted(user, workflow):
        return workflow
    raise AuthException(
        f'User {user.email} is not permitted to access workflow {workflow_id}')
Ejemplo n.º 19
0
def get_collection_metadata(user: User, collection: Collection) -> Dict[str, Any]:
    """
    Get the attributes of a collection.
    :param user:
    :param collection:
    :return:
    """
    if is_read_permitted(user, collection):
        collection_info = collection.to_dict()
        for key, value in collection.get_file_metadata().items():
            if key not in collection_info:  # ensures that database entries take precedence over file attributes
                collection_info[key] = value
        return collection_info
    raise AuthException(f'User {user.email} is not authorized to view collection {collection.id}')
Ejemplo n.º 20
0
def get_sample(user: User, sample_id: int) -> Sample:
    """
    Get the attributes and dataset paths of the sample with sample_id
    :param user:
    :param sample_id:
    :return:
    """
    sample = Sample.query.filter_by(id=sample_id).first()
    if sample is None:
        raise NotFoundException(f'No sample with id {sample_id}')
    if is_read_permitted(user, sample):
        return sample
    raise AuthException(
        f'User {user.email} is not permitted to access sample {sample_id}')
Ejemplo n.º 21
0
def get_external_file(user: User, external_file_id: int) -> ExternalFile:
    """
    Get a record corresponding to an external file
    :param user:
    :param external_file_id:
    :return:
    """
    external_file = ExternalFile.query.filter_by(id=external_file_id).first()
    if external_file is None:
        raise NotFoundException(f'No external file with id {external_file_id}')
    if is_read_permitted(user, external_file):
        return external_file
    raise AuthException(
        f'User {user.id} is not authorized to view external file {external_file.id}'
    )
Ejemplo n.º 22
0
def attach_sample(user: User, sample: Sample, sample_group: SampleGroup) -> SampleGroup:
    """
    Make a sample a member of a sample group.
    :param user:
    :param sample:
    :param sample_group:
    :return:
    """
    if is_write_permitted(user, sample_group) and is_read_permitted(user, sample):
        if sample not in sample_group.samples:
            sample_group.samples.append(sample)
        sample_group.last_editor = user
        db.session.commit()
        return sample_group
    raise AuthException(f'User {user.email} is not permitted to attach {sample.id} to group {sample_group.id}')
Ejemplo n.º 23
0
def get_external_file_by_path(user: User, filename: str) -> ExternalFile:
    """
    Get the external file record for the file with path filename
    :param user:
    :param filename:
    :return:
    """
    external_file = ExternalFile.query.filter_by(filename=filename).first()
    if external_file is None:
        raise NotFoundException(
            f'No external file record exists for {filename}')
    if is_read_permitted(user, external_file):
        return external_file
    raise AuthException(
        f'User {user.id} is not authorized to view external file record for {filename}'
    )
Ejemplo n.º 24
0
def get_sample_metadata(user: User, sample: Sample) -> Dict[str, Any]:
    """
    Get the attributes of the sample with sample_id
    :param user:
    :param sample:
    :return:
    """

    if is_read_permitted(user, sample):
        collection_info = sample.to_dict()
        for key, value in sample.get_file_metadata().items():
            if key not in collection_info:  # ensures that database entries take precedence over file attributes
                collection_info[key] = value
        return collection_info
    raise AuthException(
        f'User {user.email} is not authorized to view collection {sample.id}')
Ejemplo n.º 25
0
def download_collection_dataframe(user: User, collection: Collection, single_column: bool = False,
                                  data_format: str = 'csv', json_orient: str = 'records') -> Dict[str, any]:
    """
    If the user is allowed to read a collection, get the contents required to send a file containing the collection
    as a pandas dataframe as CSV
    :param user:
    :param collection:
    :param single_column: whether to only include single-column attributes in dataframe
    :param data_format: file format of dataframe
    :param json_orient: pandas json orientation if json is data_format, otherwise ignored
    :return:
    """
    if is_read_permitted(user, collection):
        return {data_format: ct.get_serialized_dataframe(collection.filename, single_column, data_format, json_orient),
                'cd': f'attachment; filename={collection.id}.{data_format}'}
    raise AuthException(f'User {user.email} is not permitted to access collection {collection.id}')
Ejemplo n.º 26
0
def download_sample_dataset(user: User, sample: Sample,
                            path: str) -> Dict[str, str]:
    """
    Download a CSV file containing a dataset found in this sample
    :param user:
    :param sample:
    :param path:
    :return:
    """
    csv_filename = f'{os.path.basename(os.path.normpath(path))}.csv'
    if is_read_permitted(user, sample):
        return {
            'csv': mdt.get_csv(sample.filename, path),
            'cd': f'attachment; filename={csv_filename}'
        }
    raise AuthException(
        f'User {user.email} is not permitted to access collection {sample.id}')
Ejemplo n.º 27
0
    def __init__(self, current_user: User, record: Any):
        super(AttributeTableData,
              self).__init__(current_user,
                             is_write_permitted(current_user, record))
        self.values = {
            'ID': AttributeTableRow('id', record.id, False),
            'Name': AttributeTableRow('name', record.name, self.editable)
        }
        if hasattr(record, 'description'):
            self.values['Description'] = AttributeTableRow(
                'description',
                record.description if record.description is not None else '',
                self.editable)
        if isinstance(record, SampleGroup):
            job = get_job(record.upload_job_id)
            self.values['Job'] = AttributeTableRow('job',
                                                   job.name,
                                                   href=get_item_link(job))
        if isinstance(record, User):
            self.values['Email'] = AttributeTableRow(
                'email', record.email, False, href=f'mailto:{record.email}')
            if is_read_permitted(current_user, record.primary_user_group):
                self.values['Primary User Group'] = AttributeTableRow(
                    'primary_user_group', record.primary_user_group.name
                    if record.primary_user_group is not None else None, False,
                    get_item_link(record.primary_user_group)
                    if record.primary_user_group is not None else None)
        if isinstance(record, OmicsRecordMixin):
            if is_read_permitted(current_user, record.owner):
                self.values['Owner'] = AttributeTableRow(
                    'owner',
                    record.owner.name if record.owner is not None else None,
                    False,
                    get_item_link(record.owner)
                    if record.owner is not None else None)
            user_group_options = [
                SelectOption(group.id, group.name, group is record.user_group)
                for group in UserGroup.query.filter(
                    UserGroup.members.contains(current_user)).all()
            ]
            self.values['User Group'] = AttributeTableRow(
                'user_group_id', record.user_group.name
                if record.user_group is not None else None, self.editable,
                None, user_group_options, False)
            permissions_options = [
                SelectOption('all_can_read', 'Anyone can view?',
                             record.all_can_read),
                SelectOption('group_can_read', 'User group members can view?',
                             record.group_can_read),
                SelectOption('all_can_write', 'Anyone can edit or delete?',
                             record.all_can_write),
                SelectOption('group_can_write',
                             'User group members can edit or delete',
                             record.group_can_write)
            ]
            self.values['Permissions'] = AttributeTableRow(
                'permissions',
                None,
                is_write_permitted(current_user, record),
                select_options=permissions_options,
                select_multiple=True,
                select_composite=True)

        if isinstance(record, Collection):
            if record.parent is not None and is_read_permitted(
                    current_user, record.parent):
                self.values['Parent Collection'] = AttributeTableRow(
                    'parent',
                    f'{record.parent.name} (Collection {record.parent.id})',
                    href=get_item_link(record.parent))
            else:
                self.values['Parent Collection'] = AttributeTableRow(
                    'parent', 'None')
            self.values['Kind'] = AttributeTableRow('kind', record.kind)
        if isinstance(record, Job):
            self.values['Type'] = AttributeTableRow('type', record.type)
            self.values['Status'] = AttributeTableRow('status', record.status)
            self.values['Submitted'] = AttributeTableRow(
                'submitted', record.submission)
            self.values['Started'] = AttributeTableRow('start', record.start)
            self.values['Ended'] = AttributeTableRow('end', record.end)
            if is_read_permitted(current_user, record.owner):
                self.values['Submitted By'] = AttributeTableRow(
                    'owner',
                    record.owner.name,
                    href=get_item_link(record.owner))
        if isinstance(record, ExternalFile):
            self.values['Path'] = AttributeTableRow('filename',
                                                    record.filename)
            self.values['File Type'] = AttributeTableRow(
                'file_type', record.file_type)
            file_info = record.get_file_info()
            if file_info is not None:
                size_mb = file_info['st_size'] / (1024 * 1024.0)
                self.values['Size'] = AttributeTableRow(
                    'file_size', f'{size_mb:.3f} MB')
                self.values['File Modified'] = AttributeTableRow(
                    'file_mtime',
                    datetime.fromtimestamp(
                        file_info['st_mtime']).strftime('%-d %b %Y %H:%M'))
        if isinstance(record, Base):
            self.values['Date Created'] = AttributeTableRow(
                'created_on', record.created_on.strftime('%-d %b %Y %H:%M'))
            self.values['Date Modified'] = AttributeTableRow(
                'updated_on', record.updated_on.strftime('%-d %b %Y %H:%M'))