Files
onepilot/tsk/common/key_file_manager.py
T
2026-04-10 13:49:54 -07:00

138 lines
4.6 KiB
Python

# tsk/common/key_file_manager.py
import os
import re
import threading
import time
from tsk.c3.ui.layout import Theme
from tsk.common.env import is_agnos
class KeyFileManager:
DATA_PARAMS_D_SECOCKEY_PATH = "/data/params/d/SecOCKey"
CACHE_PARAMS_SECOCKEY_PATH = "/cache/params/SecOCKey"
HOME_SECOCKEY_PATH = os.path.expanduser("~/SecOCKey")
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance.installed_key = cls._read_key_from_files()
threading.Thread(target=cls._instance._update_key_status_loop, daemon=True).start()
return cls._instance
@staticmethod
def _is_key_valid(key: str) -> bool:
"""Checks if the key is a valid 32-character lowercase hexadecimal string."""
if not isinstance(key, str):
return False
if len(key) != 32:
return False
pattern = r"^[0-9a-f]{32}$"
return bool(re.match(pattern, key))
@staticmethod
def _read_key_from_file(file_path: str) -> str | None:
"""
Reads and validates a key from the given file path.
If the key is invalid, the file is deleted.
Returns:
The key if it's valid, None otherwise.
"""
if not os.path.exists(file_path):
return None
try:
with open(file_path, "r") as f:
key = f.read().strip()
if KeyFileManager._is_key_valid(key):
return key
else:
# Key is invalid, delete the file
try:
os.remove(file_path)
print(f"Deleted invalid key file: {file_path} which contained {key}")
except Exception as e:
print(f"Error deleting invalid key file {file_path}: {e}")
return None
except Exception as e:
print(f"Error reading key file {file_path}: {e}")
return None # Return None on any error
@staticmethod
def _read_key_from_files() -> str | None:
"""Reads the key from the appropriate file(s) based on the AGNOS environment."""
if not is_agnos():
return KeyFileManager._read_key_from_file(KeyFileManager.HOME_SECOCKEY_PATH)
data_params_d_secockey = KeyFileManager._read_key_from_file(KeyFileManager.DATA_PARAMS_D_SECOCKEY_PATH)
cache_params_secockey = KeyFileManager._read_key_from_file(KeyFileManager.CACHE_PARAMS_SECOCKEY_PATH)
existing_key = cache_params_secockey or data_params_d_secockey
if not existing_key:
return None
# Write the existing key to missing files
if data_params_d_secockey != existing_key:
KeyFileManager._write_key_to_file(KeyFileManager.DATA_PARAMS_D_SECOCKEY_PATH, existing_key)
if cache_params_secockey != existing_key:
KeyFileManager._write_key_to_file(KeyFileManager.CACHE_PARAMS_SECOCKEY_PATH, existing_key)
return existing_key
@staticmethod
def _write_key_to_file(file_path: str, key: str) -> None:
"""Writes the key to the specified file path."""
print(f"Writing key to file: {key} {file_path}")
try:
with open(file_path, "w") as f:
f.write(key)
except Exception as e:
print(f"Error writing key to file {file_path}: {e}")
def _update_key_status_loop(self) -> None:
"""Periodically updates the key status."""
while True:
self.installed_key = KeyFileManager._read_key_from_files()
time.sleep(Theme.status_update_interval) # Check every x second
def install_key(self, key: str) -> None:
"""Installs the key by writing it to the appropriate file(s) based on the AGNOS environment."""
if not KeyFileManager._is_key_valid(key):
print("Invalid key format. Installation aborted.")
return
if not is_agnos():
KeyFileManager._write_key_to_file(KeyFileManager.HOME_SECOCKEY_PATH, key)
KeyFileManager._installed_key = KeyFileManager._read_key_from_files()
return
KeyFileManager._write_key_to_file(KeyFileManager.DATA_PARAMS_D_SECOCKEY_PATH, key)
KeyFileManager._write_key_to_file(KeyFileManager.CACHE_PARAMS_SECOCKEY_PATH, key)
self.installed_key = KeyFileManager._read_key_from_files()
def uninstall_key(self) -> None:
"""Deletes the key from the appropriate file(s) based on the AGNOS environment."""
def _delete_file(file_path: str):
if os.path.exists(file_path):
try:
os.remove(file_path)
print(f"Deleted key file: {file_path}")
except Exception as e:
print(f"Error deleting key file {file_path}: {e}")
if not is_agnos():
_delete_file(KeyFileManager.HOME_SECOCKEY_PATH)
else:
_delete_file(KeyFileManager.DATA_PARAMS_D_SECOCKEY_PATH)
_delete_file(KeyFileManager.CACHE_PARAMS_SECOCKEY_PATH)
self.installed_key = KeyFileManager._read_key_from_files()