diff --git a/src/app.py b/src/app.py index e6a10bf3..4164e875 100644 --- a/src/app.py +++ b/src/app.py @@ -2146,6 +2146,59 @@ def get_revisions_list(id): return jsonify(results) +""" +Get all organs associated with a given dataset + +The gateway treats this endpoint as public accessible + +Parameters +---------- +id : str + The HuBMAP ID (e.g. HBM123.ABCD.456) or UUID of given entity + +Returns +------- +json + a list of all the organs associated with the target dataset +""" +@app.route('/datasets//organs', methods=['GET']) +def get_associated_organs_from_dataset(id): + # Token is not required, but if an invalid token provided, + # we need to tell the client with a 401 error + validate_token_if_auth_header_exists(request) + + # Use the internal token to query the target entity + # since public entities don't require user token + token = get_internal_token() + + # Query target entity against uuid-api and neo4j and return as a dict if exists + entity_dict = query_target_entity(id, token) + normalized_entity_type = entity_dict['entity_type'] + + # Only for Dataset + if normalized_entity_type != 'Dataset': + bad_request_error("The entity of given id is not a Dataset") + + # published/public datasets don't require token + if entity_dict['status'].lower() != DATASET_STATUS_PUBLISHED: + # Token is required and the user must belong to HuBMAP-READ group + token = get_user_token(request, non_public_access_required=True) + + # By now, either the entity is public accessible or + # the user token has the correct access level + associated_organs = app_neo4j_queries.get_associated_organs_from_dataset(neo4j_driver_instance, entity_dict['uuid']) + + # If there are zero items in the list associated organs, then there are no associated + # Organs and a 404 will be returned. + if len(associated_organs) < 1: + not_found_error("the dataset does not have any associated organs") + + complete_entities_list = schema_manager.get_complete_entities_list(token, associated_organs) + + # Final result after normalization + final_result = schema_manager.normalize_entities_list_for_response(complete_entities_list) + + return jsonify(final_result) #################################################################################################### ## Internal Functions diff --git a/src/app_neo4j_queries.py b/src/app_neo4j_queries.py index f761936a..4edc421d 100644 --- a/src/app_neo4j_queries.py +++ b/src/app_neo4j_queries.py @@ -891,6 +891,32 @@ def get_dataset_revision_number(neo4j_driver, uuid): return revision_number +""" +Retrieve the list of uuids for organs associated with a given dataset + +Parameters +---------- +neo4j_driver : neo4j.Driver object + The neo4j database connection pool +uuid : str + The uuid of the target entity: Dataset +""" +def get_associated_organs_from_dataset(neo4j_driver, dataset_uuid): + results = [] + query = (f"MATCH (ds:Dataset)<-[*]-(organ:Sample {{specimen_type:'organ'}}) " + f"WHERE ds.uuid='{dataset_uuid}'" + f"RETURN apoc.coll.toSet(COLLECT(organ)) AS {record_field_name}") + logger.debug("======get_associated_organs_from_dataset() query======") + logger.debug(query) + + with neo4j_driver.session() as session: + record = session.read_transaction(_execute_readonly_tx, query) + + if record and record[record_field_name]: + results = _nodes_to_dicts(record[record_field_name]) + + return results + #################################################################################################### ## Internal Functions ####################################################################################################