Loading services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py +6 −3 Original line number Diff line number Diff line Loading @@ -68,12 +68,15 @@ def all_service_apis_get(api_invoker_id, api_name=None, api_version=None, comm_t if request.is_json: service_kpis = ServiceKpis.from_dict(request.get_json()()) # noqa: E501 current_app.logger.info("Discovering service apis") query_params = {"api_name": api_name, "api_version": api_version, "comm_type": comm_type, "protocol": protocol, "aef_id": aef_id, "data_format": data_format, "api_cat":api_cat, "supported_features":supported_features, "api_supported_features":api_supported_features} "api_cat": api_cat, "api_supported_features": api_supported_features, "supported_features": supported_features} if supported_features is not None: supp_feat_dict = DiscoveredAPIs.return_supp_feat_dict(supported_features) current_app.logger.info(supp_feat_dict) if supp_feat_dict['VendSpecQueryParams']: for q_params in request.args: if "vend-spec" in q_params: Loading services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py +42 −9 Original line number Diff line number Diff line Loading @@ -5,6 +5,20 @@ from ..models.discovered_apis import DiscoveredAPIs from ..util import serialize_clean_camel_case from ..core.resources import Resource import json from ..vendor_specific import find_attribute_in_body, filter_apis_with_vendor_specific_params, remove_vendor_specific_fields def filter_fields(filtered_apis): key_filter = [ "api_name", "api_id", "aef_profiles", "description", "supported_features", "shareable_info", "service_api_category", "api_supp_feats", "pub_api_path", "ccf_id" ] field_filtered_api = {} for key in filtered_apis.keys(): if key in key_filter or 'vendorSpecific' in key: field_filtered_api[key] = filtered_apis[key] return field_filtered_api class DiscoverApisOperations(Resource): Loading Loading @@ -37,17 +51,17 @@ class DiscoverApisOperations(Resource): "api_supported_features": "api_supp_feats" } vend_spec_query_params_n_values = {} supp_feat = query_params["supported_features"] del query_params["supported_features"] for param in query_params: current_app.logger.info(query_params[param]) if query_params[param] is not None: if "vend-spec" in param: current_app.logger.info("vend-spec in param") vend_param = param.split("vend-spec-")[1] attribute_path = query_params[param]["target"].split('/') attribute = "aef_profiles.0." + attribute_path[1] + "." + attribute_path[2] my_params.append({attribute: query_params[param]["value"]}) vend_spec_query_params_n_values[attribute_path[1] + "." + vend_param] = query_params[param]["value"] elif param in ["api_version", "comm_type", "protocol", "aef_id", "data_format"]: current_app.logger.info(query_params_name[param]) current_app.logger.info(query_params_name[param].replace("QPV", query_params[param])) my_params.append(json.loads(query_params_name[param].replace("QPV", query_params[param]))) else: my_params.append({query_params_name[param]: query_params[param]}) Loading @@ -55,10 +69,29 @@ class DiscoverApisOperations(Resource): if my_params: my_query = {"$and": my_params} discoved_apis = services.find(my_query, {"_id":0, "api_name":1, "api_id":1, "aef_profiles":1, "description":1, "supported_features":1, "shareable_info":1, "service_api_category":1, "api_supp_feats":1, "pub_api_path":1, "ccf_id":1}) discoved_apis = services.find(my_query, {"_id":0}) json_docs = [] if supp_feat is None: for discoved_api in discoved_apis: vendor_specific_fields_path = find_attribute_in_body(discoved_api, '') json_docs.append(filter_fields(remove_vendor_specific_fields(discoved_api, vendor_specific_fields_path))) else: supported_features = DiscoveredAPIs.return_supp_feat_dict(supp_feat) if supported_features['VendSpecQueryParams']: for discoved_api in discoved_apis: vendor_specific_fields_path = find_attribute_in_body(discoved_api, '') if vendor_specific_fields_path: if vend_spec_query_params_n_values: vs_filtered_apis = filter_apis_with_vendor_specific_params(discoved_api, vend_spec_query_params_n_values, vendor_specific_fields_path) if vs_filtered_apis: json_docs.append(filter_fields(vs_filtered_apis)) else: json_docs.append(filter_fields(discoved_api)) else: for discoved_api in discoved_apis: json_docs.append(discoved_api) vendor_specific_fields_path = find_attribute_in_body(discoved_api, '') if not vendor_specific_fields_path: json_docs.append(filter_fields(discoved_api)) if len(json_docs) == 0: return not_found_error(detail="API Invoker " + api_invoker_id + " has no API Published that accomplish filter conditions", cause="No API Published accomplish filter conditions") Loading services/TS29222_CAPIF_Discover_Service_API/service_apis/models/discovered_apis.py +4 −3 Original line number Diff line number Diff line Loading @@ -32,13 +32,14 @@ class DiscoveredAPIs(Model): @classmethod def return_supp_feat_dict(cls, supp_feat): TOTAL_FEATURES = 3 supp_feat_in_hex = int(supp_feat, 16) supp_feat_in_bin = bin(supp_feat_in_hex)[2:] supp_feat_in_bin = bin(supp_feat_in_hex)[2:].zfill(TOTAL_FEATURES)[::-1] return { "RNAA": True if supp_feat_in_bin[0] == "1" else False, "ApiSupportedFeatureQuery": True if supp_feat_in_bin[0] == "1" else False, "VendSpecQueryParams": True if supp_feat_in_bin[1] == "1" else False, "ApiSupportedFeatureQuery": True if supp_feat_in_bin[2] == "1" else False, "RNAA": True if supp_feat_in_bin[2] == "1" else False } @classmethod Loading services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py 0 → 100644 +91 −0 Original line number Diff line number Diff line import re def find_attribute_in_body(test, path): f_key = [] if type(test) == dict: for k, v in test.items(): if 'vendorSpecific' in k: if path == '': temp_path = k else: temp_path = path + "." + k f_key.append(temp_path) elif type(v) == dict: if path == '': temp_path = k else: temp_path = path + "." + k f_key += find_attribute_in_body(v, temp_path) elif type(v) == list: if path == '': temp_path = k else: temp_path = path + "." + k for i, val in enumerate(v): f_key += find_attribute_in_body(val, temp_path + "." + str(i)) return f_key def vendor_specific_key_n_value(vendor_specific_fields, body): vendor_specific = {} for field in vendor_specific_fields: parts = field.split('.') tmp_body = body for part in parts: if part.isnumeric(): part = int(part) v = tmp_body[part] tmp_body = v vendor_specific[field] = v return vendor_specific def add_vend_spec_fields(vendor_specific, serviceapidescription_dict): pattern = re.compile(r'(?<!^)(?=[A-Z])') for field, value in vendor_specific.items(): parts = field.split('.') tmp_body = serviceapidescription_dict vs_field = parts[-1] for part in parts[:-1]: if part.isnumeric(): part = int(part) else: part = pattern.sub('_', part).lower() tmp_body = tmp_body[part] tmp_body[vs_field] = value return tmp_body def remove_vendor_specific_fields(discoved_api, vendor_specific_fields_path): for path in vendor_specific_fields_path: tmp_body = discoved_api parts = path.split('.') vs_field = parts[-1] for path_piece in parts[:-1]: if path_piece.isnumeric(): path_piece = int(path_piece) tmp_body = tmp_body[path_piece] del tmp_body[vs_field] return discoved_api def filter_apis_with_vendor_specific_params(discoved_api, vend_spec_query_params_n_values, vendor_specific_fields_path): for k, v in vend_spec_query_params_n_values.items(): parts = k.split('.') for path in vendor_specific_fields_path: if parts[0] in path: path_pieces = path.split('.') tmp_body = discoved_api vs_field = path_pieces[-1] for path_piece in path_pieces[:-1]: if path_piece.isnumeric(): path_piece = int(path_piece) v_2 = tmp_body[path_piece] tmp_body = v_2 if parts[1] in tmp_body[vs_field].keys(): if tmp_body[vs_field][parts[1]] != v: return {} else: return {} return discoved_api No newline at end of file services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py +20 −6 Original line number Diff line number Diff line Loading @@ -7,6 +7,9 @@ from cryptography import x509 from cryptography.hazmat.backends import default_backend from ..core.validate_user import ControlAccess from functools import wraps from published_apis.vendor_specific import vendor_specific_key_n_value, find_attribute_in_body from ..core.responses import bad_request_error service_operations = PublishServiceOperations() Loading Loading @@ -82,18 +85,29 @@ def apf_id_service_apis_post(apf_id, body): # noqa: E501 """ current_app.logger.info("Publishing service") if 'supportedFeatures' not in body: return bad_request_error( detail="supportedFeatures not present in request", cause="supportedFeatures not present", invalid_params=[{"param": "supportedFeatures", "reason": "not defined"}] ) supp_feat_dict = ServiceAPIDescription.return_supp_feat_dict( body['supportedFeatures']) vendor_specific = [] vendor_specific_fields = find_attribute_in_body(body, '') if supp_feat_dict['VendorExt'] ^ bool(vendor_specific_fields): return bad_request_error( detail="If and only if VendorExt feature is enabled, then vendor-specific fields should be defined", cause="Vendor extensibility misconfiguration", invalid_params=[{"param": "vendor extensibility", "reason": "wrong definition"}] ) if request.is_json: if supp_feat_dict['VendorExt']: aef_profile_array = body['aefProfiles'] for (profile, i) in zip(aef_profile_array, range(len(aef_profile_array))): for key, val in profile.items(): if 'vendorSpecific' in key: vendor_specific.append((i, key, val)) vendor_specific = vendor_specific_key_n_value(vendor_specific_fields, body) body = ServiceAPIDescription.from_dict(request.get_json()) res = service_operations.add_serviceapidescription( Loading Loading
services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py +6 −3 Original line number Diff line number Diff line Loading @@ -68,12 +68,15 @@ def all_service_apis_get(api_invoker_id, api_name=None, api_version=None, comm_t if request.is_json: service_kpis = ServiceKpis.from_dict(request.get_json()()) # noqa: E501 current_app.logger.info("Discovering service apis") query_params = {"api_name": api_name, "api_version": api_version, "comm_type": comm_type, "protocol": protocol, "aef_id": aef_id, "data_format": data_format, "api_cat":api_cat, "supported_features":supported_features, "api_supported_features":api_supported_features} "api_cat": api_cat, "api_supported_features": api_supported_features, "supported_features": supported_features} if supported_features is not None: supp_feat_dict = DiscoveredAPIs.return_supp_feat_dict(supported_features) current_app.logger.info(supp_feat_dict) if supp_feat_dict['VendSpecQueryParams']: for q_params in request.args: if "vend-spec" in q_params: Loading
services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py +42 −9 Original line number Diff line number Diff line Loading @@ -5,6 +5,20 @@ from ..models.discovered_apis import DiscoveredAPIs from ..util import serialize_clean_camel_case from ..core.resources import Resource import json from ..vendor_specific import find_attribute_in_body, filter_apis_with_vendor_specific_params, remove_vendor_specific_fields def filter_fields(filtered_apis): key_filter = [ "api_name", "api_id", "aef_profiles", "description", "supported_features", "shareable_info", "service_api_category", "api_supp_feats", "pub_api_path", "ccf_id" ] field_filtered_api = {} for key in filtered_apis.keys(): if key in key_filter or 'vendorSpecific' in key: field_filtered_api[key] = filtered_apis[key] return field_filtered_api class DiscoverApisOperations(Resource): Loading Loading @@ -37,17 +51,17 @@ class DiscoverApisOperations(Resource): "api_supported_features": "api_supp_feats" } vend_spec_query_params_n_values = {} supp_feat = query_params["supported_features"] del query_params["supported_features"] for param in query_params: current_app.logger.info(query_params[param]) if query_params[param] is not None: if "vend-spec" in param: current_app.logger.info("vend-spec in param") vend_param = param.split("vend-spec-")[1] attribute_path = query_params[param]["target"].split('/') attribute = "aef_profiles.0." + attribute_path[1] + "." + attribute_path[2] my_params.append({attribute: query_params[param]["value"]}) vend_spec_query_params_n_values[attribute_path[1] + "." + vend_param] = query_params[param]["value"] elif param in ["api_version", "comm_type", "protocol", "aef_id", "data_format"]: current_app.logger.info(query_params_name[param]) current_app.logger.info(query_params_name[param].replace("QPV", query_params[param])) my_params.append(json.loads(query_params_name[param].replace("QPV", query_params[param]))) else: my_params.append({query_params_name[param]: query_params[param]}) Loading @@ -55,10 +69,29 @@ class DiscoverApisOperations(Resource): if my_params: my_query = {"$and": my_params} discoved_apis = services.find(my_query, {"_id":0, "api_name":1, "api_id":1, "aef_profiles":1, "description":1, "supported_features":1, "shareable_info":1, "service_api_category":1, "api_supp_feats":1, "pub_api_path":1, "ccf_id":1}) discoved_apis = services.find(my_query, {"_id":0}) json_docs = [] if supp_feat is None: for discoved_api in discoved_apis: vendor_specific_fields_path = find_attribute_in_body(discoved_api, '') json_docs.append(filter_fields(remove_vendor_specific_fields(discoved_api, vendor_specific_fields_path))) else: supported_features = DiscoveredAPIs.return_supp_feat_dict(supp_feat) if supported_features['VendSpecQueryParams']: for discoved_api in discoved_apis: vendor_specific_fields_path = find_attribute_in_body(discoved_api, '') if vendor_specific_fields_path: if vend_spec_query_params_n_values: vs_filtered_apis = filter_apis_with_vendor_specific_params(discoved_api, vend_spec_query_params_n_values, vendor_specific_fields_path) if vs_filtered_apis: json_docs.append(filter_fields(vs_filtered_apis)) else: json_docs.append(filter_fields(discoved_api)) else: for discoved_api in discoved_apis: json_docs.append(discoved_api) vendor_specific_fields_path = find_attribute_in_body(discoved_api, '') if not vendor_specific_fields_path: json_docs.append(filter_fields(discoved_api)) if len(json_docs) == 0: return not_found_error(detail="API Invoker " + api_invoker_id + " has no API Published that accomplish filter conditions", cause="No API Published accomplish filter conditions") Loading
services/TS29222_CAPIF_Discover_Service_API/service_apis/models/discovered_apis.py +4 −3 Original line number Diff line number Diff line Loading @@ -32,13 +32,14 @@ class DiscoveredAPIs(Model): @classmethod def return_supp_feat_dict(cls, supp_feat): TOTAL_FEATURES = 3 supp_feat_in_hex = int(supp_feat, 16) supp_feat_in_bin = bin(supp_feat_in_hex)[2:] supp_feat_in_bin = bin(supp_feat_in_hex)[2:].zfill(TOTAL_FEATURES)[::-1] return { "RNAA": True if supp_feat_in_bin[0] == "1" else False, "ApiSupportedFeatureQuery": True if supp_feat_in_bin[0] == "1" else False, "VendSpecQueryParams": True if supp_feat_in_bin[1] == "1" else False, "ApiSupportedFeatureQuery": True if supp_feat_in_bin[2] == "1" else False, "RNAA": True if supp_feat_in_bin[2] == "1" else False } @classmethod Loading
services/TS29222_CAPIF_Discover_Service_API/service_apis/vendor_specific.py 0 → 100644 +91 −0 Original line number Diff line number Diff line import re def find_attribute_in_body(test, path): f_key = [] if type(test) == dict: for k, v in test.items(): if 'vendorSpecific' in k: if path == '': temp_path = k else: temp_path = path + "." + k f_key.append(temp_path) elif type(v) == dict: if path == '': temp_path = k else: temp_path = path + "." + k f_key += find_attribute_in_body(v, temp_path) elif type(v) == list: if path == '': temp_path = k else: temp_path = path + "." + k for i, val in enumerate(v): f_key += find_attribute_in_body(val, temp_path + "." + str(i)) return f_key def vendor_specific_key_n_value(vendor_specific_fields, body): vendor_specific = {} for field in vendor_specific_fields: parts = field.split('.') tmp_body = body for part in parts: if part.isnumeric(): part = int(part) v = tmp_body[part] tmp_body = v vendor_specific[field] = v return vendor_specific def add_vend_spec_fields(vendor_specific, serviceapidescription_dict): pattern = re.compile(r'(?<!^)(?=[A-Z])') for field, value in vendor_specific.items(): parts = field.split('.') tmp_body = serviceapidescription_dict vs_field = parts[-1] for part in parts[:-1]: if part.isnumeric(): part = int(part) else: part = pattern.sub('_', part).lower() tmp_body = tmp_body[part] tmp_body[vs_field] = value return tmp_body def remove_vendor_specific_fields(discoved_api, vendor_specific_fields_path): for path in vendor_specific_fields_path: tmp_body = discoved_api parts = path.split('.') vs_field = parts[-1] for path_piece in parts[:-1]: if path_piece.isnumeric(): path_piece = int(path_piece) tmp_body = tmp_body[path_piece] del tmp_body[vs_field] return discoved_api def filter_apis_with_vendor_specific_params(discoved_api, vend_spec_query_params_n_values, vendor_specific_fields_path): for k, v in vend_spec_query_params_n_values.items(): parts = k.split('.') for path in vendor_specific_fields_path: if parts[0] in path: path_pieces = path.split('.') tmp_body = discoved_api vs_field = path_pieces[-1] for path_piece in path_pieces[:-1]: if path_piece.isnumeric(): path_piece = int(path_piece) v_2 = tmp_body[path_piece] tmp_body = v_2 if parts[1] in tmp_body[vs_field].keys(): if tmp_body[vs_field][parts[1]] != v: return {} else: return {} return discoved_api No newline at end of file
services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py +20 −6 Original line number Diff line number Diff line Loading @@ -7,6 +7,9 @@ from cryptography import x509 from cryptography.hazmat.backends import default_backend from ..core.validate_user import ControlAccess from functools import wraps from published_apis.vendor_specific import vendor_specific_key_n_value, find_attribute_in_body from ..core.responses import bad_request_error service_operations = PublishServiceOperations() Loading Loading @@ -82,18 +85,29 @@ def apf_id_service_apis_post(apf_id, body): # noqa: E501 """ current_app.logger.info("Publishing service") if 'supportedFeatures' not in body: return bad_request_error( detail="supportedFeatures not present in request", cause="supportedFeatures not present", invalid_params=[{"param": "supportedFeatures", "reason": "not defined"}] ) supp_feat_dict = ServiceAPIDescription.return_supp_feat_dict( body['supportedFeatures']) vendor_specific = [] vendor_specific_fields = find_attribute_in_body(body, '') if supp_feat_dict['VendorExt'] ^ bool(vendor_specific_fields): return bad_request_error( detail="If and only if VendorExt feature is enabled, then vendor-specific fields should be defined", cause="Vendor extensibility misconfiguration", invalid_params=[{"param": "vendor extensibility", "reason": "wrong definition"}] ) if request.is_json: if supp_feat_dict['VendorExt']: aef_profile_array = body['aefProfiles'] for (profile, i) in zip(aef_profile_array, range(len(aef_profile_array))): for key, val in profile.items(): if 'vendorSpecific' in key: vendor_specific.append((i, key, val)) vendor_specific = vendor_specific_key_n_value(vendor_specific_fields, body) body = ServiceAPIDescription.from_dict(request.get_json()) res = service_operations.add_serviceapidescription( Loading