From ec1bda7ef578a384744ee1929edc0411fc0af6ad Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sun, 29 Jun 2025 22:16:36 -0400 Subject: [PATCH] Backup index to Nostr after password change --- src/password_manager/manager.py | 13 +++++++++ src/tests/test_password_change.py | 46 +++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/tests/test_password_change.py diff --git a/src/password_manager/manager.py b/src/password_manager/manager.py index c891417..2054dab 100644 --- a/src/password_manager/manager.py +++ b/src/password_manager/manager.py @@ -1202,6 +1202,19 @@ class PasswordManager: ) print(colored("Master password changed successfully.", "green")) + + # Automatically push the newly re-encrypted index to Nostr so the + # latest state is backed up remotely after a password change. + try: + encrypted_data = self.get_encrypted_data() + if encrypted_data: + self.nostr_client.publish_json_to_nostr(encrypted_data) + logging.info( + "Encrypted index posted to Nostr after password change." + ) + except Exception as nostr_error: + logging.error(f"Failed to post updated index to Nostr: {nostr_error}") + logging.error(traceback.format_exc()) except Exception as e: logging.error(f"Failed to change password: {e}") logging.error(traceback.format_exc()) diff --git a/src/tests/test_password_change.py b/src/tests/test_password_change.py new file mode 100644 index 0000000..12efc66 --- /dev/null +++ b/src/tests/test_password_change.py @@ -0,0 +1,46 @@ +import sys +from pathlib import Path +from tempfile import TemporaryDirectory +from types import SimpleNamespace +from unittest.mock import patch + +from cryptography.fernet import Fernet + +sys.path.append(str(Path(__file__).resolve().parents[1])) + +from password_manager.encryption import EncryptionManager +from password_manager.entry_management import EntryManager +from password_manager.config_manager import ConfigManager +from password_manager.manager import PasswordManager + + +def test_change_password_triggers_nostr_backup(monkeypatch): + with TemporaryDirectory() as tmpdir: + fp = Path(tmpdir) + enc_mgr = EncryptionManager(Fernet.generate_key(), fp) + entry_mgr = EntryManager(enc_mgr, fp) + cfg_mgr = ConfigManager(enc_mgr, fp) + + pm = PasswordManager.__new__(PasswordManager) + pm.encryption_manager = enc_mgr + pm.entry_manager = entry_mgr + pm.config_manager = cfg_mgr + pm.password_generator = SimpleNamespace(encryption_manager=enc_mgr) + pm.fingerprint_dir = fp + pm.current_fingerprint = "fp" + pm.parent_seed = "seed" + pm.store_hashed_password = lambda pw: None + pm.verify_password = lambda pw: True + + monkeypatch.setattr( + "password_manager.manager.prompt_existing_password", lambda *_: "old" + ) + monkeypatch.setattr( + "password_manager.manager.prompt_for_password", lambda: "new" + ) + + with patch("password_manager.manager.NostrClient") as MockClient: + mock_instance = MockClient.return_value + pm.nostr_client = mock_instance + pm.change_password() + mock_instance.publish_json_to_nostr.assert_called_once()