Loading services/helper/helper_service/controllers/helper_controller.py +6 −0 Original line number Original line Diff line number Diff line Loading @@ -191,3 +191,9 @@ def remove_config_category(): return jsonify(message="Missing 'category_name' in request body"), 400 return jsonify(message="Missing 'category_name' in request body"), 400 return helper_operation.remove_config_category(category_name) return helper_operation.remove_config_category(category_name) @helper_routes.route("/helper/getCcfId", methods=["GET"]) def get_ccf_id(): """Returns the current CAPIF ccfId""" return helper_operation.get_ccf_id() services/helper/helper_service/core/helper_operations.py +46 −10 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,8 @@ from utils.utils import ( class HelperOperations: class HelperOperations: PROTECTED_FIELDS = ["ccf_id"] def __init__(self): def __init__(self): self.db = MongoDatabse() self.db = MongoDatabse() self.mimetype = 'application/json' self.mimetype = 'application/json' Loading Loading @@ -228,6 +230,10 @@ class HelperOperations: """ """ current_app.logger.debug(f"Updating configuration parameter: {param_path} with value: {new_value}") current_app.logger.debug(f"Updating configuration parameter: {param_path} with value: {new_value}") # Protect immutable fields if any(param_path.startswith(field) for field in self.PROTECTED_FIELDS): return jsonify(message=f"The parameter '{param_path}' is immutable and cannot be modified"), 403 config_col = self.db.get_col_by_name(self.db.capif_configuration) config_col = self.db.get_col_by_name(self.db.capif_configuration) existing_config = config_col.find_one({}, {"_id": 0}) existing_config = config_col.find_one({}, {"_id": 0}) Loading @@ -251,9 +257,6 @@ class HelperOperations: def replace_configuration(self, new_config): def replace_configuration(self, new_config): """ Replace all current settings with a new one. """ current_app.logger.debug("Replacing entire CAPIF configuration") current_app.logger.debug("Replacing entire CAPIF configuration") error_response = validate_snake_case_keys(new_config) error_response = validate_snake_case_keys(new_config) Loading @@ -263,16 +266,18 @@ class HelperOperations: config_col = self.db.get_col_by_name(self.db.capif_configuration) config_col = self.db.get_col_by_name(self.db.capif_configuration) existing_config = config_col.find_one({}, {"_id": 0}) existing_config = config_col.find_one({}, {"_id": 0}) if existing_config: if not existing_config: new_config = convert_nested_values(new_config, existing_config) return jsonify(message="No existing configuration found"), 404 result = config_col.replace_one({}, new_config, upsert=True) # Preserve protected fields for field in self.PROTECTED_FIELDS: if field in existing_config: new_config[field] = existing_config[field] if result.matched_count == 0: new_config = convert_nested_values(new_config, existing_config) return jsonify(message="No existing configuration found; a new one was created"), 201 result = config_col.replace_one({}, new_config, upsert=True) return jsonify(message="Configuration replaced successfully"), 200 return jsonify(message="Configuration replaced successfully (protected fields preserved)"), 200 def add_new_configuration(self, category_name, category_values): def add_new_configuration(self, category_name, category_values): Loading @@ -281,6 +286,10 @@ class HelperOperations: """ """ current_app.logger.debug(f"Adding new category: {category_name} with values: {category_values}") current_app.logger.debug(f"Adding new category: {category_name} with values: {category_values}") # Block protected field creation if category_name in self.PROTECTED_FIELDS: return jsonify(message=f"The category '{category_name}' is immutable and cannot be modified"), 403 config_col = self.db.get_col_by_name(self.db.capif_configuration) config_col = self.db.get_col_by_name(self.db.capif_configuration) category_name_snake = to_snake_case(category_name) category_name_snake = to_snake_case(category_name) Loading @@ -299,6 +308,11 @@ class HelperOperations: def add_new_config_setting(self, param_path, new_value): def add_new_config_setting(self, param_path, new_value): """Add a new parameter in 'settings'.""" """Add a new parameter in 'settings'.""" current_app.logger.debug(f"Adding new configuration setting: {param_path} with value: {new_value}") current_app.logger.debug(f"Adding new configuration setting: {param_path} with value: {new_value}") # Block protected field creation if any(param_path.startswith(field) for field in self.PROTECTED_FIELDS): return jsonify(message=f"The parameter '{param_path}' is immutable and cannot be added or modified"), 403 config_col = self.db.get_col_by_name(self.db.capif_configuration) config_col = self.db.get_col_by_name(self.db.capif_configuration) param_path_snake = ".".join(to_snake_case(part) for part in param_path.split(".")) param_path_snake = ".".join(to_snake_case(part) for part in param_path.split(".")) Loading @@ -316,6 +330,10 @@ class HelperOperations: """Removes a specific parameter inside 'settings'.""" """Removes a specific parameter inside 'settings'.""" current_app.logger.debug(f"Removing configuration parameter: {param_path}") current_app.logger.debug(f"Removing configuration parameter: {param_path}") # Prevent deletion of protected fields if any(param_path.startswith(field) for field in self.PROTECTED_FIELDS): return jsonify(message=f"The parameter '{param_path}' is immutable and cannot be removed"), 403 config_col = self.db.get_col_by_name(self.db.capif_configuration) config_col = self.db.get_col_by_name(self.db.capif_configuration) param_path_snake = ".".join(to_snake_case(part) for part in param_path.split(".")) param_path_snake = ".".join(to_snake_case(part) for part in param_path.split(".")) Loading @@ -334,6 +352,10 @@ class HelperOperations: """Removes an entire category inside 'settings'.""" """Removes an entire category inside 'settings'.""" current_app.logger.debug(f"Removing configuration category: {category_name}") current_app.logger.debug(f"Removing configuration category: {category_name}") # Prevent deletion of protected fields if category_name in self.PROTECTED_FIELDS: return jsonify(message=f"The category '{category_name}' is immutable and cannot be removed"), 403 config_col = self.db.get_col_by_name(self.db.capif_configuration) config_col = self.db.get_col_by_name(self.db.capif_configuration) category_name_snake = to_snake_case(category_name) category_name_snake = to_snake_case(category_name) Loading @@ -346,3 +368,17 @@ class HelperOperations: return jsonify(message=f"No configuration found or category '{category_name_snake}' not removed"), 404 return jsonify(message=f"No configuration found or category '{category_name_snake}' not removed"), 404 return jsonify(message=f"Category '{category_name_snake}' removed successfully"), 200 return jsonify(message=f"Category '{category_name_snake}' removed successfully"), 200 def get_ccf_id(self): """ Returns the current CAPIF unique identifier (ccf_id). """ current_app.logger.debug("Retrieving ccf_id from capif_configuration") config_col = self.db.get_col_by_name(self.db.capif_configuration) config = config_col.find_one({}, {"_id": 0, "ccf_id": 1}) if not config or "ccf_id" not in config: return jsonify(message="ccf_id not found"), 404 return jsonify(ccf_id=config["ccf_id"]), 200 services/helper/helper_service/db/db.py +16 −2 Original line number Original line Diff line number Diff line import time import time import uuid from bson.codec_options import CodecOptions from bson.codec_options import CodecOptions from config import Config from config import Config Loading Loading @@ -59,8 +60,21 @@ class MongoDatabse(): # Read configuration from config.yaml # Read configuration from config.yaml default_config = self.config["capif_configuration"] default_config = self.config["capif_configuration"] # Generate unique ccf_id ccf_id = str(uuid.uuid4()) default_config["ccf_id"] = ccf_id capif_col.insert_one(default_config) capif_col.insert_one(default_config) print("Default data inserted into the capif_configuration collection from config.yaml") print(f"Default data inserted into capif_configuration from config.yaml with ccf_id={ccf_id}") else: else: print("The capif_configuration collection already contains data. No default values were inserted.") # Ensure ccf_id exists even if config already there existing_config = capif_col.find_one({}, {"_id": 0}) if "ccf_id" not in existing_config: ccf_id = str(uuid.uuid4()) capif_col.update_one({}, {"$set": {"ccf_id": ccf_id}}) print(f"Added missing ccf_id={ccf_id} to existing CAPIF configuration") else: print("Capif_configuration already contains data with a unique ccf_id. No default values inserted.") Loading
services/helper/helper_service/controllers/helper_controller.py +6 −0 Original line number Original line Diff line number Diff line Loading @@ -191,3 +191,9 @@ def remove_config_category(): return jsonify(message="Missing 'category_name' in request body"), 400 return jsonify(message="Missing 'category_name' in request body"), 400 return helper_operation.remove_config_category(category_name) return helper_operation.remove_config_category(category_name) @helper_routes.route("/helper/getCcfId", methods=["GET"]) def get_ccf_id(): """Returns the current CAPIF ccfId""" return helper_operation.get_ccf_id()
services/helper/helper_service/core/helper_operations.py +46 −10 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,8 @@ from utils.utils import ( class HelperOperations: class HelperOperations: PROTECTED_FIELDS = ["ccf_id"] def __init__(self): def __init__(self): self.db = MongoDatabse() self.db = MongoDatabse() self.mimetype = 'application/json' self.mimetype = 'application/json' Loading Loading @@ -228,6 +230,10 @@ class HelperOperations: """ """ current_app.logger.debug(f"Updating configuration parameter: {param_path} with value: {new_value}") current_app.logger.debug(f"Updating configuration parameter: {param_path} with value: {new_value}") # Protect immutable fields if any(param_path.startswith(field) for field in self.PROTECTED_FIELDS): return jsonify(message=f"The parameter '{param_path}' is immutable and cannot be modified"), 403 config_col = self.db.get_col_by_name(self.db.capif_configuration) config_col = self.db.get_col_by_name(self.db.capif_configuration) existing_config = config_col.find_one({}, {"_id": 0}) existing_config = config_col.find_one({}, {"_id": 0}) Loading @@ -251,9 +257,6 @@ class HelperOperations: def replace_configuration(self, new_config): def replace_configuration(self, new_config): """ Replace all current settings with a new one. """ current_app.logger.debug("Replacing entire CAPIF configuration") current_app.logger.debug("Replacing entire CAPIF configuration") error_response = validate_snake_case_keys(new_config) error_response = validate_snake_case_keys(new_config) Loading @@ -263,16 +266,18 @@ class HelperOperations: config_col = self.db.get_col_by_name(self.db.capif_configuration) config_col = self.db.get_col_by_name(self.db.capif_configuration) existing_config = config_col.find_one({}, {"_id": 0}) existing_config = config_col.find_one({}, {"_id": 0}) if existing_config: if not existing_config: new_config = convert_nested_values(new_config, existing_config) return jsonify(message="No existing configuration found"), 404 result = config_col.replace_one({}, new_config, upsert=True) # Preserve protected fields for field in self.PROTECTED_FIELDS: if field in existing_config: new_config[field] = existing_config[field] if result.matched_count == 0: new_config = convert_nested_values(new_config, existing_config) return jsonify(message="No existing configuration found; a new one was created"), 201 result = config_col.replace_one({}, new_config, upsert=True) return jsonify(message="Configuration replaced successfully"), 200 return jsonify(message="Configuration replaced successfully (protected fields preserved)"), 200 def add_new_configuration(self, category_name, category_values): def add_new_configuration(self, category_name, category_values): Loading @@ -281,6 +286,10 @@ class HelperOperations: """ """ current_app.logger.debug(f"Adding new category: {category_name} with values: {category_values}") current_app.logger.debug(f"Adding new category: {category_name} with values: {category_values}") # Block protected field creation if category_name in self.PROTECTED_FIELDS: return jsonify(message=f"The category '{category_name}' is immutable and cannot be modified"), 403 config_col = self.db.get_col_by_name(self.db.capif_configuration) config_col = self.db.get_col_by_name(self.db.capif_configuration) category_name_snake = to_snake_case(category_name) category_name_snake = to_snake_case(category_name) Loading @@ -299,6 +308,11 @@ class HelperOperations: def add_new_config_setting(self, param_path, new_value): def add_new_config_setting(self, param_path, new_value): """Add a new parameter in 'settings'.""" """Add a new parameter in 'settings'.""" current_app.logger.debug(f"Adding new configuration setting: {param_path} with value: {new_value}") current_app.logger.debug(f"Adding new configuration setting: {param_path} with value: {new_value}") # Block protected field creation if any(param_path.startswith(field) for field in self.PROTECTED_FIELDS): return jsonify(message=f"The parameter '{param_path}' is immutable and cannot be added or modified"), 403 config_col = self.db.get_col_by_name(self.db.capif_configuration) config_col = self.db.get_col_by_name(self.db.capif_configuration) param_path_snake = ".".join(to_snake_case(part) for part in param_path.split(".")) param_path_snake = ".".join(to_snake_case(part) for part in param_path.split(".")) Loading @@ -316,6 +330,10 @@ class HelperOperations: """Removes a specific parameter inside 'settings'.""" """Removes a specific parameter inside 'settings'.""" current_app.logger.debug(f"Removing configuration parameter: {param_path}") current_app.logger.debug(f"Removing configuration parameter: {param_path}") # Prevent deletion of protected fields if any(param_path.startswith(field) for field in self.PROTECTED_FIELDS): return jsonify(message=f"The parameter '{param_path}' is immutable and cannot be removed"), 403 config_col = self.db.get_col_by_name(self.db.capif_configuration) config_col = self.db.get_col_by_name(self.db.capif_configuration) param_path_snake = ".".join(to_snake_case(part) for part in param_path.split(".")) param_path_snake = ".".join(to_snake_case(part) for part in param_path.split(".")) Loading @@ -334,6 +352,10 @@ class HelperOperations: """Removes an entire category inside 'settings'.""" """Removes an entire category inside 'settings'.""" current_app.logger.debug(f"Removing configuration category: {category_name}") current_app.logger.debug(f"Removing configuration category: {category_name}") # Prevent deletion of protected fields if category_name in self.PROTECTED_FIELDS: return jsonify(message=f"The category '{category_name}' is immutable and cannot be removed"), 403 config_col = self.db.get_col_by_name(self.db.capif_configuration) config_col = self.db.get_col_by_name(self.db.capif_configuration) category_name_snake = to_snake_case(category_name) category_name_snake = to_snake_case(category_name) Loading @@ -346,3 +368,17 @@ class HelperOperations: return jsonify(message=f"No configuration found or category '{category_name_snake}' not removed"), 404 return jsonify(message=f"No configuration found or category '{category_name_snake}' not removed"), 404 return jsonify(message=f"Category '{category_name_snake}' removed successfully"), 200 return jsonify(message=f"Category '{category_name_snake}' removed successfully"), 200 def get_ccf_id(self): """ Returns the current CAPIF unique identifier (ccf_id). """ current_app.logger.debug("Retrieving ccf_id from capif_configuration") config_col = self.db.get_col_by_name(self.db.capif_configuration) config = config_col.find_one({}, {"_id": 0, "ccf_id": 1}) if not config or "ccf_id" not in config: return jsonify(message="ccf_id not found"), 404 return jsonify(ccf_id=config["ccf_id"]), 200
services/helper/helper_service/db/db.py +16 −2 Original line number Original line Diff line number Diff line import time import time import uuid from bson.codec_options import CodecOptions from bson.codec_options import CodecOptions from config import Config from config import Config Loading Loading @@ -59,8 +60,21 @@ class MongoDatabse(): # Read configuration from config.yaml # Read configuration from config.yaml default_config = self.config["capif_configuration"] default_config = self.config["capif_configuration"] # Generate unique ccf_id ccf_id = str(uuid.uuid4()) default_config["ccf_id"] = ccf_id capif_col.insert_one(default_config) capif_col.insert_one(default_config) print("Default data inserted into the capif_configuration collection from config.yaml") print(f"Default data inserted into capif_configuration from config.yaml with ccf_id={ccf_id}") else: else: print("The capif_configuration collection already contains data. No default values were inserted.") # Ensure ccf_id exists even if config already there existing_config = capif_col.find_one({}, {"_id": 0}) if "ccf_id" not in existing_config: ccf_id = str(uuid.uuid4()) capif_col.update_one({}, {"$set": {"ccf_id": ccf_id}}) print(f"Added missing ccf_id={ccf_id} to existing CAPIF configuration") else: print("Capif_configuration already contains data with a unique ccf_id. No default values inserted.")