Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add/raise appropriate error for /cql endpoint where no filter is provided #330

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions prez/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
NoEndpointNodeshapeException,
NoProfilesException,
PrefixNotFoundException,
URINotFoundException,
URINotFoundException, MissingFilterQueryError,
)
from prez.middleware import create_validate_header_middleware
from prez.repositories import OxrdflibRepo, PyoxigraphRepo, RemoteSparqlRepo
Expand Down Expand Up @@ -59,7 +59,7 @@
catch_no_endpoint_nodeshape_exception,
catch_no_profiles_exception,
catch_prefix_not_found_exception,
catch_uri_not_found_exception,
catch_uri_not_found_exception, catch_missing_filter_query_param,
)
from prez.services.generate_profiles import create_profiles_graph
from prez.services.prez_logging import setup_logger
Expand Down Expand Up @@ -181,6 +181,7 @@ def assemble_app(
NoProfilesException: catch_no_profiles_exception,
InvalidSPARQLQueryException: catch_invalid_sparql_query,
NoEndpointNodeshapeException: catch_no_endpoint_nodeshape_exception,
MissingFilterQueryError: catch_missing_filter_query_param
},
**kwargs
)
Expand Down
51 changes: 28 additions & 23 deletions prez/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
)
from prez.exceptions.model_exceptions import (
NoEndpointNodeshapeException,
URINotFoundException,
URINotFoundException, MissingFilterQueryError,
)
from prez.enums import SearchMethod
from prez.models.query_params import QueryParams
Expand Down Expand Up @@ -147,6 +147,29 @@ async def load_annotations_data_to_oxigraph(store: Store):
store.load(file_bytes, "application/n-triples")



async def get_endpoint_uri_type(
request: Request,
system_repo: Repo = Depends(get_system_repo),
) -> tuple[URIRef, URIRef]:
"""
Returns the URI of the endpoint and its type (ObjectEndpoint or ListingEndpoint)
"""
endpoint_uri = URIRef(request.scope.get("route").name)
ep_type_fs = await get_classes_single(endpoint_uri, system_repo)
ep_types = list(ep_type_fs)

# Iterate over each item in ep_types
for ep_type in ep_types:
# Check if the current ep_type is either ObjectEndpoint or ListingEndpoint
if ep_type in [ONT.ObjectEndpoint, ONT.ListingEndpoint]:
return endpoint_uri, ep_type
raise ValueError(
"Endpoint must be declared as either a 'https://prez.dev/ont/ObjectEndpoint' or a "
"'https://prez.dev/ont/ListingEndpoint' in order for the appropriate profile to be determined."
)


async def cql_post_parser_dependency(
request: Request,
queryable_props: list = Depends(get_queryable_props),
Expand All @@ -168,6 +191,7 @@ async def cql_post_parser_dependency(
async def cql_get_parser_dependency(
query_params: QueryParams = Depends(),
queryable_props: list = Depends(get_queryable_props),
endpoint_uri_type: str = Depends(get_endpoint_uri_type),
) -> CQLParser:
if query_params._filter:
try:
Expand All @@ -186,6 +210,9 @@ async def cql_get_parser_dependency(
raise HTTPException(
status_code=400, detail="Invalid CQL format: Parsing failed."
)
elif endpoint_uri_type[0] == URIRef('https://prez.dev/endpoint/extended-ogc-records/cql-get'):
raise MissingFilterQueryError("filter query parameter with a valid CQL JSON expression must be provided when "
"using the /cql endpoint.")


async def get_jena_fts_shacl_predicates(system_repo: Repo):
Expand Down Expand Up @@ -268,28 +295,6 @@ async def generate_search_query(
return search_query


async def get_endpoint_uri_type(
request: Request,
system_repo: Repo = Depends(get_system_repo),
) -> tuple[URIRef, URIRef]:
"""
Returns the URI of the endpoint and its type (ObjectEndpoint or ListingEndpoint)
"""
endpoint_uri = URIRef(request.scope.get("route").name)
ep_type_fs = await get_classes_single(endpoint_uri, system_repo)
ep_types = list(ep_type_fs)

# Iterate over each item in ep_types
for ep_type in ep_types:
# Check if the current ep_type is either ObjectEndpoint or ListingEndpoint
if ep_type in [ONT.ObjectEndpoint, ONT.ListingEndpoint]:
return endpoint_uri, ep_type
raise ValueError(
"Endpoint must be declared as either a 'https://prez.dev/ont/ObjectEndpoint' or a "
"'https://prez.dev/ont/ListingEndpoint' in order for the appropriate profile to be determined."
)


async def generate_concept_hierarchy_query(
request: Request,
endpoint_uri_type: tuple[URIRef, URIRef] = Depends(get_endpoint_uri_type),
Expand Down
9 changes: 9 additions & 0 deletions prez/exceptions/model_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,12 @@ def __init__(self, ep_uri: str, hierarchy_level: int):
f"{hierarchy_level}, and parent URI"
)
super().__init__(self.message)


class MissingFilterQueryError(ValueError):
"""
Raised when a filter query is missing.
"""
def __init__(self, message):
self.message = message
super().__init__(self.message)
4 changes: 2 additions & 2 deletions prez/routers/ogc_features_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
NoEndpointNodeshapeException,
NoProfilesException,
PrefixNotFoundException,
URINotFoundException,
URINotFoundException, MissingFilterQueryError,
)
from prez.models.ogc_features import OGCFeaturesLandingPage, generate_landing_page_links
from prez.models.query_params import QueryParams
Expand All @@ -44,7 +44,7 @@
catch_no_endpoint_nodeshape_exception,
catch_no_profiles_exception,
catch_prefix_not_found_exception,
catch_uri_not_found_exception,
catch_uri_not_found_exception, catch_missing_filter_query_param,
)
from prez.services.listings import ogc_features_listing_function
from prez.services.objects import ogc_features_object_function
Expand Down
13 changes: 12 additions & 1 deletion prez/services/exception_catchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
NoEndpointNodeshapeException,
NoProfilesException,
PrefixNotFoundException,
URINotFoundException,
URINotFoundException, MissingFilterQueryError,
)


Expand Down Expand Up @@ -90,3 +90,14 @@ async def catch_no_endpoint_nodeshape_exception(
"detail": exc.message,
},
)

async def catch_missing_filter_query_param(
request: Request, exc: MissingFilterQueryError
):
return JSONResponse(
status_code=400,
content={
"error": "Bad Request",
"detail": exc.message,
},
)
Loading