diff --git a/sdk/test/model/test_string_constraints.py b/sdk/test/model/test_string_constraints.py index 55d5789f..24afa091 100644 --- a/sdk/test/model/test_string_constraints.py +++ b/sdk/test/model/test_string_constraints.py @@ -1,4 +1,4 @@ -# Copyright (c) 2025 the Eclipse BaSyx Authors +# Copyright (c) 2026 the Eclipse BaSyx Authors # # This program and the accompanying materials are made available under the terms of the MIT License, available in # the LICENSE file of this project. diff --git a/server/app/interfaces/discovery.py b/server/app/interfaces/discovery.py index c86c1b08..b18f9a65 100644 --- a/server/app/interfaces/discovery.py +++ b/server/app/interfaces/discovery.py @@ -15,7 +15,7 @@ from app import model as server_model from app.adapter import jsonization from app.interfaces.base import BaseWSGIApp, HTTPApiDecoder -from app.util.converters import IdentifierToBase64URLConverter +from app.util.converters import IdentifierToBase64URLConverter, base64url_decode class DiscoveryStore: @@ -98,6 +98,10 @@ def __init__(self, persistent_store: DiscoveryStore, base_path: str = "/api/v3.1 Submount( "/lookup/shells", [ + # Todo: This route is deprecated in the specification, but needed for interoperability + # with the BaSyx UI https://github.com/eclipse-basyx/basyx-aas-web-ui. + # Once this route is no longer needed, we should consider removing it. + Rule("/", methods=["GET"], endpoint=self.get_all_aas_ids_by_asset_link), Rule( "/", methods=["GET"], @@ -118,6 +122,37 @@ def __init__(self, persistent_store: DiscoveryStore, base_path: str = "/api/v3.1 strict_slashes=False, ) + def get_all_aas_ids_by_asset_link( + self, request: Request, url_args: dict, response_t: type, **_kwargs + ) -> Response: + asset_ids_param = request.args.get("assetIds", "") + if not asset_ids_param: + raise werkzeug.exceptions.BadRequest("Missing query parameter 'assetIds'") + + try: + decoded_str = base64url_decode(asset_ids_param) + payload = json.loads(decoded_str) + except (ValueError, json.JSONDecodeError) as exc: + raise werkzeug.exceptions.BadRequest(f"Invalid query parameter 'assetIds': {exc}") from exc + + if isinstance(payload, dict): + payload = [payload] + + if not isinstance(payload, list): + raise werkzeug.exceptions.BadRequest("Decoded assetIds payload must be a JSON object or list") + + matching_aas_keys = set() + for item in payload: + if not isinstance(item, dict): + raise werkzeug.exceptions.BadRequest("Each asset link must be a JSON object") + + asset_link = server_model.AssetLink(item["name"], item["value"]) + aas_keys = self.persistent_store.search_aas_ids_by_asset_link(asset_link) + matching_aas_keys.update(aas_keys) + + paginated_slice, cursor = self._get_slice(request, list(matching_aas_keys)) + return response_t(list(paginated_slice), cursor=cursor) + def search_all_aas_ids_by_asset_link( self, request: Request, url_args: dict, response_t: type, **_kwargs ) -> Response: