mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 07:18:47 +00:00
Add editing options for 2FA entries
This commit is contained in:
@@ -267,9 +267,10 @@ When choosing **Add Entry**, you can now select from:
|
||||
1. From the main menu choose **Modify an Existing Entry** and enter the index of the 2FA code you want to edit.
|
||||
2. SeedPass will show the current label, period, digit count, and archived status.
|
||||
3. Enter new values or press **Enter** to keep the existing settings.
|
||||
4. The updated entry is saved back to your encrypted vault.
|
||||
5. Archived entries are hidden from lists but can be viewed or restored from the **List Archived** menu.
|
||||
6. When editing an archived entry you'll be prompted to restore it after saving your changes.
|
||||
4. When retrieving a 2FA entry you can press **E** to edit the label, period or digit count, or **A** to archive/unarchive it.
|
||||
5. The updated entry is saved back to your encrypted vault.
|
||||
6. Archived entries are hidden from lists but can be viewed or restored from the **List Archived** menu.
|
||||
7. When editing an archived entry you'll be prompted to restore it after saving your changes.
|
||||
|
||||
### Using Secret Mode
|
||||
|
||||
|
@@ -1674,6 +1674,9 @@ class PasswordManager:
|
||||
if entry_type == EntryType.PASSWORD.value:
|
||||
print(colored("U. Edit Username", "cyan"))
|
||||
print(colored("R. Edit URL", "cyan"))
|
||||
elif entry_type == EntryType.TOTP.value:
|
||||
print(colored("P. Edit Period", "cyan"))
|
||||
print(colored("D. Edit Digits", "cyan"))
|
||||
choice = input("Select option or press Enter to go back: ").strip().lower()
|
||||
if not choice:
|
||||
break
|
||||
@@ -1693,6 +1696,22 @@ class PasswordManager:
|
||||
self.entry_manager.modify_entry(index, url=new_url)
|
||||
self.is_dirty = True
|
||||
self.last_update = time.time()
|
||||
elif entry_type == EntryType.TOTP.value and choice == "p":
|
||||
period_str = input("New period (seconds): ").strip()
|
||||
if period_str.isdigit():
|
||||
self.entry_manager.modify_entry(index, period=int(period_str))
|
||||
self.is_dirty = True
|
||||
self.last_update = time.time()
|
||||
else:
|
||||
print(colored("Invalid period value.", "red"))
|
||||
elif entry_type == EntryType.TOTP.value and choice == "d":
|
||||
digits_str = input("New digits: ").strip()
|
||||
if digits_str.isdigit():
|
||||
self.entry_manager.modify_entry(index, digits=int(digits_str))
|
||||
self.is_dirty = True
|
||||
self.last_update = time.time()
|
||||
else:
|
||||
print(colored("Invalid digits value.", "red"))
|
||||
else:
|
||||
print(colored("Invalid choice.", "red"))
|
||||
entry = self.entry_manager.retrieve_entry(index) or entry
|
||||
|
57
src/tests/test_manager_edit_totp.py
Normal file
57
src/tests/test_manager_edit_totp.py
Normal file
@@ -0,0 +1,57 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from helpers import create_vault, TEST_SEED, TEST_PASSWORD
|
||||
|
||||
sys.path.append(str(Path(__file__).resolve().parents[1]))
|
||||
|
||||
from password_manager.entry_management import EntryManager
|
||||
from password_manager.backup import BackupManager
|
||||
from password_manager.manager import PasswordManager, EncryptionMode
|
||||
from password_manager.config_manager import ConfigManager
|
||||
|
||||
|
||||
class FakeNostrClient:
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.published = []
|
||||
|
||||
def publish_snapshot(self, data: bytes):
|
||||
self.published.append(data)
|
||||
return None, "abcd"
|
||||
|
||||
|
||||
def test_edit_totp_period_from_retrieve(monkeypatch):
|
||||
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 = FakeNostrClient()
|
||||
pm.fingerprint_dir = tmp_path
|
||||
pm.is_dirty = False
|
||||
pm.secret_mode_enabled = False
|
||||
|
||||
entry_mgr.add_totp("Example", TEST_SEED)
|
||||
|
||||
inputs = iter(["0", "e", "p", "45", "", ""])
|
||||
monkeypatch.setattr("builtins.input", lambda *a, **k: next(inputs))
|
||||
monkeypatch.setattr(pm.entry_manager, "get_totp_code", lambda *a, **k: "123456")
|
||||
monkeypatch.setattr(
|
||||
pm.entry_manager, "get_totp_time_remaining", lambda *a, **k: 1
|
||||
)
|
||||
monkeypatch.setattr("password_manager.manager.time.sleep", lambda *a, **k: None)
|
||||
monkeypatch.setattr("password_manager.manager.timed_input", lambda *a, **k: "b")
|
||||
|
||||
pm.handle_retrieve_entry()
|
||||
entry = entry_mgr.retrieve_entry(0)
|
||||
assert entry["period"] == 45
|
20
src/tests/test_modify_totp_entry.py
Normal file
20
src/tests/test_modify_totp_entry.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from helpers import create_vault, TEST_SEED, TEST_PASSWORD
|
||||
|
||||
from password_manager.entry_management import EntryManager
|
||||
from password_manager.backup import BackupManager
|
||||
from password_manager.config_manager import ConfigManager
|
||||
|
||||
|
||||
def test_modify_totp_entry_period_digits_and_archive(tmp_path):
|
||||
vault, _ = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
|
||||
cfg_mgr = ConfigManager(vault, tmp_path)
|
||||
backup_mgr = BackupManager(tmp_path, cfg_mgr)
|
||||
em = EntryManager(vault, backup_mgr)
|
||||
|
||||
em.add_totp("Example", TEST_SEED, period=30, digits=6)
|
||||
em.modify_entry(0, period=60, digits=8, archived=True)
|
||||
|
||||
entry = em.retrieve_entry(0)
|
||||
assert entry["period"] == 60
|
||||
assert entry["digits"] == 8
|
||||
assert entry["archived"] is True
|
Reference in New Issue
Block a user