diff --git a/chord_metadata_service/restapi/api_views.py b/chord_metadata_service/restapi/api_views.py index 9595f18e6..41112a232 100644 --- a/chord_metadata_service/restapi/api_views.py +++ b/chord_metadata_service/restapi/api_views.py @@ -2,9 +2,7 @@ from adrf.decorators import api_view from bento_lib.responses import errors -from django.db.models import QuerySet -from drf_spectacular.utils import extend_schema, inline_serializer -from rest_framework import serializers, status +from rest_framework import status from rest_framework.decorators import permission_classes from rest_framework.request import Request as DrfRequest from rest_framework.response import Response @@ -12,9 +10,8 @@ from chord_metadata_service.authz.helpers import get_data_type_query_permissions from chord_metadata_service.authz.middleware import authz_middleware from chord_metadata_service.authz.permissions import BentoAllowAny -from chord_metadata_service.authz.types import DataTypeDiscoveryPermissions from chord_metadata_service.chord.data_types import DATA_TYPE_PHENOPACKET, DATA_TYPE_EXPERIMENT -from chord_metadata_service.discovery.scope import ValidatedDiscoveryScope, get_request_discovery_scope +from chord_metadata_service.discovery.scope import get_request_discovery_scope from chord_metadata_service.experiments import models as experiments_models from chord_metadata_service.experiments.summaries import dt_experiment_summary from chord_metadata_service.metadata.service_info import get_service_info @@ -37,54 +34,6 @@ async def service_info(_request: DrfRequest): return Response(await get_service_info()) -async def build_overview_response( - scope: ValidatedDiscoveryScope, - dt_permissions: DataTypeDiscoveryPermissions, - phenopackets: QuerySet | None = None, - experiments: QuerySet | None = None, -) -> Response: - phenopackets_summary, experiments_summary = await asyncio.gather( - dt_phenopacket_summary(scope, dt_permissions[DATA_TYPE_PHENOPACKET], phenopackets), - dt_experiment_summary(scope, dt_permissions[DATA_TYPE_EXPERIMENT], experiments), - ) - - return Response({ - DATA_TYPE_PHENOPACKET: phenopackets_summary, - DATA_TYPE_EXPERIMENT: experiments_summary, - }) - - -@extend_schema( - description="Overview of all Phenopackets in the database", - responses={ - 200: inline_serializer( - name='overview_response', - fields={ - 'phenopackets': serializers.IntegerField(), - 'data_type_specific': serializers.JSONField(), - } - ) - } -) -@api_view(["GET"]) -@permission_classes([BentoAllowAny]) -async def overview(request: DrfRequest): - """ - get: - Overview of all Phenopackets and experiments in the database - private endpoint - """ - - # TODO: permissions based on project - this endpoint should be scrapped / completely rethought - # use node level discovery config for private overview - discovery_scope = ValidatedDiscoveryScope(project=None, dataset=None) - - dt_permissions = await get_data_type_query_permissions( - request, [DATA_TYPE_PHENOPACKET, DATA_TYPE_EXPERIMENT], discovery_scope.as_authz_resource() - ) - - return await build_overview_response(discovery_scope, dt_permissions) - - @api_view(["GET"]) @permission_classes([BentoAllowAny]) def extra_properties_schema_types(_request: DrfRequest): @@ -132,9 +81,12 @@ async def search_overview(request: DrfRequest): # If we don't have query:data on phenopackets, we cannot request a search overview return Response(errors.forbidden_error("Forbidden"), status=status.HTTP_403_FORBIDDEN) - return await build_overview_response( - scope, - dt_permissions, - phenopackets=phenopackets, - experiments=experiments, + phenopackets_summary, experiments_summary = await asyncio.gather( + dt_phenopacket_summary(scope, dt_permissions[DATA_TYPE_PHENOPACKET], phenopackets), + dt_experiment_summary(scope, dt_permissions[DATA_TYPE_EXPERIMENT], experiments), ) + + return Response({ + DATA_TYPE_PHENOPACKET: phenopackets_summary, + DATA_TYPE_EXPERIMENT: experiments_summary, + }) diff --git a/chord_metadata_service/restapi/tests/test_api.py b/chord_metadata_service/restapi/tests/test_api.py index 1095de08b..5539311b6 100644 --- a/chord_metadata_service/restapi/tests/test_api.py +++ b/chord_metadata_service/restapi/tests/test_api.py @@ -73,46 +73,6 @@ def setUp(self) -> None: self.experiment_result = exp_m.ExperimentResult.objects.create(**exp_c.valid_experiment_result()) self.experiment.experiment_results.set([self.experiment_result]) - def test_overview(self): - response = self.dt_authz_full_get('/api/overview') - response_obj = response.json() - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertIsInstance(response_obj, dict) - # phenopackets - phenopacket_res = response_obj['phenopacket'] - self.assertEqual(phenopacket_res['count'], 2) - self.assertEqual(phenopacket_res['data_type_specific']['individuals']['count'], 2) - self.assertIsInstance(phenopacket_res['data_type_specific']['individuals']['age'], dict) - self.assertEqual( - phenopacket_res['data_type_specific']['individuals']['age'], - {**{'40': 1, '30': 1}, **phenopacket_res['data_type_specific']['individuals']['age']}) - self.assertEqual(phenopacket_res['data_type_specific']['biosamples']['count'], 2) - self.assertEqual(phenopacket_res['data_type_specific']['phenotypic_features']['count'], 1) - self.assertEqual(phenopacket_res['data_type_specific']['diseases']['count'], 1) - # experiments - experiment_res = response_obj['experiment'] - self.assertEqual(experiment_res['count'], 2) - self.assertEqual( - experiment_res['data_type_specific']['experiments']['study_type']['Whole genome Sequencing'], 2) - self.assertEqual( - experiment_res['data_type_specific']['experiments']['experiment_type']['DNA Methylation'], 2 - ) - self.assertEqual(experiment_res['data_type_specific']['experiments']['molecule']['total RNA'], 2) - self.assertEqual(experiment_res['data_type_specific']['experiments']['library_strategy']['Bisulfite-Seq'], 2) - self.assertEqual(experiment_res['data_type_specific']['experiments']['library_source']['Genomic'], 2) - self.assertEqual(experiment_res['data_type_specific']['experiments']['library_selection']['PCR'], 2) - self.assertEqual(experiment_res['data_type_specific']['experiments']['library_layout']['Single'], 2) - self.assertEqual(experiment_res['data_type_specific']['experiments']['extraction_protocol']['NGS'], 2) - self.assertEqual(experiment_res['data_type_specific']['experiment_results']['count'], 1) - self.assertEqual(experiment_res['data_type_specific']['experiment_results']['file_format']['VCF'], 1) - self.assertEqual( - experiment_res['data_type_specific']['experiment_results']['data_output_type']['Derived data'], 1 - ) - self.assertEqual(experiment_res['data_type_specific']['experiment_results']['usage']['download'], 1) - self.assertEqual(experiment_res['data_type_specific']['instruments']['count'], 1) - self.assertEqual(experiment_res['data_type_specific']['instruments']['platform']['Illumina'], 2) - self.assertEqual(experiment_res['data_type_specific']['instruments']['model']['Illumina HiSeq 4000'], 2) - def test_search_overview(self): payload = json.dumps({'id': [ph_c.VALID_INDIVIDUAL_1['id']]}) response = self.dt_authz_full_post(reverse('search-overview'), data=payload, content_type='application/json') diff --git a/chord_metadata_service/restapi/urls.py b/chord_metadata_service/restapi/urls.py index 0c5177422..977c638ce 100644 --- a/chord_metadata_service/restapi/urls.py +++ b/chord_metadata_service/restapi/urls.py @@ -12,7 +12,7 @@ from chord_metadata_service.patients import api_views as individual_views from chord_metadata_service.phenopackets import api_views as phenopacket_views from chord_metadata_service.resources import api_views as resources_views -from chord_metadata_service.restapi.api_views import overview, search_overview, extra_properties_schema_types +from chord_metadata_service.restapi.api_views import search_overview, extra_properties_schema_types from chord_metadata_service.restapi.routers import BatchListRouter __all__ = ["router", "batch_router", "urlpatterns"] @@ -61,7 +61,6 @@ path('extra_properties_schema_types', extra_properties_schema_types, name="extra-properties-schema-types"), # overviews (statistics) - path('overview', overview, name="overview"), path('search_overview', search_overview, name="search-overview"), # public endpoints (no confidential information leak) diff --git a/docs/modules/overview_api.rst b/docs/modules/overview_api.rst deleted file mode 100644 index bd2c3df18..000000000 --- a/docs/modules/overview_api.rst +++ /dev/null @@ -1,8 +0,0 @@ -Overview API -============ - -:code:`api/overview` GET: returns an overview of all phenopackets, individuals and other related data types. -The overview includes counts for individuals, unique diseases, phenotypic features, experiments and other information. - -:code:`api/mcode_overview` GET: returns an overview of mcode-based data. -The overview includes counts for individuals, cancer conditions, cancer related procedures and cancer status. \ No newline at end of file