Пример #1
0
async def create_protocol(
    protocol: ProtocolModel,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    protocol_dict = protocol.dict()
    protocol = Protocol()
    protocol_version = ProtocolVersion(data=strip_metadata(protocol_dict),
                                       server_version=settings.server_version)
    protocol_version.protocol = protocol
    protocol.current = protocol_version
    add_owner(protocol, current_user.username)
    db.add_all([protocol, protocol_version])
    db.commit()
    add_policy(enforcer,
               user=current_user.username,
               path=f"/protocol/{str(protocol.id)}",
               method="GET")
    add_policy(enforcer,
               user=current_user.username,
               path=f"/protocol/{str(protocol.id)}",
               method="PUT")
    add_policy(enforcer,
               user=current_user.username,
               path=f"/protocol/{str(protocol.id)}",
               method="DELETE")
    return versioned_row_to_dict(protocol, protocol_version)
Пример #2
0
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)
Пример #3
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)
Пример #4
0
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)
Пример #5
0
 def post(self):
     run_dict = request.json
     protocol_id = extract_protocol_id(run_dict)
     run_dict.pop('protocol', None)
     if not protocol_id:
         abort(400)
         return
     protocol = Protocol.query.get(protocol_id)
     if not protocol:
         abort(400)
         return
     run = Run()
     run_version = RunVersion(data=strip_metadata(run_dict),
                              server_version=app.config['SERVER_VERSION'])
     run_version.run = run
     run.current = run_version
     run.protocol_version_id = protocol.version_id
     add_owner(run)
     db.session.add_all([run, run_version])
     samples = get_samples(run, run_version)
     if samples:
         for sample in samples:
             db.session.merge(sample)
     db.session.commit()
     add_policy(path=f"/run/{str(run.id)}", method="GET")
     add_policy(path=f"/run/{str(run.id)}", method="PUT")
     add_policy(path=f"/run/{str(run.id)}", method="DELETE")
     return run_to_dict(run, run_version)
Пример #6
0
async def create_user(
    user: UserModel,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    user_dict = user.dict()

    # Drop the roles field if it was provided.
    user_dict.pop('roles', None)
    new_user = User(id=current_user.username if current_user.username else 42)
    new_user_version = UserVersion(data=strip_metadata(user_dict),
                                   server_version=settings.server_version)
    new_user_version.user = new_user
    new_user.current = new_user_version
    add_owner(new_user, current_user.username)
    db.add_all([new_user, new_user_version])
    db.commit()
    add_policy(enforcer,
               user=current_user.username,
               path=f"/user/{str(new_user.id)}",
               method="GET")
    add_policy(enforcer,
               user=current_user.username,
               path=f"/user/{str(new_user.id)}",
               method="PUT")
    return add_role(enforcer, versioned_row_to_dict(new_user,
                                                    new_user_version))
Пример #7
0
async def update_sample(sample_id: str, sample: SampleResult, db: Session = Depends(get_db), current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    sample_dict = sample.dict()
    new_sample = db.query(Sample).get(sample_id)
    if not new_sample or new_sample.is_deleted:
        raise HTTPException(status_code=404, detail='Sample not found')
    if not change_allowed(run_to_sample(new_sample), sample_dict):
        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.session.add(new_sample_version)
    db.session.commit()
    return run_to_sample(new_sample)
Пример #8
0
 def post(self):
     protocol_dict = request.json
     protocol = Protocol()
     protocol_version = ProtocolVersion(
         data=strip_metadata(protocol_dict),
         server_version=app.config['SERVER_VERSION'])
     protocol_version.protocol = protocol
     protocol.current = protocol_version
     add_owner(protocol)
     db.session.add_all([protocol, protocol_version])
     db.session.commit()
     add_policy(path=f"/protocol/{str(protocol.id)}", method="GET")
     add_policy(path=f"/protocol/{str(protocol.id)}", method="PUT")
     add_policy(path=f"/protocol/{str(protocol.id)}", method="DELETE")
     return versioned_row_to_dict(api, protocol, protocol_version)
Пример #9
0
 def post(self):
     user_dict = request.json
     # Drop the roles field if it was provided.
     user_dict.pop('roles', None)
     user = User(id=request.current_user["sub"] if request.
                 current_user["sub"] else 42)
     user_version = UserVersion(data=strip_metadata(user_dict),
                                server_version=app.config['SERVER_VERSION'])
     user_version.user = user
     user.current = user_version
     add_owner(user)
     db.session.add_all([user, user_version])
     db.session.commit()
     add_policy(path=f"/user/{str(user.id)}", method="GET")
     add_policy(path=f"/user/{str(user.id)}", method="PUT")
     return add_role(versioned_row_to_dict(api, user, user_version))
Пример #10
0
 def put(self, sample_id):
     sample_dict = request.json
     sample = Sample.query.get(sample_id)
     if not sample or sample.is_deleted:
         abort(404)
         return
     if not change_allowed(run_to_sample(sample), sample_dict):
         abort(403)
         return
     sample_version = SampleVersion(
         data=strip_metadata(sample_dict),
         server_version=app.config['SERVER_VERSION'])
     sample_version.sample = sample
     add_updator(sample_version)
     sample.current = sample_version
     db.session.add(sample_version)
     db.session.commit()
     return run_to_sample(sample)
Пример #11
0
    def put(self, user_id):
        user_id = urllib.parse.unquote(user_id)

        user_dict = request.json
        # Drop the roles field if it was provided.
        user_dict.pop('roles', None)
        user_dict = request.json
        user = User.query.get(user_id)
        if not user or user.is_deleted:
            abort(404)
            return
        user_version = UserVersion(data=strip_metadata(user_dict),
                                   server_version=app.config['SERVER_VERSION'])
        user_version.user = user
        add_updator(user_version)
        user.current = user_version
        db.session.add(user_version)
        db.session.commit()
        return add_role(versioned_row_to_dict(api, user, user.current))
Пример #12
0
 def put(self, protocol_id):
     protocol_dict = request.json
     protocol = Protocol.query.get(protocol_id)
     if not protocol or protocol.is_deleted:
         abort(404)
         return
     if not change_allowed(
             versioned_row_to_dict(api, protocol, protocol.current),
             protocol_dict):
         abort(403)
         return
     protocol_version = ProtocolVersion(
         data=strip_metadata(protocol_dict),
         server_version=app.config['SERVER_VERSION'])
     protocol_version.protocol = protocol
     add_updator(protocol_version)
     protocol.current = protocol_version
     db.session.add(protocol_version)
     db.session.commit()
     return versioned_row_to_dict(api, protocol, protocol.current)
Пример #13
0
async def create_run(
    run: RunModel,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    run_dict = run.dict()
    protocol_id = extract_protocol_id(run_dict)
    run_dict.pop('protocol', None)
    if not protocol_id:
        raise HTTPException(status_code=400, detail='Invalid Protocol ID')
    protocol = db.query(Protocol).get(protocol_id)
    if not protocol:
        raise HTTPException(status_code=400,
                            detail='Invalid Protocol (Not Found)')
    new_run = Run()
    new_run_version = RunVersion(data=strip_metadata(run_dict),
                                 server_version=settings.server_version)
    new_run_version.run = new_run
    new_run.current = new_run_version
    new_run.protocol_version_id = protocol.version_id
    add_owner(new_run, current_user.username)
    db.add_all([new_run, new_run_version])
    samples = get_samples(new_run_version, protocol.current)
    if samples:
        for sample in samples:
            db.merge(sample)
    db.commit()
    add_policy(enforcer,
               user=current_user.username,
               path=f"/run/{str(new_run.id)}",
               method="GET")
    add_policy(enforcer,
               user=current_user.username,
               path=f"/run/{str(new_run.id)}",
               method="PUT")
    add_policy(enforcer,
               user=current_user.username,
               path=f"/run/{str(new_run.id)}",
               method="DELETE")
    return run_to_dict(new_run, new_run_version)
Пример #14
0
 def put(self, run_id, sample_id):
     sample_dict = request.json
     # This field shouldn't be updated by users.
     # sample_dict.pop('protocol', None)
     sample = Sample.query.filter(
         Sample.sample_version_id == sample.version_id).filter(
             Sample.sample_id == sample_id).first()
     if not sample or sample.is_deleted:
         abort(404)
         return
     if not change_allowed(run_to_dict(run, run.current), {}):
         abort(403)
         return
     sample_version = SampleVersion(
         data=strip_metadata(sample_dict),
         server_version=app.config['SERVER_VERSION'])
     sample_version.sample = sample
     add_updator(sample_version)
     sample.current = sample_version
     db.session.add(sample_version)
     db.session.commit()
     return run_to_sample(sample)
Пример #15
0
async def update_user(
    user_id: str,
    user: UserModel,
    enforcer: casbin.Enforcer = Depends(get_enforcer),
    db: Session = Depends(get_db),
    current_user: Auth0ClaimsPatched = Depends(get_current_user)):
    user_id = urllib.parse.unquote(user_id)

    user_dict = user.dict()
    # Drop the roles field if it was provided.
    user_dict.pop('roles', None)
    new_user = db.query(User).get(user_id)
    if not new_user or new_user.is_deleted:
        raise HTTPException(status_code=404, detail='User Not Found')
    new_user_version = UserVersion(data=strip_metadata(user_dict),
                                   server_version=settings.server_version)
    new_user_version.user = new_user
    add_updator(new_user_version, current_user.username)
    new_user.current = new_user_version
    db.add(new_user_version)
    db.commit()
    return add_role(enforcer, versioned_row_to_dict(new_user,
                                                    new_user.current))
Пример #16
0
 def put(self, run_id):
     run_dict = request.json
     # This field shouldn't be updated by users.
     run_dict.pop('protocol', None)
     run = Run.query.get(run_id)
     if not run or run.is_deleted:
         abort(404)
         return
     if not change_allowed(run_to_dict(run, run.current), run_dict):
         abort(403)
         return
     run_version = RunVersion(data=strip_metadata(run_dict),
                              server_version=app.config['SERVER_VERSION'])
     run_version.run = run
     add_updator(run_version)
     run.current = run_version
     db.session.add(run_version)
     samples = get_samples(run, run_version)
     if samples:
         for sample in samples:
             db.session.merge(sample)
     db.session.commit()
     return run_to_dict(run, run.current)
Пример #17
0
async def patch_run(
    request: Request,
    run_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"/run/{str(run_id)}",
                        method="PUT"):
        raise HTTPException(status_code=403, detail='Insufficient Permissions')

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

    record_timing(request, note=f"Fetched run {run_id}")

    run_dict = versioned_row_to_dict(new_run, new_run.current)
    run_dict.pop('protocol', None)
    json_patch = jsonpatch.JsonPatch(patch)
    run_dict.pop('protocol', None)
    run_dict = json_patch.apply(run_dict)

    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)
    original_run_version = new_run.current
    new_run.current = new_run_version
    db.add(new_run_version)
    db.commit()

    record_timing(request, note=f"Saved changes to run {run_id}")

    samples_dirty = False
    for operation in patch:
        operation_path = operation.get('path', '')
        # Check for changes to the path: /sections/*/blocks/*/plates
        if re.search(
                "^/(sections/([^/]+/(blocks/([^/]+/(plates(/.*)?)?)?)?)?)?$",
                operation_path):
            samples_dirty = True
            break
        # Check for changes to the path: /sections/*/blocks/*/plateSequencingResults
        if re.search(
                "^/(sections/([^/]+/(blocks/([^/]+/(plateSequencingResults(/.*)?)?)?)?)?)?$",
                operation_path):
            samples_dirty = True
            break
        # Check for changes to the path: /protocol/sections/*/blocks/*/plateMarkers
        if re.search(
                "^/(protocol/(sections/([^/]+/(blocks/([^/]+/(plateMarkers(/.*)?)?)?)?)?)?)?$",
                operation_path):
            samples_dirty = True
            break

    if samples_dirty:
        logger.info("======================================")
        logger.info(
            f"Regenerating samples for run_version: ({new_run.id}, {new_run_version.id})"
        )
        samples = get_samples(new_run_version, new_run.protocol_version)

        record_timing(
            request,
            note=f"Regenerated run {new_run.id} samples (len: {len(samples)})")

        if samples:
            for sample in samples:
                db.merge(sample)
        logger.info(
            f"Generated {len(samples)} samples for run_version: ({new_run.id}, {new_run_version.id})"
        )
        logger.info("======================================")

        record_timing(
            request,
            note=f"Saved {len(samples)} regenerated samples to run {new_run.id}"
        )
    else:
        logger.info("======================================")
        logger.info(
            f"Using old samples for run_version: ({new_run.id}, {new_run_version.id})"
        )
        samples = db.query(Sample)\
            .filter(Sample.run_version_id == original_run_version.id)\
            .distinct()
        sample_count = 0
        for sample in samples:
            new_sample_version = clone_model(db,
                                             sample.current,
                                             run_version_id=new_run_version.id)
            new_sample = clone_model(db,
                                     sample,
                                     current=new_sample_version,
                                     run_version_id=new_run_version.id)
            db.merge(new_sample)
            sample_count += 1
        logger.info(
            f"Attached {sample_count} existing samples to run_version: ({new_run.id}, {new_run_version.id})"
        )
        logger.info("======================================")

        record_timing(
            request,
            note=f"Attached {sample_count} existing samples to run {new_run.id}"
        )

    db.commit()
    return run_to_dict(new_run, new_run.current)