mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-09 15:58:48 +00:00
Merge pull request #587 from PR0M3TH3AN/codex/update-entrymanager-to-include-verbose-parameter
Add verbose flag for listing entries
This commit is contained in:
@@ -920,6 +920,7 @@ class EntryManager:
|
|||||||
filter_kind: str | None = None,
|
filter_kind: str | None = None,
|
||||||
*,
|
*,
|
||||||
include_archived: bool = False,
|
include_archived: bool = False,
|
||||||
|
verbose: bool = True,
|
||||||
) -> List[Tuple[int, str, Optional[str], Optional[str], bool]]:
|
) -> List[Tuple[int, str, Optional[str], Optional[str], bool]]:
|
||||||
"""List entries in the index with optional sorting and filtering.
|
"""List entries in the index with optional sorting and filtering.
|
||||||
|
|
||||||
@@ -932,7 +933,8 @@ class EntryManager:
|
|||||||
|
|
||||||
if not entries_data:
|
if not entries_data:
|
||||||
logger.info("No entries found.")
|
logger.info("No entries found.")
|
||||||
print(colored("No entries found.", "yellow"))
|
if verbose:
|
||||||
|
print(colored("No entries found.", "yellow"))
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def sort_key(item: Tuple[str, Dict[str, Any]]):
|
def sort_key(item: Tuple[str, Dict[str, Any]]):
|
||||||
@@ -987,51 +989,59 @@ class EntryManager:
|
|||||||
)
|
)
|
||||||
|
|
||||||
logger.debug(f"Total entries found: {len(entries)}")
|
logger.debug(f"Total entries found: {len(entries)}")
|
||||||
for idx, entry in filtered_items:
|
if verbose:
|
||||||
etype = entry.get("type", entry.get("kind", EntryType.PASSWORD.value))
|
for idx, entry in filtered_items:
|
||||||
print(colored(f"Index: {idx}", "cyan"))
|
etype = entry.get(
|
||||||
if etype == EntryType.TOTP.value:
|
"type", entry.get("kind", EntryType.PASSWORD.value)
|
||||||
print(colored(" Type: TOTP", "cyan"))
|
)
|
||||||
print(colored(f" Label: {entry.get('label', '')}", "cyan"))
|
print(colored(f"Index: {idx}", "cyan"))
|
||||||
print(colored(f" Derivation Index: {entry.get('index')}", "cyan"))
|
if etype == EntryType.TOTP.value:
|
||||||
print(
|
print(colored(" Type: TOTP", "cyan"))
|
||||||
colored(
|
print(colored(f" Label: {entry.get('label', '')}", "cyan"))
|
||||||
f" Period: {entry.get('period', 30)}s Digits: {entry.get('digits', 6)}",
|
print(
|
||||||
"cyan",
|
colored(f" Derivation Index: {entry.get('index')}", "cyan")
|
||||||
)
|
)
|
||||||
)
|
print(
|
||||||
elif etype == EntryType.PASSWORD.value:
|
colored(
|
||||||
print(
|
f" Period: {entry.get('period', 30)}s Digits: {entry.get('digits', 6)}",
|
||||||
colored(
|
"cyan",
|
||||||
f" Label: {entry.get('label', entry.get('website', ''))}",
|
)
|
||||||
"cyan",
|
|
||||||
)
|
)
|
||||||
)
|
elif etype == EntryType.PASSWORD.value:
|
||||||
print(
|
print(
|
||||||
colored(f" Username: {entry.get('username') or 'N/A'}", "cyan")
|
colored(
|
||||||
)
|
f" Label: {entry.get('label', entry.get('website', ''))}",
|
||||||
print(colored(f" URL: {entry.get('url') or 'N/A'}", "cyan"))
|
"cyan",
|
||||||
print(
|
)
|
||||||
colored(
|
|
||||||
f" Archived: {'Yes' if entry.get('archived', entry.get('blacklisted', False)) else 'No'}",
|
|
||||||
"cyan",
|
|
||||||
)
|
)
|
||||||
)
|
print(
|
||||||
else:
|
colored(
|
||||||
print(colored(f" Label: {entry.get('label', '')}", "cyan"))
|
f" Username: {entry.get('username') or 'N/A'}", "cyan"
|
||||||
print(
|
)
|
||||||
colored(
|
|
||||||
f" Derivation Index: {entry.get('index', idx)}",
|
|
||||||
"cyan",
|
|
||||||
)
|
)
|
||||||
)
|
print(colored(f" URL: {entry.get('url') or 'N/A'}", "cyan"))
|
||||||
print("-" * 40)
|
print(
|
||||||
|
colored(
|
||||||
|
f" Archived: {'Yes' if entry.get('archived', entry.get('blacklisted', False)) else 'No'}",
|
||||||
|
"cyan",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print(colored(f" Label: {entry.get('label', '')}", "cyan"))
|
||||||
|
print(
|
||||||
|
colored(
|
||||||
|
f" Derivation Index: {entry.get('index', idx)}",
|
||||||
|
"cyan",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print("-" * 40)
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to list entries: {e}", exc_info=True)
|
logger.error(f"Failed to list entries: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to list entries: {e}", "red"))
|
if verbose:
|
||||||
|
print(colored(f"Error: Failed to list entries: {e}", "red"))
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def search_entries(
|
def search_entries(
|
||||||
|
@@ -3240,7 +3240,9 @@ class PasswordManager:
|
|||||||
def handle_view_archived_entries(self) -> None:
|
def handle_view_archived_entries(self) -> None:
|
||||||
"""Display archived entries and optionally view or restore them."""
|
"""Display archived entries and optionally view or restore them."""
|
||||||
try:
|
try:
|
||||||
archived = self.entry_manager.list_entries(include_archived=True)
|
archived = self.entry_manager.list_entries(
|
||||||
|
include_archived=True, verbose=False
|
||||||
|
)
|
||||||
archived = [e for e in archived if e[4]]
|
archived = [e for e in archived if e[4]]
|
||||||
if not archived:
|
if not archived:
|
||||||
self.notify("No archived entries found.", level="WARNING")
|
self.notify("No archived entries found.", level="WARNING")
|
||||||
@@ -3286,7 +3288,7 @@ class PasswordManager:
|
|||||||
self.last_update = time.time()
|
self.last_update = time.time()
|
||||||
pause()
|
pause()
|
||||||
archived = self.entry_manager.list_entries(
|
archived = self.entry_manager.list_entries(
|
||||||
include_archived=True
|
include_archived=True, verbose=False
|
||||||
)
|
)
|
||||||
archived = [e for e in archived if e[4]]
|
archived = [e for e in archived if e[4]]
|
||||||
if not archived:
|
if not archived:
|
||||||
|
@@ -152,3 +152,41 @@ def test_view_archived_entries_removed_after_restore(monkeypatch, capsys):
|
|||||||
note = pm.notifications.get_nowait()
|
note = pm.notifications.get_nowait()
|
||||||
assert note.level == "WARNING"
|
assert note.level == "WARNING"
|
||||||
assert note.message == "No archived entries found."
|
assert note.message == "No archived entries found."
|
||||||
|
|
||||||
|
|
||||||
|
def test_archived_entries_menu_hides_active(monkeypatch, capsys):
|
||||||
|
with TemporaryDirectory() as tmpdir:
|
||||||
|
tmp_path = Path(tmpdir)
|
||||||
|
vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
|
||||||
|
cfg_mgr = ConfigManager(vault, tmp_path)
|
||||||
|
backup_mgr = BackupManager(tmp_path, cfg_mgr)
|
||||||
|
entry_mgr = EntryManager(vault, backup_mgr)
|
||||||
|
|
||||||
|
pm = PasswordManager.__new__(PasswordManager)
|
||||||
|
pm.encryption_mode = EncryptionMode.SEED_ONLY
|
||||||
|
pm.encryption_manager = enc_mgr
|
||||||
|
pm.vault = vault
|
||||||
|
pm.entry_manager = entry_mgr
|
||||||
|
pm.backup_manager = backup_mgr
|
||||||
|
pm.parent_seed = TEST_SEED
|
||||||
|
pm.nostr_client = SimpleNamespace()
|
||||||
|
pm.fingerprint_dir = tmp_path
|
||||||
|
pm.is_dirty = False
|
||||||
|
pm.notifications = queue.Queue()
|
||||||
|
|
||||||
|
archived_idx = entry_mgr.add_entry("archived.com", 8)
|
||||||
|
active_idx = entry_mgr.add_entry("active.com", 8)
|
||||||
|
|
||||||
|
# Archive only the first entry
|
||||||
|
monkeypatch.setattr("builtins.input", lambda *_: str(archived_idx))
|
||||||
|
pm.handle_archive_entry()
|
||||||
|
assert entry_mgr.retrieve_entry(archived_idx)["archived"] is True
|
||||||
|
assert entry_mgr.retrieve_entry(active_idx)["archived"] is False
|
||||||
|
|
||||||
|
# View archived entries and immediately exit
|
||||||
|
inputs = iter([""])
|
||||||
|
monkeypatch.setattr("builtins.input", lambda *_: next(inputs))
|
||||||
|
pm.handle_view_archived_entries()
|
||||||
|
out = capsys.readouterr().out
|
||||||
|
assert "archived.com" in out
|
||||||
|
assert "active.com" not in out
|
||||||
|
Reference in New Issue
Block a user