Loading services/helper/helper_service/core/helper_operations.py +20 −5 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ import requests from config import Config from db.db import MongoDatabse from flask import jsonify, current_app from utils.utils import to_snake_case, convert_dict_keys_to_snake_case, validate_snake_case_keys from utils.utils import to_snake_case, convert_dict_keys_to_snake_case, validate_snake_case_keys, get_nested_value, convert_value_to_original_type, convert_nested_values class HelperOperations: Loading Loading @@ -223,7 +223,18 @@ class HelperOperations: config_col = self.db.get_col_by_name(self.db.capif_configuration) update_query = {"$set": {param_path: new_value}} existing_config = config_col.find_one({}, {"_id": 0}) current_value = get_nested_value(existing_config, param_path) if current_value is None: return jsonify(message=f"The parameter '{param_path}' does not exist in the configuration"), 404 converted_value = convert_value_to_original_type(new_value, current_value) if isinstance(converted_value, tuple): return converted_value update_query = {"$set": {param_path: converted_value}} result = config_col.update_one({}, update_query) if result.modified_count == 0: Loading @@ -234,7 +245,7 @@ class HelperOperations: def replace_configuration(self, new_config): """ Replaces all current settings with a new one. Replace all current settings with a new one. """ current_app.logger.debug("Replacing entire CAPIF configuration") Loading @@ -243,6 +254,10 @@ class HelperOperations: return error_response 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) Loading @@ -255,7 +270,7 @@ class HelperOperations: def add_new_configuration(self, category_name, category_values): """ Adds a new category of parameters in 'settings'. Add a new category of parameters in 'settings'. """ current_app.logger.debug(f"Adding new category: {category_name} with values: {category_values}") Loading services/helper/helper_service/utils/utils.py +56 −0 Original line number Diff line number Diff line Loading @@ -33,3 +33,59 @@ def validate_snake_case_keys(obj, path="root"): error_response = validate_snake_case_keys(value, f"{path}.{key}") if error_response: return error_response def get_nested_value(config, path): """ Obtiene un valor dentro de un diccionario anidado siguiendo una ruta de claves separadas por puntos. """ keys = path.split('.') for key in keys: if isinstance(config, dict) and key in config: config = config[key] else: return None return config def convert_value_to_original_type(new_value, current_value): """ Convierte new_value al tipo de current_value si es posible. """ if isinstance(current_value, int): try: return int(new_value) except ValueError: return jsonify(message=f"Valor inválido: {new_value} no es un entero"), 400 elif isinstance(current_value, float): try: return float(new_value) except ValueError: return jsonify(message=f"Valor inválido: {new_value} no es un flotante"), 400 elif isinstance(current_value, bool): if isinstance(new_value, str) and new_value.lower() in ["true", "false"]: return new_value.lower() == "true" elif not isinstance(new_value, bool): return jsonify(message=f"Valor inválido: {new_value} no es un booleano"), 400 return new_value def convert_nested_values(new_data, reference_data): """ Recorre recursivamente new_data y convierte los valores al tipo original basado en reference_data. """ if isinstance(new_data, dict) and isinstance(reference_data, dict): for key, value in new_data.items(): if key in reference_data: new_data[key] = convert_nested_values(value, reference_data[key]) elif isinstance(reference_data, int): try: return int(new_data) except ValueError: return new_data elif isinstance(reference_data, float): try: return float(new_data) except ValueError: return new_data elif isinstance(reference_data, bool): if isinstance(new_data, str) and new_data.lower() in ["true", "false"]: return new_data.lower() == "true" return new_data No newline at end of file Loading
services/helper/helper_service/core/helper_operations.py +20 −5 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ import requests from config import Config from db.db import MongoDatabse from flask import jsonify, current_app from utils.utils import to_snake_case, convert_dict_keys_to_snake_case, validate_snake_case_keys from utils.utils import to_snake_case, convert_dict_keys_to_snake_case, validate_snake_case_keys, get_nested_value, convert_value_to_original_type, convert_nested_values class HelperOperations: Loading Loading @@ -223,7 +223,18 @@ class HelperOperations: config_col = self.db.get_col_by_name(self.db.capif_configuration) update_query = {"$set": {param_path: new_value}} existing_config = config_col.find_one({}, {"_id": 0}) current_value = get_nested_value(existing_config, param_path) if current_value is None: return jsonify(message=f"The parameter '{param_path}' does not exist in the configuration"), 404 converted_value = convert_value_to_original_type(new_value, current_value) if isinstance(converted_value, tuple): return converted_value update_query = {"$set": {param_path: converted_value}} result = config_col.update_one({}, update_query) if result.modified_count == 0: Loading @@ -234,7 +245,7 @@ class HelperOperations: def replace_configuration(self, new_config): """ Replaces all current settings with a new one. Replace all current settings with a new one. """ current_app.logger.debug("Replacing entire CAPIF configuration") Loading @@ -243,6 +254,10 @@ class HelperOperations: return error_response 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) Loading @@ -255,7 +270,7 @@ class HelperOperations: def add_new_configuration(self, category_name, category_values): """ Adds a new category of parameters in 'settings'. Add a new category of parameters in 'settings'. """ current_app.logger.debug(f"Adding new category: {category_name} with values: {category_values}") Loading
services/helper/helper_service/utils/utils.py +56 −0 Original line number Diff line number Diff line Loading @@ -33,3 +33,59 @@ def validate_snake_case_keys(obj, path="root"): error_response = validate_snake_case_keys(value, f"{path}.{key}") if error_response: return error_response def get_nested_value(config, path): """ Obtiene un valor dentro de un diccionario anidado siguiendo una ruta de claves separadas por puntos. """ keys = path.split('.') for key in keys: if isinstance(config, dict) and key in config: config = config[key] else: return None return config def convert_value_to_original_type(new_value, current_value): """ Convierte new_value al tipo de current_value si es posible. """ if isinstance(current_value, int): try: return int(new_value) except ValueError: return jsonify(message=f"Valor inválido: {new_value} no es un entero"), 400 elif isinstance(current_value, float): try: return float(new_value) except ValueError: return jsonify(message=f"Valor inválido: {new_value} no es un flotante"), 400 elif isinstance(current_value, bool): if isinstance(new_value, str) and new_value.lower() in ["true", "false"]: return new_value.lower() == "true" elif not isinstance(new_value, bool): return jsonify(message=f"Valor inválido: {new_value} no es un booleano"), 400 return new_value def convert_nested_values(new_data, reference_data): """ Recorre recursivamente new_data y convierte los valores al tipo original basado en reference_data. """ if isinstance(new_data, dict) and isinstance(reference_data, dict): for key, value in new_data.items(): if key in reference_data: new_data[key] = convert_nested_values(value, reference_data[key]) elif isinstance(reference_data, int): try: return int(new_data) except ValueError: return new_data elif isinstance(reference_data, float): try: return float(new_data) except ValueError: return new_data elif isinstance(reference_data, bool): if isinstance(new_data, str) and new_data.lower() in ["true", "false"]: return new_data.lower() == "true" return new_data No newline at end of file