Esempio n. 1
0
    def get(self):
        if not check_access(path=f"/run/{str(run_id)}", method="GET"):
            abort(403)
            return
        run = Run.query.get(run_id)
        if not run or run.is_deleted:
            abort(404)
            return

        return [{
            'id': attachment.id,
            'name': attachment.name,
        } for attachment in run.attachments
                if check_access(path=f"/run/{str(run.id)}", method="GET")
                and attachment]
Esempio n. 2
0
File: run.py Progetto: lab-grid/flow
async def update_run(
    run_id: int,
    run: RunModel,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run_id)}",
                        method="PUT"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    run_dict = run.dict()
    # This field shouldn't be updated by users.
    run_dict.pop('protocol', None)
    new_run = db.query(Run).get(run_id)
    if not new_run or new_run.is_deleted:
        raise HTTPException(status_code=404, detail='Run Not Found')
    if not change_allowed(run_to_dict(new_run, new_run.current), run_dict):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')
    new_run_version = RunVersion(data=strip_metadata(run_dict),
                                 server_version=settings.server_version)
    new_run_version.run = new_run
    add_updator(new_run_version, current_user.username)
    new_run.current = new_run_version
    db.add(new_run_version)
    samples = get_samples(new_run_version, new_run.protocol_version)
    if samples:
        for sample in samples:
            db.merge(sample)
    db.commit()
    return run_to_dict(new_run, new_run.current)
Esempio n. 3
0
File: run.py Progetto: lab-grid/flow
def crud_get_run(
    item_to_dict,
    enforcer: casbin.Enforcer,
    db: Session,
    current_user: Auth0ClaimsPatched,
    run_id: int,
    version_id: Optional[int] = None,
) -> dict:
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run_id)}",
                        method="GET"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    if version_id:
        run_version = db.query(RunVersion)\
            .filter(RunVersion.id == version_id)\
            .filter(Run.id == run_id)\
            .first()
        if (not run_version) or run_version.run.is_deleted:
            raise HTTPException(status_code=404, detail='Run Not Found')
        return item_to_dict(run_version.run)

    run = db.query(Run).get(run_id)
    if (not run) or run.is_deleted:
        raise HTTPException(status_code=404, detail='Run Not Found')

    return item_to_dict(fix_plate_markers_run(db, run))
Esempio n. 4
0
def crud_get_sample(
    item_to_dict,

    enforcer: casbin.Enforcer,
    db: Session,
    current_user: Auth0ClaimsPatched,

    sample_id: str,
    plate_id: str,
    run_version_id: int,
    protocol_version_id: int,
    version_id: Optional[int] = None,
) -> dict:
    sample = db.query(Sample).get(sample_id)
    if not check_access(enforcer, user=current_user.username, path=f"/run/{str(sample.run_version.run_id)}", method="GET"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    if version_id:
        sample_version = SampleVersion.query\
            .filter(SampleVersion.id == version_id)\
            .filter(Sample.id == sample_id)\
            .first()
        if (not sample_version) or sample_version.sample.is_deleted:
            raise HTTPException(status_code=404, detail='Sample Not Found')
        return item_to_dict(sample_version.sample)

    sample = db.query(Sample).get((sample_id, plate_id, run_version_id, protocol_version_id))
    if (not sample) or sample.is_deleted:
        raise HTTPException(status_code=404, detail='Sample Not Found')
    return item_to_dict(sample)
Esempio n. 5
0
def crud_get_user(
    item_to_dict,
    enforcer: casbin.Enforcer,
    db: Session,
    current_user: Auth0ClaimsPatched,
    user_id: int,
    version_id: Optional[int] = None,
) -> dict:
    user_id = urllib.parse.unquote(user_id)
    if user_id != current_user.username and not check_access(
            enforcer,
            user=current_user.username,
            path=f"/user/{str(user_id)}",
            method="GET"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    if version_id:
        user_version = db.query(UserVersion)\
            .filter(UserVersion.id == version_id)\
            .filter(User.id == user_id)\
            .first()
        if (not user_version) or user_version.user.is_deleted:
            raise HTTPException(status_code=404, detail='User Not Found')
        return item_to_dict(user_version.user)

    user = db.query(User).get(user_id)
    if (not user) or user.is_deleted:
        raise HTTPException(status_code=404, detail='User Not Found')

    return item_to_dict(user)
Esempio n. 6
0
async def patch_protocol(
    protocol_id: int,
    patch: list,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/protocol/{str(protocol_id)}",
                        method="PUT"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    new_protocol = db.query(Protocol).get(protocol_id)
    if not new_protocol or new_protocol.is_deleted:
        raise HTTPException(status_code=404, detail='Protocol Not Found')

    protocol_dict = versioned_row_to_dict(new_protocol, new_protocol.current)
    json_patch = jsonpatch.JsonPatch(patch)
    protocol_dict = json_patch.apply(protocol_dict)

    if not change_allowed(
            versioned_row_to_dict(new_protocol, new_protocol.current),
            protocol_dict):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    new_protocol_version = ProtocolVersion(
        data=strip_metadata(protocol_dict),
        server_version=settings.server_version)
    new_protocol_version.protocol = new_protocol
    add_updator(new_protocol_version, current_user.username)
    new_protocol.current = new_protocol_version
    db.add(new_protocol_version)
    db.commit()
    return versioned_row_to_dict(new_protocol, new_protocol.current)
Esempio n. 7
0
File: run.py Progetto: lab-grid/flow
async def delete_run_attachment(
    run_id: int,
    attachment_id: int,
    purge: bool = False,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run_id)}",
                        method="GET"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')
    run = db.query(Run).get(run_id)
    if not run or run.is_deleted:
        raise HTTPException(status_code=404, detail='Run Not Found')

    attachment = db.query(Attachment).get(attachment_id)
    if not attachment or attachment.is_deleted:
        raise HTTPException(status_code=404, detail='Attachment Not Found')
    if purge:
        db.delete(attachment)
    else:
        attachment.is_deleted = True
    db.commit()
    return success
Esempio n. 8
0
File: run.py Progetto: lab-grid/flow
async def update_run_sample(
    run_id: int,
    sample_id: str,
    sample: SampleResult,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run_id)}",
                        method="PUT"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    run = db.query(Run).get(run_id)
    if not run or run.is_deleted:
        raise HTTPException(status_code=404, detail='Run Not Found')

    sample_dict = sample.dict()
    new_sample = db.query(Sample).filter(
        Sample.sample_version_id == new_sample.version_id).filter(
            Sample.sample_id == sample_id).first()
    if not new_sample or new_sample.is_deleted:
        raise HTTPException(status_code=404, detail='Sample Not Found')
    if not change_allowed(run_to_dict(run, run.current), {}):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')
    new_sample_version = SampleVersion(data=strip_metadata(sample_dict),
                                       server_version=settings.server_version)
    new_sample_version.sample = new_sample
    add_updator(new_sample_version, current_user.username)
    new_sample.current = new_sample_version
    db.add(new_sample_version)
    db.commit()
    return run_to_sample(new_sample)
Esempio n. 9
0
def crud_get_protocol(
    item_to_dict,
    enforcer: casbin.Enforcer,
    db: Session,
    current_user: Auth0ClaimsPatched,
    protocol_id: int,
    version_id: Optional[int] = None,
) -> dict:
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/protocol/{str(protocol_id)}",
                        method="GET"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    if version_id:
        protocol_version = ProtocolVersion.query\
            .filter(ProtocolVersion.id == version_id)\
            .filter(Protocol.id == protocol_id)\
            .first()
        if (not protocol_version) or protocol_version.protocol.is_deleted:
            raise HTTPException(status_code=404, detail='Protocol Not Found')
        return item_to_dict(protocol_version.protocol)

    protocol = db.query(Protocol).get(protocol_id)
    if (not protocol) or protocol.is_deleted:
        raise HTTPException(status_code=404, detail='Protocol Not Found')
    return item_to_dict(fix_plate_markers_protocol(db, protocol))
Esempio n. 10
0
 def decorated(*args, **kwargs):
     if check_access(path=f"/protocol/{kwargs.get('protocol_id')}",
                     method=method):
         return f(*args, **kwargs)
     raise AuthError(
         {
             'code': 'forbidden',
             'description': 'User is not allowed to perform this action'
         }, 403)
Esempio n. 11
0
File: run.py Progetto: lab-grid/flow
async def export_run_samples_csv(
    run_id: Optional[int] = None,
    protocol: Optional[int] = None,
    plate: Optional[str] = None,
    reagent: Optional[str] = None,
    creator: Optional[str] = None,
    archived: Optional[bool] = None,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run_id)}",
                        method="GET"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')
    run = db.query(Run).get(run_id)
    if not run or run.is_deleted:
        raise HTTPException(status_code=404, detail='Run Not Found')

    samples = crud_get_run_samples(
        item_to_dict=lambda sample: run_to_sample(sample),
        enforcer=enforcer,
        db=db,
        current_user=current_user,
        run_id=run_id,
        protocol=protocol,
        plate=plate,
        reagent=reagent,
        creator=creator,
        archived=archived,
    )

    # Process each sample and add in flattened run data (with a filter).
    flattened_run = flatten_list_or_dict(
        run_to_dict(run, run.current, False),
        '(attachments|type|definition|protocol|plates|plateSequencingResults|plateMarkers)'
    )
    flattened_samples = []
    sample_headers = set()
    for sample in samples['samples']:
        flattened_sample = {**flattened_run, **flatten_list_or_dict(sample)}
        flattened_samples.append(flattened_sample)
        sample_headers.update(flattened_sample.keys())

    sample_headers = list(sample_headers)
    sample_headers.sort()
    csvfile = io.StringIO()
    writer = csv.writer(csvfile, quoting=csv.QUOTE_NONNUMERIC)
    writer.writerow(sample_headers)
    for flattened_sample in flattened_samples:
        writer.writerow(
            [flattened_sample.get(header, '') for header in sample_headers])

    return Response(csvfile.getvalue(), media_type='text/csv')
Esempio n. 12
0
async def get_permissions(
    protocol_id: int,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/protocol/{str(protocol_id)}",
                        method="GET"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    return get_policies(enforcer, path=f"/protocol/{protocol_id}")
Esempio n. 13
0
 def get(self, run_id, sample_id):
     if not check_access(path=f"/run/{str(run_id)}", method="GET"):
         abort(403)
         return
     run = Run.query.get(run_id)
     if not run or run.is_deleted:
         abort(404)
         return
     sample = Sample.query.filter(
         Sample.run_version_id == run.version_id).filter(
             Sample.sample_id == sample_id).first()
     # sample = get_samples(run=run, run_version=run.current, sample_id=sample_id).first()
     return run_to_sample(sample)
Esempio n. 14
0
File: run.py Progetto: lab-grid/flow
async def get_run_attachments(
    run_id: int,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run_id)}",
                        method="GET"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    run = db.query(Run).get(run_id)
    if not run or run.is_deleted:
        raise HTTPException(status_code=404, detail='Run Not Found')

    return [
        AttachmentModel(id=attachment.id, name=attachment.name)
        for attachment in run.attachments
        if check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run.id)}",
                        method="GET") and attachment
    ]
Esempio n. 15
0
File: run.py Progetto: lab-grid/flow
async def delete_permission(
    run_id: int,
    method: str,
    user_id: str,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run_id)}",
                        method="PUT"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    delete_policy(enforcer, user=user_id, path=f"/run/{run_id}", method=method)
    return success
Esempio n. 16
0
    def get(self, run_id, attachment_id):
        if not check_access(path=f"/run/{str(run_id)}", method="GET"):
            abort(403)
            return
        run = Run.query.get(run_id)
        if not run or run.is_deleted:
            abort(404)
            return

        attachment = Attachment.query.get(attachment_id)
        if not attachment or attachment.is_deleted:
            abort(404)
            return

        return app.response_class(
            attachment.data,
            mimetype=attachment.mimetype
            if attachment.mimetype else 'application/octet-stream')
Esempio n. 17
0
    def get(self):
        results = {}
        if request.args.get('page') is not None or request.args.get(
                'per_page') is not None:
            page = int(
                request.args.get('page')) if request.args.get('page') else 1
            per_page = int(request.args.get('per_page')) if request.args.get(
                'per_page') else 20
            page_query = User.query.filter(User.is_deleted != True).paginate(
                page=page, per_page=per_page)
            results['page'] = page_query.page
            results['pageCount'] = page_query.pages
            query = page_query.items
        else:
            query = User.query.filter(User.is_deleted != True).all()

        results['users'] = [
            add_role(versioned_row_to_dict(api, user, user.current))
            for user in query
            if check_access(path=f"/user/{user.id}", method="GET")
        ]
        return results
Esempio n. 18
0
async def delete_protocol(
    protocol_id: int,
    purge: bool = False,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/protocol/{str(protocol_id)}",
                        method="DELETE"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    protocol = db.query(Protocol).get(protocol_id)
    if not protocol or protocol.is_deleted:
        raise HTTPException(status_code=404, detail='Protocol Not Found')
    if purge:
        db.delete(protocol)
    else:
        protocol.is_deleted = True
    db.commit()
    delete_policy(enforcer, path=f"/protocol/{str(protocol.id)}")
    return success
Esempio n. 19
0
File: run.py Progetto: lab-grid/flow
def crud_get_run_sample(
    item_to_dict,
    enforcer: casbin.Enforcer,
    db: Session,
    current_user: Auth0ClaimsPatched,
    run_id: int,
    sample_id: str,
    version_id: Optional[int] = None,
) -> dict:
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run_id)}",
                        method="GET"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')
    run = db.query(Run).get(run_id)
    if not run or run.is_deleted:
        raise HTTPException(status_code=404, detail='Run Not Found')
    sample = db.query(Sample)\
        .filter(Sample.run_version_id == run.version_id)\
        .filter(Sample.sample_id == sample_id)\
        .first()
    return item_to_dict(sample)
Esempio n. 20
0
File: run.py Progetto: lab-grid/flow
async def get_run_attachment(
    run_id: int,
    attachment_id: int,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run_id)}",
                        method="GET"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')
    run = db.query(Run).get(run_id)
    if not run or run.is_deleted:
        raise HTTPException(status_code=404, detail='Run Not Found')

    attachment = db.query(Attachment).get(attachment_id)
    if not attachment or attachment.is_deleted:
        raise HTTPException(status_code=404, detail='Attachment Not Found')

    return StreamingResponse(
        io.BytesIO(attachment.data),
        media_type=attachment.mimetype
        if attachment.mimetype else 'application/octet-stream')
Esempio n. 21
0
def crud_get_users(
    item_to_dict,
    enforcer: casbin.Enforcer,
    db: Session,
    current_user: Auth0ClaimsPatched,
    archived: Optional[bool] = None,
    page: Optional[int] = None,
    per_page: Optional[int] = None,
) -> List[dict]:
    return paginatify(
        items_label='users',
        items=[
            user for user in all_users(db, archived).order_by(
                User.created_on.desc())
            if check_access(enforcer,
                            user=current_user.username,
                            path=f"/user/{str(user.id)}",
                            method="GET") and user and user.current
        ],
        item_to_dict=item_to_dict,
        page=page,
        per_page=per_page,
    )
Esempio n. 22
0
File: run.py Progetto: lab-grid/flow
async def delete_run(
    run_id: int,
    purge: bool = False,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run_id)}",
                        method="DELETE"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

    run = db.query(Run).get(run_id)
    if not run or run.is_deleted:
        raise HTTPException(status_code=404, detail='Run Not Found')
    if purge:
        db.delete(run)
    else:
        run.is_deleted = True
        # TODO: Mark all samples as deleted/archived?
    db.commit()
    delete_policy(enforcer, path=f"/run/{str(run.id)}")
    return success
Esempio n. 23
0
File: run.py Progetto: lab-grid/flow
async def create_run_attachment(
    run_id: int,
    file: UploadFile = File(...),
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run_id)}",
                        method="GET"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')
    run = db.query(Run).get(run_id)
    if not run or run.is_deleted:
        raise HTTPException(status_code=404, detail='Run Not Found')

    attachment = Attachment(
        name=file.filename,
        mimetype=file.content_type,
        data=await file.read(),
    )

    db.add(attachment)
    db.commit()
    return AttachmentModel(id=attachment.id, name=attachment.name)
Esempio n. 24
0
    def delete(self, run_id, attachment_id):
        if not check_access(path=f"/run/{str(run_id)}", method="GET"):
            abort(403)
            return
        run = Run.query.get(run_id)
        if not run or run.is_deleted:
            abort(404)
            return

        purge = request.args.get('purge') == 'true' if request.args.get(
            'purge') else False

        attachment = Attachment.query.get(attachment_id)
        if not attachment or attachment.is_deleted:
            abort(404)
            return
        if purge:
            db.session.delete(attachment)
        else:
            attachment.is_deleted = True
        db.session.commit()
        return {
            'success': True,
        }
Esempio n. 25
0
    def post(self, run_id):
        if not check_access(path=f"/run/{str(run_id)}", method="GET"):
            abort(403)
            return
        run = Run.query.get(run_id)
        if not run or run.is_deleted:
            abort(404)
            return

        args = upload_parser.parse_args()
        uploaded_file = args['file']

        attachment = Attachment(
            name=secure_filename(uploaded_file.filename),
            mimetype=uploaded_file.content_type,
            data=uploaded_file.read(),
        )

        db.session.add(attachment)
        db.session.commit()
        return {
            'id': attachment.id,
            'name': attachment.name,
        }
Esempio n. 26
0
File: run.py Progetto: lab-grid/flow
def crud_get_runs(
    item_to_dict,
    enforcer: casbin.Enforcer,
    db: Session,
    current_user: Auth0ClaimsPatched,
    protocol: Optional[int] = None,
    run: Optional[int] = None,
    plate: Optional[str] = None,
    reagent: Optional[str] = None,
    sample: Optional[str] = None,
    creator: Optional[str] = None,
    archived: Optional[bool] = None,
    page: Optional[int] = None,
    per_page: Optional[int] = None,
) -> List[dict]:
    runs_queries = []

    # Add filter specific queries. These will be intersected later on.
    if protocol:
        runs_queries.append(
            all_runs(db, archived)\
                .join(ProtocolVersion, ProtocolVersion.id == Run.protocol_version_id)\
                .filter(ProtocolVersion.protocol_id == protocol)
        )
    if run:
        runs_queries.append(
            all_runs(db, archived)\
                .filter(Run.id == run)
        )
    if plate:
        run_version_query = all_runs(db, archived)\
            .join(RunVersion, RunVersion.id == Run.version_id)
        runs_subquery = filter_by_plate_label(run_version_query, plate)
        runs_queries.append(runs_subquery)
    if reagent:
        run_version_query = all_runs(db, archived)\
            .join(RunVersion, RunVersion.id == Run.version_id)
        runs_subquery = filter_by_reagent_label(run_version_query, reagent)
        runs_queries.append(runs_subquery)
    if sample:
        run_version_query = all_runs(db, archived)\
            .join(RunVersion, RunVersion.id == Run.version_id)
        runs_subquery = filter_by_sample_label(run_version_query, sample)
        runs_queries.append(runs_subquery)
    if creator:
        runs_queries.append(
            all_runs(db, archived)\
                # .filter(Run.id == run)

                .filter(Run.created_by == creator)
        )

    # Add a basic non-deleted items query if no filters were specified.
    if len(runs_queries) == 0:
        runs_queries.append(all_runs(db, archived))

    # Only return the intersection of all queries.
    runs_query = reduce(lambda a, b: a.intersect(b), runs_queries)

    return paginatify(
        items_label='runs',
        items=[
            run
            for run in runs_query.distinct().order_by(Run.created_on.desc())
            if check_access(enforcer,
                            user=current_user.username,
                            path=f"/run/{str(run.id)}",
                            method="GET") and run and run.current
        ],
        item_to_dict=lambda run: item_to_dict(fix_plate_markers_run(db, run)),
        page=page,
        per_page=per_page,
    )
Esempio n. 27
0
def graphql_crud_get_samples(
    enforcer: casbin.Enforcer,
    current_user: Auth0CurrentUserPatched,
    info: ResolveInfo,

    # Search parameters
    protocol: Optional[int] = None,
    run: Optional[int] = None,
    plate: Optional[str] = None,
    reagent: Optional[str] = None,
    sample: Optional[str] = None,
    creator: Optional[str] = None,
    archived: Optional[bool] = None,

    # Paging parameters
    page: Optional[int] = None,
    per_page: Optional[int] = None,
):
    # Calculate which top level fields to remove.
    top_level_ignore = {
        'sample_id', 'plate_id', 'run_version_id', 'protocol_version_id',
        'created_by', 'created_on', 'updated_by', 'updated_on', 'run_id',
        'protocol_id'
    }

    # Flatten `info` parameter into jsonb_query_path statements.
    select_args = []
    top_level = set()
    for result in graphql_ast_flatten_field(info.field_asts[0], info.fragments,
                                            info.return_type, info.schema):
        result_parts = result.split('.')
        if len(result_parts) > 3 and result_parts[3] not in top_level_ignore:
            top_level.add(result_parts[3])
    jsonb_fields = [
        'sample_id',
        'sampleID',
        'plate_id',
        'plateID',
        'run_version_id',
        'protocol_version_id',
        'created_by',
        'created_on',
        'updated_by',
        'updated_on',
        'run_id',
        'runID',
        'protocol_id',
        'protocolID',
    ]
    select_args = [
        Sample.sample_id.label('sample_id'),
        Sample.sample_id.label('sampleID'),
        Sample.plate_id.label('plate_id'),
        Sample.plate_id.label('plateID'),
        Sample.run_version_id.label('run_version_id'),
        Sample.protocol_version_id.label('protocol_version_id'),
        Sample.created_by.label('created_by'),
        Sample.created_on.label('created_on'),
        SampleVersion.updated_by.label('updated_by'),
        SampleVersion.updated_on.label('updated_on'),
        RunVersion.run_id.label('run_id'),
        RunVersion.run_id.label('runID'),
        ProtocolVersion.protocol_id.label('protocol_id'),
        ProtocolVersion.protocol_id.label('protocolID'),
    ]
    for field in top_level:
        jsonb_fields.append(field)
        select_args.append(SampleVersion.data[field].label(field))

    db = get_session(info)

    # Join with additional tables as necessary for search params.
    from_tables = OrderedDict()
    filters = []

    if protocol:
        filters.append(ProtocolVersion.protocol_id == protocol)
    if run:
        filters.append(RunVersion.run_id == run)
    if plate:
        filters.append(Sample.plate_id.like(f"%{plate}%"))
    if reagent:
        filters.append(filter_by_reagent_label_filter(reagent))
    if sample:
        filters.append(Sample.sample_id.like(f"%{sample}%"))
    if creator:
        filters.append(Sample.created_by == creator)
    if archived is None or archived == False:
        filters.append(Sample.is_deleted == False)

    query = db.query(*select_args)\
        .select_from(Sample)\
        .join(SampleVersion, SampleVersion.id == Sample.version_id)\
        .join(RunVersion, RunVersion.id == Sample.run_version_id)\
        .join(ProtocolVersion, ProtocolVersion.id == Sample.protocol_version_id)
    for join_cls, join_filter in from_tables.items():
        query = query.join(join_cls, join_filter)

    # Apply search filters.
    for search_filter in filters:
        query = query.filter(search_filter)

    # Get results
    query = query.distinct().order_by(Sample.created_on.desc())
    rows = [
        sample for sample in query
        if check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(sample.run_id)}",
                        method="GET")
    ]

    return paginatify(
        items_label='samples',
        items=rows,
        item_to_dict=lambda sample: SampleResult.parse_obj(
            add_sample_id(sample._asdict())),
        page=page,
        per_page=per_page,
    )
Esempio n. 28
0
    def get(self):
        protocol = int(request.args.get('protocol')) if request.args.get(
            'protocol') else None
        run = int(request.args.get('run')) if request.args.get('run') else None
        plate = request.args.get('plate')
        reagent = request.args.get('reagent')
        sample = request.args.get('sample')
        creator = request.args.get('creator')
        archived = request.args.get('archived') == 'true' if request.args.get(
            'archived') else False

        samples_queries = []

        # Add filter specific queries. These will be intersected later on.
        if protocol:
            samples_queries.append(
                all_samples(archived)\
                    .join(ProtocolVersion, ProtocolVersion.id == Sample.protocol_version_id)\
                    .filter(ProtocolVersion.protocol_id == protocol)
            )
        if run:
            samples_queries.append(
                all_samples(archived)\
                    .join(RunVersion, RunVersion.id == Sample.run_version_id)\
                    .filter(RunVersion.run_id == run)
            )
        if plate:
            samples_queries.append(
                all_samples(archived)\
                    .filter(Sample.plate_id == plate)
            )
        if reagent:
            run_version_query = all_samples(archived)\
                .join(RunVersion, RunVersion.id == Sample.run_version_id)
            samples_subquery = filter_by_reagent_label(run_version_query,
                                                       reagent)
            samples_queries.append(samples_subquery)
        if sample:
            samples_queries.append(
                all_samples(archived)\
                    .filter(Sample.sample_id == sample)
            )
        if creator:
            samples_queries.append(
                all_samples(archived)\
                    .filter(Sample.created_by == creator)
            )

        # Add a basic non-deleted items query if no filters were specified.
        if len(samples_queries) == 0:
            samples_queries.append(all_samples(archived))

        # Only return the intersection of all queries.
        samples_query = reduce(lambda a, b: a.intersect(b), samples_queries)

        results = {}
        if request.args.get('page') is not None or request.args.get(
                'per_page') is not None:
            page = int(
                request.args.get('page')) if request.args.get('page') else 1
            per_page = int(request.args.get('per_page')) if request.args.get(
                'per_page') else 20
            page_query = samples_query.distinct().order_by(
                Sample.created_on.desc()).paginate(page=page,
                                                   per_page=per_page)
            results['page'] = page_query.page
            results['pageCount'] = page_query.pages
            query = page_query.items
        else:
            query = samples_query.distinct().order_by(Sample.created_on.desc())

        results['samples'] = [
            run_to_sample(sample) for sample in query
            if check_access(path=f"/run/{str(sample.run_version.run_id)}",
                            method="GET") and sample and sample.current
        ]
        return results
Esempio n. 29
0
File: run.py Progetto: lab-grid/flow
def crud_get_run_samples(
    item_to_dict,
    enforcer: casbin.Enforcer,
    db: Session,
    current_user: Auth0ClaimsPatched,
    run_id: Optional[int] = None,
    protocol: Optional[int] = None,
    plate: Optional[str] = None,
    reagent: Optional[str] = None,
    creator: Optional[str] = None,
    archived: Optional[bool] = None,
    page: Optional[int] = None,
    per_page: Optional[int] = None,
) -> List[dict]:
    if not check_access(enforcer,
                        user=current_user.username,
                        path=f"/run/{str(run_id)}",
                        method="GET"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')
    run = db.query(Run).get(run_id)
    if not run or run.is_deleted:
        raise HTTPException(status_code=404, detail='Run Not Found')

    samples_queries = []

    # Add filter specific queries. These will be intersected later on.
    if protocol:
        samples_queries.append(
            all_samples(db, run, archived)\
                .join(ProtocolVersion, ProtocolVersion.id == Sample.protocol_version_id)\
                .filter(ProtocolVersion.protocol_id == protocol)
        )
    if plate:
        samples_queries.append(
            all_samples(db, run, archived)\
                .filter(Sample.plate_id == plate)
        )
    if reagent:
        run_version_query = all_samples(db, run, archived)\
            .join(RunVersion, RunVersion.id == Sample.run_version_id)
        samples_subquery = filter_by_reagent_label(run_version_query, reagent)
        samples_queries.append(samples_subquery)
    if creator:
        samples_queries.append(
            all_samples(db, run, archived)\
                .filter(Sample.created_by == creator)
        )

    # Add a basic non-deleted items query if no filters were specified.
    if len(samples_queries) == 0:
        samples_queries.append(all_samples(db, run, archived))

    # Only return the intersection of all queries.
    samples_query = reduce(lambda a, b: a.intersect(b), samples_queries)

    return paginatify(
        items_label='samples',
        items=[
            sample for sample in samples_query.distinct().order_by(
                Sample.sample_id.asc())
        ],
        item_to_dict=item_to_dict,
        page=page,
        per_page=per_page,
    )
Esempio n. 30
0
    def get(self):
        run = int(request.args.get('run')) if request.args.get('run') else None
        plate = request.args.get('plate')
        reagent = request.args.get('reagent')
        sample = request.args.get('sample')
        creator = request.args.get('creator')
        archived = request.args.get('archived') == 'true' if request.args.get(
            'archived') else False

        protocols_queries = []
        if run:
            protocols_queries.append(
                all_protocols(archived)\
                    .join(ProtocolVersion, ProtocolVersion.protocol_id == Protocol.id)\
                    .join(Run, Run.protocol_version_id == ProtocolVersion.id)\
                    .filter(Run.id == run)
            )
        if plate:
            run_version_query = all_protocols(archived)\
                .join(ProtocolVersion, ProtocolVersion.protocol_id == Protocol.id)\
                .join(Run, Run.protocol_version_id == ProtocolVersion.id)\
                .join(RunVersion, RunVersion.id == Run.version_id)
            protocols_subquery = filter_by_plate_label(run_version_query,
                                                       plate)
            protocols_queries.append(protocols_subquery)
        if reagent:
            run_version_query = all_protocols(archived)\
                .join(ProtocolVersion, ProtocolVersion.protocol_id == Protocol.id)\
                .join(Run, Run.protocol_version_id == ProtocolVersion.id)\
                .join(RunVersion, RunVersion.id == Run.version_id)
            protocols_subquery = filter_by_reagent_label(
                run_version_query, reagent)
            protocols_queries.append(protocols_subquery)
        if sample:
            run_version_query = all_protocols(archived)\
                .join(ProtocolVersion, ProtocolVersion.protocol_id == Protocol.id)\
                .join(Run, Run.protocol_version_id == ProtocolVersion.id)\
                .join(RunVersion, RunVersion.id == Run.version_id)
            protocols_subquery = filter_by_sample_label(
                run_version_query, sample)
            protocols_queries.append(protocols_subquery)
        if creator:
            protocols_queries.append(
                all_protocols(archived)\
                    # .filter(Protocol.id == protocol)\
                    .filter(Protocol.created_by == creator)
            )

        # Add a basic non-deleted items query if no filters were specified.
        if len(protocols_queries) == 0:
            protocols_queries.append(all_protocols(archived))

        # Only return the intersection of all queries.
        protocols_query = reduce(lambda a, b: a.intersect(b),
                                 protocols_queries)

        results = {}
        if request.args.get('page') is not None or request.args.get(
                'per_page') is not None:
            page = int(
                request.args.get('page')) if request.args.get('page') else 1
            per_page = int(request.args.get('per_page')) if request.args.get(
                'per_page') else 20
            page_query = protocols_query.distinct().order_by(
                Protocol.created_on.desc()).paginate(page=page,
                                                     per_page=per_page)
            results['page'] = page_query.page
            results['pageCount'] = page_query.pages
            query = page_query.items
        else:
            query = protocols_query.distinct().order_by(
                Protocol.created_on.desc())

        results['protocols'] = [
            versioned_row_to_dict(api, protocol, protocol.current)
            for protocol in query
            if check_access(path=f"/protocol/{str(protocol.id)}", method="GET")
            and protocol and protocol.current
        ]
        return results