mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-09 07:48:57 +00:00
Add quick unlock flag and event logging
This commit is contained in:
@@ -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."""
|
||||||
|
@@ -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)
|
||||||
|
@@ -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")
|
||||||
|
34
src/tests/test_quick_unlock_default.py
Normal file
34
src/tests/test_quick_unlock_default.py
Normal 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)
|
Reference in New Issue
Block a user