From 6691667bb1b553230c9ce6775e9d305bae6aa1f9 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Thu, 3 Jul 2025 11:35:12 -0400 Subject: [PATCH] Refactor EntryManager to use BackupManager --- examples/entry_management_demo.py | 4 +- src/password_manager/entry_management.py | 59 +++++-------------- src/password_manager/manager.py | 5 +- src/tests/test_entries_empty.py | 4 +- src/tests/test_entry_add.py | 10 +++- .../test_entry_management_checksum_path.py | 12 ++-- src/tests/test_export_totp_codes.py | 2 +- src/tests/test_manager_add_totp.py | 2 +- src/tests/test_manager_display_totp_codes.py | 4 +- src/tests/test_manager_retrieve_totp.py | 2 +- src/tests/test_manager_workflow.py | 4 +- src/tests/test_nostr_backup.py | 6 +- src/tests/test_nostr_dummy_client.py | 4 +- src/tests/test_nostr_index_size.py | 4 +- src/tests/test_password_change.py | 4 +- .../test_password_unlock_after_change.py | 4 +- src/tests/test_profile_management.py | 4 +- src/tests/test_totp_entry.py | 10 +++- 18 files changed, 70 insertions(+), 74 deletions(-) diff --git a/examples/entry_management_demo.py b/examples/entry_management_demo.py index 030187d..d5a29d8 100644 --- a/examples/entry_management_demo.py +++ b/examples/entry_management_demo.py @@ -4,6 +4,7 @@ from cryptography.fernet import Fernet from password_manager.encryption import EncryptionManager from password_manager.vault import Vault from password_manager.entry_management import EntryManager +from password_manager.backup import BackupManager from constants import initialize_app @@ -13,7 +14,8 @@ def main() -> None: key = Fernet.generate_key() enc = EncryptionManager(key, Path(".")) vault = Vault(enc, Path(".")) - manager = EntryManager(vault, Path(".")) + backup_mgr = BackupManager(Path(".")) + manager = EntryManager(vault, backup_mgr) index = manager.add_entry( "Example Website", diff --git a/src/password_manager/entry_management.py b/src/password_manager/entry_management.py index 87285ca..95539e5 100644 --- a/src/password_manager/entry_management.py +++ b/src/password_manager/entry_management.py @@ -19,10 +19,7 @@ import json import logging import hashlib import sys -import os import shutil -import time -import traceback from typing import Optional, Tuple, Dict, Any, List from pathlib import Path @@ -32,7 +29,7 @@ from password_manager.entry_types import EntryType from password_manager.totp import TotpManager from password_manager.vault import Vault -from utils.file_lock import exclusive_lock +from password_manager.backup import BackupManager # Instantiate the logger @@ -40,15 +37,16 @@ logger = logging.getLogger(__name__) class EntryManager: - def __init__(self, vault: Vault, fingerprint_dir: Path): - """ - Initializes the EntryManager with the EncryptionManager and fingerprint directory. + def __init__(self, vault: Vault, backup_manager: BackupManager): + """Initialize the EntryManager. - :param vault: The Vault instance for file access. - :param fingerprint_dir: The directory corresponding to the fingerprint. + Parameters: + vault: The Vault instance for file access. + backup_manager: Manages creation of entry database backups. """ self.vault = vault - self.fingerprint_dir = fingerprint_dir + self.backup_manager = backup_manager + self.fingerprint_dir = backup_manager.fingerprint_dir # Use paths relative to the fingerprint directory self.index_file = self.fingerprint_dir / "seedpass_entries_db.json.enc" @@ -141,7 +139,7 @@ class EntryManager: self._save_index(data) self.update_checksum() - self.backup_index_file() + self.backup_manager.create_backup() logger.info(f"Entry added successfully at index {index}.") print(colored(f"[+] Entry added successfully at index {index}.", "green")) @@ -203,7 +201,7 @@ class EntryManager: self._save_index(data) self.update_checksum() - self.backup_index_file() + self.backup_manager.create_backup() try: return TotpManager.make_otpauth_uri(label, secret, period, digits) @@ -219,7 +217,7 @@ class EntryManager: data["entries"][str(index)] = {"type": EntryType.SSH.value, "notes": notes} self._save_index(data) self.update_checksum() - self.backup_index_file() + self.backup_manager.create_backup() raise NotImplementedError("SSH key entry support not implemented yet") def add_seed(self, notes: str = "") -> int: @@ -230,7 +228,7 @@ class EntryManager: data["entries"][str(index)] = {"type": EntryType.SEED.value, "notes": notes} self._save_index(data) self.update_checksum() - self.backup_index_file() + self.backup_manager.create_backup() raise NotImplementedError("Seed entry support not implemented yet") def get_totp_code( @@ -355,7 +353,7 @@ class EntryManager: self._save_index(data) self.update_checksum() - self.backup_index_file() + self.backup_manager.create_backup() logger.info(f"Entry at index {index} modified successfully.") print( @@ -445,7 +443,7 @@ class EntryManager: logger.debug(f"Deleted entry at index {index}.") self.vault.save_index(data) self.update_checksum() - self.backup_index_file() + self.backup_manager.create_backup() logger.info(f"Entry at index {index} deleted successfully.") print( colored( @@ -491,35 +489,6 @@ class EntryManager: logger.error(f"Failed to update checksum: {e}", exc_info=True) print(colored(f"Error: Failed to update checksum: {e}", "red")) - def backup_index_file(self) -> None: - """ - Creates a backup of the encrypted JSON index file to prevent data loss. - """ - try: - # self.index_file already includes the fingerprint directory - index_file_path = self.index_file - if not index_file_path.exists(): - logger.warning( - f"Index file '{index_file_path}' does not exist. No backup created." - ) - return - - timestamp = int(time.time()) - backup_filename = f"entries_db_backup_{timestamp}.json.enc" - backup_path = self.fingerprint_dir / backup_filename - - with open(index_file_path, "rb") as original_file, open( - backup_path, "wb" - ) as backup_file: - shutil.copyfileobj(original_file, backup_file) - - logger.debug(f"Backup created at '{backup_path}'.") - print(colored(f"[+] Backup created at '{backup_path}'.", "green")) - - except Exception as e: - logger.error(f"Failed to create backup: {e}", exc_info=True) - print(colored(f"Warning: Failed to create backup: {e}", "yellow")) - def restore_from_backup(self, backup_path: str) -> None: """ Restores the index file from a specified backup file. diff --git a/src/password_manager/manager.py b/src/password_manager/manager.py index 07c6156..0d6afe2 100644 --- a/src/password_manager/manager.py +++ b/src/password_manager/manager.py @@ -751,9 +751,10 @@ class PasswordManager: raise ValueError("EncryptionManager is not initialized.") # Reinitialize the managers with the updated EncryptionManager and current fingerprint context + self.backup_manager = BackupManager(fingerprint_dir=self.fingerprint_dir) self.entry_manager = EntryManager( vault=self.vault, - fingerprint_dir=self.fingerprint_dir, + backup_manager=self.backup_manager, ) self.password_generator = PasswordGenerator( @@ -762,8 +763,6 @@ class PasswordManager: bip85=self.bip85, ) - self.backup_manager = BackupManager(fingerprint_dir=self.fingerprint_dir) - # Load relay configuration and initialize NostrClient self.config_manager = ConfigManager( vault=self.vault, diff --git a/src/tests/test_entries_empty.py b/src/tests/test_entries_empty.py index 4c466b5..b3ac16e 100644 --- a/src/tests/test_entries_empty.py +++ b/src/tests/test_entries_empty.py @@ -6,13 +6,15 @@ from helpers import create_vault, TEST_SEED, TEST_PASSWORD sys.path.append(str(Path(__file__).resolve().parents[1])) from password_manager.entry_management import EntryManager +from password_manager.backup import BackupManager from password_manager.vault import Vault def test_list_entries_empty(): with TemporaryDirectory() as tmpdir: vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, Path(tmpdir)) + backup_mgr = BackupManager(Path(tmpdir)) + entry_mgr = EntryManager(vault, backup_mgr) entries = entry_mgr.list_entries() assert entries == [] diff --git a/src/tests/test_entry_add.py b/src/tests/test_entry_add.py index 71731b8..f5cb1f4 100644 --- a/src/tests/test_entry_add.py +++ b/src/tests/test_entry_add.py @@ -9,13 +9,15 @@ from helpers import create_vault, TEST_SEED, TEST_PASSWORD sys.path.append(str(Path(__file__).resolve().parents[1])) from password_manager.entry_management import EntryManager +from password_manager.backup import BackupManager from password_manager.vault import Vault def test_add_and_retrieve_entry(): with TemporaryDirectory() as tmpdir: vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, Path(tmpdir)) + backup_mgr = BackupManager(Path(tmpdir)) + entry_mgr = EntryManager(vault, backup_mgr) index = entry_mgr.add_entry("example.com", 12, "user") entry = entry_mgr.retrieve_entry(index) @@ -47,7 +49,8 @@ def test_add_and_retrieve_entry(): def test_round_trip_entry_types(method, expected_type): with TemporaryDirectory() as tmpdir: vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, Path(tmpdir)) + backup_mgr = BackupManager(Path(tmpdir)) + entry_mgr = EntryManager(vault, backup_mgr) if method == "add_entry": index = entry_mgr.add_entry("example.com", 8) @@ -68,7 +71,8 @@ def test_round_trip_entry_types(method, expected_type): def test_legacy_entry_defaults_to_password(): with TemporaryDirectory() as tmpdir: vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, Path(tmpdir)) + backup_mgr = BackupManager(Path(tmpdir)) + entry_mgr = EntryManager(vault, backup_mgr) index = entry_mgr.add_entry("example.com", 8) diff --git a/src/tests/test_entry_management_checksum_path.py b/src/tests/test_entry_management_checksum_path.py index c002008..05e8d97 100644 --- a/src/tests/test_entry_management_checksum_path.py +++ b/src/tests/test_entry_management_checksum_path.py @@ -6,6 +6,7 @@ from helpers import create_vault, TEST_SEED, TEST_PASSWORD sys.path.append(str(Path(__file__).resolve().parents[1])) from password_manager.entry_management import EntryManager +from password_manager.backup import BackupManager from password_manager.vault import Vault @@ -13,7 +14,8 @@ def test_update_checksum_writes_to_expected_path(): with TemporaryDirectory() as tmpdir: tmp_path = Path(tmpdir) vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, tmp_path) + backup_mgr = BackupManager(tmp_path) + entry_mgr = EntryManager(vault, backup_mgr) # create an empty index file vault.save_index({"entries": {}}) @@ -27,10 +29,12 @@ def test_backup_index_file_creates_backup_in_directory(): with TemporaryDirectory() as tmpdir: tmp_path = Path(tmpdir) vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, tmp_path) + backup_mgr = BackupManager(tmp_path) + entry_mgr = EntryManager(vault, backup_mgr) vault.save_index({"entries": {}}) - entry_mgr.backup_index_file() + entry_mgr.backup_manager.create_backup() - backups = list(tmp_path.glob("entries_db_backup_*.json.enc")) + backup_dir = tmp_path / "backups" + backups = list(backup_dir.glob("entries_db_backup_*.json.enc")) assert len(backups) == 1 diff --git a/src/tests/test_export_totp_codes.py b/src/tests/test_export_totp_codes.py index 0c40936..5250d28 100644 --- a/src/tests/test_export_totp_codes.py +++ b/src/tests/test_export_totp_codes.py @@ -21,8 +21,8 @@ class FakeNostrClient: def test_handle_export_totp_codes(monkeypatch, tmp_path): vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, tmp_path) backup_mgr = BackupManager(tmp_path) + entry_mgr = EntryManager(vault, backup_mgr) pm = PasswordManager.__new__(PasswordManager) pm.encryption_mode = EncryptionMode.SEED_ONLY diff --git a/src/tests/test_manager_add_totp.py b/src/tests/test_manager_add_totp.py index f7ccdf6..0a1e102 100644 --- a/src/tests/test_manager_add_totp.py +++ b/src/tests/test_manager_add_totp.py @@ -25,8 +25,8 @@ def test_handle_add_totp(monkeypatch, capsys): with TemporaryDirectory() as tmpdir: tmp_path = Path(tmpdir) vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, tmp_path) backup_mgr = BackupManager(tmp_path) + entry_mgr = EntryManager(vault, backup_mgr) pm = PasswordManager.__new__(PasswordManager) pm.encryption_mode = EncryptionMode.SEED_ONLY diff --git a/src/tests/test_manager_display_totp_codes.py b/src/tests/test_manager_display_totp_codes.py index b462c36..0c52bfe 100644 --- a/src/tests/test_manager_display_totp_codes.py +++ b/src/tests/test_manager_display_totp_codes.py @@ -24,8 +24,8 @@ def test_handle_display_totp_codes(monkeypatch, capsys): with TemporaryDirectory() as tmpdir: tmp_path = Path(tmpdir) vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, tmp_path) backup_mgr = BackupManager(tmp_path) + entry_mgr = EntryManager(vault, backup_mgr) pm = PasswordManager.__new__(PasswordManager) pm.encryption_mode = EncryptionMode.SEED_ONLY @@ -62,8 +62,8 @@ def test_display_totp_codes_excludes_blacklisted(monkeypatch, capsys): with TemporaryDirectory() as tmpdir: tmp_path = Path(tmpdir) vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, tmp_path) backup_mgr = BackupManager(tmp_path) + entry_mgr = EntryManager(vault, backup_mgr) pm = PasswordManager.__new__(PasswordManager) pm.encryption_mode = EncryptionMode.SEED_ONLY diff --git a/src/tests/test_manager_retrieve_totp.py b/src/tests/test_manager_retrieve_totp.py index c29b6a3..4b28bfc 100644 --- a/src/tests/test_manager_retrieve_totp.py +++ b/src/tests/test_manager_retrieve_totp.py @@ -24,8 +24,8 @@ def test_handle_retrieve_totp_entry(monkeypatch, capsys): with TemporaryDirectory() as tmpdir: tmp_path = Path(tmpdir) vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, tmp_path) backup_mgr = BackupManager(tmp_path) + entry_mgr = EntryManager(vault, backup_mgr) pm = PasswordManager.__new__(PasswordManager) pm.encryption_mode = EncryptionMode.SEED_ONLY diff --git a/src/tests/test_manager_workflow.py b/src/tests/test_manager_workflow.py index d78d43a..8d00a8c 100644 --- a/src/tests/test_manager_workflow.py +++ b/src/tests/test_manager_workflow.py @@ -29,8 +29,8 @@ def test_manager_workflow(monkeypatch): with TemporaryDirectory() as tmpdir: tmp_path = Path(tmpdir) vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, tmp_path) backup_mgr = BackupManager(tmp_path) + entry_mgr = EntryManager(vault, backup_mgr) monkeypatch.setattr("password_manager.manager.NostrClient", FakeNostrClient) @@ -64,7 +64,7 @@ def test_manager_workflow(monkeypatch): pm.handle_add_password() assert pm.is_dirty is False - backups = list(tmp_path.glob("entries_db_backup_*.json.enc")) + backups = list((tmp_path / "backups").glob("entries_db_backup_*.json.enc")) assert len(backups) == 1 checksum_file = tmp_path / "seedpass_entries_db_checksum.txt" assert checksum_file.exists() diff --git a/src/tests/test_nostr_backup.py b/src/tests/test_nostr_backup.py index 0ab10f8..0d0ab9d 100644 --- a/src/tests/test_nostr_backup.py +++ b/src/tests/test_nostr_backup.py @@ -8,6 +8,7 @@ from helpers import create_vault, TEST_SEED, TEST_PASSWORD sys.path.append(str(Path(__file__).resolve().parents[1])) from password_manager.entry_management import EntryManager +from password_manager.backup import BackupManager from password_manager.vault import Vault from nostr.client import NostrClient @@ -16,7 +17,8 @@ def test_backup_and_publish_to_nostr(): with TemporaryDirectory() as tmpdir: tmp_path = Path(tmpdir) vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, tmp_path) + backup_mgr = BackupManager(tmp_path) + entry_mgr = EntryManager(vault, backup_mgr) # create an index by adding an entry entry_mgr.add_entry("example.com", 12) @@ -34,7 +36,7 @@ def test_backup_and_publish_to_nostr(): enc_mgr, "decrypt_parent_seed", return_value="seed" ): nostr_client = NostrClient(enc_mgr, "fp") - entry_mgr.backup_index_file() + entry_mgr.backup_manager.create_backup() result = asyncio.run(nostr_client.publish_snapshot(encrypted_index)) mock_publish.assert_awaited_with(encrypted_index) diff --git a/src/tests/test_nostr_dummy_client.py b/src/tests/test_nostr_dummy_client.py index fe4e998..0f94836 100644 --- a/src/tests/test_nostr_dummy_client.py +++ b/src/tests/test_nostr_dummy_client.py @@ -4,12 +4,14 @@ import math from helpers import create_vault, dummy_nostr_client from password_manager.entry_management import EntryManager +from password_manager.backup import BackupManager from nostr.client import prepare_snapshot def test_manifest_generation(tmp_path): vault, enc_mgr = create_vault(tmp_path) - entry_mgr = EntryManager(vault, tmp_path) + backup_mgr = BackupManager(tmp_path) + entry_mgr = EntryManager(vault, backup_mgr) entry_mgr.add_entry("example.com", 12) entry_mgr.add_entry("test.com", 12) encrypted = vault.get_encrypted_index() diff --git a/src/tests/test_nostr_index_size.py b/src/tests/test_nostr_index_size.py index 00dc430..7860cad 100644 --- a/src/tests/test_nostr_index_size.py +++ b/src/tests/test_nostr_index_size.py @@ -16,6 +16,7 @@ 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.backup import BackupManager from password_manager.vault import Vault from nostr.client import NostrClient, Kind, KindStandard @@ -40,7 +41,8 @@ def test_nostr_index_size_limits(): ) npub = client.key_manager.get_npub() vault = Vault(enc_mgr, tmpdir) - entry_mgr = EntryManager(vault, Path(tmpdir)) + backup_mgr = BackupManager(Path(tmpdir)) + entry_mgr = EntryManager(vault, backup_mgr) delay = float(os.getenv("NOSTR_TEST_DELAY", "5")) size = 16 diff --git a/src/tests/test_password_change.py b/src/tests/test_password_change.py index 5be68fb..a3880a8 100644 --- a/src/tests/test_password_change.py +++ b/src/tests/test_password_change.py @@ -10,6 +10,7 @@ sys.path.append(str(Path(__file__).resolve().parents[1])) from password_manager.entry_management import EntryManager from password_manager.config_manager import ConfigManager +from password_manager.backup import BackupManager from password_manager.vault import Vault from password_manager.manager import PasswordManager, EncryptionMode @@ -18,7 +19,8 @@ def test_change_password_triggers_nostr_backup(monkeypatch): with TemporaryDirectory() as tmpdir: fp = Path(tmpdir) vault, enc_mgr = create_vault(fp, TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, fp) + backup_mgr = BackupManager(fp) + entry_mgr = EntryManager(vault, backup_mgr) cfg_mgr = ConfigManager(vault, fp) pm = PasswordManager.__new__(PasswordManager) diff --git a/src/tests/test_password_unlock_after_change.py b/src/tests/test_password_unlock_after_change.py index 5fabc93..f2d6126 100644 --- a/src/tests/test_password_unlock_after_change.py +++ b/src/tests/test_password_unlock_after_change.py @@ -10,6 +10,7 @@ sys.path.append(str(Path(__file__).resolve().parents[1])) from password_manager.encryption import EncryptionManager from password_manager.vault import Vault from password_manager.entry_management import EntryManager +from password_manager.backup import BackupManager from password_manager.config_manager import ConfigManager from password_manager.manager import PasswordManager, EncryptionMode from utils.key_derivation import derive_index_key, derive_key_from_password @@ -29,7 +30,8 @@ def test_password_change_and_unlock(monkeypatch): enc_mgr = EncryptionManager(index_key, fp) seed_mgr = EncryptionManager(seed_key, fp) vault = Vault(enc_mgr, fp) - entry_mgr = EntryManager(vault, fp) + backup_mgr = BackupManager(fp) + entry_mgr = EntryManager(vault, backup_mgr) cfg_mgr = ConfigManager(vault, fp) vault.save_index({"entries": {}}) diff --git a/src/tests/test_profile_management.py b/src/tests/test_profile_management.py index 6aab635..21707ed 100644 --- a/src/tests/test_profile_management.py +++ b/src/tests/test_profile_management.py @@ -14,6 +14,7 @@ import constants import password_manager.manager as manager_module from password_manager.vault import Vault from password_manager.entry_management import EntryManager +from password_manager.backup import BackupManager from password_manager.manager import EncryptionMode @@ -51,7 +52,8 @@ def test_add_and_delete_entry(monkeypatch): assert pm.fingerprint_manager.current_fingerprint == fingerprint vault, enc_mgr = create_vault(fingerprint_dir, TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, fingerprint_dir) + backup_mgr = BackupManager(fingerprint_dir) + entry_mgr = EntryManager(vault, backup_mgr) pm.encryption_manager = enc_mgr pm.vault = vault diff --git a/src/tests/test_totp_entry.py b/src/tests/test_totp_entry.py index d79aa41..27b752c 100644 --- a/src/tests/test_totp_entry.py +++ b/src/tests/test_totp_entry.py @@ -10,6 +10,7 @@ from helpers import create_vault, TEST_SEED, TEST_PASSWORD sys.path.append(str(Path(__file__).resolve().parents[1])) from password_manager.entry_management import EntryManager +from password_manager.backup import BackupManager from password_manager.vault import Vault from password_manager.totp import TotpManager import pyotp @@ -18,7 +19,8 @@ import pyotp def test_add_totp_and_get_code(): with TemporaryDirectory() as tmpdir: vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, Path(tmpdir)) + backup_mgr = BackupManager(Path(tmpdir)) + entry_mgr = EntryManager(vault, backup_mgr) uri = entry_mgr.add_totp("Example", TEST_SEED) assert uri.startswith("otpauth://totp/") @@ -41,7 +43,8 @@ def test_add_totp_and_get_code(): def test_totp_time_remaining(monkeypatch): with TemporaryDirectory() as tmpdir: vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD) - entry_mgr = EntryManager(vault, Path(tmpdir)) + backup_mgr = BackupManager(Path(tmpdir)) + entry_mgr = EntryManager(vault, backup_mgr) entry_mgr.add_totp("Example", TEST_SEED) @@ -52,7 +55,8 @@ def test_totp_time_remaining(monkeypatch): def test_add_totp_imported(tmp_path): vault, enc = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD) - em = EntryManager(vault, tmp_path) + backup_mgr = BackupManager(tmp_path) + em = EntryManager(vault, backup_mgr) secret = "JBSWY3DPEHPK3PXP" em.add_totp("Imported", TEST_SEED, secret=secret) entry = em.retrieve_entry(0)