mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-09 15:58:48 +00:00
refactor: extract sensitive entry display helper
This commit is contained in:
@@ -153,6 +153,7 @@ class PasswordManager:
|
|||||||
self.profile_stack: list[tuple[str, Path, str]] = []
|
self.profile_stack: list[tuple[str, Path, str]] = []
|
||||||
self.last_unlock_duration: float | None = None
|
self.last_unlock_duration: float | None = None
|
||||||
self.verbose_timing: bool = False
|
self.verbose_timing: bool = False
|
||||||
|
self._suppress_entry_actions_menu: bool = False
|
||||||
|
|
||||||
# Initialize the fingerprint manager first
|
# Initialize the fingerprint manager first
|
||||||
self.initialize_fingerprint_manager()
|
self.initialize_fingerprint_manager()
|
||||||
@@ -2053,33 +2054,18 @@ class PasswordManager:
|
|||||||
logging.error(f"Error displaying QR menu: {e}", exc_info=True)
|
logging.error(f"Error displaying QR menu: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to display QR codes: {e}", "red"))
|
print(colored(f"Error: Failed to display QR codes: {e}", "red"))
|
||||||
|
|
||||||
def handle_retrieve_entry(self) -> None:
|
def display_sensitive_entry_info(self, entry: dict, index: int) -> None:
|
||||||
"""
|
"""Display information for a sensitive entry.
|
||||||
Handles retrieving a password from the index by prompting the user for the index number
|
|
||||||
and displaying the corresponding password and associated details.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
fp, parent_fp, child_fp = self.header_fingerprint_args
|
|
||||||
clear_header_with_notification(
|
|
||||||
self,
|
|
||||||
fp,
|
|
||||||
"Main Menu > Retrieve Entry",
|
|
||||||
parent_fingerprint=parent_fp,
|
|
||||||
child_fingerprint=child_fp,
|
|
||||||
)
|
|
||||||
index_input = input(
|
|
||||||
"Enter the index number of the entry to retrieve: "
|
|
||||||
).strip()
|
|
||||||
if not index_input.isdigit():
|
|
||||||
print(colored("Error: Index must be a number.", "red"))
|
|
||||||
pause()
|
|
||||||
return
|
|
||||||
index = int(index_input)
|
|
||||||
|
|
||||||
entry = self.entry_manager.retrieve_entry(index)
|
Parameters
|
||||||
if not entry:
|
----------
|
||||||
pause()
|
entry: dict
|
||||||
return
|
Entry data retrieved from the vault.
|
||||||
|
index: int
|
||||||
|
Index of the entry being displayed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._suppress_entry_actions_menu = False
|
||||||
|
|
||||||
entry_type = entry.get("type", entry.get("kind", EntryType.PASSWORD.value))
|
entry_type = entry.get("type", entry.get("kind", EntryType.PASSWORD.value))
|
||||||
if isinstance(entry_type, str):
|
if isinstance(entry_type, str):
|
||||||
@@ -2139,12 +2125,11 @@ class PasswordManager:
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
if exit_loop:
|
if exit_loop:
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - best effort
|
||||||
logging.error(f"Error generating TOTP code: {e}", exc_info=True)
|
logging.error(f"Error generating TOTP code: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to generate TOTP code: {e}", "red"))
|
print(colored(f"Error: Failed to generate TOTP code: {e}", "red"))
|
||||||
self._entry_actions_menu(index, entry)
|
|
||||||
pause()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if entry_type == EntryType.SSH.value:
|
if entry_type == EntryType.SSH.value:
|
||||||
notes = entry.get("notes", "")
|
notes = entry.get("notes", "")
|
||||||
label = entry.get("label", "")
|
label = entry.get("label", "")
|
||||||
@@ -2178,13 +2163,11 @@ class PasswordManager:
|
|||||||
else:
|
else:
|
||||||
print(colored("Private Key:", "cyan"))
|
print(colored("Private Key:", "cyan"))
|
||||||
print(color_text(priv_pem, "deterministic"))
|
print(color_text(priv_pem, "deterministic"))
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - best effort
|
||||||
logging.error(f"Error deriving SSH key pair: {e}", exc_info=True)
|
logging.error(f"Error deriving SSH key pair: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to derive SSH keys: {e}", "red"))
|
print(colored(f"Error: Failed to derive SSH keys: {e}", "red"))
|
||||||
pause()
|
|
||||||
self._entry_actions_menu(index, entry)
|
|
||||||
pause()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if entry_type == EntryType.SEED.value:
|
if entry_type == EntryType.SEED.value:
|
||||||
notes = entry.get("notes", "")
|
notes = entry.get("notes", "")
|
||||||
label = entry.get("label", "")
|
label = entry.get("label", "")
|
||||||
@@ -2214,7 +2197,6 @@ class PasswordManager:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print(color_text(phrase, "deterministic"))
|
print(color_text(phrase, "deterministic"))
|
||||||
# Removed QR code display prompt and output
|
|
||||||
if confirm_action("Show derived entropy as hex? (Y/N): "):
|
if confirm_action("Show derived entropy as hex? (Y/N): "):
|
||||||
from local_bip85.bip85 import BIP85
|
from local_bip85.bip85 import BIP85
|
||||||
from bip_utils import Bip39SeedGenerator
|
from bip_utils import Bip39SeedGenerator
|
||||||
@@ -2230,13 +2212,11 @@ class PasswordManager:
|
|||||||
words_len=words,
|
words_len=words,
|
||||||
)
|
)
|
||||||
print(color_text(f"Entropy: {entropy.hex()}", "deterministic"))
|
print(color_text(f"Entropy: {entropy.hex()}", "deterministic"))
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - best effort
|
||||||
logging.error(f"Error deriving seed phrase: {e}", exc_info=True)
|
logging.error(f"Error deriving seed phrase: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to derive seed phrase: {e}", "red"))
|
print(colored(f"Error: Failed to derive seed phrase: {e}", "red"))
|
||||||
pause()
|
|
||||||
self._entry_actions_menu(index, entry)
|
|
||||||
pause()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if entry_type == EntryType.PGP.value:
|
if entry_type == EntryType.PGP.value:
|
||||||
notes = entry.get("notes", "")
|
notes = entry.get("notes", "")
|
||||||
label = entry.get("user_id", "")
|
label = entry.get("user_id", "")
|
||||||
@@ -2268,13 +2248,11 @@ class PasswordManager:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print(color_text(priv_key, "deterministic"))
|
print(color_text(priv_key, "deterministic"))
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - best effort
|
||||||
logging.error(f"Error deriving PGP key: {e}", exc_info=True)
|
logging.error(f"Error deriving PGP key: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to derive PGP key: {e}", "red"))
|
print(colored(f"Error: Failed to derive PGP key: {e}", "red"))
|
||||||
pause()
|
|
||||||
self._entry_actions_menu(index, entry)
|
|
||||||
pause()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if entry_type == EntryType.NOSTR.value:
|
if entry_type == EntryType.NOSTR.value:
|
||||||
label = entry.get("label", "")
|
label = entry.get("label", "")
|
||||||
notes = entry.get("notes", "")
|
notes = entry.get("notes", "")
|
||||||
@@ -2295,18 +2273,14 @@ class PasswordManager:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print(color_text(f"nsec: {nsec}", "deterministic"))
|
print(color_text(f"nsec: {nsec}", "deterministic"))
|
||||||
# QR code display removed for npub and nsec
|
|
||||||
if notes:
|
if notes:
|
||||||
print(colored(f"Notes: {notes}", "cyan"))
|
print(colored(f"Notes: {notes}", "cyan"))
|
||||||
tags = entry.get("tags", [])
|
tags = entry.get("tags", [])
|
||||||
if tags:
|
if tags:
|
||||||
print(colored(f"Tags: {', '.join(tags)}", "cyan"))
|
print(colored(f"Tags: {', '.join(tags)}", "cyan"))
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - best effort
|
||||||
logging.error(f"Error deriving Nostr keys: {e}", exc_info=True)
|
logging.error(f"Error deriving Nostr keys: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to derive Nostr keys: {e}", "red"))
|
print(colored(f"Error: Failed to derive Nostr keys: {e}", "red"))
|
||||||
pause()
|
|
||||||
self._entry_actions_menu(index, entry)
|
|
||||||
pause()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if entry_type == EntryType.KEY_VALUE.value:
|
if entry_type == EntryType.KEY_VALUE.value:
|
||||||
@@ -2322,8 +2296,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Tags: {', '.join(tags)}", "cyan"))
|
print(colored(f"Tags: {', '.join(tags)}", "cyan"))
|
||||||
print(
|
print(
|
||||||
colored(
|
colored(
|
||||||
f"Archived Status: {'Archived' if archived else 'Active'}",
|
f"Archived Status: {'Archived' if archived else 'Active'}", "cyan"
|
||||||
"cyan",
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if self.secret_mode_enabled:
|
if self.secret_mode_enabled:
|
||||||
@@ -2354,9 +2327,7 @@ class PasswordManager:
|
|||||||
if show == "y":
|
if show == "y":
|
||||||
for f_label, f_value in hidden_fields:
|
for f_label, f_value in hidden_fields:
|
||||||
if self.secret_mode_enabled:
|
if self.secret_mode_enabled:
|
||||||
copy_to_clipboard(
|
copy_to_clipboard(f_value, self.clipboard_clear_delay)
|
||||||
f_value, self.clipboard_clear_delay
|
|
||||||
)
|
|
||||||
print(
|
print(
|
||||||
colored(
|
colored(
|
||||||
f"[+] {f_label} copied to clipboard. Will clear in {self.clipboard_clear_delay} seconds.",
|
f"[+] {f_label} copied to clipboard. Will clear in {self.clipboard_clear_delay} seconds.",
|
||||||
@@ -2365,9 +2336,8 @@ class PasswordManager:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print(colored(f" {f_label}: {f_value}", "cyan"))
|
print(colored(f" {f_label}: {f_value}", "cyan"))
|
||||||
self._entry_actions_menu(index, entry)
|
|
||||||
pause()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if entry_type == EntryType.MANAGED_ACCOUNT.value:
|
if entry_type == EntryType.MANAGED_ACCOUNT.value:
|
||||||
label = entry.get("label", "")
|
label = entry.get("label", "")
|
||||||
notes = entry.get("notes", "")
|
notes = entry.get("notes", "")
|
||||||
@@ -2383,8 +2353,7 @@ class PasswordManager:
|
|||||||
print(colored(f"Tags: {', '.join(tags)}", "cyan"))
|
print(colored(f"Tags: {', '.join(tags)}", "cyan"))
|
||||||
print(
|
print(
|
||||||
colored(
|
colored(
|
||||||
f"Archived Status: {'Archived' if archived else 'Active'}",
|
f"Archived Status: {'Archived' if archived else 'Active'}", "cyan"
|
||||||
"cyan",
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
action = (
|
action = (
|
||||||
@@ -2408,17 +2377,14 @@ class PasswordManager:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print(color_text(seed, "deterministic"))
|
print(color_text(seed, "deterministic"))
|
||||||
# QR code display removed for managed account seed
|
|
||||||
self._entry_actions_menu(index, entry)
|
|
||||||
pause()
|
|
||||||
return
|
return
|
||||||
if action == "l":
|
if action == "l":
|
||||||
|
self._suppress_entry_actions_menu = True
|
||||||
self.load_managed_account(index)
|
self.load_managed_account(index)
|
||||||
return
|
return
|
||||||
self._entry_actions_menu(index, entry)
|
|
||||||
pause()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Default: PASSWORD
|
||||||
website_name = entry.get("label", entry.get("website"))
|
website_name = entry.get("label", entry.get("website"))
|
||||||
length = entry.get("length")
|
length = entry.get("length")
|
||||||
username = entry.get("username")
|
username = entry.get("username")
|
||||||
@@ -2485,15 +2451,11 @@ class PasswordManager:
|
|||||||
else:
|
else:
|
||||||
print(colored(f" {label}: {value}", "cyan"))
|
print(colored(f" {label}: {value}", "cyan"))
|
||||||
if hidden_fields:
|
if hidden_fields:
|
||||||
show = (
|
show = input("Reveal hidden fields? (y/N): ").strip().lower()
|
||||||
input("Reveal hidden fields? (y/N): ").strip().lower()
|
|
||||||
)
|
|
||||||
if show == "y":
|
if show == "y":
|
||||||
for label, value in hidden_fields:
|
for label, value in hidden_fields:
|
||||||
if self.secret_mode_enabled:
|
if self.secret_mode_enabled:
|
||||||
copy_to_clipboard(
|
copy_to_clipboard(value, self.clipboard_clear_delay)
|
||||||
value, self.clipboard_clear_delay
|
|
||||||
)
|
|
||||||
print(
|
print(
|
||||||
colored(
|
colored(
|
||||||
f"[+] {label} copied to clipboard. Will clear in {self.clipboard_clear_delay} seconds.",
|
f"[+] {label} copied to clipboard. Will clear in {self.clipboard_clear_delay} seconds.",
|
||||||
@@ -2504,8 +2466,42 @@ class PasswordManager:
|
|||||||
print(colored(f" {label}: {value}", "cyan"))
|
print(colored(f" {label}: {value}", "cyan"))
|
||||||
else:
|
else:
|
||||||
print(colored("Error: Failed to retrieve the password.", "red"))
|
print(colored("Error: Failed to retrieve the password.", "red"))
|
||||||
|
return
|
||||||
|
|
||||||
|
def handle_retrieve_entry(self) -> None:
|
||||||
|
"""Prompt for an index and display the corresponding entry."""
|
||||||
|
try:
|
||||||
|
fp, parent_fp, child_fp = self.header_fingerprint_args
|
||||||
|
clear_header_with_notification(
|
||||||
|
self,
|
||||||
|
fp,
|
||||||
|
"Main Menu > Retrieve Entry",
|
||||||
|
parent_fingerprint=parent_fp,
|
||||||
|
child_fingerprint=child_fp,
|
||||||
|
)
|
||||||
|
index_input = input(
|
||||||
|
"Enter the index number of the entry to retrieve: "
|
||||||
|
).strip()
|
||||||
|
if not index_input.isdigit():
|
||||||
|
print(colored("Error: Index must be a number.", "red"))
|
||||||
|
pause()
|
||||||
|
return
|
||||||
|
index = int(index_input)
|
||||||
|
|
||||||
|
entry = self.entry_manager.retrieve_entry(index)
|
||||||
|
if not entry:
|
||||||
|
pause()
|
||||||
|
return
|
||||||
|
|
||||||
|
self.display_sensitive_entry_info(entry, index)
|
||||||
|
pause()
|
||||||
|
|
||||||
|
if getattr(self, "_suppress_entry_actions_menu", False):
|
||||||
|
return
|
||||||
|
|
||||||
self._entry_actions_menu(index, entry)
|
self._entry_actions_menu(index, entry)
|
||||||
pause()
|
pause()
|
||||||
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error during password retrieval: {e}", exc_info=True)
|
logging.error(f"Error during password retrieval: {e}", exc_info=True)
|
||||||
print(colored(f"Error: Failed to retrieve password: {e}", "red"))
|
print(colored(f"Error: Failed to retrieve password: {e}", "red"))
|
||||||
@@ -3914,9 +3910,9 @@ class PasswordManager:
|
|||||||
)
|
)
|
||||||
stats["backup_count"] = len(backups)
|
stats["backup_count"] = len(backups)
|
||||||
stats["backup_dir"] = str(self.backup_manager.backup_dir)
|
stats["backup_dir"] = str(self.backup_manager.backup_dir)
|
||||||
stats["additional_backup_path"] = (
|
stats[
|
||||||
self.config_manager.get_additional_backup_path()
|
"additional_backup_path"
|
||||||
)
|
] = self.config_manager.get_additional_backup_path()
|
||||||
|
|
||||||
# Nostr sync info
|
# Nostr sync info
|
||||||
manifest = getattr(self.nostr_client, "current_manifest", None)
|
manifest = getattr(self.nostr_client, "current_manifest", None)
|
||||||
|
Reference in New Issue
Block a user