mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 07:18:47 +00:00
Add AuthGuard for inactivity locking and CLI lock command
This commit is contained in:
@@ -455,6 +455,14 @@ def vault_lock(ctx: typer.Context) -> None:
|
||||
typer.echo("locked")
|
||||
|
||||
|
||||
@app.command("lock")
|
||||
def root_lock(ctx: typer.Context) -> None:
|
||||
"""Lock the vault for the active profile."""
|
||||
vault_service, _profile, _sync = _get_services(ctx)
|
||||
vault_service.lock()
|
||||
typer.echo("locked")
|
||||
|
||||
|
||||
@vault_app.command("stats")
|
||||
def vault_stats(ctx: typer.Context) -> None:
|
||||
"""Display statistics about the current seed profile."""
|
||||
|
@@ -109,6 +109,24 @@ class Notification:
|
||||
level: str = "INFO"
|
||||
|
||||
|
||||
class AuthGuard:
|
||||
"""Helper to enforce inactivity timeouts."""
|
||||
|
||||
def __init__(
|
||||
self, manager: "PasswordManager", time_fn: callable = time.time
|
||||
) -> None:
|
||||
self.manager = manager
|
||||
self._time_fn = time_fn
|
||||
|
||||
def check_timeout(self) -> None:
|
||||
"""Lock the vault if the inactivity timeout has been exceeded."""
|
||||
timeout = getattr(self.manager, "inactivity_timeout", 0)
|
||||
if self.manager.locked or timeout <= 0:
|
||||
return
|
||||
if self._time_fn() - self.manager.last_activity > timeout:
|
||||
self.manager.lock_vault()
|
||||
|
||||
|
||||
class PasswordManager:
|
||||
"""
|
||||
PasswordManager Class
|
||||
@@ -161,6 +179,7 @@ class PasswordManager:
|
||||
self._suppress_entry_actions_menu: bool = False
|
||||
self.last_bip85_idx: int = 0
|
||||
self.last_sync_ts: int = 0
|
||||
self.auth_guard = AuthGuard(self)
|
||||
|
||||
# Initialize the fingerprint manager first
|
||||
self.initialize_fingerprint_manager()
|
||||
@@ -240,7 +259,12 @@ class PasswordManager:
|
||||
return (None, parent_fp, self.current_fingerprint)
|
||||
|
||||
def update_activity(self) -> None:
|
||||
"""Record the current time as the last user activity."""
|
||||
"""Record activity and enforce inactivity timeout."""
|
||||
guard = getattr(self, "auth_guard", None)
|
||||
if guard is None:
|
||||
guard = AuthGuard(self)
|
||||
self.auth_guard = guard
|
||||
guard.check_timeout()
|
||||
self.last_activity = time.time()
|
||||
|
||||
def notify(self, message: str, level: str = "INFO") -> None:
|
||||
|
@@ -91,3 +91,32 @@ def test_input_timeout_triggers_lock(monkeypatch):
|
||||
|
||||
assert locked["locked"] == 1
|
||||
assert locked["unlocked"] == 1
|
||||
|
||||
|
||||
def test_update_activity_checks_timeout(monkeypatch):
|
||||
"""AuthGuard in update_activity locks the vault after inactivity."""
|
||||
import seedpass.core.manager as manager
|
||||
|
||||
now = {"val": 0.0}
|
||||
monkeypatch.setattr(manager.time, "time", lambda: now["val"])
|
||||
|
||||
pm = manager.PasswordManager.__new__(manager.PasswordManager)
|
||||
pm.inactivity_timeout = 0.5
|
||||
pm.last_activity = 0.0
|
||||
pm.locked = False
|
||||
called = {}
|
||||
|
||||
def lock():
|
||||
called["locked"] = True
|
||||
pm.locked = True
|
||||
|
||||
pm.lock_vault = lock
|
||||
pm.auth_guard = manager.AuthGuard(pm, time_fn=lambda: now["val"])
|
||||
|
||||
now["val"] = 0.4
|
||||
pm.update_activity()
|
||||
assert not called
|
||||
|
||||
now["val"] = 1.1
|
||||
pm.update_activity()
|
||||
assert called["locked"] is True
|
||||
|
@@ -153,6 +153,23 @@ def test_vault_lock(monkeypatch):
|
||||
assert pm.locked is True
|
||||
|
||||
|
||||
def test_root_lock(monkeypatch):
|
||||
called = {}
|
||||
|
||||
def lock():
|
||||
called["locked"] = True
|
||||
pm.locked = True
|
||||
|
||||
pm = SimpleNamespace(
|
||||
lock_vault=lock, locked=False, select_fingerprint=lambda fp: None
|
||||
)
|
||||
monkeypatch.setattr(cli, "PasswordManager", lambda: pm)
|
||||
result = runner.invoke(app, ["lock"])
|
||||
assert result.exit_code == 0
|
||||
assert called.get("locked") is True
|
||||
assert pm.locked is True
|
||||
|
||||
|
||||
def test_vault_reveal_parent_seed(monkeypatch, tmp_path):
|
||||
called = {}
|
||||
|
||||
|
Reference in New Issue
Block a user