From bdfb9335488b03fea24ac47379713c87b7559f86 Mon Sep 17 00:00:00 2001 From: SimplifiedPrivacy Date: Thu, 20 Aug 2026 12:23:37 -0400 Subject: [PATCH] Sudo config management. Properly delete the config for protocol changes, and install it using the generic commands module --- change_log.md | 4 +++ .../profile_state/update_profile.py | 13 ++++++++ .../encrypted_proxy/configure_singbox.py | 30 ++++++++----------- .../general_tools/manage_sudo_configs.py | 21 +++++++++++++ core/services/subscriptions/subscriptions.py | 2 +- 5 files changed, 52 insertions(+), 18 deletions(-) create mode 100644 core/services/networking/systemwide/general_tools/manage_sudo_configs.py diff --git a/change_log.md b/change_log.md index d5335fe..ef0b8a4 100644 --- a/change_log.md +++ b/change_log.md @@ -1,5 +1,9 @@ # Major Change Log: +# Vless Introduced +### Aug 20, 2026 +Vless is now working. Config Parsing and setup is stable, and increased the wait time for connection testing. But this is a temporary solution. The real answer is not a static time check, but a dynamic result reading for when to test. Which then has it's own timeout time +
# Assassin Introduced ### Aug 18, 2026 diff --git a/core/controllers/profile_state/update_profile.py b/core/controllers/profile_state/update_profile.py index 3c3c0ad..f655eb8 100644 --- a/core/controllers/profile_state/update_profile.py +++ b/core/controllers/profile_state/update_profile.py @@ -1,6 +1,7 @@ # utils from core.errors.logger import logger from core.models.Result import Result, ResultError +from core.services.networking.systemwide.general_tools.manage_sudo_configs import remove_sudo_config # JSON Models from core.models.BaseProfile import BaseProfile as Profile @@ -88,9 +89,21 @@ def update_profile( # profile.application_version.version_number = browser_version elif key == 'protocol': + # ============= SAME VALUE ============= + if profile.connection.code == new_value: + error_msg = f"This is NOT changing the protocol, it already was {new_value}" + return Result(valid=False, message=error_msg, error_type=ResultError.INVALID_INPUT) + # ============= SYSTEMWIDE ============= if profile.connection == 'system-wide': if new_value in SYSTEMWIDE_CHOICES: + # REMOVE PAST CONFIG: + removed = remove_sudo_config(profile) + if not removed.valid: + error_msg = "You must give permission to delete the previous protocol's config file." + return Result(valid=False, message=error_msg, error_type=ResultError.PERMISSION) + + # UPDATE PROFILE profile.connection.code = new_value final_data = "edit_session" else: diff --git a/core/services/networking/systemwide/encrypted_proxy/configure_singbox.py b/core/services/networking/systemwide/encrypted_proxy/configure_singbox.py index 9070b83..edc5353 100644 --- a/core/services/networking/systemwide/encrypted_proxy/configure_singbox.py +++ b/core/services/networking/systemwide/encrypted_proxy/configure_singbox.py @@ -4,6 +4,8 @@ from core.services.networking.httpx import connect from core.services.networking.systemwide.encrypted_proxy.hysteria_config import build_hysteria_config from core.services.networking.systemwide.encrypted_proxy.vless_config import build_vless_config, parse_vless_link +from core.utils.basic_operations.write_or_read_from_json import write_json_to_file +from core.utils.run_commands import run_generic_command # Models from core.models.pydantic_models.HysteriaData import HysteriaData @@ -177,28 +179,25 @@ def attach_config_to_sudo_folder( logger.info("About to save to backup config path") backup_path = f'{backup_folder}/backup.conf.bak' - try: - with open(backup_path, "w") as configuration_file: - json.dump(config_data, configuration_file, indent=4) - logger.info("Saved to backup config path!") - except Exception as e: - logger.error(e) + saved_backup = write_json_to_file(data=config_data, filepath=backup_path) + if not saved_backup: + logger.error("Backup Save was not successfull") return False configuration_is_attached = False failed_attempt_count = 0 while not configuration_is_attached and failed_attempt_count < 3: - logger.info(f"Trying attempt {failed_attempt_count} to write to the sudo folder..") - try: - process = subprocess.Popen(('pkexec', 'install', '-D', backup_path, sudo_filepath, '-o', 'root', '-m', '744')) - configuration_is_attached = not bool(os.waitpid(process.pid, 0)[1] >> 8) - except Exception as e: - logger.error(e) - - if not configuration_is_attached: + human_readable_goal = f"Attempt {failed_attempt_count} to write to the sudo folder" + logger.info(human_readable_goal) + command = ['pkexec', 'install', '-D', backup_path, sudo_filepath, '-o', 'root', '-m', '744'] + result_object = run_generic_command(command, human_readable_goal, timeout=5) + if result_object.valid: + configuration_is_attached = True + else: failed_attempt_count += 1 + if not configuration_is_attached: raise ProfileModificationError('The configuration could not be attached.') return False # redundant @@ -230,9 +229,6 @@ def post_operator_proxy(billing_code: str, protocol: str, connection_observer: C # convert the error message here return False -# no longer needed: -# 'location_id': location_id, -# 'subscription_plan_id': subscription_plan_id, diff --git a/core/services/networking/systemwide/general_tools/manage_sudo_configs.py b/core/services/networking/systemwide/general_tools/manage_sudo_configs.py new file mode 100644 index 0000000..c83c6db --- /dev/null +++ b/core/services/networking/systemwide/general_tools/manage_sudo_configs.py @@ -0,0 +1,21 @@ +from core.utils.run_commands import run_generic_command +from core.models.Result import Result +from core.models.system.SystemProfile import SystemProfile + +def get_target_filename(profile: SystemProfile) -> str: + if profile.connection.code == "wireguard": + return "wg.conf" + else: + return "proxy.json" + +def remove_sudo_config(profile: SystemProfile) -> Result: + # FILE PATH: + base_folder = profile.get_system_config_path() + file_name = get_target_filename(profile) + sudo_filepath = f"{base_folder}/{file_name}" + + # REMOVE: + command = ['pkexec', 'rm', '-f', sudo_filepath] + human_readable_goal = "Removing file from sudo folder" + return run_generic_command(command, human_readable_goal, timeout=35) + diff --git a/core/services/subscriptions/subscriptions.py b/core/services/subscriptions/subscriptions.py index cc1b3d2..742f3ad 100644 --- a/core/services/subscriptions/subscriptions.py +++ b/core/services/subscriptions/subscriptions.py @@ -52,7 +52,7 @@ def activate_subscription( # Already activated—nothing to do if profile.subscription.has_been_activated(): - logger.info("sub has already been activated, returnining true") + logger.info("Sub has already been activated") return True # ==================================================