def update_collection(collection_id: int, collection: CollectionModel, current_user: int = Depends(get_current_user)): """ Update the collection. Note that some updates are silently failing when not compatible with the composing projects. *Currently only for admins* """ sce = CollectionsService() with RightsThrower(sce): present_collection = sce.query(current_user, collection_id) if present_collection is None: raise HTTPException(status_code=404, detail="Collection not found") # noinspection PyUnresolvedReferences present_collection.update( session=sce.session, title=collection.title, project_ids=collection.project_ids, provider_user=collection.provider_user, contact_user=collection.contact_user, citation=collection.citation, abstract=collection.abstract, description=collection.description, creator_users=collection.creator_users, associate_users=collection.associate_users, creator_orgs=collection.creator_organisations, associate_orgs=collection.associate_organisations)
def system_error(_current_user: int = Depends(get_current_user)): """ This entry point will return a 500 internal error, on purpose so the stack trace is visible and client can see what it gives. """ with RightsThrower(): assert False
def update_project(project_id: int, project: ProjectModel, current_user: int = Depends(get_current_user)): """ Update the project. Note that some fields will NOT be updated and simply ignored, e.g. *free_cols. """ sce = ProjectsService() with RightsThrower(sce): present_project: ProjectBO = sce.query(current_user, project_id, for_managing=True) with ValidityThrower(): # noinspection PyUnresolvedReferences present_project.update(session=sce.session, title=project.title, visible=project.visible, status=project.status, projtype=project.projtype, init_classif_list=project.init_classif_list, classiffieldlist=project.classiffieldlist, popoverfieldlist=project.popoverfieldlist, cnn_network_id=project.cnn_network_id, comments=project.comments, contact=project.contact, managers=project.managers, annotators=project.annotators, viewers=project.viewers, license_=project.license)
def get_object_set( project_id: int, filters: ProjectFiltersModel, order_field: Optional[str] = None, # TODO: order_field should be a user-visible field name, not nXXX, in case of free field window_start: Optional[int] = None, window_size: Optional[int] = None, current_user: Optional[int] = Depends(get_optional_current_user) ) -> ObjectSetQueryRsp: """ Return object ids for the given project with the filters. Optionally: - order_field will order the result using given field, If prefixed with "-" then it will be reversed. - window_start & window_size allows to return only a slice of the result. """ sce = ObjectManager() with RightsThrower(sce): rsp = ObjectSetQueryRsp() obj_with_parents, total = sce.query(current_user, project_id, filters, order_field, window_start, window_size) rsp.total_ids = total rsp.object_ids = [with_p[0] for with_p in obj_with_parents] rsp.acquisition_ids = [with_p[1] for with_p in obj_with_parents] rsp.sample_ids = [with_p[2] for with_p in obj_with_parents] rsp.project_ids = [with_p[3] for with_p in obj_with_parents] # TODO: Despite the ORJSON encode above, this response is still quite slow due to a call # to def jsonable_encoder (in FastAPI encoders.py) return rsp
def project_recompute_geography( project_id: int, current_user: int = Depends(get_current_user)) -> None: """ Recompute geography information for all samples in project. """ sce = ProjectsService() with RightsThrower(sce): sce.recompute_geo(current_user, project_id)
def erase_collection( collection_id: int, current_user: int = Depends(get_current_user)) -> int: """ Delete the collection, i.e. the precious fields, as the projects are just unliked from the collection. """ sce = CollectionsService() with RightsThrower(sce): return sce.delete(current_user, collection_id)
def project_stats(project_id: int, current_user: int = Depends(get_current_user)): """ Check consistency of a project. """ sce = ProjectStatsFetcher(project_id) with RightsThrower(sce): return sce.run(current_user)
def update_object_set( req: BulkUpdateReq, current_user: int = Depends(get_current_user)) -> int: """ Update all the objects with given IDs and values Current user needs Manage right on all projects of specified objects. """ sce = ObjectManager() with RightsThrower(sce): return sce.update_set(current_user, req.target_ids, req.updates)
def project_subset(project_id: int, params: SubsetReq, current_user: int = Depends(get_current_user)): """ Subset a project into another one. """ sce = SubsetServiceOnProject(project_id, params) with RightsThrower(sce): return sce.run(current_user)
def simple_import(project_id: int, params: SimpleImportReq, current_user: int = Depends(get_current_user)): """ Import images only, with same metadata for all. """ sce = SimpleImport(project_id, params) with RightsThrower(sce): return sce.run(current_user)
def real_import(project_id: int, params: ImportRealReq, current_user: int = Depends(get_current_user)): """ Import an EcoTaxa archive or directory. """ sce = RealImport(project_id, params) with RightsThrower(sce): return sce.run(current_user)
def update_processes( req: BulkUpdateReq, current_user: int = Depends(get_current_user)) -> int: """ Do the required update for each process in the set. Return the number of updated entities. """ sce = ProcessesService() with RightsThrower(sce): return sce.update_set(current_user, req.target_ids, req.updates)
def import_preparation(project_id: int, params: ImportPrepReq, current_user: int = Depends(get_current_user)): """ Prepare/validate the import of an EcoTaxa archive or directory. """ sce = ImportAnalysis(project_id, params) with RightsThrower(sce): return sce.run(current_user)
def acquisitions_search(project_id: int, current_user: Optional[int] = Depends(get_optional_current_user)) \ -> List[AcquisitionBO]: """ Read all acquisitions for a project. """ sce = AcquisitionsService() with RightsThrower(sce): ret = sce.search(current_user, project_id) return ret
def update_samples( req: BulkUpdateReq, current_user: int = Depends(get_current_user)) -> int: """ Do the required update for each sample in the set. Any non-null field in the model is written to every impacted sample. Return the number of updated entities. """ sce = SamplesService() with RightsThrower(sce): return sce.update_set(current_user, req.target_ids, req.updates)
def erase_object_set( object_ids: ObjectIDListT, current_user: int = Depends(get_current_user) ) -> Tuple[int, int, int, int]: """ Delete the objects with given object ids. Current user needs Manage right on all projects of specified objects. """ sce = ObjectManager() with RightsThrower(sce): return sce.delete(current_user, object_ids)
def instrument_query(project_ids: str) \ -> List[str]: """ Query for instruments, either inside specific project(s) or globally. """ sce = InstrumentsService() proj_ids = _split_num_list(project_ids) with RightsThrower(sce): ret = sce.query(proj_ids) return ret
def search_collection(title: str, current_user: int = Depends(get_current_user)): """ Search for collections. *Currently only for admins* """ sce = CollectionsService() with RightsThrower(sce): matching_collections = sce.search(current_user, title) return matching_collections
def project_set_get_stats( ids: str, current_user: int = Depends(get_current_user) ) -> List[ProjectTaxoStats]: """ Read projects statistics, i.e. used taxa and classification states. """ sce = ProjectsService() num_ids = _split_num_list(ids) with RightsThrower(sce): ret = sce.read_stats(current_user, num_ids) return ret
def project_set_get_user_stats( ids: str, current_user: int = Depends(get_current_user) ) -> List[ProjectUserStats]: """ Read projects user statistics. """ sce = ProjectsService() num_ids = _split_num_list(ids) with RightsThrower(sce): ret = sce.read_user_stats(current_user, num_ids) return ret
async def check_taxa_db( aphia_id: int, current_user: int = Depends(get_current_user) ) -> Response: # pragma:nocover """ Check that the given aphia_id is correctly stored. """ sce = TaxonomyChangeService(1) with RightsThrower(sce): msg = await sce.check_id(current_user, aphia_id) # Below produces a chunked HTTP encoding, which is officially only HTTP 1.1 protocol return Response(msg, media_type="text/plain")
def reset_object_set_to_predicted( project_id: int, filters: ProjectFiltersModel, current_user: int = Depends(get_current_user) ) -> None: """ Reset to Predicted all objects for the given project with the filters. """ sce = ObjectManager() with RightsThrower(sce): return sce.reset_to_predicted(current_user, project_id, filters)
async def login(params: LoginReq) -> str: """ Login barrier. If successful, the login will return a JWT which will have to be used in Bearer authentication scheme for subsequent calls. -`username`: User *email* which was used during registration -`password`: User password """ sce = LoginService() with RightsThrower(sce): return sce.validate_login(params.username, params.password)
def object_query_history(object_id: int, current_user: Optional[int] = Depends(get_optional_current_user)) \ -> List[HistoricalClassification]: """ Read a single object's history. """ sce = ObjectService() with RightsThrower(sce): ret = sce.query_history(current_user, object_id) if ret is None: raise HTTPException(status_code=404, detail="Object not found") return ret
def process_query(process_id: int, current_user: Optional[int] = Depends(get_optional_current_user)) \ -> ProcessBO: """ Read a single object. """ sce = ProcessesService() with RightsThrower(sce): ret = sce.query(current_user, process_id) if ret is None: raise HTTPException(status_code=404, detail="Process not found") return ret
def sample_query(sample_id: int, current_user: Optional[int] = Depends(get_optional_current_user)) \ -> SampleBO: """ Read a single object. """ sce = SamplesService() with RightsThrower(sce): ret = sce.query(current_user, sample_id) if ret is None: raise HTTPException(status_code=404, detail="Sample not found") return ret
def acquisition_query(acquisition_id: int, current_user: Optional[int] = Depends(get_optional_current_user)) \ -> AcquisitionBO: """ Read a single object. """ sce = AcquisitionsService() with RightsThrower(sce): ret = sce.query(current_user, acquisition_id) if ret is None: raise HTTPException(status_code=404, detail="Acquisition not found") return ret
def get_collection(collection_id: int, current_user: int = Depends(get_current_user)): """ Read a collection by its ID. *Currently only for admins* """ sce = CollectionsService() with RightsThrower(sce): present_collection = sce.query(current_user, collection_id) if present_collection is None: raise HTTPException(status_code=404, detail="Collection not found") return present_collection
def project_query( project_id: int, for_managing: Optional[bool] = False, current_user: Optional[int] = Depends(get_optional_current_user) ) -> ProjectBO: """ Read project if it exists for current user, eventually for managing it. """ sce = ProjectsService() for_managing = bool(for_managing) with RightsThrower(sce): ret = sce.query(current_user, project_id, for_managing) return ret
def project_merge( project_id: int, source_project_id: int, dry_run: bool, current_user: int = Depends(get_current_user)) -> MergeRsp: """ Merge another project into this one. It's more a phagocytosis than a merge, as the source will see all its objects gone and will be erased. - param `dry_run`: If set, then only a diagnostic of doability will be done. """ sce = MergeService(project_id, source_project_id, dry_run) with RightsThrower(sce): return sce.run(current_user)