Surgery on ConnectionController! Huge separation of ConnectionController & ProfileController into naked function modules for enabling a connection, registering wireguard keys, coordinating proxy configs, subscriptions, endpoint verification, and the logistical flow. Additionally enums were used for type checking, instead of polymorphic functions. This version is stable and confirmed working for systemwide and session wireguard, but not yet proxies.

This commit is contained in:
SimplifiedPrivacy 2026-07-18 23:35:48 -04:00
parent 9740e0f53b
commit 2ccbdba06b
10 changed files with 375 additions and 129 deletions

View file

@ -1,5 +1,11 @@
# Major Change Log: # Major Change Log:
# 2.4.2
### Surgery on ConnectionController
Huge separation of ConnectionController & ProfileController into naked function modules for enabling a connection, registering wireguard keys, coordinating proxy configs, subscriptions, endpoint verification, and the logistical flow. Additionally enums were used for type checking, instead of polymorphic functions. This version is stable and confirmed working for systemwide and session wireguard, but not yet proxies.
<br/>
# 2.4.1 # 2.4.1
### Enums for Profile types. ### Enums for Profile types.
July 18, 2026 July 18, 2026

View file

@ -3,14 +3,14 @@ from core.errors.logger import logger
from core.services.networking.general_connection_tools.testing_evaluating import await_connection, system_uses_wireguard_interface, await_network_interface from core.services.networking.general_connection_tools.testing_evaluating import await_connection, system_uses_wireguard_interface, await_network_interface
from core.services.networking.systemwide.systemwide_wireguard import establish_system_connection, terminate_system_connection from core.services.networking.systemwide.systemwide_wireguard import establish_system_connection, terminate_system_connection
from core.services.verification.endpoint_verification import verify_wireguard_endpoint from core.services.keys_and_verifications.endpoint_verification import verify_wireguard_endpoint
from collections.abc import Callable from collections.abc import Callable
from core.Constants import Constants from core.Constants import Constants
from core.Errors import InvalidSubscriptionError, MissingSubscriptionError, ConnectionUnprotectedError, ConnectionTerminationError, CommandNotFoundError from core.Errors import InvalidSubscriptionError, MissingSubscriptionError, ConnectionUnprotectedError, ConnectionTerminationError, CommandNotFoundError
from core.controllers.ConfigurationController import ConfigurationController from core.controllers.ConfigurationController import ConfigurationController
from core.controllers.ProfileController import ProfileController # from core.controllers.ProfileController import ProfileController
from core.controllers.SessionStateController import SessionStateController from core.controllers.SessionStateController import SessionStateController
from core.controllers.SystemStateController import SystemStateController from core.controllers.SystemStateController import SystemStateController
from core.models.BaseProfile import ProfileType from core.models.BaseProfile import ProfileType
@ -60,86 +60,87 @@ class ConnectionController:
else: else:
return None return None
@staticmethod # @staticmethod
def establish_connection(profile: Union[SessionProfile, SystemProfile], ignore: tuple[type[Exception]] = (), connection_observer: Optional[ConnectionObserver] = None): # def establish_connection(profile: Union[SessionProfile, SystemProfile], ignore: tuple[type[Exception]] = (), connection_observer: Optional[ConnectionObserver] = None):
connection = profile.connection # connection = profile.connection
# needs_proxy_configuration comes from the child connection models # # needs_proxy_configuration comes from the child connection models
# for the system it returns false blindly. for the session is checks if the connection type is masked. # # for the system it returns false blindly. for the session is checks if the connection type is masked.
# if connection.masked and not profile.has_proxy_configuration(): # # if connection.masked and not profile.has_proxy_configuration():
if connection.needs_proxy_configuration() and not profile.has_proxy_configuration(): # if connection.needs_proxy_configuration() and not profile.has_proxy_configuration():
if profile.has_subscription(): # if profile.has_subscription():
if not profile.subscription.has_been_activated(): # if not profile.subscription.has_been_activated():
ProfileController.activate_subscription(profile, connection_observer=connection_observer) # ProfileController.activate_subscription(profile, connection_observer=connection_observer)
proxy_configuration = ConnectionController.with_preferred_connection(profile.subscription.billing_code, task=WebServiceApiService.get_proxy_configuration, connection_observer=connection_observer) # proxy_configuration = ConnectionController.with_preferred_connection(profile.subscription.billing_code, task=WebServiceApiService.get_proxy_configuration, connection_observer=connection_observer)
if proxy_configuration is None: # if proxy_configuration is None:
raise InvalidSubscriptionError() # raise InvalidSubscriptionError()
profile.attach_proxy_configuration(proxy_configuration) # profile.attach_proxy_configuration(proxy_configuration)
else: # else:
raise MissingSubscriptionError() # raise MissingSubscriptionError()
# The needs_wireguard_configuration comes from the connection model, and can be transitioned to get it directly from the object's data # # The needs_wireguard_configuration comes from the connection model,
# The has_wireguard_configuration comes from each polymorph object doing an os check on if the wg config exists # # and can be transitioned to get it directly from the object's data
if connection.needs_wireguard_configuration() and not profile.has_wireguard_configuration(): # # The has_wireguard_configuration comes from each polymorph object doing an os check on if the wg config exists
# if connection.needs_wireguard_configuration() and not profile.has_wireguard_configuration():
if profile.has_subscription(): # if profile.has_subscription():
if not profile.subscription.has_been_activated(): # if not profile.subscription.has_been_activated():
ProfileController.activate_subscription(profile, connection_observer=connection_observer) # ProfileController.activate_subscription(profile, connection_observer=connection_observer)
ProfileController.register_wireguard_session(profile, connection_observer=connection_observer) # ProfileController.register_wireguard_session(profile, connection_observer=connection_observer)
else: # else:
if profile.is_system_profile(): # if profile.is_system_profile():
if system_uses_wireguard_interface() and SystemStateController.exists(): # if system_uses_wireguard_interface() and SystemStateController.exists():
try: # try:
terminate_system_connection() # terminate_system_connection()
except ConnectionTerminationError: # except ConnectionTerminationError:
pass # pass
raise MissingSubscriptionError() # raise MissingSubscriptionError()
if profile.is_session_profile(): # if profile.is_session_profile():
try: # try:
return ConnectionController.establish_session_connection(profile, ignore=ignore, connection_observer=connection_observer) # return ConnectionController.establish_session_connection(profile, ignore=ignore, connection_observer=connection_observer)
except ConnectionError: # except ConnectionError:
if ConnectionController.__should_renegotiate(profile): # if ConnectionController.__should_renegotiate(profile):
ProfileController.register_wireguard_session(profile, connection_observer=connection_observer) # ProfileController.register_wireguard_session(profile, connection_observer=connection_observer)
return ConnectionController.establish_session_connection(profile, ignore=ignore, connection_observer=connection_observer) # return ConnectionController.establish_session_connection(profile, ignore=ignore, connection_observer=connection_observer)
else: # else:
raise ConnectionError('The connection could not be established.') # raise ConnectionError('The connection could not be established.')
if profile.is_system_profile(): # if profile.is_system_profile():
try: # try:
return establish_system_connection(profile, ignore=ignore, connection_observer=connection_observer) # return establish_system_connection(profile, ignore=ignore, connection_observer=connection_observer)
except ConnectionError: # except ConnectionError:
if ConnectionController.__should_renegotiate(profile): # if ConnectionController.__should_renegotiate(profile):
ProfileController.register_wireguard_session(profile, connection_observer=connection_observer) # ProfileController.register_wireguard_session(profile, connection_observer=connection_observer)
return establish_system_connection(profile, ignore=ignore, connection_observer=connection_observer) # return establish_system_connection(profile, ignore=ignore, connection_observer=connection_observer)
else: # else:
raise ConnectionError('The connection could not be established.') # raise ConnectionError('The connection could not be established.')
return None # return None
@staticmethod @staticmethod
def establish_session_connection(profile: SessionProfile, ignore: tuple[type[Exception]] = (), connection_observer: Optional[ConnectionObserver] = None): def establish_session_connection(profile: SessionProfile, ignore: tuple[type[Exception]] = (), connection_observer: Optional[ConnectionObserver] = None):
@ -158,6 +159,7 @@ class ConnectionController:
if not ConnectionUnprotectedError in ignore: if not ConnectionUnprotectedError in ignore:
raise ConnectionUnprotectedError('Connection unprotected while the system is not using a WireGuard interface.') raise ConnectionUnprotectedError('Connection unprotected while the system is not using a WireGuard interface.')
else: else:
from core.controllers.ProfileController import ProfileController
ProfileController.disable(profile) ProfileController.disable(profile)
if profile.connection.code == 'tor': if profile.connection.code == 'tor':
@ -509,15 +511,15 @@ class ConnectionController:
# raise ConnectionError('The connection could not be established.') # raise ConnectionError('The connection could not be established.')
@staticmethod # @staticmethod
def __should_renegotiate(profile: Union[SessionProfile, SystemProfile]): # def __should_renegotiate(profile: Union[SessionProfile, SystemProfile]):
if not profile.has_subscription(): # if not profile.has_subscription():
raise MissingSubscriptionError() # raise MissingSubscriptionError()
if profile.connection.needs_wireguard_configuration() and profile.has_wireguard_configuration(): # if profile.connection.needs_wireguard_configuration() and profile.has_wireguard_configuration():
if profile.subscription.has_been_activated(): # if profile.subscription.has_been_activated():
return True # return True
return False # return False

View file

@ -1,6 +1,6 @@
from core.services.networking.systemwide.systemwide_wireguard import terminate_system_connection from core.services.networking.systemwide.systemwide_wireguard import terminate_system_connection
from core.services.networking.general_connection_tools.testing_evaluating import system_uses_wireguard_interface from core.services.networking.general_connection_tools.testing_evaluating import system_uses_wireguard_interface
from core.services.verification.endpoint_verification import verify_wireguard_endpoint from core.services.networking.general_connection_tools.connection_enable import establish_connection
from core.Errors import InvalidSubscriptionError, MissingSubscriptionError, ConnectionTerminationError, ProfileActivationError, ProfileDeactivationError, MissingLocationError, ConnectionUnprotectedError, EndpointVerificationError, ProfileStateConflictError from core.Errors import InvalidSubscriptionError, MissingSubscriptionError, ConnectionTerminationError, ProfileActivationError, ProfileDeactivationError, MissingLocationError, ConnectionUnprotectedError, EndpointVerificationError, ProfileStateConflictError
from core.controllers.ApplicationController import ApplicationController from core.controllers.ApplicationController import ApplicationController
@ -41,20 +41,31 @@ class ProfileController:
@staticmethod @staticmethod
def enable(profile: Union[SessionProfile, SystemProfile], ignore: tuple[type[Exception]] = (), pristine: bool = False, asynchronous: bool = False, profile_observer: ProfileObserver = None, application_version_observer: ApplicationVersionObserver = None, connection_observer: ConnectionObserver = None): def enable(
profile: Union[SessionProfile, SystemProfile],
ignore: tuple[type[Exception]] = (),
pristine: bool = False,
asynchronous: bool = False,
profile_observer: ProfileObserver = None,
application_version_observer: ApplicationVersionObserver = None,
connection_observer: ConnectionObserver = None):
from core.controllers.ConnectionController import ConnectionController from core.controllers.ConnectionController import ConnectionController
# =========== ALREADY ENABLED ============
if ProfileController.is_enabled(profile): if ProfileController.is_enabled(profile):
if not ProfileStateConflictError in ignore: if not ProfileStateConflictError in ignore:
raise ProfileStateConflictError('The profile is already enabled or its session was not properly terminated.') raise ProfileStateConflictError('The profile is already enabled or its session was not properly terminated.')
else: else:
ProfileController.disable(profile) ProfileController.disable(profile)
# =========== PRISTINE ============
if pristine: if pristine:
profile.delete_data() profile.delete_data()
# ============================================================================
# SESSION
# ============================================================================
if profile.is_session_profile(): if profile.is_session_profile():
application_version = profile.application_version application_version = profile.application_version
@ -63,7 +74,7 @@ class ProfileController:
ApplicationVersionController.install(application_version, application_version_observer=application_version_observer, connection_observer=connection_observer) ApplicationVersionController.install(application_version, application_version_observer=application_version_observer, connection_observer=connection_observer)
try: try:
port_number = ConnectionController.establish_connection(profile, ignore=ignore, connection_observer=connection_observer) port_number = establish_connection(profile, ignore=ignore, connection_observer=connection_observer)
except ConnectionError: except ConnectionError:
raise ProfileActivationError('The profile could not be enabled.') raise ProfileActivationError('The profile could not be enabled.')
@ -72,10 +83,12 @@ class ProfileController:
ApplicationController.launch(application_version, profile, port_number, asynchronous=asynchronous, profile_observer=profile_observer) ApplicationController.launch(application_version, profile, port_number, asynchronous=asynchronous, profile_observer=profile_observer)
# ============================================================================
# SYSTEMWIDE
# ============================================================================
if profile.is_system_profile(): if profile.is_system_profile():
try: try:
ConnectionController.establish_connection(profile, ignore=ignore, connection_observer=connection_observer) establish_connection(profile, ignore=ignore, connection_observer=connection_observer)
except ConnectionError: except ConnectionError:
raise ProfileActivationError('The profile could not be enabled.') raise ProfileActivationError('The profile could not be enabled.')
@ -215,28 +228,28 @@ class ProfileController:
def has_proxy_configuration(profile: Union[SessionProfile, SystemProfile]): def has_proxy_configuration(profile: Union[SessionProfile, SystemProfile]):
profile.has_proxy_configuration() profile.has_proxy_configuration()
@staticmethod # @staticmethod
def register_wireguard_session(profile: Union[SessionProfile, SystemProfile], connection_observer: Optional[ConnectionObserver] = None): # def register_wireguard_session(profile: Union[SessionProfile, SystemProfile], connection_observer: Optional[ConnectionObserver] = None):
from core.controllers.ConnectionController import ConnectionController # from core.controllers.ConnectionController import ConnectionController
if not profile.has_subscription(): # if not profile.has_subscription():
raise MissingSubscriptionError() # raise MissingSubscriptionError()
if not profile.has_location(): # if not profile.has_location():
raise MissingLocationError() # raise MissingLocationError()
wireguard_keys = ProfileController.__generate_wireguard_keys() # wireguard_keys = ProfileController.__generate_wireguard_keys()
wireguard_configuration = ConnectionController.with_preferred_connection(profile.location.country_code, profile.location.code, profile.subscription.billing_code, wireguard_keys.get('public'), task=WebServiceApiService.post_wireguard_session, connection_observer=connection_observer) # wireguard_configuration = ConnectionController.with_preferred_connection(profile.location.country_code, profile.location.code, profile.subscription.billing_code, wireguard_keys.get('public'), task=WebServiceApiService.post_wireguard_session, connection_observer=connection_observer)
if wireguard_configuration is None: # if wireguard_configuration is None:
raise InvalidSubscriptionError() # raise InvalidSubscriptionError()
expression = re.compile(r'^(PrivateKey =)\s?$', re.MULTILINE) # expression = re.compile(r'^(PrivateKey =)\s?$', re.MULTILINE)
wireguard_configuration = re.sub(expression, r'\1 ' + wireguard_keys.get('private'), wireguard_configuration) # wireguard_configuration = re.sub(expression, r'\1 ' + wireguard_keys.get('private'), wireguard_configuration)
profile.attach_wireguard_configuration(wireguard_configuration) # profile.attach_wireguard_configuration(wireguard_configuration)
@staticmethod @staticmethod
def get_wireguard_configuration_path(profile: Union[SessionProfile, SystemProfile]): def get_wireguard_configuration_path(profile: Union[SessionProfile, SystemProfile]):
@ -288,23 +301,23 @@ class ProfileController:
# except Exception: # except Exception:
# raise EndpointVerificationError('The WireGuard endpoint could not be verified.') # raise EndpointVerificationError('The WireGuard endpoint could not be verified.')
@staticmethod # @staticmethod
def __generate_wireguard_keys(): # def __generate_wireguard_keys():
from cryptography.hazmat.primitives import serialization # from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey # from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
raw_private_key = X25519PrivateKey.generate() # raw_private_key = X25519PrivateKey.generate()
public_key = raw_private_key.public_key().public_bytes( # public_key = raw_private_key.public_key().public_bytes(
encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw # encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw
) # )
private_key = raw_private_key.private_bytes( # private_key = raw_private_key.private_bytes(
encoding=serialization.Encoding.Raw, format=serialization.PrivateFormat.Raw, encryption_algorithm=serialization.NoEncryption() # encoding=serialization.Encoding.Raw, format=serialization.PrivateFormat.Raw, encryption_algorithm=serialization.NoEncryption()
) # )
return dict( # return dict(
private=base64.b64encode(private_key).decode(), # private=base64.b64encode(private_key).decode(),
public=base64.b64encode(public_key).decode() # public=base64.b64encode(public_key).decode()
) # )

View file

@ -0,0 +1,66 @@
from core.models.session.SessionProfile import SessionProfile
from core.models.system.SystemProfile import SystemProfile
from core.Errors import MissingSubscriptionError, MissingLocationError, InvalidSubscriptionError
from core.services.WebServiceApiService import WebServiceApiService
from core.controllers.ConnectionController import ConnectionController
from core.observers.ConnectionObserver import ConnectionObserver
from typing import Union, Optional
import base64
import re
def register_wireguard_session(
profile: Union[SessionProfile, SystemProfile],
connection_observer: Optional[ConnectionObserver] = None
):
"""Register a WireGuard session for the given profile."""
if not profile.has_subscription():
raise MissingSubscriptionError()
if not profile.has_location():
raise MissingLocationError()
wireguard_keys = _generate_wireguard_keys()
wireguard_configuration = ConnectionController.with_preferred_connection(
profile.location.country_code,
profile.location.code,
profile.subscription.billing_code,
wireguard_keys.get('public'),
task=WebServiceApiService.post_wireguard_session,
connection_observer=connection_observer
)
if wireguard_configuration is None:
raise InvalidSubscriptionError()
wireguard_configuration = _inject_private_key(wireguard_configuration, wireguard_keys.get('private'))
profile.attach_wireguard_configuration(wireguard_configuration)
def _generate_wireguard_keys() -> dict:
"""Generate WireGuard public/private key pair."""
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
raw_private_key = X25519PrivateKey.generate()
public_key = raw_private_key.public_key().public_bytes(
encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw
)
private_key = raw_private_key.private_bytes(
encoding=serialization.Encoding.Raw, format=serialization.PrivateFormat.Raw, encryption_algorithm=serialization.NoEncryption()
)
return dict(
private=base64.b64encode(private_key).decode(),
public=base64.b64encode(public_key).decode()
)
def _inject_private_key(config: str, private_key: str) -> str:
"""Inject private key into WireGuard config."""
expression = re.compile(r'^(PrivateKey =)\s?$', re.MULTILINE)
return re.sub(expression, r'\1 ' + private_key, config)

View file

@ -0,0 +1,129 @@
from core.services.networking.general_connection_tools.testing_evaluating import system_uses_wireguard_interface
from core.services.networking.systemwide.systemwide_wireguard import establish_system_connection, terminate_system_connection
from core.services.keys_and_verifications.wireguard_keys import register_wireguard_session
from core.models.session.SessionConnection import SessionConnectionTypes
from core.models.system.SystemConnection import SystemConnectionTypes
from core.errors.logger import logger
from core.errors.exceptions import *
from typing import Union, Optional, Callable
from core.models.session.SessionProfile import SessionProfile
from core.models.system.SystemProfile import SystemProfile
from core.Errors import ConnectionTerminationError, InvalidSubscriptionError
from core.services.WebServiceApiService import WebServiceApiService
from core.controllers.ConnectionController import ConnectionController
from core.models.BaseProfile import ProfileType
from core.services.subscriptions.subscriptions import activate_subscription
from core.observers.ConnectionObserver import ConnectionObserver
from core.controllers.SystemStateController import SystemStateController
wireguard_types = [SystemConnectionTypes.WIREGUARD, SessionConnectionTypes.WIREGUARD]
def establish_connection(
profile: Union[SessionProfile, SystemProfile],
ignore: tuple[type[Exception]] = (),
connection_observer: Optional[ConnectionObserver] = None,
):
"""Establish a connection for the given profile."""
logger.info(f"[CONNECTION] Checking subscription..")
_ensure_subscription_ready(profile, connection_observer)
logger.info(f"[CONNECTION] Checking proxy configuration..")
_ensure_proxy_configured(profile, connection_observer)
logger.info(f"[CONNECTION] Checking Wireguard configuration..")
_ensure_wireguard_configured(profile, connection_observer)
establish_fn = {
ProfileType.SESSION: ConnectionController.establish_session_connection,
ProfileType.SYSTEM: establish_system_connection,
}[profile.type]
return _establish_with_renegotiation(profile, establish_fn, ignore, connection_observer)
def _ensure_subscription_ready(
profile: Union[SessionProfile, SystemProfile],
connection_observer: Optional[ConnectionObserver],
):
"""Activate subscription (idempotent)."""
activate_subscription(profile, connection_observer=connection_observer)
def _ensure_proxy_configured(
profile: Union[SessionProfile, SystemProfile],
connection_observer: Optional[ConnectionObserver],
):
"""Setup proxy config if needed."""
if not profile.connection.needs_proxy_configuration():
return
_ensure_subscription_ready(profile, connection_observer)
proxy_config = ConnectionController.with_preferred_connection(
profile.subscription.billing_code,
task=WebServiceApiService.get_proxy_configuration,
connection_observer=connection_observer
)
if proxy_config is None:
raise InvalidSubscriptionError()
profile.attach_proxy_configuration(proxy_config)
def _ensure_wireguard_configured(
profile: Union[SessionProfile, SystemProfile],
connection_observer: Optional[ConnectionObserver],
):
"""Setup WireGuard config if needed."""
logger.info(f"[CONNECTION] Checking if this profile needs a wg config. The profile.connection.code is {profile.connection.code}")
if profile.connection.code not in wireguard_types:
logger.info(f"[CONNECTION] This profile {profile.id} does NOT need a wireguard config")
return
if profile.type == ProfileType.SYSTEM:
if system_uses_wireguard_interface() and SystemStateController.exists():
logger.info(f"[CONNECTION] There is a systemwide profile that is already is active.")
try:
terminate_system_connection()
except ConnectionTerminationError as e:
logger.error(f"[CONNECTION] Previous Systemwide Wireguard connection could not be disabled. {e}")
_ensure_subscription_ready(profile, connection_observer)
logger.info(f"[CONNECTION] Checking if the profile already has a wg config..")
if not profile.has_wireguard_configuration():
logger.info(f"[CONNECTION] Profile does NOT have WG keys and it needs it. Registering a NEW wg session..")
register_wireguard_session(profile, connection_observer=connection_observer)
def _establish_with_renegotiation(
profile: Union[SessionProfile, SystemProfile],
establish_fn: Callable,
ignore: tuple[type[Exception]],
connection_observer: Optional[ConnectionObserver],
):
"""Attempt connection, renegotiate WireGuard once if needed."""
try:
logger.info(f"[CONNECTION] Connecting..")
return establish_fn(profile, ignore=ignore, connection_observer=connection_observer)
except ConnectionError:
if __should_renegotiate(profile):
logger.info(f"[CONNECTION] Renegotiating a new wg key session with API..")
register_wireguard_session(profile, connection_observer=connection_observer)
return establish_fn(profile, ignore=ignore, connection_observer=connection_observer)
raise ConnectionError('The connection could not be established.')
def __should_renegotiate(profile: Union[SessionProfile, SystemProfile]):
if not profile.has_subscription():
raise MissingSubscriptionError()
if profile.connection.code in wireguard_types and profile.has_wireguard_configuration():
if profile.subscription.has_been_activated():
return True
else:
return False

View file

@ -1,23 +1,7 @@
# from core.errors.exceptions import *
# from core.errors.logger import logger
# from collections.abc import Callable
from core.Constants import Constants from core.Constants import Constants
from core.Errors import CommandNotFoundError from core.Errors import CommandNotFoundError
# from core.controllers.ConfigurationController import ConfigurationController
# from core.controllers.ProfileController import ProfileController
# from core.controllers.SessionStateController import SessionStateController
# from core.controllers.SystemStateController import SystemStateController
# from core.models.BaseProfile import ProfileType
# from core.models.session.SessionProfile import SessionProfile
# from core.models.system.SystemProfile import SystemProfile
# from core.models.system.SystemState import SystemState
from core.observers.ConnectionObserver import ConnectionObserver from core.observers.ConnectionObserver import ConnectionObserver
# from core.services.WebServiceApiService import WebServiceApiService
from essentials.modules.TorModule import TorModule from essentials.modules.TorModule import TorModule
# from essentials.services.ConnectionService import ConnectionService
# from pathlib import Path
# from subprocess import CalledProcessError
from typing import Optional from typing import Optional
import os import os
import random import random
@ -25,7 +9,6 @@ import re
import shutil import shutil
import subprocess import subprocess
import sys import sys
# import tempfile
import time import time
@ -105,7 +88,7 @@ def __test_connection(port_number: Optional[int] = None, timeout: float = 4.0):
raise ConnectionError('The connection could not be established.') raise ConnectionError('The connection could not be established.')
# Kept a duplicate in connection controller # Kept a duplicate in connection controller, because Tor uses it. and circular imports are an issue for now. Refactor later.
def get_proxies(port_number: int): def get_proxies(port_number: int):
return dict( return dict(

View file

@ -1,35 +1,21 @@
from core.services.networking.general_connection_tools.testing_evaluating import await_connection, system_uses_wireguard_interface, terminate_tor_connection from core.services.networking.general_connection_tools.testing_evaluating import await_connection, system_uses_wireguard_interface, terminate_tor_connection
from core.services.verification.endpoint_verification import verify_wireguard_endpoint from core.services.keys_and_verifications.endpoint_verification import verify_wireguard_endpoint
# from core.errors.exceptions import *
# from core.errors.logger import logger
# from collections.abc import Callable
from core.Constants import Constants from core.Constants import Constants
from core.Errors import ConnectionTerminationError, CommandNotFoundError from core.Errors import ConnectionTerminationError, CommandNotFoundError
from core.controllers.ConfigurationController import ConfigurationController from core.controllers.ConfigurationController import ConfigurationController
# from core.controllers.ProfileController import ProfileController
# from core.controllers.SessionStateController import SessionStateController
from core.controllers.SystemStateController import SystemStateController from core.controllers.SystemStateController import SystemStateController
from core.models.BaseProfile import ProfileType from core.models.BaseProfile import ProfileType
from core.models.session.SessionProfile import SessionProfile from core.models.session.SessionProfile import SessionProfile
from core.models.system.SystemProfile import SystemProfile from core.models.system.SystemProfile import SystemProfile
from core.models.system.SystemState import SystemState from core.models.system.SystemState import SystemState
from core.observers.ConnectionObserver import ConnectionObserver from core.observers.ConnectionObserver import ConnectionObserver
# from core.services.WebServiceApiService import WebServiceApiService
# from essentials.modules.TorModule import TorModule
# from essentials.services.ConnectionService import ConnectionService
# from pathlib import Path
from subprocess import CalledProcessError from subprocess import CalledProcessError
from typing import Optional from typing import Optional
import os import os
# import random
import re import re
import shutil import shutil
import subprocess import subprocess
# import sys
# import tempfile
import time import time
def terminate_system_connection(): def terminate_system_connection():

View file

@ -0,0 +1,61 @@
from typing import Union, Optional
from core.models.session.SessionProfile import SessionProfile
from core.models.system.SystemProfile import SystemProfile
from core.Errors import MissingSubscriptionError, InvalidSubscriptionError
from core.services.WebServiceApiService import WebServiceApiService
from core.controllers.ConnectionController import ConnectionController
from core.observers.ConnectionObserver import ConnectionObserver
def activate_subscription(
profile: Union[SessionProfile, SystemProfile],
connection_observer: Optional[ConnectionObserver] = None
) -> bool:
"""
Purpose:
Ensure subscription is ready.
Features:
Idempotent.
Checks local first
Confusion:
This returns True both if was already active or just activated.
Returns:
Returns True if subscription was already active.
Returns True if subscription was just activated.
Errors:
True.
Raises if subscription is missing or invalid. (not false)
"""
if not profile.has_subscription():
raise MissingSubscriptionError()
# Already activated—nothing to do
if profile.subscription.has_been_activated():
return True
# Fetch and activate
subscription = ConnectionController.with_preferred_connection(
profile.subscription.billing_code,
task=WebServiceApiService.get_subscription,
connection_observer=connection_observer
)
if subscription is None:
raise InvalidSubscriptionError()
profile.subscription = subscription
profile.save()
return True
def is_subscription_ready(profile: Union[SessionProfile, SystemProfile]) -> bool:
"""Check if subscription exists and is activated (no side effects)."""
return (
profile.has_subscription()
and profile.subscription.has_been_activated()
)

View file

@ -1,6 +1,6 @@
[project] [project]
name = "sp-hydra-veil-core" name = "sp-hydra-veil-core"
version = "2.4.1" version = "2.4.2"
authors = [ authors = [
{ name = "Simplified Privacy" }, { name = "Simplified Privacy" },
] ]