Bug fixes and tweaks for transitions
This commit is contained in:
parent
b29a44cf95
commit
d35fc0db4b
10 changed files with 51 additions and 24 deletions
|
|
@ -1,3 +0,0 @@
|
||||||
from core.utils.run_commands import test_broken_pipe_on_process_death
|
|
||||||
|
|
||||||
test_broken_pipe_on_process_death()
|
|
||||||
|
|
@ -8,7 +8,7 @@ if TYPE_CHECKING:
|
||||||
from core.Constants import Constants
|
from core.Constants import Constants
|
||||||
# from core.observers.BaseObserver import BaseObserver
|
# from core.observers.BaseObserver import BaseObserver
|
||||||
from core.services.using_tickets.use_ticket_orchestrator import use_ticket_orchestrator
|
from core.services.using_tickets.use_ticket_orchestrator import use_ticket_orchestrator
|
||||||
|
from core.models.Result import Result, ResultError
|
||||||
from core.services.prepare_tickets.ticket_tracker import does_ticket_tracker_exist
|
from core.services.prepare_tickets.ticket_tracker import does_ticket_tracker_exist
|
||||||
|
|
||||||
# from core.services.prepare_tickets import setup_ticket_tracker
|
# from core.services.prepare_tickets import setup_ticket_tracker
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,11 @@ def denormalize(data, mapping_file):
|
||||||
extract_from_nested - This function checks it's actually a dictionary and extracts it
|
extract_from_nested - This function checks it's actually a dictionary and extracts it
|
||||||
"""
|
"""
|
||||||
value = extract_from_nested(each_item, field['path'])
|
value = extract_from_nested(each_item, field['path'])
|
||||||
|
|
||||||
|
# If nested path didn't work, try using the field name as a flat key
|
||||||
|
if value is None:
|
||||||
|
value = each_item.get(field['name'])
|
||||||
|
|
||||||
# Store the extracted value. If it wasn't there, then it's None
|
# Store the extracted value. If it wasn't there, then it's None
|
||||||
each_denormalized_piece[field['name']] = value
|
each_denormalized_piece[field['name']] = value
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ def switch_endpoint_domain(domain: str) -> dict:
|
||||||
"operators": f"https://{domain}/api/v1/operators",
|
"operators": f"https://{domain}/api/v1/operators",
|
||||||
"client_version": f"https://{domain}/api/v1/platforms/linux-x86_64/appimage/client-versions",
|
"client_version": f"https://{domain}/api/v1/platforms/linux-x86_64/appimage/client-versions",
|
||||||
"subscriptions": f"https://{domain}/api/v1/subscription-plans",
|
"subscriptions": f"https://{domain}/api/v1/subscription-plans",
|
||||||
"applications": f"https://{domain}/api/v1/platforms/linux-x86_64/applications",
|
# "applications": f"https://{domain}/api/v1/platforms/linux-x86_64/applications",
|
||||||
"application_versions": f"https://{domain}/api/v1/platforms/linux-x86_64/application-versions",
|
"application_versions": f"https://{domain}/api/v1/platforms/linux-x86_64/application-versions",
|
||||||
"dependencies": f"https://{domain}/api/v1/dependencies"
|
"dependencies": f"https://{domain}/api/v1/dependencies"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -161,8 +161,12 @@ def orchestrate_closing(current_state: SystemState, interface: str) -> Result:
|
||||||
for strategy in strategies:
|
for strategy in strategies:
|
||||||
result = _try_with_permission_fallback(strategy, interface)
|
result = _try_with_permission_fallback(strategy, interface)
|
||||||
if result.valid:
|
if result.valid:
|
||||||
|
# remove state json:
|
||||||
|
SystemState.dissolve()
|
||||||
return result
|
return result
|
||||||
if not interface_tools.exists(interface):
|
if not interface_tools.exists(interface):
|
||||||
|
# remove state json:
|
||||||
|
SystemState.dissolve()
|
||||||
return Result(valid=True, message="Tunnel inactive despite strategy failure")
|
return Result(valid=True, message="Tunnel inactive despite strategy failure")
|
||||||
|
|
||||||
return Result(valid=False, message=f"All {quantity_of_strategies} strategies tried, we simply can not bring down the proxy, which is still up.")
|
return Result(valid=False, message=f"All {quantity_of_strategies} strategies tried, we simply can not bring down the proxy, which is still up.")
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ from core.services.networking.systemwide.encrypted_proxy.hysteria_config import
|
||||||
from core.services.networking.systemwide.encrypted_proxy.vless_config import build_vless_config, parse_vless_link
|
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.basic_operations.write_or_read_from_json import write_json_to_file
|
||||||
from core.utils.run_commands import run_generic_command
|
from core.utils.run_commands import run_generic_command
|
||||||
|
from core.utils.basic_operations.does_file_exist import does_file_exist
|
||||||
|
|
||||||
|
|
||||||
# Models
|
# Models
|
||||||
from core.models.pydantic_models.HysteriaData import HysteriaData
|
from core.models.pydantic_models.HysteriaData import HysteriaData
|
||||||
|
|
@ -191,7 +193,7 @@ def attach_config_to_sudo_folder(
|
||||||
human_readable_goal = f"Attempt {failed_attempt_count} to write to the sudo folder"
|
human_readable_goal = f"Attempt {failed_attempt_count} to write to the sudo folder"
|
||||||
logger.info(human_readable_goal)
|
logger.info(human_readable_goal)
|
||||||
command = ['pkexec', 'install', '-D', backup_path, sudo_filepath, '-o', 'root', '-m', '744']
|
command = ['pkexec', 'install', '-D', backup_path, sudo_filepath, '-o', 'root', '-m', '744']
|
||||||
result_object = run_generic_command(command, human_readable_goal, timeout=5)
|
result_object = run_generic_command(command, human_readable_goal, timeout=40)
|
||||||
if result_object.valid:
|
if result_object.valid:
|
||||||
configuration_is_attached = True
|
configuration_is_attached = True
|
||||||
else:
|
else:
|
||||||
|
|
@ -202,7 +204,8 @@ def attach_config_to_sudo_folder(
|
||||||
raise ProfileModificationError('The configuration could not be attached.')
|
raise ProfileModificationError('The configuration could not be attached.')
|
||||||
return False # redundant
|
return False # redundant
|
||||||
|
|
||||||
return True
|
# confirm file exists before we continue,
|
||||||
|
return does_file_exist(sudo_filepath)
|
||||||
|
|
||||||
|
|
||||||
def post_operator_proxy(billing_code: str, protocol: str, connection_observer: ConnectionObserver) -> dict:
|
def post_operator_proxy(billing_code: str, protocol: str, connection_observer: ConnectionObserver) -> dict:
|
||||||
|
|
|
||||||
|
|
@ -297,15 +297,22 @@ def start_singbox(
|
||||||
if not ip_result.valid:
|
if not ip_result.valid:
|
||||||
logger.error(f"IP address check is unable to connect. Killing Singbox pid {process_id}")
|
logger.error(f"IP address check is unable to connect. Killing Singbox pid {process_id}")
|
||||||
closed = orchestrate_closing(current_state=current_state, interface=Constants.SINGBOX_TUN_IF)
|
closed = orchestrate_closing(current_state=current_state, interface=Constants.SINGBOX_TUN_IF)
|
||||||
raise ConnectionError("Could not connect with IP adddress check.")
|
if closed.valid:
|
||||||
# return Result(valid=False, error_type=ResultError.CONNECTION, message="Could not connect with IP adddress check.")
|
logger.info("Closed singbox. Redundant state removal now taking place..")
|
||||||
|
# redundant state removal. This is a repeat of the close_Singbox doing it.
|
||||||
|
SystemState.dissolve()
|
||||||
|
|
||||||
|
# raise ConnectionError("Could not connect with IP adddress check.")
|
||||||
|
return Result(valid=False, error_type=ResultError.CONNECTION, message="Could not connect with IP adddress check.")
|
||||||
|
|
||||||
observed_ip_address = ip_result.data
|
observed_ip_address = ip_result.data
|
||||||
if observed_ip_address == server_ip:
|
logger.info(f"""
|
||||||
logger.info("Observed IP matches the intended server IP. Proceeding..")
|
observed_ip_address: {observed_ip_address}
|
||||||
if connection_observer:
|
observed_ip_address type: {type(observed_ip_address)}
|
||||||
connection_observer.notify("connecting", f"IP Matched! {server_ip}")
|
server_ip: {server_ip}
|
||||||
else:
|
server_ip type: {type(server_ip)}
|
||||||
|
""")
|
||||||
|
if str(observed_ip_address) != str(server_ip):
|
||||||
error_msg = f"Connection didn't work, it's leaking! IP address check of {observed_ip_address} does NOT match the intended {server_ip}."
|
error_msg = f"Connection didn't work, it's leaking! IP address check of {observed_ip_address} does NOT match the intended {server_ip}."
|
||||||
logger.error(f"{error_msg} Killing Singbox pid {process_id}")
|
logger.error(f"{error_msg} Killing Singbox pid {process_id}")
|
||||||
closed = orchestrate_closing(current_state=current_state, interface=Constants.SINGBOX_TUN_IF)
|
closed = orchestrate_closing(current_state=current_state, interface=Constants.SINGBOX_TUN_IF)
|
||||||
|
|
@ -314,12 +321,17 @@ def start_singbox(
|
||||||
connection_observer.notify("connecting", error_for_user)
|
connection_observer.notify("connecting", error_for_user)
|
||||||
return Result(valid=False, error_type=ResultError.LEAK_ISSUE, message=error_msg)
|
return Result(valid=False, error_type=ResultError.LEAK_ISSUE, message=error_msg)
|
||||||
|
|
||||||
|
|
||||||
|
logger.info("Observed IP matches the intended server IP. Proceeding..")
|
||||||
|
if connection_observer:
|
||||||
|
connection_observer.notify("connecting", f"IP Matched! {server_ip}")
|
||||||
|
|
||||||
# ============= FIREWALL =============
|
# ============= FIREWALL =============
|
||||||
logger.info(f"Attempting to enable the Firewall for {Constants.SINGBOX_TUN_IF} and {Constants.SINGBOX_INTERNAL_SUBNET}...")
|
logger.info(f"Attempting to enable the Firewall for {Constants.SINGBOX_TUN_IF} and {Constants.SINGBOX_INTERNAL_SUBNET}...")
|
||||||
firewall_result = enable_firewall_w_retry( # this function is "generic" as it's protocol neutral
|
firewall_result = enable_firewall_w_retry( # this function is "generic" as it's protocol neutral
|
||||||
interface_name=Constants.SINGBOX_TUN_IF,
|
interface_name=str(Constants.SINGBOX_TUN_IF),
|
||||||
server_ip=server_ip,
|
server_ip=str(server_ip),
|
||||||
internal_subnet = Constants.SINGBOX_INTERNAL_SUBNET,
|
internal_subnet = (Constants.SINGBOX_INTERNAL_SUBNET),
|
||||||
max_retries = 2
|
max_retries = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ def is_subscription_ready(profile: Union[SessionProfile, SystemProfile]) -> bool
|
||||||
|
|
||||||
|
|
||||||
def get_subscription(billing_code: str, connection_observer: ConnectionObserver) -> Subscription:
|
def get_subscription(billing_code: str, connection_observer: ConnectionObserver) -> Subscription:
|
||||||
|
print(f"calling get_subscription with {billing_code}")
|
||||||
|
|
||||||
billing_code = billing_code.replace('-', '').upper()
|
billing_code = billing_code.replace('-', '').upper()
|
||||||
billing_code_fragments = re.findall('....?', billing_code)
|
billing_code_fragments = re.findall('....?', billing_code)
|
||||||
|
|
@ -126,6 +127,7 @@ def get_subscription(billing_code: str, connection_observer: ConnectionObserver)
|
||||||
|
|
||||||
|
|
||||||
def get_invoice(billing_code: str, connection_observer: ConnectionObserver) -> Invoice:
|
def get_invoice(billing_code: str, connection_observer: ConnectionObserver) -> Invoice:
|
||||||
|
print(f"calling get_invoice to get an invoice")
|
||||||
|
|
||||||
url = f'{Constants.SP_API_BASE_URL}/invoices/current'
|
url = f'{Constants.SP_API_BASE_URL}/invoices/current'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -197,15 +197,15 @@ def coordinate_cache_sync(
|
||||||
# ================== VALIDATE DATA ==================
|
# ================== VALIDATE DATA ==================
|
||||||
|
|
||||||
# Extract the data from our own trusted function without type checking,
|
# Extract the data from our own trusted function without type checking,
|
||||||
new_data = api_result.data
|
original_data = api_result.data
|
||||||
|
|
||||||
if new_data:
|
if original_data:
|
||||||
logger.debug(f"We got an API response with some data, let's check if it's a valid format...")
|
logger.debug(f"We got an API response with some data, let's check if it's a valid format...")
|
||||||
|
|
||||||
# Validate the API's payload, (we don't trust the API's structure)
|
# Validate the API's payload, (we don't trust the API's structure)
|
||||||
if not isinstance(new_data, dict):
|
if not isinstance(original_data, dict):
|
||||||
error_msg = f"API returned invalid metadata of {type(new_data)}. When 'new_data' has to be in dictionary format. The raw data is {new_data}"
|
error_msg = f"API returned invalid metadata of {type(original_data)}. When 'original_data' has to be in dictionary format. The raw data is {original_data}"
|
||||||
client_observer.notify('synchronizing', f'Server replied with invalid metadata of type {type(new_data)}')
|
client_observer.notify('synchronizing', f'Server replied with invalid metadata of type {type(original_data)}')
|
||||||
logger.error(error_msg)
|
logger.error(error_msg)
|
||||||
return {
|
return {
|
||||||
"success": False,
|
"success": False,
|
||||||
|
|
@ -214,8 +214,12 @@ def coordinate_cache_sync(
|
||||||
"error": error_msg,
|
"error": error_msg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# de-"data" it if it has it:
|
||||||
|
new_data = original_data.get('data', original_data)
|
||||||
|
print(f"new_data is {new_data}")
|
||||||
|
|
||||||
if "version" not in new_data:
|
if "version" not in new_data:
|
||||||
error_msg = "API returned invalid metadata: missing 'version' key"
|
error_msg = f"API returned invalid metadata: missing 'version' key. The data is {new_data}"
|
||||||
logger.error(error_msg)
|
logger.error(error_msg)
|
||||||
return {
|
return {
|
||||||
"success": False,
|
"success": False,
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ def use_ticket_orchestrator(
|
||||||
|
|
||||||
# even if not saved return it back, so it can be saved with the profile by other functions,
|
# even if not saved return it back, so it can be saved with the profile by other functions,
|
||||||
return Result(valid=True, data=billing_code)
|
return Result(valid=True, data=billing_code)
|
||||||
|
# return {"valid": True, "data": billing_code}
|
||||||
|
|
||||||
# EXPIRED
|
# EXPIRED
|
||||||
if not valid and message == "expired":
|
if not valid and message == "expired":
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue