sp-hydra-veil-core/core/controllers/ProfileController.py

158 lines
6.4 KiB
Python

from core.services.profiles.ProfileRepository import ProfileRepository
# 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.connection_enable import establish_connection
# from core.services.networking.systemwide.systemwide_utils import get_firewall_setting, get_dns_setting
# from core.services.networking.systemwide.encrypted_proxy.singbox_runner import end_singbox
# from core.services.networking.systemwide import killswitch
from core.services.subscriptions import subscriptions
# from core.errors.exceptions import FirewallError
from core.models.Result import Result, ResultError
# from core.observers.TicketObserver import TicketObserver
# from core.services.assassin.ticket_respawn import respawn_profile
# from core.services.assassin import assassin_tools
from core.errors.logger import logger
from core.Errors import InvalidSubscriptionError, MissingSubscriptionError
#, ConnectionTerminationError, ProfileActivationError, ProfileDeactivationError, MissingLocationError, ConnectionUnprotectedError, EndpointVerificationError, ProfileStateConflictError
# from core.controllers.ApplicationController import ApplicationController
# from core.controllers.ApplicationVersionController import ApplicationVersionController
# from core.controllers.SessionStateController import SessionStateController
# from core.controllers.SystemStateController import SystemStateController
from core.models.BaseProfile import BaseProfile as Profile
from core.models.Subscription import Subscription
from core.models.session.SessionProfile import SessionProfile
from core.models.system.SystemProfile import SystemProfile
from core.observers.ApplicationVersionObserver import ApplicationVersionObserver
from core.observers.ConnectionObserver import ConnectionObserver
from core.observers.ProfileObserver import ProfileObserver
from core.services.WebServiceApiService import WebServiceApiService
from typing import Union, Optional
import base64
import re
import time
class ProfileController:
# Initialize the singleton repository
_repo = ProfileRepository()
@staticmethod
def get(id: int) -> Union[SessionProfile, SystemProfile, None]:
# Controller no longer talks to the Model; it talks to the Repo
return ProfileController._repo.get(id)
@staticmethod
def get_all():
return ProfileController._repo.get_all()
@staticmethod
def create(profile: Union[SessionProfile, SystemProfile], profile_observer: ProfileObserver = None):
# Call the helper with the 'created' event
ProfileController._save_and_sync(profile, 'created', profile_observer)
@staticmethod
def update(profile: Union[SessionProfile, SystemProfile], profile_observer: ProfileObserver = None):
# Call the helper with the 'updated' event
ProfileController._save_and_sync(profile, 'updated', profile_observer)
@staticmethod
def _save_and_sync(profile, event_type: str, observer: ProfileObserver = None):
"""Private helper to handle the actual persistence and cache synchronization."""
# 1. Persist to disk
profile.save()
# 2. update cache to prevent drift
ProfileController._repo.update_cache(profile)
# 3. Notify observer
if observer is not None:
observer.notify(event_type, profile)
@staticmethod
def delete(profile: Union[SessionProfile, SystemProfile], profile_observer: ProfileObserver = None):
"""Remove the profile from both disk and cache"""
# 1. Save to temp variable:
profile_id = profile.id
# 2. Permanently delete from disk
profile.delete()
# 3. update cache with the temp variable to prevent drift
ProfileController._repo.invalidate(profile_id=profile_id)
@staticmethod
def attach_subscription(profile: Union[SessionProfile, SystemProfile], subscription: Subscription):
profile.subscription = subscription
profile.save()
@staticmethod
def activate_subscription(profile: Union[SessionProfile, SystemProfile], connection_observer: Optional[ConnectionObserver] = None):
from core.controllers.ConnectionController import ConnectionController
if profile.has_subscription():
subscription = subscriptions.get_subscription(
billing_code=profile.subscription.billing_code,
connection_observer=connection_observer
)
# legacy:
# subscription = ConnectionController.with_preferred_connection(profile.subscription.billing_code, task=WebServiceApiService.get_subscription, connection_observer=connection_observer)
if subscription is not None:
profile.subscription = subscription
profile.save()
else:
raise InvalidSubscriptionError()
else:
raise MissingSubscriptionError()
@staticmethod
def get_invoice(profile: Union[SessionProfile, SystemProfile]):
if profile.has_subscription():
# return subscriptions.get_invoice(billing_code=profile.subscription.billing_code)
return WebServiceApiService.get_invoice(profile.subscription.billing_code)
else:
return None
@staticmethod
def attach_proxy_configuration(profile: Union[SessionProfile, SystemProfile]):
if profile.is_session_profile() and profile.has_subscription():
proxy_configuration = WebServiceApiService.get_proxy_configuration(profile.subscription.billing_code)
if proxy_configuration is not None:
profile.attach_proxy_configuration(proxy_configuration)
@staticmethod
def get_proxy_configuration(profile: Union[SessionProfile, SystemProfile]):
if profile.is_session_profile():
return profile.get_proxy_configuration()
else:
return None
@staticmethod
def has_proxy_configuration(profile: Union[SessionProfile, SystemProfile]):
profile.has_proxy_configuration()
@staticmethod
def get_wireguard_configuration_path(profile: Union[SessionProfile, SystemProfile]):
return profile.get_wireguard_configuration_path()
@staticmethod
def has_wireguard_configuration(profile: Union[SessionProfile, SystemProfile]):
return profile.has_wireguard_configuration()