diff --git a/src/password_manager/manager.py b/src/password_manager/manager.py index f44e94b..0b68745 100644 --- a/src/password_manager/manager.py +++ b/src/password_manager/manager.py @@ -265,8 +265,13 @@ class PasswordManager: Prompts the user to select an existing fingerprint or add a new one. """ try: - print(colored("\nAvailable Seed Profiles:", "cyan")) fingerprints = self.fingerprint_manager.list_fingerprints() + current = self.fingerprint_manager.current_fingerprint + if current and current in fingerprints: + self.select_fingerprint(current) + return + + print(colored("\nAvailable Seed Profiles:", "cyan")) for idx, fp in enumerate(fingerprints, start=1): print(colored(f"{idx}. {fp}", "cyan")) diff --git a/src/tests/test_last_used_fingerprint.py b/src/tests/test_last_used_fingerprint.py new file mode 100644 index 0000000..b097c4a --- /dev/null +++ b/src/tests/test_last_used_fingerprint.py @@ -0,0 +1,60 @@ +import importlib +from pathlib import Path +from tempfile import TemporaryDirectory + +import constants +import password_manager.manager as manager_module +from utils.fingerprint_manager import FingerprintManager +from password_manager.manager import EncryptionMode + +from helpers import TEST_SEED + + +def test_last_used_fingerprint(monkeypatch): + with TemporaryDirectory() as tmpdir: + tmp_path = Path(tmpdir) + monkeypatch.setattr(Path, "home", lambda: tmp_path) + + importlib.reload(constants) + importlib.reload(manager_module) + + fm = FingerprintManager(constants.APP_DIR) + fp = fm.add_fingerprint(TEST_SEED) + assert fm.current_fingerprint == fp + + # Ensure persistence on reload + fm2 = FingerprintManager(constants.APP_DIR) + assert fm2.current_fingerprint == fp + + def init_fm(self): + self.fingerprint_manager = fm2 + + monkeypatch.setattr( + manager_module.PasswordManager, "initialize_fingerprint_manager", init_fm + ) + monkeypatch.setattr( + manager_module.PasswordManager, + "setup_encryption_manager", + lambda *a, **k: True, + ) + monkeypatch.setattr( + manager_module.PasswordManager, "initialize_bip85", lambda self: None + ) + monkeypatch.setattr( + manager_module.PasswordManager, "initialize_managers", lambda self: None + ) + monkeypatch.setattr( + manager_module.PasswordManager, + "sync_index_from_nostr_if_missing", + lambda self: None, + ) + monkeypatch.setattr( + manager_module.PasswordManager, "verify_password", lambda *a, **k: True + ) + monkeypatch.setattr( + "builtins.input", + lambda *a, **k: (_ for _ in ()).throw(AssertionError("prompted")), + ) + + pm = manager_module.PasswordManager() + assert pm.current_fingerprint == fp diff --git a/src/utils/fingerprint_manager.py b/src/utils/fingerprint_manager.py index a47a942..34ee4a0 100644 --- a/src/utils/fingerprint_manager.py +++ b/src/utils/fingerprint_manager.py @@ -34,8 +34,7 @@ class FingerprintManager: self.app_dir = app_dir self.fingerprints_file = self.app_dir / "fingerprints.json" self._ensure_app_directory() - self.fingerprints = self._load_fingerprints() - self.current_fingerprint: Optional[str] = None + self.fingerprints, self.current_fingerprint = self._load_fingerprints() def get_current_fingerprint_dir(self) -> Optional[Path]: """ @@ -63,28 +62,25 @@ class FingerprintManager: ) raise - def _load_fingerprints(self) -> List[str]: - """ - Loads the list of fingerprints from the fingerprints.json file. - - Returns: - List[str]: A list of fingerprint strings. - """ + def _load_fingerprints(self) -> tuple[list[str], Optional[str]]: + """Return stored fingerprints and the last used fingerprint.""" try: if self.fingerprints_file.exists(): with open(self.fingerprints_file, "r") as f: data = json.load(f) - fingerprints = data.get("fingerprints", []) - logger.debug(f"Loaded fingerprints: {fingerprints}") - return fingerprints - else: + fingerprints = data.get("fingerprints", []) + current = data.get("last_used") logger.debug( - "fingerprints.json not found. Initializing empty fingerprint list." + f"Loaded fingerprints: {fingerprints} (last used: {current})" ) - return [] + return fingerprints, current + logger.debug( + "fingerprints.json not found. Initializing empty fingerprint list." + ) + return [], None except Exception as e: logger.error(f"Failed to load fingerprints: {e}", exc_info=True) - return [] + return [], None def _save_fingerprints(self): """ @@ -92,8 +88,17 @@ class FingerprintManager: """ try: with open(self.fingerprints_file, "w") as f: - json.dump({"fingerprints": self.fingerprints}, f, indent=4) - logger.debug(f"Fingerprints saved: {self.fingerprints}") + json.dump( + { + "fingerprints": self.fingerprints, + "last_used": self.current_fingerprint, + }, + f, + indent=4, + ) + logger.debug( + f"Fingerprints saved: {self.fingerprints} (last used: {self.current_fingerprint})" + ) except Exception as e: logger.error(f"Failed to save fingerprints: {e}", exc_info=True) raise @@ -111,6 +116,7 @@ class FingerprintManager: fingerprint = generate_fingerprint(seed_phrase) if fingerprint and fingerprint not in self.fingerprints: self.fingerprints.append(fingerprint) + self.current_fingerprint = fingerprint self._save_fingerprints() logger.info(f"Fingerprint {fingerprint} added successfully.") # Create fingerprint directory @@ -138,6 +144,10 @@ class FingerprintManager: if fingerprint in self.fingerprints: try: self.fingerprints.remove(fingerprint) + if self.current_fingerprint == fingerprint: + self.current_fingerprint = ( + self.fingerprints[0] if self.fingerprints else None + ) self._save_fingerprints() # Remove fingerprint directory fingerprint_dir = self.app_dir / fingerprint @@ -181,6 +191,7 @@ class FingerprintManager: """ if fingerprint in self.fingerprints: self.current_fingerprint = fingerprint + self._save_fingerprints() logger.info(f"Fingerprint {fingerprint} selected.") return True else: