Pass config manager to backup

This commit is contained in:
thePR0M3TH3AN
2025-07-03 11:47:38 -04:00
parent c72b08a2e9
commit a5aefd8548
20 changed files with 81 additions and 34 deletions

View File

@@ -19,6 +19,8 @@ import traceback
from pathlib import Path
from termcolor import colored
from password_manager.config_manager import ConfigManager
from utils.file_lock import exclusive_lock
from constants import APP_DIR
@@ -37,14 +39,16 @@ class BackupManager:
BACKUP_FILENAME_TEMPLATE = "entries_db_backup_{timestamp}.json.enc"
def __init__(self, fingerprint_dir: Path):
def __init__(self, fingerprint_dir: Path, config_manager: ConfigManager):
"""
Initializes the BackupManager with the fingerprint directory.
Parameters:
fingerprint_dir (Path): The directory corresponding to the fingerprint.
config_manager (ConfigManager): Configuration manager for profile settings.
"""
self.fingerprint_dir = fingerprint_dir
self.config_manager = config_manager
self.backup_dir = self.fingerprint_dir / "backups"
self.backup_dir.mkdir(parents=True, exist_ok=True)
self.index_file = self.fingerprint_dir / "seedpass_entries_db.json.enc"

View File

@@ -751,7 +751,14 @@ 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.config_manager = ConfigManager(
vault=self.vault,
fingerprint_dir=self.fingerprint_dir,
)
self.backup_manager = BackupManager(
fingerprint_dir=self.fingerprint_dir,
config_manager=self.config_manager,
)
self.entry_manager = EntryManager(
vault=self.vault,
backup_manager=self.backup_manager,
@@ -764,10 +771,6 @@ class PasswordManager:
)
# Load relay configuration and initialize NostrClient
self.config_manager = ConfigManager(
vault=self.vault,
fingerprint_dir=self.fingerprint_dir,
)
config = self.config_manager.load_config()
relay_list = config.get("relays", list(DEFAULT_RELAYS))
self.inactivity_timeout = config.get(

View File

@@ -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.backup import BackupManager
from password_manager.config_manager import ConfigManager
def test_backup_restore_workflow(monkeypatch):
with TemporaryDirectory() as tmpdir:
fp_dir = Path(tmpdir)
vault, enc_mgr = create_vault(fp_dir, TEST_SEED, TEST_PASSWORD)
backup_mgr = BackupManager(fp_dir)
cfg_mgr = ConfigManager(vault, fp_dir)
backup_mgr = BackupManager(fp_dir, cfg_mgr)
index_file = fp_dir / "seedpass_entries_db.json.enc"

View File

@@ -9,6 +9,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.backup import BackupManager
from password_manager.config_manager import ConfigManager
from utils.key_derivation import derive_index_key, derive_key_from_password
@@ -34,9 +35,12 @@ def _reader(index_key: bytes, dir_path: Path, loops: int, out: Queue) -> None:
out.put(repr(e))
def _backup(dir_path: Path, loops: int, out: Queue) -> None:
def _backup(index_key: bytes, dir_path: Path, loops: int, out: Queue) -> None:
try:
bm = BackupManager(dir_path)
enc = EncryptionManager(index_key, dir_path)
vault = Vault(enc, dir_path)
cfg = ConfigManager(vault, dir_path)
bm = BackupManager(dir_path, cfg)
for _ in range(loops):
bm.create_backup()
except Exception as e: # pragma: no cover - capture
@@ -58,7 +62,7 @@ def test_concurrency_stress(tmp_path: Path, loops: int, _):
Process(target=_writer, args=(index_key, tmp_path, loops, q)),
Process(target=_reader, args=(index_key, tmp_path, loops, q)),
Process(target=_reader, args=(index_key, tmp_path, loops, q)),
Process(target=_backup, args=(tmp_path, loops, q)),
Process(target=_backup, args=(index_key, tmp_path, loops, q)),
]
for p in procs:

View File

@@ -8,12 +8,14 @@ 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.config_manager import ConfigManager
def test_list_entries_empty():
with TemporaryDirectory() as tmpdir:
vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD)
backup_mgr = BackupManager(Path(tmpdir))
cfg_mgr = ConfigManager(vault, Path(tmpdir))
backup_mgr = BackupManager(Path(tmpdir), cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
entries = entry_mgr.list_entries()

View File

@@ -11,12 +11,14 @@ 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.config_manager import ConfigManager
def test_add_and_retrieve_entry():
with TemporaryDirectory() as tmpdir:
vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD)
backup_mgr = BackupManager(Path(tmpdir))
cfg_mgr = ConfigManager(vault, Path(tmpdir))
backup_mgr = BackupManager(Path(tmpdir), cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
index = entry_mgr.add_entry("example.com", 12, "user")
@@ -49,7 +51,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)
backup_mgr = BackupManager(Path(tmpdir))
cfg_mgr = ConfigManager(vault, Path(tmpdir))
backup_mgr = BackupManager(Path(tmpdir), cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
if method == "add_entry":
@@ -71,7 +74,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)
backup_mgr = BackupManager(Path(tmpdir))
cfg_mgr = ConfigManager(vault, Path(tmpdir))
backup_mgr = BackupManager(Path(tmpdir), cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
index = entry_mgr.add_entry("example.com", 8)

View File

@@ -8,13 +8,15 @@ 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.config_manager import ConfigManager
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)
backup_mgr = BackupManager(tmp_path)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
# create an empty index file
@@ -29,7 +31,8 @@ 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)
backup_mgr = BackupManager(tmp_path)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
vault.save_index({"entries": {}})

View File

@@ -11,6 +11,7 @@ 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.manager import PasswordManager, EncryptionMode
from password_manager.config_manager import ConfigManager
from password_manager.totp import TotpManager
@@ -21,7 +22,8 @@ class FakeNostrClient:
def test_handle_export_totp_codes(monkeypatch, tmp_path):
vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
backup_mgr = BackupManager(tmp_path)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
pm = PasswordManager.__new__(PasswordManager)

View File

@@ -10,6 +10,7 @@ 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.manager import PasswordManager, EncryptionMode
from password_manager.config_manager import ConfigManager
class FakeNostrClient:
@@ -25,7 +26,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)
backup_mgr = BackupManager(tmp_path)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
pm = PasswordManager.__new__(PasswordManager)

View File

@@ -9,6 +9,7 @@ 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.manager import PasswordManager, EncryptionMode
from password_manager.config_manager import ConfigManager
class FakeNostrClient:
@@ -24,7 +25,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)
backup_mgr = BackupManager(tmp_path)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
pm = PasswordManager.__new__(PasswordManager)
@@ -62,7 +64,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)
backup_mgr = BackupManager(tmp_path)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
pm = PasswordManager.__new__(PasswordManager)

View File

@@ -9,6 +9,7 @@ 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.manager import PasswordManager, EncryptionMode, TotpManager
from password_manager.config_manager import ConfigManager
class FakeNostrClient:
@@ -24,7 +25,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)
backup_mgr = BackupManager(tmp_path)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
pm = PasswordManager.__new__(PasswordManager)

View File

@@ -9,6 +9,7 @@ from password_manager.entry_management import EntryManager
from password_manager.vault import Vault
from password_manager.backup import BackupManager
from password_manager.manager import PasswordManager, EncryptionMode
from password_manager.config_manager import ConfigManager
class FakePasswordGenerator:
@@ -29,7 +30,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)
backup_mgr = BackupManager(tmp_path)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
monkeypatch.setattr("password_manager.manager.NostrClient", FakeNostrClient)

View File

@@ -10,6 +10,7 @@ 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.config_manager import ConfigManager
from nostr.client import NostrClient
@@ -17,7 +18,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)
backup_mgr = BackupManager(tmp_path)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
# create an index by adding an entry

View File

@@ -5,12 +5,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 password_manager.config_manager import ConfigManager
from nostr.client import prepare_snapshot
def test_manifest_generation(tmp_path):
vault, enc_mgr = create_vault(tmp_path)
backup_mgr = BackupManager(tmp_path)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
entry_mgr.add_entry("example.com", 12)
entry_mgr.add_entry("test.com", 12)

View File

@@ -18,6 +18,7 @@ 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 password_manager.config_manager import ConfigManager
from nostr.client import NostrClient, Kind, KindStandard
@@ -41,7 +42,8 @@ def test_nostr_index_size_limits():
)
npub = client.key_manager.get_npub()
vault = Vault(enc_mgr, tmpdir)
backup_mgr = BackupManager(Path(tmpdir))
cfg_mgr = ConfigManager(vault, Path(tmpdir))
backup_mgr = BackupManager(Path(tmpdir), cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
delay = float(os.getenv("NOSTR_TEST_DELAY", "5"))

View File

@@ -19,9 +19,9 @@ 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)
backup_mgr = BackupManager(fp)
entry_mgr = EntryManager(vault, backup_mgr)
cfg_mgr = ConfigManager(vault, fp)
backup_mgr = BackupManager(fp, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
pm = PasswordManager.__new__(PasswordManager)
pm.encryption_mode = EncryptionMode.SEED_ONLY

View File

@@ -30,9 +30,9 @@ def test_password_change_and_unlock(monkeypatch):
enc_mgr = EncryptionManager(index_key, fp)
seed_mgr = EncryptionManager(seed_key, fp)
vault = Vault(enc_mgr, fp)
backup_mgr = BackupManager(fp)
entry_mgr = EntryManager(vault, backup_mgr)
cfg_mgr = ConfigManager(vault, fp)
backup_mgr = BackupManager(fp, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
vault.save_index({"entries": {}})
cfg_mgr.save_config(

View File

@@ -11,6 +11,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.backup import BackupManager
from password_manager.config_manager import ConfigManager
from password_manager.portable_backup import export_backup, import_backup
from utils.key_derivation import derive_index_key, derive_key_from_password
@@ -27,7 +28,8 @@ def setup_vault(tmp: Path):
index_key = derive_index_key(SEED)
enc_mgr = EncryptionManager(index_key, tmp)
vault = Vault(enc_mgr, tmp)
backup = BackupManager(tmp)
cfg = ConfigManager(vault, tmp)
backup = BackupManager(tmp, cfg)
return vault, backup

View File

@@ -16,6 +16,7 @@ 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
from password_manager.config_manager import ConfigManager
def test_add_and_delete_entry(monkeypatch):
@@ -52,7 +53,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)
backup_mgr = BackupManager(fingerprint_dir)
cfg_mgr = ConfigManager(vault, fingerprint_dir)
backup_mgr = BackupManager(fingerprint_dir, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
pm.encryption_manager = enc_mgr

View File

@@ -12,6 +12,7 @@ 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.config_manager import ConfigManager
from password_manager.totp import TotpManager
import pyotp
@@ -19,7 +20,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)
backup_mgr = BackupManager(Path(tmpdir))
cfg_mgr = ConfigManager(vault, Path(tmpdir))
backup_mgr = BackupManager(Path(tmpdir), cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
uri = entry_mgr.add_totp("Example", TEST_SEED)
@@ -43,7 +45,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)
backup_mgr = BackupManager(Path(tmpdir))
cfg_mgr = ConfigManager(vault, Path(tmpdir))
backup_mgr = BackupManager(Path(tmpdir), cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
entry_mgr.add_totp("Example", TEST_SEED)
@@ -55,7 +58,8 @@ def test_totp_time_remaining(monkeypatch):
def test_add_totp_imported(tmp_path):
vault, enc = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
backup_mgr = BackupManager(tmp_path)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
em = EntryManager(vault, backup_mgr)
secret = "JBSWY3DPEHPK3PXP"
em.add_totp("Imported", TEST_SEED, secret=secret)