Add quick unlock flag and event logging

This commit is contained in:
thePR0M3TH3AN
2025-08-05 23:05:11 -04:00
parent 4f11db5aa4
commit 94d0b80dce
4 changed files with 49 additions and 5 deletions

View File

@@ -51,7 +51,7 @@ class ConfigManager:
"backup_interval": 0, "backup_interval": 0,
"secret_mode_enabled": False, "secret_mode_enabled": False,
"clipboard_clear_delay": 45, "clipboard_clear_delay": 45,
"quick_unlock": False, "quick_unlock_enabled": False,
"nostr_max_retries": MAX_RETRIES, "nostr_max_retries": MAX_RETRIES,
"nostr_retry_delay": float(RETRY_DELAY), "nostr_retry_delay": float(RETRY_DELAY),
"min_uppercase": 2, "min_uppercase": 2,
@@ -80,7 +80,7 @@ class ConfigManager:
data.setdefault("backup_interval", 0) data.setdefault("backup_interval", 0)
data.setdefault("secret_mode_enabled", False) data.setdefault("secret_mode_enabled", False)
data.setdefault("clipboard_clear_delay", 45) data.setdefault("clipboard_clear_delay", 45)
data.setdefault("quick_unlock", False) data.setdefault("quick_unlock_enabled", data.get("quick_unlock", False))
data.setdefault("nostr_max_retries", MAX_RETRIES) data.setdefault("nostr_max_retries", MAX_RETRIES)
data.setdefault("nostr_retry_delay", float(RETRY_DELAY)) data.setdefault("nostr_retry_delay", float(RETRY_DELAY))
data.setdefault("min_uppercase", 2) data.setdefault("min_uppercase", 2)
@@ -320,13 +320,13 @@ class ConfigManager:
def set_quick_unlock(self, enabled: bool) -> None: def set_quick_unlock(self, enabled: bool) -> None:
"""Persist the quick unlock toggle.""" """Persist the quick unlock toggle."""
cfg = self.load_config(require_pin=False) cfg = self.load_config(require_pin=False)
cfg["quick_unlock"] = bool(enabled) cfg["quick_unlock_enabled"] = bool(enabled)
self.save_config(cfg) self.save_config(cfg)
def get_quick_unlock(self) -> bool: def get_quick_unlock(self) -> bool:
"""Retrieve whether quick unlock is enabled.""" """Retrieve whether quick unlock is enabled."""
cfg = self.load_config(require_pin=False) cfg = self.load_config(require_pin=False)
return bool(cfg.get("quick_unlock", False)) return bool(cfg.get("quick_unlock_enabled", False))
def set_nostr_max_retries(self, retries: int) -> None: def set_nostr_max_retries(self, retries: int) -> None:
"""Persist the maximum number of Nostr retry attempts.""" """Persist the maximum number of Nostr retry attempts."""

View File

@@ -17,6 +17,7 @@ import hashlib
from typing import Optional, Literal from typing import Optional, Literal
import shutil import shutil
import time import time
from datetime import datetime, timezone
import builtins import builtins
import threading import threading
import queue import queue
@@ -345,6 +346,15 @@ class PasswordManager:
self.initialize_managers() self.initialize_managers()
self.locked = False self.locked = False
self.update_activity() self.update_activity()
if (
getattr(self, "config_manager", None)
and self.config_manager.get_quick_unlock()
):
logger.info(
"Quick unlock used by %s at %s",
self.current_fingerprint or "unknown",
datetime.now(timezone.utc).isoformat(),
)
self.last_unlock_duration = time.perf_counter() - start self.last_unlock_duration = time.perf_counter() - start
if getattr(self, "verbose_timing", False): if getattr(self, "verbose_timing", False):
logger.info("Vault unlocked in %.2f seconds", self.last_unlock_duration) logger.info("Vault unlocked in %.2f seconds", self.last_unlock_duration)

View File

@@ -23,7 +23,7 @@ def test_config_defaults_and_round_trip():
assert cfg["pin_hash"] == "" assert cfg["pin_hash"] == ""
assert cfg["password_hash"] == "" assert cfg["password_hash"] == ""
assert cfg["additional_backup_path"] == "" assert cfg["additional_backup_path"] == ""
assert cfg["quick_unlock"] is False assert cfg["quick_unlock_enabled"] is False
assert cfg["kdf_iterations"] == 50_000 assert cfg["kdf_iterations"] == 50_000
cfg_mgr.set_pin("1234") cfg_mgr.set_pin("1234")

View File

@@ -0,0 +1,34 @@
import logging
from types import SimpleNamespace
from pathlib import Path
import sys
import pytest
sys.path.append(str(Path(__file__).resolve().parents[1]))
from seedpass.core.manager import PasswordManager
from seedpass.core.config_manager import ConfigManager
from helpers import create_vault, TEST_SEED, TEST_PASSWORD
def test_quick_unlock_default_off(tmp_path):
vault, _ = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
cfg_mgr = ConfigManager(vault, tmp_path)
assert cfg_mgr.get_quick_unlock() is False
def test_quick_unlock_logs_event(tmp_path, caplog):
pm = PasswordManager.__new__(PasswordManager)
pm.fingerprint_dir = tmp_path
pm.current_fingerprint = "user123"
pm.setup_encryption_manager = lambda *a, **k: None
pm.initialize_bip85 = lambda: None
pm.initialize_managers = lambda: None
pm.update_activity = lambda: None
pm.config_manager = SimpleNamespace(get_quick_unlock=lambda: True)
with caplog.at_level(logging.INFO):
pm.unlock_vault(password="pw")
assert any("Quick unlock used by user123" in rec.message for rec in caplog.records)