mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 07:18:47 +00:00
Guard missing Nostr client in background sync
This commit is contained in:
@@ -1401,6 +1401,8 @@ class PasswordManager:
|
||||
|
||||
async def sync_index_from_nostr_async(self) -> None:
|
||||
"""Always fetch the latest vault data from Nostr and update the local index."""
|
||||
if not getattr(self, "nostr_client", None):
|
||||
return
|
||||
start = time.perf_counter()
|
||||
try:
|
||||
if getattr(self, "current_fingerprint", None):
|
||||
@@ -1518,6 +1520,8 @@ class PasswordManager:
|
||||
"""Launch a thread to synchronize the vault without blocking the UI."""
|
||||
if getattr(self, "offline_mode", False):
|
||||
return
|
||||
if getattr(self, "nostr_client", None) is None:
|
||||
return
|
||||
if getattr(self, "_sync_task", None) and not getattr(
|
||||
self._sync_task, "done", True
|
||||
):
|
||||
@@ -1529,7 +1533,7 @@ class PasswordManager:
|
||||
await self.sync_index_from_nostr_async()
|
||||
except Exception as exc:
|
||||
logger.warning(f"Background sync failed: {exc}")
|
||||
if hasattr(self, "error_queue"):
|
||||
if hasattr(self, "error_queue") and getattr(self, "nostr_client", None):
|
||||
self.error_queue.put(exc)
|
||||
|
||||
try:
|
||||
@@ -1615,6 +1619,9 @@ class PasswordManager:
|
||||
local index file was written. Returns ``False`` otherwise. The local
|
||||
index file is not created on failure.
|
||||
"""
|
||||
if not getattr(self, "nostr_client", None):
|
||||
return False
|
||||
|
||||
index_file = self.fingerprint_dir / "seedpass_entries_db.json.enc"
|
||||
if index_file.exists():
|
||||
return True
|
||||
@@ -1680,6 +1687,8 @@ class PasswordManager:
|
||||
asyncio.run(self.sync_index_from_nostr_if_missing_async())
|
||||
|
||||
async def sync_index_from_nostr_if_missing_async(self) -> None:
|
||||
if not getattr(self, "nostr_client", None):
|
||||
return
|
||||
success = await self.attempt_initial_sync_async()
|
||||
if not success:
|
||||
self.vault.save_index({"schema_version": LATEST_VERSION, "entries": {}})
|
||||
|
@@ -12,6 +12,7 @@ def _make_pm():
|
||||
pm.notify = lambda msg, level="INFO": pm.notifications.put(
|
||||
manager_module.Notification(msg, level)
|
||||
)
|
||||
pm.nostr_client = object()
|
||||
return pm
|
||||
|
||||
|
||||
|
@@ -1,10 +1,14 @@
|
||||
import sys
|
||||
import importlib
|
||||
import queue
|
||||
import time
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from helpers import create_vault, TEST_SEED, TEST_PASSWORD
|
||||
|
||||
sys.path.append(str(Path(__file__).resolve().parents[1]))
|
||||
@@ -12,6 +16,7 @@ sys.path.append(str(Path(__file__).resolve().parents[1]))
|
||||
import main
|
||||
from nostr.client import DEFAULT_RELAYS
|
||||
from seedpass.core.config_manager import ConfigManager
|
||||
from seedpass.core.manager import Notification, PasswordManager
|
||||
from seedpass.core.vault import Vault
|
||||
from utils.fingerprint_manager import FingerprintManager
|
||||
|
||||
@@ -137,3 +142,31 @@ def test_settings_menu_change_password_incorrect(monkeypatch, capsys):
|
||||
|
||||
out = capsys.readouterr().out
|
||||
assert "Incorrect password" in out
|
||||
|
||||
|
||||
def test_settings_menu_without_nostr_client(monkeypatch):
|
||||
pm = PasswordManager.__new__(PasswordManager)
|
||||
pm.offline_mode = False
|
||||
pm.nostr_client = None
|
||||
pm.notifications = queue.Queue()
|
||||
pm.error_queue = queue.Queue()
|
||||
pm.notify = lambda msg, level="INFO": pm.notifications.put(Notification(msg, level))
|
||||
pm.is_dirty = False
|
||||
pm.last_update = time.time()
|
||||
pm.last_activity = time.time()
|
||||
pm.update_activity = lambda: None
|
||||
pm.lock_vault = lambda: None
|
||||
pm.unlock_vault = lambda: None
|
||||
pm.start_background_relay_check = lambda: None
|
||||
pm.poll_background_errors = PasswordManager.poll_background_errors.__get__(pm)
|
||||
pm.display_stats = lambda: None
|
||||
|
||||
inputs = iter(["7", ""])
|
||||
monkeypatch.setattr(main, "timed_input", lambda *_: next(inputs))
|
||||
monkeypatch.setattr("builtins.input", lambda *_: "")
|
||||
|
||||
with pytest.raises(SystemExit):
|
||||
main.display_menu(pm, sync_interval=1000, inactivity_timeout=1000)
|
||||
|
||||
assert pm.error_queue.empty()
|
||||
assert pm.notifications.empty()
|
||||
|
@@ -17,6 +17,7 @@ def test_unlock_triggers_sync(monkeypatch, tmp_path):
|
||||
pm.setup_encryption_manager = lambda *a, **k: None
|
||||
pm.initialize_bip85 = lambda: None
|
||||
pm.initialize_managers = lambda: None
|
||||
pm.nostr_client = object()
|
||||
called = {"sync": False}
|
||||
|
||||
async def fake_sync(self):
|
||||
@@ -62,6 +63,7 @@ def test_quick_unlock_background_sync(monkeypatch, tmp_path):
|
||||
def test_start_background_sync_running_loop(monkeypatch):
|
||||
pm = PasswordManager.__new__(PasswordManager)
|
||||
pm.offline_mode = False
|
||||
pm.nostr_client = object()
|
||||
called = {"init": False, "sync": False}
|
||||
|
||||
async def fake_attempt(self):
|
||||
|
Reference in New Issue
Block a user