mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 07:18:47 +00:00
Merge pull request #545 from PR0M3TH3AN/codex/new-task
Replace yellow prints with warning notifications
This commit is contained in:
@@ -723,7 +723,7 @@ class PasswordManager:
|
||||
Handles the setup process when no existing parent seed is found.
|
||||
Asks the user whether to enter an existing BIP-85 seed or generate a new one.
|
||||
"""
|
||||
print(colored("No existing seed found. Let's set up a new one!", "yellow"))
|
||||
self.notify("No existing seed found. Let's set up a new one!", level="WARNING")
|
||||
|
||||
choice = input(
|
||||
"Do you want to (1) Enter an existing BIP-85 seed or (2) Generate a new BIP-85 seed? (1/2): "
|
||||
@@ -827,7 +827,7 @@ class PasswordManager:
|
||||
sys.exit(1)
|
||||
except KeyboardInterrupt:
|
||||
logging.info("Operation cancelled by user.")
|
||||
print(colored("\nOperation cancelled by user.", "yellow"))
|
||||
self.notify("Operation cancelled by user.", level="WARNING")
|
||||
sys.exit(0)
|
||||
|
||||
def generate_new_seed(self) -> Optional[str]:
|
||||
@@ -879,7 +879,7 @@ class PasswordManager:
|
||||
|
||||
return fingerprint # Return the generated fingerprint
|
||||
else:
|
||||
print(colored("Seed generation cancelled. Exiting.", "yellow"))
|
||||
self.notify("Seed generation cancelled. Exiting.", level="WARNING")
|
||||
sys.exit(0)
|
||||
|
||||
def validate_bip85_seed(self, seed: str) -> bool:
|
||||
@@ -1434,7 +1434,7 @@ class PasswordManager:
|
||||
if not confirm_action(
|
||||
"WARNING: Displaying SSH keys reveals sensitive information. Continue? (Y/N): "
|
||||
):
|
||||
print(colored("SSH key display cancelled.", "yellow"))
|
||||
self.notify("SSH key display cancelled.", level="WARNING")
|
||||
return
|
||||
|
||||
print(colored(f"\n[+] SSH key entry added with ID {index}.\n", "green"))
|
||||
@@ -1493,7 +1493,7 @@ class PasswordManager:
|
||||
if not confirm_action(
|
||||
"WARNING: Displaying the seed phrase reveals sensitive information. Continue? (Y/N): "
|
||||
):
|
||||
print(colored("Seed phrase display cancelled.", "yellow"))
|
||||
self.notify("Seed phrase display cancelled.", level="WARNING")
|
||||
return
|
||||
|
||||
print(
|
||||
@@ -1568,7 +1568,7 @@ class PasswordManager:
|
||||
if not confirm_action(
|
||||
"WARNING: Displaying the PGP key reveals sensitive information. Continue? (Y/N): "
|
||||
):
|
||||
print(colored("PGP key display cancelled.", "yellow"))
|
||||
self.notify("PGP key display cancelled.", level="WARNING")
|
||||
return
|
||||
|
||||
print(colored(f"\n[+] PGP key entry added with ID {index}.\n", "green"))
|
||||
@@ -2003,7 +2003,7 @@ class PasswordManager:
|
||||
entry = self.entry_manager.retrieve_entry(index) or entry
|
||||
return
|
||||
|
||||
print(colored("No QR codes available for this entry.", "yellow"))
|
||||
self.notify("No QR codes available for this entry.", level="WARNING")
|
||||
except Exception as e: # pragma: no cover - best effort
|
||||
logging.error(f"Error displaying QR menu: {e}", exc_info=True)
|
||||
print(colored(f"Error: Failed to display QR codes: {e}", "red"))
|
||||
@@ -2103,7 +2103,7 @@ class PasswordManager:
|
||||
if not confirm_action(
|
||||
"WARNING: Displaying SSH keys reveals sensitive information. Continue? (Y/N): "
|
||||
):
|
||||
print(colored("SSH key display cancelled.", "yellow"))
|
||||
self.notify("SSH key display cancelled.", level="WARNING")
|
||||
return
|
||||
try:
|
||||
priv_pem, pub_pem = self.entry_manager.get_ssh_key_pair(
|
||||
@@ -2142,7 +2142,7 @@ class PasswordManager:
|
||||
if not confirm_action(
|
||||
"WARNING: Displaying the seed phrase reveals sensitive information. Continue? (Y/N): "
|
||||
):
|
||||
print(colored("Seed phrase display cancelled.", "yellow"))
|
||||
self.notify("Seed phrase display cancelled.", level="WARNING")
|
||||
return
|
||||
try:
|
||||
phrase = self.entry_manager.get_seed_phrase(index, self.parent_seed)
|
||||
@@ -2193,7 +2193,7 @@ class PasswordManager:
|
||||
if not confirm_action(
|
||||
"WARNING: Displaying the PGP key reveals sensitive information. Continue? (Y/N): "
|
||||
):
|
||||
print(colored("PGP key display cancelled.", "yellow"))
|
||||
self.notify("PGP key display cancelled.", level="WARNING")
|
||||
return
|
||||
try:
|
||||
priv_key, fingerprint = self.entry_manager.get_pgp_key(
|
||||
@@ -2385,11 +2385,9 @@ class PasswordManager:
|
||||
if url:
|
||||
print(colored(f"URL: {url}", "cyan"))
|
||||
if blacklisted:
|
||||
print(
|
||||
colored(
|
||||
f"Warning: This password is archived and should not be used.",
|
||||
"yellow",
|
||||
)
|
||||
self.notify(
|
||||
"Warning: This password is archived and should not be used.",
|
||||
level="WARNING",
|
||||
)
|
||||
|
||||
password = self.password_generator.generate_password(length, index)
|
||||
@@ -2522,8 +2520,9 @@ class PasswordManager:
|
||||
if period_input.isdigit():
|
||||
new_period = int(period_input)
|
||||
else:
|
||||
print(
|
||||
colored("Invalid period value. Keeping current.", "yellow")
|
||||
self.notify(
|
||||
"Invalid period value. Keeping current.",
|
||||
level="WARNING",
|
||||
)
|
||||
digits_input = input(
|
||||
f"Enter new digit count (current: {digits}): "
|
||||
@@ -2533,11 +2532,9 @@ class PasswordManager:
|
||||
if digits_input.isdigit():
|
||||
new_digits = int(digits_input)
|
||||
else:
|
||||
print(
|
||||
colored(
|
||||
"Invalid digits value. Keeping current.",
|
||||
"yellow",
|
||||
)
|
||||
self.notify(
|
||||
"Invalid digits value. Keeping current.",
|
||||
level="WARNING",
|
||||
)
|
||||
blacklist_input = (
|
||||
input(
|
||||
@@ -2553,11 +2550,9 @@ class PasswordManager:
|
||||
elif blacklist_input == "n":
|
||||
new_blacklisted = False
|
||||
else:
|
||||
print(
|
||||
colored(
|
||||
"Invalid input for archived status. Keeping the current status.",
|
||||
"yellow",
|
||||
)
|
||||
self.notify(
|
||||
"Invalid input for archived status. Keeping the current status.",
|
||||
level="WARNING",
|
||||
)
|
||||
new_blacklisted = blacklisted
|
||||
|
||||
@@ -2644,11 +2639,9 @@ class PasswordManager:
|
||||
elif blacklist_input == "n":
|
||||
new_blacklisted = False
|
||||
else:
|
||||
print(
|
||||
colored(
|
||||
"Invalid input for archived status. Keeping the current status.",
|
||||
"yellow",
|
||||
)
|
||||
self.notify(
|
||||
"Invalid input for archived status. Keeping the current status.",
|
||||
level="WARNING",
|
||||
)
|
||||
new_blacklisted = blacklisted
|
||||
|
||||
@@ -2749,11 +2742,9 @@ class PasswordManager:
|
||||
elif blacklist_input == "n":
|
||||
new_blacklisted = False
|
||||
else:
|
||||
print(
|
||||
colored(
|
||||
"Invalid input for archived status. Keeping the current status.",
|
||||
"yellow",
|
||||
)
|
||||
self.notify(
|
||||
"Invalid input for archived status. Keeping the current status.",
|
||||
level="WARNING",
|
||||
)
|
||||
new_blacklisted = blacklisted
|
||||
|
||||
@@ -2837,13 +2828,13 @@ class PasswordManager:
|
||||
)
|
||||
query = input("Enter search string: ").strip()
|
||||
if not query:
|
||||
print(colored("No search string provided.", "yellow"))
|
||||
self.notify("No search string provided.", level="WARNING")
|
||||
pause()
|
||||
return
|
||||
|
||||
results = self.entry_manager.search_entries(query)
|
||||
if not results:
|
||||
print(colored("No matching entries found.", "yellow"))
|
||||
self.notify("No matching entries found.", level="WARNING")
|
||||
pause()
|
||||
return
|
||||
|
||||
@@ -3068,7 +3059,7 @@ class PasswordManager:
|
||||
if not confirm_action(
|
||||
f"Are you sure you want to delete entry {index_to_delete}? (Y/N): "
|
||||
):
|
||||
print(colored("Deletion cancelled.", "yellow"))
|
||||
self.notify("Deletion cancelled.", level="WARNING")
|
||||
return
|
||||
|
||||
self.entry_manager.delete_entry(index_to_delete)
|
||||
@@ -3115,7 +3106,7 @@ class PasswordManager:
|
||||
archived = self.entry_manager.list_entries(include_archived=True)
|
||||
archived = [e for e in archived if e[4]]
|
||||
if not archived:
|
||||
print(colored("No archived entries found.", "yellow"))
|
||||
self.notify("No archived entries found.", level="WARNING")
|
||||
pause()
|
||||
return
|
||||
while True:
|
||||
@@ -3196,7 +3187,7 @@ class PasswordManager:
|
||||
totp_list.append((label, int(idx_str), period, imported))
|
||||
|
||||
if not totp_list:
|
||||
print(colored("No 2FA entries found.", "yellow"))
|
||||
self.notify("No 2FA entries found.", level="WARNING")
|
||||
return
|
||||
|
||||
totp_list.sort(key=lambda t: t[0].lower())
|
||||
@@ -3274,11 +3265,9 @@ class PasswordManager:
|
||||
try:
|
||||
verified = verify_checksum(current_checksum, SCRIPT_CHECKSUM_FILE)
|
||||
except FileNotFoundError:
|
||||
print(
|
||||
colored(
|
||||
"Checksum file missing. Run scripts/update_checksum.py or choose 'Generate Script Checksum' in Settings.",
|
||||
"yellow",
|
||||
)
|
||||
self.notify(
|
||||
"Checksum file missing. Run scripts/update_checksum.py or choose 'Generate Script Checksum' in Settings.",
|
||||
level="WARNING",
|
||||
)
|
||||
logging.warning("Checksum file missing during verification.")
|
||||
return
|
||||
@@ -3301,7 +3290,7 @@ class PasswordManager:
|
||||
def handle_update_script_checksum(self) -> None:
|
||||
"""Generate a new checksum for the manager script."""
|
||||
if not confirm_action("Generate new script checksum? (Y/N): "):
|
||||
print(colored("Operation cancelled.", "yellow"))
|
||||
self.notify("Operation cancelled.", level="WARNING")
|
||||
return
|
||||
try:
|
||||
fp, parent_fp, child_fp = self.header_fingerprint_args
|
||||
@@ -3500,7 +3489,7 @@ class PasswordManager:
|
||||
)
|
||||
|
||||
if not totp_entries:
|
||||
print(colored("No 2FA codes to export.", "yellow"))
|
||||
self.notify("No 2FA codes to export.", level="WARNING")
|
||||
return None
|
||||
|
||||
dest_str = input(
|
||||
@@ -3548,17 +3537,13 @@ class PasswordManager:
|
||||
child_fingerprint=child_fp,
|
||||
)
|
||||
print(colored("\n=== Backup Parent Seed ===", "yellow"))
|
||||
print(
|
||||
colored(
|
||||
"Warning: Revealing your parent seed is a highly sensitive operation.",
|
||||
"yellow",
|
||||
)
|
||||
self.notify(
|
||||
"Warning: Revealing your parent seed is a highly sensitive operation.",
|
||||
level="WARNING",
|
||||
)
|
||||
print(
|
||||
colored(
|
||||
"Ensure you're in a secure, private environment and no one is watching your screen.",
|
||||
"yellow",
|
||||
)
|
||||
self.notify(
|
||||
"Ensure you're in a secure, private environment and no one is watching your screen.",
|
||||
level="WARNING",
|
||||
)
|
||||
|
||||
# Verify user's identity with secure password verification
|
||||
@@ -3573,7 +3558,7 @@ class PasswordManager:
|
||||
if not confirm_action(
|
||||
"Are you absolutely sure you want to reveal your parent seed? (Y/N): "
|
||||
):
|
||||
print(colored("Operation cancelled by user.", "yellow"))
|
||||
self.notify("Operation cancelled by user.", level="WARNING")
|
||||
return
|
||||
|
||||
# Reveal the parent seed
|
||||
|
@@ -2,6 +2,7 @@ import sys
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from types import SimpleNamespace
|
||||
import queue
|
||||
|
||||
from helpers import create_vault, TEST_SEED, TEST_PASSWORD
|
||||
|
||||
@@ -37,6 +38,7 @@ def test_archive_entry_from_retrieve(monkeypatch):
|
||||
pm.nostr_client = SimpleNamespace()
|
||||
pm.fingerprint_dir = tmp_path
|
||||
pm.secret_mode_enabled = False
|
||||
pm.notifications = queue.Queue()
|
||||
|
||||
index = entry_mgr.add_entry("example.com", 8)
|
||||
|
||||
@@ -68,6 +70,7 @@ def test_restore_entry_from_retrieve(monkeypatch):
|
||||
pm.nostr_client = SimpleNamespace()
|
||||
pm.fingerprint_dir = tmp_path
|
||||
pm.secret_mode_enabled = False
|
||||
pm.notifications = queue.Queue()
|
||||
|
||||
index = entry_mgr.add_entry("example.com", 8)
|
||||
entry_mgr.archive_entry(index)
|
||||
|
@@ -2,6 +2,7 @@ import sys
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from types import SimpleNamespace
|
||||
import queue
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -67,6 +68,7 @@ def test_view_archived_entries_cli(monkeypatch):
|
||||
pm.nostr_client = SimpleNamespace()
|
||||
pm.fingerprint_dir = tmp_path
|
||||
pm.is_dirty = False
|
||||
pm.notifications = queue.Queue()
|
||||
|
||||
idx = entry_mgr.add_entry("example.com", 8)
|
||||
|
||||
@@ -98,6 +100,7 @@ def test_view_archived_entries_view_only(monkeypatch, capsys):
|
||||
pm.nostr_client = SimpleNamespace()
|
||||
pm.fingerprint_dir = tmp_path
|
||||
pm.is_dirty = False
|
||||
pm.notifications = queue.Queue()
|
||||
|
||||
idx = entry_mgr.add_entry("example.com", 8)
|
||||
|
||||
@@ -131,6 +134,7 @@ def test_view_archived_entries_removed_after_restore(monkeypatch, capsys):
|
||||
pm.nostr_client = SimpleNamespace()
|
||||
pm.fingerprint_dir = tmp_path
|
||||
pm.is_dirty = False
|
||||
pm.notifications = queue.Queue()
|
||||
|
||||
idx = entry_mgr.add_entry("example.com", 8)
|
||||
|
||||
@@ -145,5 +149,6 @@ def test_view_archived_entries_removed_after_restore(monkeypatch, capsys):
|
||||
|
||||
monkeypatch.setattr("builtins.input", lambda *_: "")
|
||||
pm.handle_view_archived_entries()
|
||||
out = capsys.readouterr().out
|
||||
assert "No archived entries found." in out
|
||||
note = pm.notifications.get_nowait()
|
||||
assert note.level == "WARNING"
|
||||
assert note.message == "No archived entries found."
|
||||
|
@@ -4,6 +4,7 @@ from pathlib import Path
|
||||
sys.path.append(str(Path(__file__).resolve().parents[1]))
|
||||
|
||||
from password_manager.manager import PasswordManager, EncryptionMode
|
||||
import queue
|
||||
|
||||
|
||||
class FakeBackupManager:
|
||||
@@ -20,6 +21,7 @@ class FakeBackupManager:
|
||||
def _make_pm():
|
||||
pm = PasswordManager.__new__(PasswordManager)
|
||||
pm.encryption_mode = EncryptionMode.SEED_ONLY
|
||||
pm.notifications = queue.Queue()
|
||||
return pm
|
||||
|
||||
|
||||
@@ -56,8 +58,9 @@ def test_handle_verify_checksum_missing(monkeypatch, tmp_path, capsys):
|
||||
|
||||
monkeypatch.setattr("password_manager.manager.verify_checksum", raise_missing)
|
||||
pm.handle_verify_checksum()
|
||||
out = capsys.readouterr().out.lower()
|
||||
assert "generate script checksum" in out
|
||||
note = pm.notifications.get_nowait()
|
||||
assert note.level == "WARNING"
|
||||
assert "generate script checksum" in note.message.lower()
|
||||
|
||||
|
||||
def test_backup_and_restore_database(monkeypatch, capsys):
|
||||
|
45
src/tests/test_manager_warning_notifications.py
Normal file
45
src/tests/test_manager_warning_notifications.py
Normal file
@@ -0,0 +1,45 @@
|
||||
import queue
|
||||
from types import SimpleNamespace
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
sys.path.append(str(Path(__file__).resolve().parents[1]))
|
||||
|
||||
from password_manager.manager import PasswordManager, EncryptionMode
|
||||
from password_manager.entry_management import EntryManager
|
||||
from password_manager.backup import BackupManager
|
||||
from helpers import create_vault, TEST_SEED, TEST_PASSWORD
|
||||
from password_manager.config_manager import ConfigManager
|
||||
|
||||
|
||||
def _make_pm(tmp_path: Path) -> PasswordManager:
|
||||
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.notifications = queue.Queue()
|
||||
return pm
|
||||
|
||||
|
||||
def test_handle_search_entries_no_query(monkeypatch, tmp_path):
|
||||
pm = _make_pm(tmp_path)
|
||||
monkeypatch.setattr(
|
||||
"password_manager.manager.clear_header_with_notification", lambda *a, **k: None
|
||||
)
|
||||
monkeypatch.setattr("password_manager.manager.pause", lambda: None)
|
||||
monkeypatch.setattr("builtins.input", lambda *_: "")
|
||||
|
||||
pm.handle_search_entries()
|
||||
note = pm.notifications.get_nowait()
|
||||
assert note.level == "WARNING"
|
||||
assert note.message == "No search string provided."
|
@@ -2,6 +2,7 @@ import builtins
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
import queue
|
||||
|
||||
sys.path.append(str(Path(__file__).resolve().parents[1]))
|
||||
|
||||
@@ -16,6 +17,7 @@ def _make_pm(tmp_path: Path) -> PasswordManager:
|
||||
pm.fingerprint_dir = tmp_path
|
||||
pm.encryption_manager = SimpleNamespace(encrypt_and_save_file=lambda *a, **k: None)
|
||||
pm.verify_password = lambda pw: True
|
||||
pm.notifications = queue.Queue()
|
||||
return pm
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user