From c12fb58ae82f75ddd08643f034da0f75ba8c9d6a Mon Sep 17 00:00:00 2001 From: Pelayo Torres Date: Fri, 20 Mar 2026 09:57:44 +0100 Subject: [PATCH 1/2] same api name allowed --- .../core/serviceapidescriptions.py | 86 +++++++++++++++++-- 1 file changed, 81 insertions(+), 5 deletions(-) diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py index c2ff0506..47cd2143 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py @@ -24,6 +24,31 @@ publisher_ops = Publisher() service_api_not_found_message = "Service API not found" +def find_duplicate_service_by_api_name_and_aef( + collection, + api_name, + aef_profiles, + excluded_api_id=None): + duplicate_query = {"api_name": api_name} + aef_ids = set() + for profile in aef_profiles or []: + if isinstance(profile, dict): + aef_id = profile.get("aef_id") + else: + aef_id = getattr(profile, "aef_id", None) + + if aef_id: + aef_ids.add(aef_id) + + aef_ids = sorted(aef_ids) + + if aef_ids: + duplicate_query["aef_profiles.aef_id"] = {"$in": aef_ids} + if excluded_api_id: + duplicate_query["api_id"] = {"$ne": excluded_api_id} + + return collection.find_one(duplicate_query), aef_ids + def return_negotiated_supp_feat_dict(supp_feat): final_supp_feat = bin(int(supp_feat, 16) & int(SUPPORTED_FEATURES_HEX, 16))[2:].zfill(TOTAL_FEATURES)[::-1] @@ -122,19 +147,30 @@ class PublishServiceOperations(Resource): try: current_app.logger.debug("Publishing service") - service = mycol.find_one( - {"api_name": serviceapidescription.api_name}) + serviceapidescription_dict = serviceapidescription.to_dict() + service, aef_ids = find_duplicate_service_by_api_name_and_aef( + mycol, + serviceapidescription.api_name, + serviceapidescription_dict.get("aef_profiles")) if service is not None: + if aef_ids: + current_app.logger.error( + "Service already registered with same api_name/aef_id pair") + return forbidden_error( + detail="Already registered service with same api name and aef id", + cause="Found service with same api name and aef id") + current_app.logger.error( "Service already registered with same api name") - return forbidden_error(detail="Already registered service with same api name", cause="Found service with same api name") + return forbidden_error( + detail="Already registered service with same api name", + cause="Found service with same api name") api_id = secrets.token_hex(15) serviceapidescription.api_id = api_id rec = dict() rec['apf_id'] = apf_id rec['onboarding_date'] = datetime.now() - serviceapidescription_dict = serviceapidescription.to_dict() if vendor_specific: serviceapidescription_dict = add_vend_spec_fields( @@ -155,7 +191,7 @@ class PublishServiceOperations(Resource): res = make_response(object=clean_n_camel_case( serviceapidescription_dict), status=201) - res.headers['Location'] = f"https://{os.getenv("CAPIF_HOSTNAME")}/published-apis/v1/{str(apf_id)}/service-apis/{str(api_id)}" + res.headers['Location'] = f"https://{os.getenv('CAPIF_HOSTNAME')}/published-apis/v1/{str(apf_id)}/service-apis/{str(api_id)}" if res.status_code == 201: current_app.logger.info("Service published") @@ -311,6 +347,26 @@ class PublishServiceOperations(Resource): service_api_description["apf_id"] = serviceapidescription_old["apf_id"] service_api_description["onboarding_date"] = serviceapidescription_old["onboarding_date"] service_api_description["api_id"] = serviceapidescription_old["api_id"] + + service_with_same_identity, aef_ids = find_duplicate_service_by_api_name_and_aef( + mycol, + service_api_description.get("api_name", serviceapidescription_old.get("api_name")), + service_api_description.get("aef_profiles", serviceapidescription_old.get("aef_profiles")), + excluded_api_id=service_api_description["api_id"]) + if service_with_same_identity is not None: + if aef_ids: + current_app.logger.error( + "Service already registered with same api_name/aef_id pair") + return forbidden_error( + detail="Already registered service with same api name and aef id", + cause="Found service with same api name and aef id") + + current_app.logger.error( + "Service already registered with same api name") + return forbidden_error( + detail="Already registered service with same api name", + cause="Found service with same api name") + service_api_description["supported_features"] = return_negotiated_supp_feat_dict(service_api_description["supported_features"])["Final"] if not return_negotiated_supp_feat_dict(service_api_description.get("supported_features"))["ApiStatusMonitoring"] and service_api_description.get("api_status", None) is not None: @@ -400,6 +456,26 @@ class PublishServiceOperations(Resource): api_status = patch_service_api_description.get("api_status", None) supported_features = patch_service_api_description.get("supported_features", None) patch_service_api_description = clean_empty(patch_service_api_description) + + service_with_same_identity, aef_ids = find_duplicate_service_by_api_name_and_aef( + mycol, + serviceapidescription_old.get("api_name"), + patch_service_api_description.get("aef_profiles", serviceapidescription_old.get("aef_profiles")), + excluded_api_id=serviceapidescription_old.get("api_id")) + if service_with_same_identity is not None: + if aef_ids: + current_app.logger.error( + "Service already registered with same api_name/aef_id pair") + return forbidden_error( + detail="Already registered service with same api name and aef id", + cause="Found service with same api name and aef id") + + current_app.logger.error( + "Service already registered with same api name") + return forbidden_error( + detail="Already registered service with same api name", + cause="Found service with same api name") + if api_status: patch_service_api_description["api_status"]=api_status if supported_features: -- GitLab From 4c8e8200a0835b6c4d27be46c5bdfaf1677f1e57 Mon Sep 17 00:00:00 2001 From: Pelayo Torres Date: Fri, 20 Mar 2026 12:30:29 +0100 Subject: [PATCH 2/2] fix api_id --- .../published_apis/core/serviceapidescriptions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py index 47cd2143..6b3ab35d 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py @@ -168,6 +168,7 @@ class PublishServiceOperations(Resource): api_id = secrets.token_hex(15) serviceapidescription.api_id = api_id + serviceapidescription_dict["api_id"] = api_id rec = dict() rec['apf_id'] = apf_id rec['onboarding_date'] = datetime.now() -- GitLab