From 5fa106f85f1cd024a5369864a9ed79135ec2b26e Mon Sep 17 00:00:00 2001 From: Katy Baulch <46493669+katybaulch@users.noreply.github.com> Date: Tue, 3 Dec 2024 12:55:36 +0000 Subject: [PATCH] Lockdown geography page route (#425) --- app/api/api_v1/routers/summaries.py | 21 ++++++-- app/models/search.py | 1 + app/repository/search.py | 3 ++ pyproject.toml | 2 +- .../summaries/test_geography_summaries.py | 50 ++++++++++++------- 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/app/api/api_v1/routers/summaries.py b/app/api/api_v1/routers/summaries.py index 444fde96..f7893864 100644 --- a/app/api/api_v1/routers/summaries.py +++ b/app/api/api_v1/routers/summaries.py @@ -5,14 +5,16 @@ """ import logging +from typing import Annotated from db_client.models.dfce import FamilyCategory, Geography -from fastapi import APIRouter, Depends, HTTPException, Request, status +from fastapi import APIRouter, Depends, Header, HTTPException, Request, status from app.clients.db.session import get_db from app.models.search import BrowseArgs, GeographySummaryFamilyResponse from app.repository.lookups import get_country_slug_from_country_code, is_country_code from app.repository.search import browse_rds_families +from app.service.custom_app import AppTokenFactory _LOGGER = logging.getLogger(__name__) @@ -24,9 +26,18 @@ summary="Gets a summary of the documents associated with a geography.", response_model=GeographySummaryFamilyResponse, ) -def search_by_geography(request: Request, geography_string: str, db=Depends(get_db)): +def search_by_geography( + request: Request, + geography_string: str, + app_token: Annotated[str, Header()], + db=Depends(get_db), +): """Searches the documents filtering by geography and grouping by category.""" + # Decode the app token and validate it. + token = AppTokenFactory() + token.decode_and_validate(db, request, app_token) + geography_slug = None if is_country_code(db, geography_string): geography_slug = get_country_slug_from_country_code(db, geography_string) @@ -36,7 +47,10 @@ def search_by_geography(request: Request, geography_string: str, db=Depends(get_ _LOGGER.info( f"Getting geography summary for {geography_slug}", - extra={"props": {"geography_slug": geography_slug}}, + extra={ + "props": {"geography_slug": geography_slug}, + "allowed_corpora_ids": token.allowed_corpora_ids, + }, ) exists = bool( @@ -60,6 +74,7 @@ def search_by_geography(request: Request, geography_string: str, db=Depends(get_ categories=[cat], offset=0, limit=None, + corpora_ids=token.allowed_corpora_ids, ), ) family_counts[cat] = len(results.families) diff --git a/app/models/search.py b/app/models/search.py index 6e8bd72c..0550221b 100644 --- a/app/models/search.py +++ b/app/models/search.py @@ -373,6 +373,7 @@ class BrowseArgs(BaseModel): geography_slugs: Optional[Sequence[str]] = None country_codes: Optional[Sequence[str]] = None + corpora_ids: Optional[Sequence[str]] = None start_year: Optional[int] = None end_year: Optional[int] = None categories: Optional[Sequence[str]] = None diff --git a/app/repository/search.py b/app/repository/search.py index a0104837..783a4a1c 100644 --- a/app/repository/search.py +++ b/app/repository/search.py @@ -71,6 +71,9 @@ def browse_rds_families(db: Session, req: BrowseArgs) -> SearchResponse: if req.categories is not None: query = query.filter(Family.family_category.in_(req.categories)) + if req.corpora_ids is not None and req.corpora_ids != []: + query = query.filter(Corpus.import_id.in_(req.corpora_ids)) + if req.sort_field == SortField.TITLE: if req.sort_order == SortOrder.DESCENDING: query = query.order_by(Family.title.desc()) diff --git a/pyproject.toml b/pyproject.toml index b5593f7f..f1fcda7a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "navigator_backend" -version = "1.19.16" +version = "1.19.17" description = "" authors = ["CPR-dev-team "] packages = [{ include = "app" }, { include = "tests" }] diff --git a/tests/non_search/routers/summaries/test_geography_summaries.py b/tests/non_search/routers/summaries/test_geography_summaries.py index ce50cf77..4d1339e3 100644 --- a/tests/non_search/routers/summaries/test_geography_summaries.py +++ b/tests/non_search/routers/summaries/test_geography_summaries.py @@ -1,17 +1,33 @@ -from http.client import NOT_FOUND, OK +from typing import Optional import pytest +from fastapi import status +TEST_HOST = "http://localhost:3000/" +GEOGRAPHY_PAGE_ENDPOINT = "/api/v1/summaries/geography" -def _url_under_test(geography: str) -> str: - return f"/api/v1/summaries/geography/{geography}" +def _make_request( + client, + token, + geography: str, + expected_status_code: int = status.HTTP_200_OK, + origin: Optional[str] = TEST_HOST, +): + headers = ( + {"app-token": token} + if origin is None + else {"app-token": token, "origin": origin} + ) -def test_endpoint_returns_families_ok_with_slug(data_client): + response = client.get(f"{GEOGRAPHY_PAGE_ENDPOINT}/{geography}", headers=headers) + assert response.status_code == expected_status_code, response.text + return response.json() + + +def test_endpoint_returns_families_ok_with_slug(data_client, valid_token): """Test the endpoint returns an empty sets of data""" - response = data_client.get(_url_under_test("moldova")) - assert response.status_code == OK - resp = response.json() + resp = _make_request(data_client, valid_token, "moldova") assert len(resp["family_counts"]) == 4 assert len(resp["top_families"]) == 4 @@ -29,11 +45,9 @@ def test_endpoint_returns_families_ok_with_slug(data_client): assert len(resp["targets"]) == 0 -def test_endpoint_returns_families_ok_with_code(data_client): +def test_endpoint_returns_families_ok_with_code(data_client, valid_token): """Test the endpoint returns an empty sets of data""" - response = data_client.get(_url_under_test("MDA")) - assert response.status_code == OK - resp = response.json() + resp = _make_request(data_client, valid_token, "MDA") assert len(resp["family_counts"]) == 4 assert len(resp["top_families"]) == 4 @@ -51,11 +65,9 @@ def test_endpoint_returns_families_ok_with_code(data_client): assert len(resp["targets"]) == 0 -def test_geography_with_families_ordered(data_client): +def test_geography_with_families_ordered(data_client, valid_token): """Test that all the data is returned ordered by published date""" - response = data_client.get(_url_under_test("afghanistan")) - assert response.status_code == OK - resp = response.json() + resp = _make_request(data_client, valid_token, "afghanistan") assert resp @@ -63,10 +75,12 @@ def test_geography_with_families_ordered(data_client): ("geo"), ["XCC", "Moldova"], ) -def test_endpoint_returns_404_when_not_found(geo, data_client): +def test_endpoint_returns_404_when_not_found(geo, data_client, valid_token): """Test the endpoint returns an empty sets of data""" - response = data_client.get(_url_under_test(geo)) - assert response.status_code == NOT_FOUND + resp = _make_request( + data_client, valid_token, geo, expected_status_code=status.HTTP_404_NOT_FOUND + ) + assert resp # TODO: Additional test to confirm that summary result counts are correct when