From 5023b0992805029048e4244138877891530eba91 Mon Sep 17 00:00:00 2001 From: SimplifiedPrivacy Date: Sat, 17 Oct 2026 17:13:42 -0400 Subject: [PATCH] Isolated error translation to it's own module. Finality to ticket payments and the ticket prep changing the Config --- core/errors/translate_error.py | 81 +++++++++++++++++++ core/services/payment_phase/payment_state.py | 25 +++++- .../payment_phase/payment_update_tools.py | 1 - .../ticket_prep_orchestrator.py | 9 ++- .../subscriptions_by_protocol.py | 7 +- 5 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 core/errors/translate_error.py diff --git a/core/errors/translate_error.py b/core/errors/translate_error.py new file mode 100644 index 0000000..6f0c85b --- /dev/null +++ b/core/errors/translate_error.py @@ -0,0 +1,81 @@ +from core.controllers.ConfigurationController import ConfigurationController +from core.models.Result import Result, ResultError +from core.errors.logger import logger +from core.Errors import ( + CommandNotFoundError, EndpointVerificationError, FileIntegrityError, + InvalidSubscriptionError, MissingSubscriptionError, ProfileActivationError, + ProfileModificationError, ProfileStateConflictError, UnsupportedApplicationVersionError, +) + + +from typing import Type, Optional + +ERROR_TO_UI_MESSAGE = { + ProfileActivationError: "The profile could not be enabled", + UnsupportedApplicationVersionError: "The application version in question is not supported", + FileIntegrityError: "Application version file integrity could not be verified.", + ProfileModificationError: "WireGuard configuration could not be attached.", +} + + +def translate_error(error: Type[Exception], profile_id: int) -> Result: + """Translate legacy core errors into actions and/or messages via Result Objects.""" + logger.error(str(error)) + + #---------------------- + # PURE MESSAGES (NO SOLUTION FUNCTION) + #---------------------- + if error in ERROR_TO_UI_MESSAGE: + error_msg = ERROR_TO_UI_MESSAGE[error] + return Result(valid=False, error_type=ResultError.UNKNOWN, message=error_msg) + + #---------------------- + # ENDPOINT VERIFICATION + #---------------------- + if isinstance(error, EndpointVerificationError): + return Result(valid=False, error_type=ResultError.ENDPOINT_VERIFICATION, message="Operator verification failed. Do you want to continue anyway?") + + #---------------------- + # STATE CONFLICT + #---------------------- + if isinstance(error, ProfileStateConflictError): + # function_choice = literally_connect( + # profile_id=profile_id, + # ignore_state_conflict=True + # ) + error_msg = "The profile is already enabled. Do you want to force enable it anyway?" + return Result(valid=False, error_type=ResultError.STATE_CONFLICT, message=error_msg) + + #---------------------- + # SUBSCRIPTION + #---------------------- + if isinstance(error, (InvalidSubscriptionError, MissingSubscriptionError)): + error_msg = f"Subscription missing or invalid for profile {profile_id}. Do you want to get a new sub?" + return Result(valid=False, error_type=ResultError.SUBSCRIPTION, message=error_msg) + + #---------------------- + # COMMAND NOT FOUND + #---------------------- + if isinstance(error, CommandNotFoundError): + # add install later!! + name_of_package = str(error.subject) + error_msg = f"You're missing the {name_of_package} package. Please install it." + return Result(valid=False, error_type=ResultError.MISSING_SOFTWARE, message=error_msg) + + else: + return Result(valid=False, error_type=ResultError.UNKNOWN, message="An unknown error occured.") + + + +def get_ignored_exceptions(ignore_state_conflict: Optional[bool] = False): + ignored_as_list = [] + endpoint_verification_enabled = ConfigurationController.get_endpoint_verification_enabled() + + if endpoint_verification_enabled: + ignored_as_list.append(EndpointVerificationError) + + if ignore_state_conflict: + ignored_as_list.append(ProfileStateConflictError) + + ignored = tuple(ignored_as_list) + return ignored diff --git a/core/services/payment_phase/payment_state.py b/core/services/payment_phase/payment_state.py index d2cf9ff..728fc29 100644 --- a/core/services/payment_phase/payment_state.py +++ b/core/services/payment_phase/payment_state.py @@ -1,4 +1,5 @@ from core.models.manage.validate_dataclass import ValidatedDataclass +from core.utils.file_tools import delete_file from core.Constants import Constants from core.models.enum_models import Currency, ProtocolChoice, PaymentType, PaymentCategory from core.errors.logger import logger @@ -129,6 +130,16 @@ class StatePersistenceMixin(ValidatedDataclass): setattr(self, field.name, value) + def wipe_data_on_disk(self): + logger.info("Starting wipe of pre-existing data") + + if not os.path.exists(self._data_file): + logger.info("File does NOT exist already") + return + + return delete_file(self._data_file) + + def exists_already(self) -> bool: return os.path.exists(self._data_file) @@ -163,6 +174,16 @@ class TicketPaymentData(StatePersistenceMixin): self.load() + def wipe(self): + """Wipe all data and start over.""" + wiped = self.wipe_data_on_disk() + self.currency = None + self.which_key = None + self.how_many_profiles = 6 + self.billing_code = None + self.use_random = False + self.paid = False + sefl.billing_pending = True @singleton @@ -192,8 +213,7 @@ class PaymentData(StatePersistenceMixin): logger.info(f"full path of self._data_file {self._data_file}") - self.load() - + self.load() @singleton @dataclass @@ -221,4 +241,3 @@ class OverallPaymentCycle(): self.profile_id = None self.got_invoice = None self.billing_code = None - diff --git a/core/services/payment_phase/payment_update_tools.py b/core/services/payment_phase/payment_update_tools.py index 606cc79..14b1ba2 100644 --- a/core/services/payment_phase/payment_update_tools.py +++ b/core/services/payment_phase/payment_update_tools.py @@ -57,7 +57,6 @@ def mark_as_paid() -> Result: billing_data.billing_pending = False billing_data.paid = True billing_data.save() - else: return not_supported() diff --git a/core/services/prepare_tickets/ticket_prep_orchestrator.py b/core/services/prepare_tickets/ticket_prep_orchestrator.py index 24dcfba..6380947 100644 --- a/core/services/prepare_tickets/ticket_prep_orchestrator.py +++ b/core/services/prepare_tickets/ticket_prep_orchestrator.py @@ -13,6 +13,8 @@ from core.services.prepare_tickets.send_blind_commitments import send_blind_comm from core.services.prepare_tickets.validate_blind_signatures import validate_blind_signatures from core.services.prepare_tickets.save_ALL_blind_sigs import save_ALL_blind_sigs from core.utils.basic_operations.does_file_exist import does_file_exist +from core.models.ConfigurationController import ConfigurationController + # errors & constants from core.Constants import Constants from core.errors.exceptions import MissingData, CriticalFailure @@ -151,13 +153,18 @@ def ticket_prep_orchestrator( ) ##################################################### - # TICKET TRACKER + # TICKET TRACKER & APP-WIDE CONFIG ##################################################### if not does_file_exist(Constants.TICKET_TRACKER_PATH): setup_tracker = setup_ticket_tracker(how_many_profiles) if not setup_tracker: return {"valid": False, "message": "failed"} + # saving on config that it's setup: + config_marked = ConfigurationController.mark_as_paid(True) + if not config_marked: + return {'valid': False, 'message': 'file_system'} + ##################################################### # FINAL EVALUATION ##################################################### diff --git a/core/services/subscriptions/subscriptions_by_protocol.py b/core/services/subscriptions/subscriptions_by_protocol.py index 6f393bc..99bf2eb 100644 --- a/core/services/subscriptions/subscriptions_by_protocol.py +++ b/core/services/subscriptions/subscriptions_by_protocol.py @@ -134,8 +134,7 @@ def start_new_payment_cycle(category: PaymentCategory, profile_id: Optional[int] return Result(valid=True, data=payment_cycle) if category == PaymentCategory.INDIVIDUAL: - # Let evaluate_repeat_cycle handle the profile_id comparison - # and the specific "same user" vs "different user" Result errors. + # evaluate if it's the same user: return evaluate_repeat_cycle(payment_cycle=payment_cycle, profile_id=profile_id) # 3. Collision Check (The "Prompt" Logic) @@ -572,3 +571,7 @@ def return_pre_existing_payment_data(profile_id: int, subscription: Subscription logger.error(error_msg) return Result(valid=False, message=error_msg, error_type=ResultError.INVALID_INPUT) + +def evaluate_ticketing(): + setup = ConfigurationController.are_tickets_setup() + \ No newline at end of file