Handle empty profile cleanup

This commit is contained in:
thePR0M3TH3AN
2025-08-05 12:24:53 -04:00
parent 0d883b2736
commit 1f669746db
4 changed files with 89 additions and 16 deletions

View File

@@ -187,11 +187,7 @@ def handle_add_new_fingerprint(password_manager: PasswordManager):
def handle_remove_fingerprint(password_manager: PasswordManager): def handle_remove_fingerprint(password_manager: PasswordManager):
""" """Handle removing an existing seed profile."""
Handles removing an existing seed profile.
:param password_manager: An instance of PasswordManager.
"""
try: try:
fingerprints = password_manager.fingerprint_manager.list_fingerprints() fingerprints = password_manager.fingerprint_manager.list_fingerprints()
if not fingerprints: if not fingerprints:
@@ -210,12 +206,24 @@ def handle_remove_fingerprint(password_manager: PasswordManager):
selected_fingerprint = fingerprints[int(choice) - 1] selected_fingerprint = fingerprints[int(choice) - 1]
confirm = confirm_action( confirm = confirm_action(
f"Are you sure you want to remove seed profile {selected_fingerprint}? This will delete all associated data. (Y/N): " f"Are you sure you want to remove seed profile {selected_fingerprint}? This will delete all associated data. (Y/N):"
) )
if confirm: if confirm:
def _cleanup_and_exit() -> None:
password_manager.current_fingerprint = None
password_manager.is_dirty = False
getattr(password_manager, "cleanup", lambda: None)()
print(colored("All seed profiles removed. Exiting.", "yellow"))
sys.exit(0)
if password_manager.fingerprint_manager.remove_fingerprint( if password_manager.fingerprint_manager.remove_fingerprint(
selected_fingerprint selected_fingerprint, _cleanup_and_exit
): ):
password_manager.current_fingerprint = (
password_manager.fingerprint_manager.current_fingerprint
)
password_manager.is_dirty = False
print( print(
colored( colored(
f"Seed profile {selected_fingerprint} removed successfully.", f"Seed profile {selected_fingerprint} removed successfully.",
@@ -1028,11 +1036,15 @@ def display_menu(
getattr(password_manager, "start_background_relay_check", lambda: None)() getattr(password_manager, "start_background_relay_check", lambda: None)()
continue continue
# Periodically push updates to Nostr # Periodically push updates to Nostr
if ( current_fp = getattr(password_manager, "current_fingerprint", None)
password_manager.is_dirty if current_fp:
and time.time() - password_manager.last_update >= sync_interval if (
): password_manager.is_dirty
handle_post_to_nostr(password_manager) and time.time() - password_manager.last_update >= sync_interval
):
handle_post_to_nostr(password_manager)
password_manager.is_dirty = False
else:
password_manager.is_dirty = False password_manager.is_dirty = False
# Flush logging handlers # Flush logging handlers

View File

@@ -15,6 +15,7 @@ def test_auto_sync_triggers_post(monkeypatch):
is_dirty=True, is_dirty=True,
last_update=time.time() - 0.2, last_update=time.time() - 0.2,
last_activity=time.time(), last_activity=time.time(),
current_fingerprint="fp",
nostr_client=SimpleNamespace(close_client_pool=lambda: None), nostr_client=SimpleNamespace(close_client_pool=lambda: None),
handle_add_password=lambda: None, handle_add_password=lambda: None,
handle_retrieve_entry=lambda: None, handle_retrieve_entry=lambda: None,

View File

@@ -0,0 +1,55 @@
import time
from types import SimpleNamespace
import pytest
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).resolve().parents[1]))
import main
from utils.fingerprint_manager import FingerprintManager
from tests.helpers import TEST_SEED
def test_profile_deletion_stops_sync(monkeypatch, tmp_path):
fm = FingerprintManager(tmp_path)
fp = fm.add_fingerprint(TEST_SEED)
calls = {"post": 0, "cleanup": 0}
def fake_post(_pm):
calls["post"] += 1
monkeypatch.setattr(main, "handle_post_to_nostr", fake_post)
monkeypatch.setattr("builtins.input", lambda *_: "1")
monkeypatch.setattr(main, "confirm_action", lambda *_: True)
pm = SimpleNamespace(
fingerprint_manager=fm,
current_fingerprint=fp,
is_dirty=False,
last_update=time.time(),
last_activity=time.time(),
nostr_client=SimpleNamespace(close_client_pool=lambda: None),
handle_add_password=lambda: None,
handle_retrieve_entry=lambda: None,
handle_modify_entry=lambda: None,
update_activity=lambda: None,
lock_vault=lambda: None,
unlock_vault=lambda: None,
start_background_sync=lambda: None,
start_background_relay_check=lambda: None,
cleanup=lambda: calls.__setitem__("cleanup", calls["cleanup"] + 1),
)
main.handle_post_to_nostr(pm)
assert calls["post"] == 1
with pytest.raises(SystemExit):
main.handle_remove_fingerprint(pm)
assert calls["post"] == 1
assert calls["cleanup"] == 1
pm.current_fingerprint = fm.current_fingerprint
assert pm.current_fingerprint is None
assert pm.is_dirty is False

View File

@@ -5,7 +5,7 @@ import json
import logging import logging
import traceback import traceback
from pathlib import Path from pathlib import Path
from typing import List, Optional from typing import Callable, List, Optional
import shutil # Ensure shutil is imported if used within the class import shutil # Ensure shutil is imported if used within the class
@@ -138,12 +138,15 @@ class FingerprintManager:
logger.error("Fingerprint generation failed.") logger.error("Fingerprint generation failed.")
return None return None
def remove_fingerprint(self, fingerprint: str) -> bool: def remove_fingerprint(
""" self, fingerprint: str, on_last_removed: Optional[Callable[[], None]] = None
Removes a fingerprint and its associated directory. ) -> bool:
"""Remove a fingerprint and its associated directory.
Parameters: Parameters:
fingerprint (str): The fingerprint to remove. fingerprint (str): The fingerprint to remove.
on_last_removed (Callable | None): Callback invoked when the last
fingerprint is deleted.
Returns: Returns:
bool: True if removed successfully, False otherwise. bool: True if removed successfully, False otherwise.
@@ -167,6 +170,8 @@ class FingerprintManager:
shutil.rmtree(child) shutil.rmtree(child)
fingerprint_dir.rmdir() fingerprint_dir.rmdir()
logger.info(f"Fingerprint {fingerprint} removed successfully.") logger.info(f"Fingerprint {fingerprint} removed successfully.")
if not self.fingerprints and on_last_removed:
on_last_removed()
return True return True
except Exception as e: except Exception as e:
logger.error( logger.error(