From 112da115ad83e721e245c736c138e2385de251c0 Mon Sep 17 00:00:00 2001 From: guillecxb Date: Fri, 31 Oct 2025 10:27:06 +0100 Subject: [PATCH 1/2] include new field ccfid --- .../controllers/helper_controller.py | 6 ++ .../helper_service/core/helper_operations.py | 56 +++++++++++++++---- services/helper/helper_service/db/db.py | 18 +++++- 3 files changed, 68 insertions(+), 12 deletions(-) diff --git a/services/helper/helper_service/controllers/helper_controller.py b/services/helper/helper_service/controllers/helper_controller.py index 19b11160..8d50f7c0 100644 --- a/services/helper/helper_service/controllers/helper_controller.py +++ b/services/helper/helper_service/controllers/helper_controller.py @@ -191,3 +191,9 @@ def remove_config_category(): return jsonify(message="Missing 'category_name' in request body"), 400 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() diff --git a/services/helper/helper_service/core/helper_operations.py b/services/helper/helper_service/core/helper_operations.py index f0c1f6d3..6f1fe63e 100644 --- a/services/helper/helper_service/core/helper_operations.py +++ b/services/helper/helper_service/core/helper_operations.py @@ -17,6 +17,8 @@ from utils.utils import ( class HelperOperations: + PROTECTED_FIELDS = ["ccf_id"] + def __init__(self): self.db = MongoDatabse() self.mimetype = 'application/json' @@ -228,6 +230,10 @@ class HelperOperations: """ 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) existing_config = config_col.find_one({}, {"_id": 0}) @@ -251,9 +257,6 @@ class HelperOperations: def replace_configuration(self, new_config): - """ - Replace all current settings with a new one. - """ current_app.logger.debug("Replacing entire CAPIF configuration") error_response = validate_snake_case_keys(new_config) @@ -263,16 +266,18 @@ class HelperOperations: config_col = self.db.get_col_by_name(self.db.capif_configuration) existing_config = config_col.find_one({}, {"_id": 0}) - if existing_config: - new_config = convert_nested_values(new_config, existing_config) - - result = config_col.replace_one({}, new_config, upsert=True) + if not existing_config: + return jsonify(message="No existing configuration found"), 404 - if result.matched_count == 0: - return jsonify(message="No existing configuration found; a new one was created"), 201 + # Preserve protected fields + for field in self.PROTECTED_FIELDS: + if field in existing_config: + new_config[field] = existing_config[field] - return jsonify(message="Configuration replaced successfully"), 200 + new_config = convert_nested_values(new_config, existing_config) + result = config_col.replace_one({}, new_config, upsert=True) + return jsonify(message="Configuration replaced successfully (protected fields preserved)"), 200 def add_new_configuration(self, category_name, category_values): @@ -281,6 +286,10 @@ class HelperOperations: """ 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) category_name_snake = to_snake_case(category_name) @@ -299,6 +308,11 @@ class HelperOperations: def add_new_config_setting(self, param_path, new_value): """Add a new parameter in 'settings'.""" 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) param_path_snake = ".".join(to_snake_case(part) for part in param_path.split(".")) @@ -316,6 +330,10 @@ class HelperOperations: """Removes a specific parameter inside 'settings'.""" 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) param_path_snake = ".".join(to_snake_case(part) for part in param_path.split(".")) @@ -334,6 +352,10 @@ class HelperOperations: """Removes an entire category inside 'settings'.""" 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) category_name_snake = to_snake_case(category_name) @@ -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"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 diff --git a/services/helper/helper_service/db/db.py b/services/helper/helper_service/db/db.py index 8a7ea94d..b4414123 100644 --- a/services/helper/helper_service/db/db.py +++ b/services/helper/helper_service/db/db.py @@ -1,4 +1,5 @@ import time +import uuid from bson.codec_options import CodecOptions from config import Config @@ -59,8 +60,21 @@ class MongoDatabse(): # Read configuration from config.yaml 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) - 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: - 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.") + -- GitLab From 535cb602abcca5e28d045231e6703c84c5f2bd5c Mon Sep 17 00:00:00 2001 From: guillecxb Date: Mon, 3 Nov 2025 14:08:32 +0100 Subject: [PATCH 2/2] unify ccf_id generation with other CAPIF services --- services/helper/helper_service/db/db.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/helper/helper_service/db/db.py b/services/helper/helper_service/db/db.py index b4414123..30c25e8b 100644 --- a/services/helper/helper_service/db/db.py +++ b/services/helper/helper_service/db/db.py @@ -1,5 +1,5 @@ import time -import uuid +import secrets from bson.codec_options import CodecOptions from config import Config @@ -61,7 +61,7 @@ class MongoDatabse(): default_config = self.config["capif_configuration"] # Generate unique ccf_id - ccf_id = str(uuid.uuid4()) + ccf_id = "CCF" + secrets.token_hex(15) default_config["ccf_id"] = ccf_id capif_col.insert_one(default_config) @@ -71,7 +71,7 @@ class MongoDatabse(): # 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()) + ccf_id = "CCF" + secrets.token_hex(15) capif_col.update_one({}, {"$set": {"ccf_id": ccf_id}}) print(f"Added missing ccf_id={ccf_id} to existing CAPIF configuration") else: -- GitLab