Refactor of Ticket flow. Stable to get confirmed Result via CLI. Not yet GUI
This commit is contained in:
parent
8dca35d5c9
commit
bf9063b1f8
12 changed files with 723 additions and 457 deletions
|
|
@ -18,11 +18,14 @@ class Constants:
|
|||
|
||||
# ticketing group:
|
||||
TICKET_API_BASE_URL: Final[str] = os.environ.get(
|
||||
"TICKET_API_BASE_URL", "https://api.hydraveil.net"
|
||||
# "TICKET_API_BASE_URL", "https://api.hydraveil.net"
|
||||
"TICKET_API_BASE_URL", "http://localhost:8000"
|
||||
)
|
||||
|
||||
SP_API_BASE_URL: Final[str] = os.environ.get('SP_API_BASE_URL', 'https://api.hydraveil.net/api/v1')
|
||||
SP_BASE_URL: Final[str] = os.environ.get('SP_BASE_URL', 'https://api.hydraveil.net/api')
|
||||
SP_API_BASE_URL: Final[str] = os.environ.get('SP_API_BASE_URL', 'http://localhost:8000/api/v1')
|
||||
SP_BASE_URL: Final[str] = os.environ.get('SP_BASE_URL', 'http://localhost:8000/api')
|
||||
# SP_API_BASE_URL: Final[str] = os.environ.get('SP_API_BASE_URL', 'https://api.hydraveil.net/api/v1')
|
||||
# SP_BASE_URL: Final[str] = os.environ.get('SP_BASE_URL', 'https://api.hydraveil.net/api')
|
||||
|
||||
PING_URL: Final[str] = os.environ.get('PING_URL', 'https://api.hydraveil.net/api/v1/health')
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ if TYPE_CHECKING:
|
|||
from core.essentials.observers.ConnectionObserver import ConnectionObserver
|
||||
from core.observers.TicketObserver import TicketObserver
|
||||
#
|
||||
from core.services.prepare_tickets.get_public_key_by_config import (
|
||||
get_public_key_from_LOCAL_files_only,
|
||||
)
|
||||
# from core.services.prepare_tickets.get_public_key_by_config import (
|
||||
# get_public_key_from_LOCAL_files_only,
|
||||
# )
|
||||
from core.services.failed_verification.is_the_key_to_blame import is_the_key_to_blame
|
||||
from core.services.failed_verification.prep_with_previously_saved_blind_sigs import (
|
||||
prep_with_previously_saved_blind_sigs,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.essentials.observers.ConnectionObserver import ConnectionObserver
|
||||
from core.observers.ConnectionObserver import ConnectionObserver
|
||||
from core.observers.TicketObserver import TicketObserver
|
||||
|
||||
from core.services.payment_phase.payment_state import TicketPaymentData
|
||||
# from core.services.prepare_tickets.get_pub_key import get_and_save_pub_key
|
||||
from core.services.prepare_tickets.get_pub_key import get_and_save_pub_key
|
||||
from core.utils.type_checker import type_checker
|
||||
from core.services.prepare_tickets.ticket_prep_orchestrator import ticket_prep_orchestrator
|
||||
from core.services.prepare_tickets.make_sure_pub_key_exists import make_sure_pub_key_exists
|
||||
|
|
@ -14,7 +10,6 @@ from core.services.prepare_tickets import ticket_tracker
|
|||
from core.services.helpers.get_how_many_profiles_were_ordered import (
|
||||
get_how_many_profiles_were_ordered,
|
||||
)
|
||||
# from core.observers.BaseObserver import BaseObserver
|
||||
from core.models.Result import Result, ResultError
|
||||
from core.errors.logger import logger
|
||||
|
||||
|
|
@ -82,11 +77,12 @@ def prepare_tickets(
|
|||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg)
|
||||
|
||||
# got_key = get_and_save_pub_key(which_key)
|
||||
# if not got_key.valid:
|
||||
# logger.error(got_key.message)
|
||||
# return got_key
|
||||
# logger.info("Got public key..")
|
||||
got_key = get_and_save_pub_key(which_key, connection_observer)
|
||||
if not got_key.valid:
|
||||
logger.error(got_key.message)
|
||||
return got_key
|
||||
public_key = got_key.data
|
||||
logger.info("Got public key..")
|
||||
|
||||
notification = "Preparing Cryptography Locally"
|
||||
if ticket_observer is not None:
|
||||
|
|
@ -95,6 +91,7 @@ def prepare_tickets(
|
|||
# ok now we have the pre-reqs, let's use this high level orchestrator,
|
||||
prep_results = ticket_prep_orchestrator(
|
||||
how_many_profiles=how_many_profiles,
|
||||
public_key=public_key,
|
||||
ticket_observer=ticket_observer,
|
||||
connection_observer=connection_observer,
|
||||
which_ticket=which_ticket, # only relevant for single ticket prep
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ if TYPE_CHECKING:
|
|||
# services
|
||||
from core.services.crypto.TicketCustomer import TicketCustomer
|
||||
from core.services.helpers.validate_number_format import number_of_valid_length
|
||||
from core.services.prepare_tickets.get_public_key_by_config import get_public_key_by_config
|
||||
# from core.services.prepare_tickets.get_public_key_by_config import get_public_key_by_config
|
||||
from core.services.prepare_tickets.get_pub_key import key_is_in_valid_format, get_pub_key
|
||||
from core.services.failed_verification.test_if_new_key_works import test_if_new_key_works
|
||||
from core.services.networking.make_url import make_url
|
||||
|
|
|
|||
252
core/services/payment_phase/old_get_pub_key.py
Normal file
252
core/services/payment_phase/old_get_pub_key.py
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
# services
|
||||
from core.services.networking.make_url import make_url
|
||||
from core.services.networking.httpx import connect
|
||||
from core.services.helpers.get_plan_data import get_plan_data
|
||||
from core.services.payment_phase.payment_state import TicketPaymentData
|
||||
|
||||
# utils
|
||||
from core.utils.get_data import read_and_convert_with_eval
|
||||
from core.models.Result import Result, ResultError
|
||||
from core.utils.basic_operations.write_or_read_from_json import get_value_from_json_file
|
||||
from core.utils.basic_operations.does_file_exist import does_file_exist
|
||||
from core.utils.basic_operations.write_string_to_text_file import write_string_to_text_file
|
||||
from core.errors.logger import logger
|
||||
from core.Constants import Constants
|
||||
|
||||
# generic
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
def key_is_in_valid_format(public_key: Any) -> bool:
|
||||
"""
|
||||
Purpose:
|
||||
Confirms a Public Key's Format with X and Y in a dictionary.
|
||||
Called by:
|
||||
get_pub_key (this module)
|
||||
validate_blind_signatures' make_sure_we_have_inputs (external modules)
|
||||
"""
|
||||
return set(public_key.keys()) == {"x", "y"}
|
||||
|
||||
|
||||
def fetch_key_from_server(which_key: str) -> dict|bool:
|
||||
"""
|
||||
Purpose:
|
||||
Gets the public key from the API.
|
||||
Called by:
|
||||
get_and_save_pub_key (this module)
|
||||
get_public_key_used (this module)
|
||||
"""
|
||||
url = make_url(which_key)
|
||||
|
||||
public_key_results = connect.single_endpoint(
|
||||
method="get",
|
||||
url=url,
|
||||
payload=None
|
||||
)
|
||||
|
||||
if not public_key_results.valid:
|
||||
error_msg = f"Error with API getting the Public Key: {public_key_results.error_type} and {public_key_results.message}"
|
||||
logger.error(error_msg)
|
||||
return False
|
||||
|
||||
# extract:
|
||||
public_key = public_key_results.data
|
||||
|
||||
return public_key
|
||||
|
||||
|
||||
def get_and_save_pub_key(which_key: str) -> Result:
|
||||
"""
|
||||
Purpose:
|
||||
Fetches a public key and saves it. But you have to know which key you want.
|
||||
Called by:
|
||||
TicketPayController's initiate_payment
|
||||
"""
|
||||
from core.Constants import Constants
|
||||
data_folder = Constants.HV_TICKETING_DATA_HOME
|
||||
file_path = f"{data_folder}/{str(which_key)}.json"
|
||||
|
||||
if not which_key:
|
||||
error_msg = "You have to know which key you want to use this function."
|
||||
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg)
|
||||
|
||||
public_key = fetch_key_from_server(which_key)
|
||||
|
||||
if not public_key:
|
||||
error_msg = "Failed to connect to the API Server to get the public key."
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.CONNECTION, message=error_msg)
|
||||
|
||||
if not key_is_in_valid_format(public_key):
|
||||
error_msg = f"The server gave the {which_key} public key in an Invalid Format."
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.INVALID_API_REPLY, message=error_msg)
|
||||
|
||||
# save it:
|
||||
if not write_string_to_text_file(public_key, file_path):
|
||||
error_msg = f"Error with saving the public key {which_key}. Please check your file system permissions. It tried to use this path: {file_path}"
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.FILE_SYSTEM, message=error_msg)
|
||||
|
||||
# finally:
|
||||
return Result(valid=True, data=public_key)
|
||||
|
||||
|
||||
def get_from_config(get_what: str) -> str|bool:
|
||||
"""
|
||||
Purpose:
|
||||
Wrapper with config file structure for external loaders.
|
||||
Called by:
|
||||
actions.begin_ticket_prep
|
||||
"""
|
||||
from core.Constants import Constants
|
||||
filepath = Constants.TICKET_BILLING
|
||||
return _get_from_config(filepath, get_what)
|
||||
|
||||
|
||||
def _get_from_config(filepath: str, what_want: str) -> str|bool:
|
||||
"""
|
||||
Get some data from a dict-based file, and handle errors.
|
||||
It assumes you have loaded the path on your own.
|
||||
"""
|
||||
try:
|
||||
return get_value_from_json_file(filepath, what_want)
|
||||
except (ValueError, KeyError) as e:
|
||||
logger.error(f"We could not get {what_want} from the config at {filepath}, because {str(e)}")
|
||||
return False
|
||||
|
||||
|
||||
def find_out_which_key_we_used() -> Result:
|
||||
"""Returns which key plan was used based on the local config."""
|
||||
|
||||
billing_data = TicketPaymentData()
|
||||
which_key = billing_data.which_key
|
||||
|
||||
if which_key:
|
||||
return Result(valid=True, data=which_key)
|
||||
|
||||
|
||||
# OLD DEAD CODE:
|
||||
|
||||
billing_folder = Constants.HV_TICKETING_CONFIG_HOME
|
||||
filepath = f"{billing_folder}/billing_choices.json"
|
||||
|
||||
if not does_file_exist(filepath):
|
||||
return Result(valid=False, error_type=ResultError.MISSING_DATA, message="The Billing Choices file is missing, we can't figure out what key or plan was used.")
|
||||
|
||||
which_key = _get_from_config(filepath, "which_key")
|
||||
if which_key:
|
||||
return Result(valid=True, data=which_key)
|
||||
|
||||
# can't find plan? try to get temp billing id.
|
||||
temp_billing_code = _get_from_config(filepath, "billing_code")
|
||||
|
||||
if not temp_billing_code:
|
||||
return Result(valid=False, error_type=ResultError.MISSING_DATA, message="The Billing Choices file does not have what key or plan was used.")
|
||||
|
||||
# fetch from server:
|
||||
fetching_result = get_plan_data(temp_billing_code)
|
||||
|
||||
if not fetching_result.valid:
|
||||
return fetching_result # this is already Result format with the error.
|
||||
|
||||
plan_data = fetching_result.data
|
||||
which_key = plan_data.get("which_key", False)
|
||||
|
||||
if which_key:
|
||||
return Result(valid=True, data=which_key)
|
||||
else:
|
||||
return Result(valid=False, error_type=ResultError.INVALID_API_REPLY, message="The API gave us a reply, but it lacked the critical key data we needed.")
|
||||
|
||||
|
||||
def get_local_copy_of_public_key(which_key: str) -> Result:
|
||||
"""Once we know which key we're looking for, get and convert it from local files."""
|
||||
|
||||
from core.Constants import Constants
|
||||
filepath = f"{Constants.HV_TICKETING_DATA_HOME}/{which_key}.json"
|
||||
|
||||
if not does_file_exist(filepath):
|
||||
return Result(valid=False, error_type=ResultError.MISSING_DATA, message=f"The file doesn't exist, or you lack the permissions to open it, at {filepath}")
|
||||
|
||||
# Convert it to the format we need:
|
||||
public_key = read_and_convert_with_eval(filepath)
|
||||
|
||||
if not public_key:
|
||||
error_msg = f"The local key of {which_key} is in the wrong format, even though the file exists."
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg)
|
||||
|
||||
# this just checks if it has an X and Y in a dictionary:
|
||||
if not key_is_in_valid_format(public_key) or not isinstance(public_key, dict):
|
||||
error_msg = f"The local key of {which_key} is in the wrong format, even though the file exists."
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg)
|
||||
|
||||
return Result(valid=True, data=public_key)
|
||||
|
||||
|
||||
def get_public_key_used(local_only: Optional[bool] = False, save_it: Optional[bool] = False) -> Result:
|
||||
"""
|
||||
1. Use the local config to figure out which key/plan
|
||||
2. See if there's a local copy first, convert it.
|
||||
3. If not fetch that from the API (unless local_only flag is on.)
|
||||
|
||||
Called by:
|
||||
TicketPrepController's prepare_tickets
|
||||
FailedVerificationController's evaluate_if_its_the_key
|
||||
"""
|
||||
# -------------------------
|
||||
# Step 1. Which key was used?
|
||||
# -------------------------
|
||||
key_results = find_out_which_key_we_used()
|
||||
|
||||
if not key_results.valid:
|
||||
return key_results
|
||||
|
||||
which_key = key_results.data
|
||||
|
||||
# -------------------------
|
||||
# Step 2. Do we have it locally?
|
||||
# -------------------------
|
||||
local_copy_result = get_local_copy_of_public_key(which_key)
|
||||
|
||||
if local_only:
|
||||
return local_copy_result
|
||||
|
||||
if local_copy_result.valid:
|
||||
return local_copy_result
|
||||
|
||||
# -------------------------
|
||||
# Step 3. Fetch it from the API
|
||||
# -------------------------
|
||||
public_key = fetch_key_from_server(which_key)
|
||||
|
||||
if not public_key:
|
||||
error_msg = f"Failed to connect to the API Server to get the public key {which_key}."
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.CONNECTION, message=error_msg)
|
||||
|
||||
if save_it:
|
||||
return save_key(public_key, which_key)
|
||||
|
||||
# if they didn't flag on save_it, then we're done:
|
||||
return Result(valid=True, data=public_key)
|
||||
|
||||
|
||||
def save_key(public_key: dict, which_key: str) -> Result:
|
||||
"""
|
||||
Purpose:
|
||||
Saves a public key locally, with a file path based on it's name.
|
||||
Called by:
|
||||
get_public_key_used (this module)
|
||||
"""
|
||||
from core.Constants import Constants
|
||||
filepath = f"{Constants.HV_TICKETING_DATA_HOME}/{which_key}.json"
|
||||
|
||||
if write_string_to_text_file(public_key, filepath):
|
||||
return Result(valid=True, data=public_key)
|
||||
else:
|
||||
error_msg = f"Error with saving the public key {which_key}. Please check your file system permissions. It tried to use this path: {filepath}"
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.FILE_SYSTEM, message=error_msg)
|
||||
|
||||
|
|
@ -1,120 +1,244 @@
|
|||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from essentials.observers.ConnectionObserver import ConnectionObserver
|
||||
from typing import Any
|
||||
# services
|
||||
from core.services.networking.make_url import make_url
|
||||
from core.services.networking.httpx import connect
|
||||
from core.services.networking.api_requests.ApiResponseModel import ApiResponse, ErrorType
|
||||
from core.services.helpers.get_plan_data import get_plan_data
|
||||
|
||||
# utils
|
||||
from core.utils.get_data import read_and_convert_with_eval
|
||||
from core.models.Result import Result, ResultError
|
||||
from core.utils.basic_operations.write_or_read_from_json import get_value_from_json_file
|
||||
from core.utils.basic_operations.does_file_exist import does_file_exist
|
||||
from core.utils.basic_operations.write_string_to_text_file import write_string_to_text_file
|
||||
# errors & constants
|
||||
from core.Constants import Constants
|
||||
from core.errors.logger import logger
|
||||
from core.Constants import Constants
|
||||
from core.observers.ConnectionObserver import ConnectionObserver
|
||||
|
||||
# generic
|
||||
import ast
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
def key_is_in_valid_format(public_key: Any) -> bool:
|
||||
"""
|
||||
Purpose:
|
||||
Confirms a Public Key's Format with X and Y in a dictionary.
|
||||
Called by:
|
||||
get_pub_key (this module)
|
||||
validate_blind_signatures' make_sure_we_have_inputs (external modules)
|
||||
"""
|
||||
return set(public_key.keys()) == {"x", "y"}
|
||||
|
||||
|
||||
def get_from_server_and_save(
|
||||
string_form_of_key_name: str,
|
||||
file_path: str,
|
||||
connection_observer: ConnectionObserver,
|
||||
) -> dict:
|
||||
|
||||
url = make_url(string_form_of_key_name)
|
||||
def fetch_key_from_server(which_key: str, connection_observer: ConnectionObserver) -> dict|bool:
|
||||
"""
|
||||
Purpose:
|
||||
Gets the public key from the API.
|
||||
Called by:
|
||||
get_and_save_pub_key (this module)
|
||||
get_public_key_used (this module)
|
||||
"""
|
||||
url = make_url(which_key)
|
||||
|
||||
public_key_results = connect.single_endpoint(
|
||||
method="get",
|
||||
url=url,
|
||||
observer=connection_observer,
|
||||
payload=None
|
||||
payload=None,
|
||||
observer=connection_observer
|
||||
)
|
||||
|
||||
if not public_key_results.valid:
|
||||
error_msg = f"Error with API getting the Public Key: {public_key_results.error_type} and {public_key_results.message}"
|
||||
logger.error(error_msg)
|
||||
return {"valid": False, "message": error_msg}
|
||||
return False
|
||||
|
||||
# extract:
|
||||
public_key = public_key_results.data
|
||||
|
||||
print(f"public_key is {public_key}")
|
||||
return public_key
|
||||
|
||||
|
||||
def get_and_save_pub_key(which_key: str, connection_observer: ConnectionObserver) -> Result:
|
||||
"""
|
||||
Purpose:
|
||||
Fetches a public key and saves it. But you have to know which key you want.
|
||||
Called by:
|
||||
TicketPayController's initiate_payment
|
||||
"""
|
||||
data_folder = Constants.HV_TICKETING_DATA_HOME
|
||||
file_path = f"{data_folder}/{str(which_key)}.json"
|
||||
|
||||
if not which_key:
|
||||
error_msg = "You have to know which key you want to use this function."
|
||||
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg)
|
||||
|
||||
public_key = fetch_key_from_server(which_key, connection_observer)
|
||||
|
||||
if not public_key:
|
||||
error_msg = "Failed to connect to the API Server to get the public key."
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.CONNECTION, message=error_msg)
|
||||
|
||||
if not key_is_in_valid_format(public_key):
|
||||
error_msg = f"The server gave the {which_key} public key in an Invalid Format."
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.INVALID_API_REPLY, message=error_msg)
|
||||
|
||||
# save it:
|
||||
did_it_save = write_string_to_text_file(public_key, file_path)
|
||||
if not write_string_to_text_file(public_key, file_path):
|
||||
error_msg = f"Error with saving the public key {which_key}. Please check your file system permissions. It tried to use this path: {file_path}"
|
||||
log_and_notify(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.FILE_SYSTEM, message=error_msg)
|
||||
|
||||
if not did_it_save:
|
||||
logger.error(f"Error with saving the public key {public_key} with write_string_to_text_file, but still returning data..")
|
||||
|
||||
# regardless of saving:
|
||||
return {"valid": True, "data": public_key}
|
||||
# finally:
|
||||
return Result(valid=True, data=public_key)
|
||||
|
||||
|
||||
def get_pub_key(
|
||||
which_key: str,
|
||||
connection_observer: ConnectionObserver,
|
||||
check_locally: str,
|
||||
) -> dict:
|
||||
def get_from_config(get_what: str) -> str|bool:
|
||||
"""
|
||||
Purpose:
|
||||
Wrapper with config file structure for external loaders.
|
||||
Called by:
|
||||
actions.begin_ticket_prep
|
||||
"""
|
||||
from core.Constants import Constants
|
||||
filepath = Constants.TICKET_BILLING
|
||||
return _get_from_config(filepath, get_what)
|
||||
|
||||
# prep file path for either saving or using the existing one:
|
||||
data_folder = Constants.HV_TICKETING_DATA_HOME
|
||||
string_form_of_key_name = str(which_key)
|
||||
file_path = f"{data_folder}/{string_form_of_key_name}.json"
|
||||
|
||||
# do we want to use the key if it's already stored locally?
|
||||
if check_locally == "local":
|
||||
# does the public key already exist locally?
|
||||
exists_already = does_file_exist(file_path)
|
||||
else:
|
||||
logger.debug("Getting Public Key from API..", exc_info=True)
|
||||
# setting this to false bypasses it being local for the next section, and skips to the end
|
||||
exists_already = False
|
||||
|
||||
# Next Section
|
||||
if exists_already == True:
|
||||
# we're going to try to get it from the file locally:
|
||||
def _get_from_config(filepath: str, what_want: str) -> str|bool:
|
||||
"""
|
||||
Get some data from a dict-based file, and handle errors.
|
||||
It assumes you have loaded the path on your own.
|
||||
"""
|
||||
try:
|
||||
with open(file_path, "r") as file:
|
||||
public_key_as_string = file.read()
|
||||
return get_value_from_json_file(filepath, what_want)
|
||||
except (ValueError, KeyError) as e:
|
||||
logger.error(f"We could not get {what_want} from the config at {filepath}, because {str(e)}")
|
||||
return False
|
||||
|
||||
# this gets in pyth dict with a single ', which is how the crypto functions need it.
|
||||
public_key = ast.literal_eval(public_key_as_string)
|
||||
|
||||
if key_is_in_valid_format(public_key):
|
||||
return {"valid": True, "data": public_key}
|
||||
def find_out_which_key_we_used() -> Result:
|
||||
"""Returns which key plan was used based on the local config."""
|
||||
|
||||
from core.Constants import Constants
|
||||
billing_folder = Constants.HV_TICKETING_CONFIG_HOME
|
||||
filepath = f"{billing_folder}/billing_choices.json"
|
||||
|
||||
if not does_file_exist(filepath):
|
||||
return Result(valid=False, error_type=ResultError.MISSING_DATA, message="The Billing Choices file is missing, we can't figure out what key or plan was used.")
|
||||
|
||||
which_key = _get_from_config(filepath, "which_key")
|
||||
if which_key:
|
||||
return Result(valid=True, data=which_key)
|
||||
|
||||
# can't find plan? try to get temp billing id.
|
||||
temp_billing_code = _get_from_config(filepath, "temp_billing_code")
|
||||
|
||||
if not temp_billing_code:
|
||||
return Result(valid=False, error_type=ResultError.MISSING_DATA, message="The Billing Choices file does not have what key or plan was used.")
|
||||
|
||||
# fetch from server:
|
||||
fetching_result = get_plan_data(temp_billing_code)
|
||||
|
||||
if not fetching_result.valid:
|
||||
return fetching_result # this is already Result format with the error.
|
||||
|
||||
plan_data = fetching_result.data
|
||||
which_key = plan_data.get("which_key", False)
|
||||
|
||||
if which_key:
|
||||
return Result(valid=True, data=which_key)
|
||||
else:
|
||||
print(
|
||||
"Key format is Invalid! Let's replace it by getting a new one from the server,"
|
||||
)
|
||||
public_key_results = get_from_server_and_save(
|
||||
string_form_of_key_name, file_path, connection_observer
|
||||
)
|
||||
return public_key_results
|
||||
return Result(valid=False, error_type=ResultError.INVALID_API_REPLY, message="The API gave us a reply, but it lacked the critical key data we needed.")
|
||||
|
||||
# but if the local key doesn't format properly, then get it from the server,
|
||||
except:
|
||||
public_key_results = get_from_server_and_save(
|
||||
string_form_of_key_name, file_path, connection_observer
|
||||
)
|
||||
|
||||
return public_key_results
|
||||
def get_local_copy_of_public_key(which_key: str) -> Result:
|
||||
"""Once we know which key we're looking for, get and convert it from local files."""
|
||||
|
||||
# no local key? get from server,
|
||||
from core.Constants import Constants
|
||||
filepath = f"{Constants.HV_TICKETING_DATA_HOME}/{which_key}.json"
|
||||
|
||||
if not does_file_exist(filepath):
|
||||
return Result(valid=False, error_type=ResultError.MISSING_DATA, message=f"The file doesn't exist, or you lack the permissions to open it, at {filepath}")
|
||||
|
||||
# Convert it to the format we need:
|
||||
public_key = read_and_convert_with_eval(filepath)
|
||||
|
||||
if not public_key:
|
||||
error_msg = f"The local key of {which_key} is in the wrong format, even though the file exists."
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg)
|
||||
|
||||
# this just checks if it has an X and Y in a dictionary:
|
||||
if not key_is_in_valid_format(public_key) or not isinstance(public_key, dict):
|
||||
error_msg = f"The local key of {which_key} is in the wrong format, even though the file exists."
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg)
|
||||
|
||||
return Result(valid=True, data=public_key)
|
||||
|
||||
|
||||
def get_public_key_used(local_only: Optional[bool] = False, save_it: Optional[bool] = False) -> Result:
|
||||
"""
|
||||
1. Use the local config to figure out which key/plan
|
||||
2. See if there's a local copy first, convert it.
|
||||
3. If not fetch that from the API (unless local_only flag is on.)
|
||||
|
||||
Called by:
|
||||
TicketPrepController's prepare_tickets
|
||||
FailedVerificationController's evaluate_if_its_the_key
|
||||
"""
|
||||
# -------------------------
|
||||
# Step 1. Which key was used?
|
||||
# -------------------------
|
||||
key_results = find_out_which_key_we_used()
|
||||
|
||||
if not key_results.valid:
|
||||
return key_results
|
||||
|
||||
which_key = key_results.data
|
||||
|
||||
# -------------------------
|
||||
# Step 2. Do we have it locally?
|
||||
# -------------------------
|
||||
local_copy_result = get_local_copy_of_public_key(which_key)
|
||||
|
||||
if local_only:
|
||||
return local_copy_result
|
||||
|
||||
if local_copy_result.valid:
|
||||
return local_copy_result
|
||||
|
||||
# -------------------------
|
||||
# Step 3. Fetch it from the API
|
||||
# -------------------------
|
||||
public_key = fetch_key_from_server(which_key)
|
||||
|
||||
if not public_key:
|
||||
error_msg = f"Failed to connect to the API Server to get the public key {which_key}."
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.CONNECTION, message=error_msg)
|
||||
|
||||
if save_it:
|
||||
return save_key(public_key, which_key)
|
||||
|
||||
# if they didn't flag on save_it, then we're done:
|
||||
return Result(valid=True, data=public_key)
|
||||
|
||||
|
||||
def save_key(public_key: dict, which_key: str) -> Result:
|
||||
"""
|
||||
Purpose:
|
||||
Saves a public key locally, with a file path based on it's name.
|
||||
Called by:
|
||||
get_public_key_used (this module)
|
||||
"""
|
||||
from core.Constants import Constants
|
||||
filepath = f"{Constants.HV_TICKETING_DATA_HOME}/{which_key}.json"
|
||||
|
||||
if write_string_to_text_file(public_key, filepath):
|
||||
return Result(valid=True, data=public_key)
|
||||
else:
|
||||
logger.debug(
|
||||
"You do not have the public key locally. So we are getting it from the server.."
|
||||
)
|
||||
public_key_results = get_from_server_and_save(
|
||||
string_form_of_key_name, file_path, connection_observer
|
||||
)
|
||||
error_msg = f"Error with saving the public key {which_key}. Please check your file system permissions. It tried to use this path: {filepath}"
|
||||
log_and_notify(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.FILE_SYSTEM, message=error_msg)
|
||||
|
||||
return public_key_results
|
||||
|
|
|
|||
|
|
@ -1,186 +0,0 @@
|
|||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from essentials.observers.ConnectionObserver import ConnectionObserver
|
||||
# services & helpers
|
||||
from core.services.networking.api_requests.ApiResponseModel import ApiResponse, ErrorType
|
||||
from core.services.prepare_tickets.get_pub_key import get_pub_key
|
||||
from core.services.prepare_tickets.get_pub_key import key_is_in_valid_format
|
||||
from core.services.helpers.get_plan_data import get_plan_data
|
||||
# utils
|
||||
from core.utils.basic_operations.filter_data import filter_data
|
||||
from core.utils.basic_operations.write_or_read_from_json import get_value_from_json_file
|
||||
from core.utils.basic_operations.does_file_exist import does_file_exist
|
||||
# constants
|
||||
from core.Constants import Constants
|
||||
# generic
|
||||
import ast
|
||||
|
||||
"""
|
||||
This service tries to get a public key, based on the config file.
|
||||
It first checks if the config file has which key it wants.
|
||||
Then it checks for a temp billing code, and if there is one, asks the server what the key is.
|
||||
"""
|
||||
|
||||
|
||||
# Get which key plan they have.
|
||||
def get_public_key_FROM_config(filepath) -> str | None:
|
||||
try:
|
||||
which_key = get_value_from_json_file(filepath, "which_key")
|
||||
return which_key
|
||||
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def get_public_key_by_config(connection_observer: ConnectionObserver) -> dict:
|
||||
list_of_failures = [None, False, ""]
|
||||
billing_folder = Constants.HV_TICKETING_CONFIG_HOME
|
||||
filepath = f"{billing_folder}/billing_choices.json"
|
||||
|
||||
which_key = get_public_key_FROM_config(filepath)
|
||||
|
||||
# if there is no key in the config?
|
||||
if which_key is None:
|
||||
|
||||
# then try to get the temp billing id.
|
||||
temp_billing_code = get_value_from_json_file(filepath, "temp_billing_code")
|
||||
|
||||
# but what if there is not even a temp billing ID?
|
||||
if temp_billing_code in list_of_failures:
|
||||
return {
|
||||
"status": False,
|
||||
"message": f"Issue with finding key plan or billing code. Please check {filepath}",
|
||||
}
|
||||
|
||||
# Now we're assuming we have a temp billing code,
|
||||
# So we can use that to get the key from the server,
|
||||
api_reply_object = get_plan_data(temp_billing_code, connection_observer)
|
||||
|
||||
complete_failure_msg = {
|
||||
"status": False,
|
||||
"message": f"Issues with both finding your local key plan and even connecting to the server for it. Please check {filepath}",
|
||||
}
|
||||
|
||||
if not api_reply_object.valid:
|
||||
return complete_failure_msg
|
||||
|
||||
reply = api_reply_object.data
|
||||
|
||||
if reply in list_of_failures:
|
||||
return complete_failure_msg
|
||||
|
||||
if not isinstance(reply, dict):
|
||||
return {
|
||||
"status": False,
|
||||
"message": f"Server returned an invalid format, and even accessing via local files. Please check {filepath}",
|
||||
}
|
||||
|
||||
# from the server's reply, get the key
|
||||
which_key = filter_data(reply, "which_key")
|
||||
if which_key in list_of_failures:
|
||||
return {
|
||||
"status": False,
|
||||
"message": f"Issues with both finding your local key plan and getting it from the server. Please check {filepath}",
|
||||
}
|
||||
# The reason we convert it to integer, only to convert it back to a string in the next functions,
|
||||
# is because those functions can be accessed directly in other ways that would have the key as an integer.
|
||||
# which_key = int(which_key)
|
||||
|
||||
# send to service:
|
||||
public_key_results = get_pub_key(which_key, connection_observer, "local")
|
||||
|
||||
# if public_key_results is None:
|
||||
# return {'status': False, 'message': "no_public_key"}
|
||||
|
||||
# assert public_key_results is not None
|
||||
return public_key_results
|
||||
|
||||
|
||||
"""
|
||||
This seems like a duplicate function, but it's used in situations where there was a failed validation.
|
||||
The other functions get the key from local files OR the api. And they save it, which would replace the key we want to study.
|
||||
Instead, this function gets it only from local files.
|
||||
"""
|
||||
|
||||
|
||||
def get_public_key_from_LOCAL_files_only(
|
||||
connection_observer: ConnectionObserver,
|
||||
) -> dict:
|
||||
billing_folder = Constants.HV_TICKETING_CONFIG_HOME
|
||||
filepath = f"{billing_folder}/billing_choices.json"
|
||||
try:
|
||||
which_key = get_value_from_json_file(filepath, "which_key")
|
||||
except:
|
||||
which_key = None
|
||||
finally:
|
||||
list_of_failures = [None, False, ""]
|
||||
if which_key in list_of_failures:
|
||||
# can't find plan? try to get temp billing id.
|
||||
temp_billing_code = get_value_from_json_file(filepath, "temp_billing_code")
|
||||
|
||||
if temp_billing_code in list_of_failures:
|
||||
return {
|
||||
"status": False,
|
||||
"message": f"Issue with finding key plan or billing code. Please check {filepath}",
|
||||
}
|
||||
|
||||
api_reply_object = get_plan_data(temp_billing_code, connection_observer)
|
||||
|
||||
complete_failure_msg = {
|
||||
"status": False,
|
||||
"message": f"Issues with both finding your local key plan and even connecting to the server for it. Please check {filepath}",
|
||||
}
|
||||
|
||||
if not api_reply_object.valid:
|
||||
return complete_failure_msg
|
||||
|
||||
reply = api_reply_object.data
|
||||
|
||||
if reply in list_of_failures:
|
||||
return complete_failure_msg
|
||||
|
||||
if not isinstance(reply, dict):
|
||||
return {
|
||||
"status": False,
|
||||
"message": f"Server returned an invalid format, and even accessing via local files. Please check {filepath}",
|
||||
}
|
||||
|
||||
which_key = filter_data(reply, "which_key")
|
||||
if which_key in list_of_failures:
|
||||
return {
|
||||
"status": False,
|
||||
"message": f"Issues with both finding your local key plan and getting it from the server. Please check {filepath}",
|
||||
}
|
||||
|
||||
# now that we know the key plan, move on to getting the data:
|
||||
data_folder = Constants.HV_TICKETING_DATA_HOME
|
||||
string_form_of_key_name = str(which_key)
|
||||
file_path = f"{data_folder}/{string_form_of_key_name}.json"
|
||||
|
||||
# does it exist?
|
||||
exists_already = does_file_exist(file_path)
|
||||
if not exists_already:
|
||||
return {"valid": False, "message": "Local key file doesn't exist"}
|
||||
|
||||
try:
|
||||
with open(file_path, "r") as file:
|
||||
public_key_as_string = file.read()
|
||||
|
||||
# this gets in pyth dict with a single ', which is how the crypto functions need it.
|
||||
public_key = ast.literal_eval(public_key_as_string)
|
||||
|
||||
# this only checks if the key has 'x' and 'y' keys:
|
||||
if key_is_in_valid_format(public_key):
|
||||
return {"valid": True, "public_key": public_key}
|
||||
else:
|
||||
return {
|
||||
"valid": False,
|
||||
"message": "Key file exists but is in an invalid format.",
|
||||
}
|
||||
except:
|
||||
return {
|
||||
"valid": False,
|
||||
"message": "Key file exists but is in an invalid format or unreadable.",
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ from typing import TYPE_CHECKING
|
|||
if TYPE_CHECKING:
|
||||
from essentials.observers.ConnectionObserver import ConnectionObserver
|
||||
#
|
||||
from core.services.prepare_tickets.get_public_key_by_config import get_public_key_by_config
|
||||
# from core.services.prepare_tickets.get_public_key_by_config import get_public_key_by_config
|
||||
from core.utils.basic_operations.does_file_exist import does_file_exist
|
||||
from core.utils.basic_operations.write_or_read_from_json import get_value_from_json_file
|
||||
from core.Constants import Constants
|
||||
|
|
|
|||
181
core/services/prepare_tickets/old_validate_blind_signatures.py
Normal file
181
core/services/prepare_tickets/old_validate_blind_signatures.py
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.observers.TicketObserver import TicketObserver
|
||||
from essentials.observers.ConnectionObserver import ConnectionObserver
|
||||
# services
|
||||
from core.services.crypto.TicketCustomer import TicketCustomer
|
||||
from core.services.prepare_tickets.get_public_key_by_config import get_public_key_by_config
|
||||
from core.services.prepare_tickets.get_pub_key import key_is_in_valid_format, get_pub_key
|
||||
# utils
|
||||
from core.utils.save_data import save_data
|
||||
from core.utils.basic_operations.write_or_read_from_json import get_value_from_json_file
|
||||
# observers, constants, errors
|
||||
from core.observers.BaseObserver import BaseObserver
|
||||
from core.models.Event import Event
|
||||
from core.Constants import Constants
|
||||
from core.errors.exceptions import *
|
||||
from core.errors.logger import logger
|
||||
# generic
|
||||
import traceback
|
||||
import json
|
||||
from typing import Optional
|
||||
|
||||
def make_sure_we_have_inputs(
|
||||
ALL_signed_blind_signatures: list,
|
||||
profile_object: TicketCustomer,
|
||||
ticket_observer: TicketObserver,
|
||||
connection_observer: ConnectionObserver,
|
||||
) -> dict:
|
||||
|
||||
try:
|
||||
if ALL_signed_blind_signatures == False or ALL_signed_blind_signatures == None:
|
||||
error_msg = "The Server gave back no data or it's missing for ALL_signed_blind_signatures in the unblind_and_prove_ALL_profiles function . This can't unblind blank data."
|
||||
logger.error(error_msg, exc_info=True)
|
||||
logger.debug(error_msg)
|
||||
return {"valid": False, "error_msg": error_msg}
|
||||
|
||||
# get the public key for entire loop:
|
||||
public_key_results = get_public_key_by_config(connection_observer)
|
||||
|
||||
# did we actually get the public key?
|
||||
if "data" not in public_key_results:
|
||||
error_msg = (
|
||||
"The validation function can't even get the public key to do it's loop"
|
||||
)
|
||||
logger.error(error_msg, exc_info=True)
|
||||
logger.debug(error_msg)
|
||||
return {"valid": False, "error_msg": error_msg}
|
||||
|
||||
public_key = public_key_results.get("data")
|
||||
|
||||
rejected_reasons = [None, False, ""]
|
||||
if public_key in rejected_reasons:
|
||||
error_msg = "The validation function can't get the public key"
|
||||
logger.debug(error_msg)
|
||||
return {"valid": False, "error_msg": error_msg}
|
||||
|
||||
# this just checks if it has an X and Y in a dictionary:
|
||||
if not key_is_in_valid_format(public_key) or not isinstance(public_key, dict):
|
||||
return {"valid": False, "error_msg": "invalid_key_format"}
|
||||
|
||||
logger.debug("Checking if the public key is even able to be loaded...")
|
||||
valid_key = profile_object.load_key(public_key)
|
||||
|
||||
if valid_key:
|
||||
logger.debug("Public Key can be loaded")
|
||||
return {"valid": True, "public_key": public_key}
|
||||
|
||||
else:
|
||||
error_msg = "The validation function is working with an invalid public key"
|
||||
logger.debug(error_msg)
|
||||
return {"valid": False, "error_msg": error_msg}
|
||||
|
||||
except:
|
||||
error_msg = (
|
||||
"We lack the ability to get all the inputs for the verification loop"
|
||||
)
|
||||
logger.error(error_msg, exc_info=True)
|
||||
logger.debug(error_msg)
|
||||
return {"valid": False, "error_msg": error_msg}
|
||||
|
||||
|
||||
"""
|
||||
Technically this entire module is optional, as it isn't used for the actual ticket preparation.
|
||||
|
||||
This module exists so the customer can be sure that the server did not maliciously sign with a fake new key,
|
||||
to try to secretly identify users (by using different keys for each one).
|
||||
"""
|
||||
|
||||
|
||||
def validate_blind_signatures(
|
||||
ALL_signed_blind_signatures: list,
|
||||
ticket_observer: TicketObserver,
|
||||
connection_observer: ConnectionObserver,
|
||||
which_ticket: Optional[int] = None,
|
||||
):
|
||||
try:
|
||||
# Setup the entire class object of "profile_object" for using all these other functions,
|
||||
profile_object = TicketCustomer()
|
||||
|
||||
# start: confirm inputs
|
||||
inputs = make_sure_we_have_inputs(
|
||||
ALL_signed_blind_signatures,
|
||||
profile_object,
|
||||
ticket_observer,
|
||||
connection_observer,
|
||||
)
|
||||
if not inputs["valid"]:
|
||||
logger.debug("ending the validation process early.")
|
||||
return inputs
|
||||
public_key = inputs["public_key"]
|
||||
# end: confirm inputs
|
||||
|
||||
# setup basic counters, flags, and lists for the loop below:
|
||||
|
||||
if which_ticket is None:
|
||||
which_ticket = 1
|
||||
|
||||
did_we_answer_the_key_question_yet = "no"
|
||||
list_of_failed_verifications = []
|
||||
|
||||
"""
|
||||
LOOP STARTS:
|
||||
|
||||
Looping through each signature, verifying it against the single public key.
|
||||
"""
|
||||
for each_blind_signature in ALL_signed_blind_signatures:
|
||||
# prep from server's format:
|
||||
blind_signature = json.loads(each_blind_signature)
|
||||
|
||||
#### Check blind signature validity for THAT signature:
|
||||
validity_data = profile_object.test_blind_signature_validity(
|
||||
which_ticket, blind_signature, public_key
|
||||
)
|
||||
|
||||
if validity_data["valid"] == True:
|
||||
# verification went fine:
|
||||
notification = f"Verified {which_ticket}'s blind signature"
|
||||
ticket_observer.notify("preparing", subject=notification)
|
||||
else:
|
||||
# is it an invalid pub key?
|
||||
if validity_data["message"] == "invalid_key":
|
||||
notification = f"Verification of all blind signatures is halted, because you have an invalid public key!"
|
||||
ticket_observer.notify("preparing", subject=notification)
|
||||
return [which_ticket]
|
||||
|
||||
# otherwise:
|
||||
list_of_failed_verifications.append(which_ticket)
|
||||
notification = f"Invalid {which_ticket} blind signature"
|
||||
ticket_observer.notify("preparing", subject=notification)
|
||||
|
||||
# bump loop for next round:
|
||||
which_ticket = which_ticket + 1
|
||||
|
||||
### LOOP DONE
|
||||
logger.debug(
|
||||
f"Exiting the validation loop with the list_of_failed_verifications: {list_of_failed_verifications}"
|
||||
)
|
||||
return list_of_failed_verifications
|
||||
|
||||
except FailedToSave as e:
|
||||
error_msg = f"FailedToSave: {e}"
|
||||
logger.error(error_msg, exc_info=True)
|
||||
return {"valid": False, "message": "error", "error": error_msg}
|
||||
|
||||
except InvalidData as e:
|
||||
error_msg = f"InvalidData error: {e}"
|
||||
logger.error(error_msg, exc_info=True)
|
||||
return {"valid": False, "message": "error", "error": error_msg}
|
||||
|
||||
except MissingData as e:
|
||||
error_msg = f"MissingData: {e}"
|
||||
logger.error(error_msg, exc_info=True)
|
||||
return {"valid": False, "message": "error", "error": error_msg}
|
||||
|
||||
except Exception as e:
|
||||
tb = traceback.extract_tb(e.__traceback__)[-1]
|
||||
error_msg = f"error type {type(e).__name__} happened on line {tb.lineno}, in function {tb.name}, giving error: {e}. The actual code in question is: {tb.line}. in this file: {tb.filename}"
|
||||
logger.error(error_msg, exc_info=True)
|
||||
return {"valid": False, "message": "error", "error": error_msg}
|
||||
|
|
@ -6,22 +6,18 @@ if TYPE_CHECKING:
|
|||
from core.observers.TicketObserver import TicketObserver
|
||||
|
||||
# services
|
||||
# from core.services.networking.httpx import connect
|
||||
# from core.services.networking.api_requests.ApiResponseModel import ApiResponse, ErrorType
|
||||
from core.services.networking.make_url import make_url
|
||||
# from core.services.payment_phase.ticket_config_tools import get_which_billing_key
|
||||
|
||||
# models & their controllers
|
||||
from core.models.manage.server_reply_tools import api_call_and_extraction, ApiCall, translate_server_failure
|
||||
from core.models.pydantic_models.ServerReply import ServerReply, ServerError
|
||||
# from core.models.session.SessionProfile import SessionProfile
|
||||
# from core.models.system.SystemProfile import SystemProfile
|
||||
from core.services.payment_phase.payment_state import TicketPaymentData
|
||||
|
||||
# utils
|
||||
from core.utils.basic_operations.write_or_read_from_json import get_value_from_json_file
|
||||
|
||||
# constants & errors
|
||||
from core.Constants import Constants
|
||||
# from core.errors.exceptions import InvalidData, ServerSideError
|
||||
from core.models.Result import Result, ResultError
|
||||
from core.errors.logger import logger
|
||||
|
||||
|
|
@ -40,12 +36,15 @@ def prep_payload_for_bulk(list_of_all_blinded_data: list) -> dict:
|
|||
Rank:
|
||||
Mini-Helper
|
||||
"""
|
||||
# get temp billing id from local storage:
|
||||
temp_billing_code = get_value_from_json_file(billing_path, "temp_billing_code")
|
||||
# billing code
|
||||
billing_data = TicketPaymentData()
|
||||
billing_code = billing_data.billing_code
|
||||
|
||||
# temp_billing_code = get_value_from_json_file(billing_path, "temp_billing_code")
|
||||
|
||||
# prep the JSON payload, it doesn't need the public key, since the server can look that up,
|
||||
payload = {
|
||||
"temp_billing_code": temp_billing_code,
|
||||
"billing_code": billing_code,
|
||||
"blinded_data": list_of_all_blinded_data,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ from __future__ import annotations
|
|||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.observers.TicketObserver import TicketObserver
|
||||
from essentials.observers.ConnectionObserver import ConnectionObserver
|
||||
from core.observers.ConnectionObserver import ConnectionObserver
|
||||
|
||||
from core.observers.TicketObserver import TicketObserver
|
||||
|
||||
from core.services.crypto.make_commitments import make_ALL_commitments
|
||||
from core.services.prepare_tickets.unblind_all_tickets import unblind_ALL_tickets
|
||||
|
|
@ -46,6 +46,7 @@ Called by:
|
|||
@type_checker
|
||||
def ticket_prep_orchestrator(
|
||||
how_many_profiles: int,
|
||||
public_key: dict,
|
||||
ticket_observer: TicketObserver,
|
||||
connection_observer: ConnectionObserver,
|
||||
which_ticket: Optional[int] = None,
|
||||
|
|
@ -106,11 +107,14 @@ def ticket_prep_orchestrator(
|
|||
# verify the server's blind signatures against the public key,
|
||||
notification = "Evaluating the Server's Blind Replies"
|
||||
ticket_observer.notify("preparing", subject=notification)
|
||||
failed_validations = validate_blind_signatures(
|
||||
blind_signatures, ticket_observer, connection_observer, which_ticket
|
||||
validations = validate_blind_signatures(
|
||||
ALL_signed_blind_signatures=blind_signatures,
|
||||
public_key=public_key,
|
||||
ticket_observer=ticket_observer,
|
||||
which_ticket=which_ticket
|
||||
)
|
||||
|
||||
logger.debug(f"failed_validations is {failed_validations}")
|
||||
failed_validations = validations.data
|
||||
|
||||
#####################################################
|
||||
# FAILED BLIND SIG VERIFICATION
|
||||
|
|
@ -129,14 +133,6 @@ def ticket_prep_orchestrator(
|
|||
message=notification
|
||||
)
|
||||
|
||||
#####################################################
|
||||
# PAID
|
||||
#####################################################
|
||||
# saving on config that it's paid:
|
||||
config_marked = ConfigurationController.mark_as_paid(True)
|
||||
if not config_marked:
|
||||
return Result(valid=False, error_type=ResultError.FILE_SYSTEM, message="Failed to mark as paid in the config. You still have the tickets locally, just can't use them till this file system error is resolved.")
|
||||
|
||||
#####################################################
|
||||
# UNBLIND
|
||||
#####################################################
|
||||
|
|
@ -149,6 +145,7 @@ def ticket_prep_orchestrator(
|
|||
connection_observer=connection_observer,
|
||||
which_ticket=which_ticket
|
||||
)
|
||||
logger.info(f"Unblind completed. Was it a success? {did_prep_work}")
|
||||
|
||||
#####################################################
|
||||
# TICKET TRACKER & APP-WIDE CONFIG
|
||||
|
|
@ -157,6 +154,7 @@ def ticket_prep_orchestrator(
|
|||
setup_tracker = setup_ticket_tracker(how_many_profiles)
|
||||
if not setup_tracker:
|
||||
return Result(valid=False, error_type=ResultError.FILE_SYSTEM, message="Failed to setup the ticket tracker. You still have the tickets locally, just can't use them till this file system error is resolved.")
|
||||
logger.info("Ticket tracker setup completed.")
|
||||
|
||||
#####################################################
|
||||
# FINAL EVALUATION
|
||||
|
|
@ -165,6 +163,7 @@ def ticket_prep_orchestrator(
|
|||
# this means it unblinded, & setup the tracker without erroring out,
|
||||
# but it does NOT mean that verification of the blind sigs worked.
|
||||
ConfigurationController.tickets_setup(True)
|
||||
logger.info("Setup Complete.")
|
||||
return Result(valid=True, message="Setup worked.")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,85 +1,17 @@
|
|||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.observers.TicketObserver import TicketObserver
|
||||
from essentials.observers.ConnectionObserver import ConnectionObserver
|
||||
|
||||
# services
|
||||
from core.services.crypto.TicketCustomer import TicketCustomer
|
||||
from core.services.prepare_tickets.get_public_key_by_config import get_public_key_by_config
|
||||
from core.services.prepare_tickets.get_pub_key import key_is_in_valid_format, get_pub_key
|
||||
|
||||
# utils
|
||||
from core.utils.save_data import save_data
|
||||
from core.utils.basic_operations.write_or_read_from_json import get_value_from_json_file
|
||||
# observers, constants, errors
|
||||
from core.observers.BaseObserver import BaseObserver
|
||||
from core.models.Event import Event
|
||||
from core.Constants import Constants
|
||||
from core.errors.exceptions import *
|
||||
from core.models.Result import Result #, ResultError
|
||||
from core.errors.logger import logger
|
||||
|
||||
# generic
|
||||
import traceback
|
||||
import json
|
||||
from typing import Optional
|
||||
|
||||
def make_sure_we_have_inputs(
|
||||
ALL_signed_blind_signatures: list,
|
||||
profile_object: TicketCustomer,
|
||||
ticket_observer: TicketObserver,
|
||||
connection_observer: ConnectionObserver,
|
||||
) -> dict:
|
||||
|
||||
try:
|
||||
if ALL_signed_blind_signatures == False or ALL_signed_blind_signatures == None:
|
||||
error_msg = "The Server gave back no data or it's missing for ALL_signed_blind_signatures in the unblind_and_prove_ALL_profiles function . This can't unblind blank data."
|
||||
logger.error(error_msg, exc_info=True)
|
||||
logger.debug(error_msg)
|
||||
return {"valid": False, "error_msg": error_msg}
|
||||
|
||||
# get the public key for entire loop:
|
||||
public_key_results = get_public_key_by_config(connection_observer)
|
||||
|
||||
# did we actually get the public key?
|
||||
if "data" not in public_key_results:
|
||||
error_msg = (
|
||||
"The validation function can't even get the public key to do it's loop"
|
||||
)
|
||||
logger.error(error_msg, exc_info=True)
|
||||
logger.debug(error_msg)
|
||||
return {"valid": False, "error_msg": error_msg}
|
||||
|
||||
public_key = public_key_results.get("data")
|
||||
|
||||
rejected_reasons = [None, False, ""]
|
||||
if public_key in rejected_reasons:
|
||||
error_msg = "The validation function can't get the public key"
|
||||
logger.debug(error_msg)
|
||||
return {"valid": False, "error_msg": error_msg}
|
||||
|
||||
# this just checks if it has an X and Y in a dictionary:
|
||||
if not key_is_in_valid_format(public_key) or not isinstance(public_key, dict):
|
||||
return {"valid": False, "error_msg": "invalid_key_format"}
|
||||
|
||||
logger.debug("Checking if the public key is even able to be loaded...")
|
||||
valid_key = profile_object.load_key(public_key)
|
||||
|
||||
if valid_key:
|
||||
logger.debug("Public Key can be loaded")
|
||||
return {"valid": True, "public_key": public_key}
|
||||
|
||||
else:
|
||||
error_msg = "The validation function is working with an invalid public key"
|
||||
logger.debug(error_msg)
|
||||
return {"valid": False, "error_msg": error_msg}
|
||||
|
||||
except:
|
||||
error_msg = (
|
||||
"We lack the ability to get all the inputs for the verification loop"
|
||||
)
|
||||
logger.error(error_msg, exc_info=True)
|
||||
logger.debug(error_msg)
|
||||
return {"valid": False, "error_msg": error_msg}
|
||||
|
||||
REJECTED_INPUTS = [False, None, "error"]
|
||||
|
||||
"""
|
||||
Technically this entire module is optional, as it isn't used for the actual ticket preparation.
|
||||
|
|
@ -91,40 +23,28 @@ to try to secretly identify users (by using different keys for each one).
|
|||
|
||||
def validate_blind_signatures(
|
||||
ALL_signed_blind_signatures: list,
|
||||
public_key: dict,
|
||||
ticket_observer: TicketObserver,
|
||||
connection_observer: ConnectionObserver,
|
||||
which_ticket: Optional[int] = None,
|
||||
):
|
||||
try:
|
||||
which_ticket: Optional[int] = None, # Single or Multiple Ticket Prep. If there's a value here, it's a single ticket.
|
||||
) -> Result:
|
||||
|
||||
# Setup the entire class object of "profile_object" for using all these other functions,
|
||||
profile_object = TicketCustomer()
|
||||
|
||||
# start: confirm inputs
|
||||
inputs = make_sure_we_have_inputs(
|
||||
ALL_signed_blind_signatures,
|
||||
profile_object,
|
||||
ticket_observer,
|
||||
connection_observer,
|
||||
)
|
||||
if not inputs["valid"]:
|
||||
logger.debug("ending the validation process early.")
|
||||
return inputs
|
||||
public_key = inputs["public_key"]
|
||||
# end: confirm inputs
|
||||
|
||||
#-----------------------------------
|
||||
# PREPARE FOR UPCOMING LOOP
|
||||
#-----------------------------------
|
||||
# setup basic counters, flags, and lists for the loop below:
|
||||
|
||||
if which_ticket is None:
|
||||
if which_ticket is None: # this is if it's a single or multiple ticket prep. And not just basic filtering
|
||||
which_ticket = 1
|
||||
|
||||
did_we_answer_the_key_question_yet = "no"
|
||||
list_of_failed_verifications = []
|
||||
|
||||
"""
|
||||
LOOP STARTS:
|
||||
|
||||
Looping through each signature, verifying it against the single public key.
|
||||
"""
|
||||
#-----------------------------------
|
||||
# LOOP:
|
||||
#-----------------------------------
|
||||
# Looping through each signature, verifying it against the single public key.
|
||||
for each_blind_signature in ALL_signed_blind_signatures:
|
||||
# prep from server's format:
|
||||
blind_signature = json.loads(each_blind_signature)
|
||||
|
|
@ -136,46 +56,23 @@ def validate_blind_signatures(
|
|||
|
||||
if validity_data["valid"] == True:
|
||||
# verification went fine:
|
||||
notification = f"Verified {which_ticket}'s blind signature"
|
||||
ticket_observer.notify("preparing", subject=notification)
|
||||
logger.info(f"Verified {which_ticket}'s blind signature")
|
||||
else:
|
||||
# is it an invalid pub key?
|
||||
if validity_data["message"] == "invalid_key":
|
||||
notification = f"Verification of all blind signatures is halted, because you have an invalid public key!"
|
||||
ticket_observer.notify("preparing", subject=notification)
|
||||
return [which_ticket]
|
||||
error_msg = "Verification of all blind signatures is halted, because you have an invalid public key!"
|
||||
return Result(valid=True, data=[which_ticket], message=error_msg)
|
||||
|
||||
# otherwise:
|
||||
list_of_failed_verifications.append(which_ticket)
|
||||
notification = f"Invalid {which_ticket} blind signature"
|
||||
ticket_observer.notify("preparing", subject=notification)
|
||||
logger.error(f"Invalid {which_ticket} blind signature")
|
||||
|
||||
# bump loop for next round:
|
||||
which_ticket = which_ticket + 1
|
||||
|
||||
### LOOP DONE
|
||||
|
||||
logger.debug(
|
||||
f"Exiting the validation loop with the list_of_failed_verifications: {list_of_failed_verifications}"
|
||||
)
|
||||
return list_of_failed_verifications
|
||||
|
||||
except FailedToSave as e:
|
||||
error_msg = f"FailedToSave: {e}"
|
||||
logger.error(error_msg, exc_info=True)
|
||||
return {"valid": False, "message": "error", "error": error_msg}
|
||||
|
||||
except InvalidData as e:
|
||||
error_msg = f"InvalidData error: {e}"
|
||||
logger.error(error_msg, exc_info=True)
|
||||
return {"valid": False, "message": "error", "error": error_msg}
|
||||
|
||||
except MissingData as e:
|
||||
error_msg = f"MissingData: {e}"
|
||||
logger.error(error_msg, exc_info=True)
|
||||
return {"valid": False, "message": "error", "error": error_msg}
|
||||
|
||||
except Exception as e:
|
||||
tb = traceback.extract_tb(e.__traceback__)[-1]
|
||||
error_msg = f"error type {type(e).__name__} happened on line {tb.lineno}, in function {tb.name}, giving error: {e}. The actual code in question is: {tb.line}. in this file: {tb.filename}"
|
||||
logger.error(error_msg, exc_info=True)
|
||||
return {"valid": False, "message": "error", "error": error_msg}
|
||||
return Result(valid=True, data=list_of_failed_verifications)
|
||||
|
|
|
|||
Loading…
Reference in a new issue