mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 15:28:44 +00:00
Merge pull request #347 from PR0M3TH3AN/codex/add-archived-flag-to-entry-management
Add archived flag to password entries
This commit is contained in:
@@ -72,6 +72,9 @@ class EntryManager:
|
|||||||
and entry.get("type") == EntryType.PASSWORD.value
|
and entry.get("type") == EntryType.PASSWORD.value
|
||||||
):
|
):
|
||||||
entry.pop("website", None)
|
entry.pop("website", None)
|
||||||
|
if "archived" not in entry and "blacklisted" in entry:
|
||||||
|
entry["archived"] = entry["blacklisted"]
|
||||||
|
entry.pop("blacklisted", None)
|
||||||
logger.debug("Index loaded successfully.")
|
logger.debug("Index loaded successfully.")
|
||||||
return data
|
return data
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -117,7 +120,7 @@ class EntryManager:
|
|||||||
length: int,
|
length: int,
|
||||||
username: Optional[str] = None,
|
username: Optional[str] = None,
|
||||||
url: Optional[str] = None,
|
url: Optional[str] = None,
|
||||||
blacklisted: bool = False,
|
archived: bool = False,
|
||||||
notes: str = "",
|
notes: str = "",
|
||||||
custom_fields: List[Dict[str, Any]] | None = None,
|
custom_fields: List[Dict[str, Any]] | None = None,
|
||||||
) -> int:
|
) -> int:
|
||||||
@@ -128,7 +131,7 @@ class EntryManager:
|
|||||||
:param length: The desired length of the password.
|
:param length: The desired length of the password.
|
||||||
:param username: (Optional) The username associated with the website.
|
:param username: (Optional) The username associated with the website.
|
||||||
:param url: (Optional) The URL of the website.
|
:param url: (Optional) The URL of the website.
|
||||||
:param blacklisted: (Optional) Whether the password is blacklisted. Defaults to False.
|
:param archived: (Optional) Whether the entry is archived. Defaults to False.
|
||||||
:param notes: (Optional) Extra notes to attach to the entry.
|
:param notes: (Optional) Extra notes to attach to the entry.
|
||||||
:return: The assigned index of the new entry.
|
:return: The assigned index of the new entry.
|
||||||
"""
|
"""
|
||||||
@@ -142,7 +145,7 @@ class EntryManager:
|
|||||||
"length": length,
|
"length": length,
|
||||||
"username": username if username else "",
|
"username": username if username else "",
|
||||||
"url": url if url else "",
|
"url": url if url else "",
|
||||||
"blacklisted": blacklisted,
|
"archived": archived,
|
||||||
"type": EntryType.PASSWORD.value,
|
"type": EntryType.PASSWORD.value,
|
||||||
"kind": EntryType.PASSWORD.value,
|
"kind": EntryType.PASSWORD.value,
|
||||||
"notes": notes,
|
"notes": notes,
|
||||||
@@ -184,6 +187,7 @@ class EntryManager:
|
|||||||
label: str,
|
label: str,
|
||||||
parent_seed: str,
|
parent_seed: str,
|
||||||
*,
|
*,
|
||||||
|
archived: bool = False,
|
||||||
secret: str | None = None,
|
secret: str | None = None,
|
||||||
index: int | None = None,
|
index: int | None = None,
|
||||||
period: int = 30,
|
period: int = 30,
|
||||||
@@ -205,6 +209,7 @@ class EntryManager:
|
|||||||
"index": index,
|
"index": index,
|
||||||
"period": period,
|
"period": period,
|
||||||
"digits": digits,
|
"digits": digits,
|
||||||
|
"archived": archived,
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
entry = {
|
entry = {
|
||||||
@@ -214,6 +219,7 @@ class EntryManager:
|
|||||||
"secret": secret,
|
"secret": secret,
|
||||||
"period": period,
|
"period": period,
|
||||||
"digits": digits,
|
"digits": digits,
|
||||||
|
"archived": archived,
|
||||||
}
|
}
|
||||||
|
|
||||||
data["entries"][str(entry_id)] = entry
|
data["entries"][str(entry_id)] = entry
|
||||||
@@ -234,6 +240,7 @@ class EntryManager:
|
|||||||
parent_seed: str,
|
parent_seed: str,
|
||||||
index: int | None = None,
|
index: int | None = None,
|
||||||
notes: str = "",
|
notes: str = "",
|
||||||
|
archived: bool = False,
|
||||||
) -> int:
|
) -> int:
|
||||||
"""Add a new SSH key pair entry.
|
"""Add a new SSH key pair entry.
|
||||||
|
|
||||||
@@ -253,6 +260,7 @@ class EntryManager:
|
|||||||
"index": index,
|
"index": index,
|
||||||
"label": label,
|
"label": label,
|
||||||
"notes": notes,
|
"notes": notes,
|
||||||
|
"archived": archived,
|
||||||
}
|
}
|
||||||
self._save_index(data)
|
self._save_index(data)
|
||||||
self.update_checksum()
|
self.update_checksum()
|
||||||
@@ -281,6 +289,7 @@ class EntryManager:
|
|||||||
key_type: str = "ed25519",
|
key_type: str = "ed25519",
|
||||||
user_id: str = "",
|
user_id: str = "",
|
||||||
notes: str = "",
|
notes: str = "",
|
||||||
|
archived: bool = False,
|
||||||
) -> int:
|
) -> int:
|
||||||
"""Add a new PGP key entry."""
|
"""Add a new PGP key entry."""
|
||||||
|
|
||||||
@@ -297,6 +306,7 @@ class EntryManager:
|
|||||||
"key_type": key_type,
|
"key_type": key_type,
|
||||||
"user_id": user_id,
|
"user_id": user_id,
|
||||||
"notes": notes,
|
"notes": notes,
|
||||||
|
"archived": archived,
|
||||||
}
|
}
|
||||||
self._save_index(data)
|
self._save_index(data)
|
||||||
self.update_checksum()
|
self.update_checksum()
|
||||||
@@ -329,6 +339,7 @@ class EntryManager:
|
|||||||
label: str,
|
label: str,
|
||||||
index: int | None = None,
|
index: int | None = None,
|
||||||
notes: str = "",
|
notes: str = "",
|
||||||
|
archived: bool = False,
|
||||||
) -> int:
|
) -> int:
|
||||||
"""Add a new Nostr key pair entry."""
|
"""Add a new Nostr key pair entry."""
|
||||||
|
|
||||||
@@ -343,6 +354,7 @@ class EntryManager:
|
|||||||
"index": index,
|
"index": index,
|
||||||
"label": label,
|
"label": label,
|
||||||
"notes": notes,
|
"notes": notes,
|
||||||
|
"archived": archived,
|
||||||
}
|
}
|
||||||
self._save_index(data)
|
self._save_index(data)
|
||||||
self.update_checksum()
|
self.update_checksum()
|
||||||
@@ -381,6 +393,7 @@ class EntryManager:
|
|||||||
index: int | None = None,
|
index: int | None = None,
|
||||||
words_num: int = 24,
|
words_num: int = 24,
|
||||||
notes: str = "",
|
notes: str = "",
|
||||||
|
archived: bool = False,
|
||||||
) -> int:
|
) -> int:
|
||||||
"""Add a new derived seed phrase entry."""
|
"""Add a new derived seed phrase entry."""
|
||||||
|
|
||||||
@@ -396,6 +409,7 @@ class EntryManager:
|
|||||||
"label": label,
|
"label": label,
|
||||||
"words": words_num,
|
"words": words_num,
|
||||||
"notes": notes,
|
"notes": notes,
|
||||||
|
"archived": archived,
|
||||||
}
|
}
|
||||||
self._save_index(data)
|
self._save_index(data)
|
||||||
self.update_checksum()
|
self.update_checksum()
|
||||||
@@ -505,13 +519,14 @@ class EntryManager:
|
|||||||
index: int,
|
index: int,
|
||||||
username: Optional[str] = None,
|
username: Optional[str] = None,
|
||||||
url: Optional[str] = None,
|
url: Optional[str] = None,
|
||||||
blacklisted: Optional[bool] = None,
|
archived: Optional[bool] = None,
|
||||||
notes: Optional[str] = None,
|
notes: Optional[str] = None,
|
||||||
*,
|
*,
|
||||||
label: Optional[str] = None,
|
label: Optional[str] = None,
|
||||||
period: Optional[int] = None,
|
period: Optional[int] = None,
|
||||||
digits: Optional[int] = None,
|
digits: Optional[int] = None,
|
||||||
custom_fields: List[Dict[str, Any]] | None = None,
|
custom_fields: List[Dict[str, Any]] | None = None,
|
||||||
|
**legacy,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Modifies an existing entry based on the provided index and new values.
|
Modifies an existing entry based on the provided index and new values.
|
||||||
@@ -519,7 +534,7 @@ class EntryManager:
|
|||||||
:param index: The index number of the entry to modify.
|
:param index: The index number of the entry to modify.
|
||||||
:param username: (Optional) The new username (password entries).
|
:param username: (Optional) The new username (password entries).
|
||||||
:param url: (Optional) The new URL (password entries).
|
:param url: (Optional) The new URL (password entries).
|
||||||
:param blacklisted: (Optional) The new blacklist status.
|
:param archived: (Optional) The new archived status.
|
||||||
:param notes: (Optional) New notes to attach to the entry.
|
:param notes: (Optional) New notes to attach to the entry.
|
||||||
:param label: (Optional) The new label for the entry.
|
:param label: (Optional) The new label for the entry.
|
||||||
:param period: (Optional) The new TOTP period in seconds.
|
:param period: (Optional) The new TOTP period in seconds.
|
||||||
@@ -564,10 +579,15 @@ class EntryManager:
|
|||||||
entry["url"] = url
|
entry["url"] = url
|
||||||
logger.debug(f"Updated URL to '{url}' for index {index}.")
|
logger.debug(f"Updated URL to '{url}' for index {index}.")
|
||||||
|
|
||||||
if blacklisted is not None:
|
if archived is None and "blacklisted" in legacy:
|
||||||
entry["blacklisted"] = blacklisted
|
archived = legacy["blacklisted"]
|
||||||
|
|
||||||
|
if archived is not None:
|
||||||
|
entry["archived"] = archived
|
||||||
|
if "blacklisted" in entry:
|
||||||
|
entry.pop("blacklisted", None)
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"Updated blacklist status to '{blacklisted}' for index {index}."
|
f"Updated archived status to '{archived}' for index {index}."
|
||||||
)
|
)
|
||||||
|
|
||||||
if notes is not None:
|
if notes is not None:
|
||||||
@@ -598,6 +618,14 @@ class EntryManager:
|
|||||||
colored(f"Error: Failed to modify entry at index {index}: {e}", "red")
|
colored(f"Error: Failed to modify entry at index {index}: {e}", "red")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def archive_entry(self, index: int) -> None:
|
||||||
|
"""Mark the specified entry as archived."""
|
||||||
|
self.modify_entry(index, archived=True)
|
||||||
|
|
||||||
|
def restore_entry(self, index: int) -> None:
|
||||||
|
"""Unarchive the specified entry."""
|
||||||
|
self.modify_entry(index, archived=False)
|
||||||
|
|
||||||
def list_entries(
|
def list_entries(
|
||||||
self, sort_by: str = "index", filter_kind: str | None = None
|
self, sort_by: str = "index", filter_kind: str | None = None
|
||||||
) -> List[Tuple[int, str, Optional[str], Optional[str], bool]]:
|
) -> List[Tuple[int, str, Optional[str], Optional[str], bool]]:
|
||||||
@@ -644,7 +672,7 @@ class EntryManager:
|
|||||||
label,
|
label,
|
||||||
entry.get("username", ""),
|
entry.get("username", ""),
|
||||||
entry.get("url", ""),
|
entry.get("url", ""),
|
||||||
entry.get("blacklisted", False),
|
entry.get("archived", entry.get("blacklisted", False)),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -677,7 +705,7 @@ class EntryManager:
|
|||||||
print(colored(f" URL: {entry.get('url') or 'N/A'}", "cyan"))
|
print(colored(f" URL: {entry.get('url') or 'N/A'}", "cyan"))
|
||||||
print(
|
print(
|
||||||
colored(
|
colored(
|
||||||
f" Blacklisted: {'Yes' if entry.get('blacklisted', False) else 'No'}",
|
f" Blacklisted: {'Yes' if entry.get('archived', entry.get('blacklisted', False)) else 'No'}",
|
||||||
"cyan",
|
"cyan",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -739,7 +767,7 @@ class EntryManager:
|
|||||||
label,
|
label,
|
||||||
username,
|
username,
|
||||||
url,
|
url,
|
||||||
entry.get("blacklisted", False),
|
entry.get("archived", entry.get("blacklisted", False)),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@@ -939,7 +939,7 @@ class PasswordManager:
|
|||||||
length,
|
length,
|
||||||
username,
|
username,
|
||||||
url,
|
url,
|
||||||
blacklisted=False,
|
archived=False,
|
||||||
notes=notes,
|
notes=notes,
|
||||||
custom_fields=custom_fields,
|
custom_fields=custom_fields,
|
||||||
)
|
)
|
||||||
@@ -1545,7 +1545,7 @@ class PasswordManager:
|
|||||||
length = entry.get("length")
|
length = entry.get("length")
|
||||||
username = entry.get("username")
|
username = entry.get("username")
|
||||||
url = entry.get("url")
|
url = entry.get("url")
|
||||||
blacklisted = entry.get("blacklisted")
|
blacklisted = entry.get("archived", entry.get("blacklisted"))
|
||||||
notes = entry.get("notes", "")
|
notes = entry.get("notes", "")
|
||||||
|
|
||||||
print(
|
print(
|
||||||
@@ -1660,7 +1660,7 @@ class PasswordManager:
|
|||||||
label = entry.get("label", "")
|
label = entry.get("label", "")
|
||||||
period = int(entry.get("period", 30))
|
period = int(entry.get("period", 30))
|
||||||
digits = int(entry.get("digits", 6))
|
digits = int(entry.get("digits", 6))
|
||||||
blacklisted = entry.get("blacklisted", False)
|
blacklisted = entry.get("archived", entry.get("blacklisted", False))
|
||||||
notes = entry.get("notes", "")
|
notes = entry.get("notes", "")
|
||||||
|
|
||||||
print(
|
print(
|
||||||
@@ -1751,7 +1751,7 @@ class PasswordManager:
|
|||||||
|
|
||||||
self.entry_manager.modify_entry(
|
self.entry_manager.modify_entry(
|
||||||
index,
|
index,
|
||||||
blacklisted=new_blacklisted,
|
archived=new_blacklisted,
|
||||||
notes=new_notes,
|
notes=new_notes,
|
||||||
label=new_label,
|
label=new_label,
|
||||||
period=new_period,
|
period=new_period,
|
||||||
@@ -1762,7 +1762,7 @@ class PasswordManager:
|
|||||||
website_name = entry.get("label", entry.get("website"))
|
website_name = entry.get("label", entry.get("website"))
|
||||||
username = entry.get("username")
|
username = entry.get("username")
|
||||||
url = entry.get("url")
|
url = entry.get("url")
|
||||||
blacklisted = entry.get("blacklisted")
|
blacklisted = entry.get("archived", entry.get("blacklisted"))
|
||||||
notes = entry.get("notes", "")
|
notes = entry.get("notes", "")
|
||||||
|
|
||||||
print(
|
print(
|
||||||
@@ -1847,8 +1847,8 @@ class PasswordManager:
|
|||||||
index,
|
index,
|
||||||
new_username,
|
new_username,
|
||||||
new_url,
|
new_url,
|
||||||
new_blacklisted,
|
archived=new_blacklisted,
|
||||||
new_notes,
|
notes=new_notes,
|
||||||
label=new_label,
|
label=new_label,
|
||||||
custom_fields=custom_fields,
|
custom_fields=custom_fields,
|
||||||
)
|
)
|
||||||
@@ -1992,7 +1992,7 @@ class PasswordManager:
|
|||||||
website = entry.get("label", entry.get("website", ""))
|
website = entry.get("label", entry.get("website", ""))
|
||||||
username = entry.get("username", "")
|
username = entry.get("username", "")
|
||||||
url = entry.get("url", "")
|
url = entry.get("url", "")
|
||||||
blacklisted = entry.get("blacklisted", False)
|
blacklisted = entry.get("archived", entry.get("blacklisted", False))
|
||||||
print(color_text(f" Label: {website}", "index"))
|
print(color_text(f" Label: {website}", "index"))
|
||||||
print(color_text(f" Username: {username or 'N/A'}", "index"))
|
print(color_text(f" Username: {username or 'N/A'}", "index"))
|
||||||
print(color_text(f" URL: {url or 'N/A'}", "index"))
|
print(color_text(f" URL: {url or 'N/A'}", "index"))
|
||||||
@@ -2115,7 +2115,7 @@ class PasswordManager:
|
|||||||
totp_list: list[tuple[str, int, int, bool]] = []
|
totp_list: list[tuple[str, int, int, bool]] = []
|
||||||
for idx_str, entry in entries.items():
|
for idx_str, entry in entries.items():
|
||||||
if entry.get("type") == EntryType.TOTP.value and not entry.get(
|
if entry.get("type") == EntryType.TOTP.value and not entry.get(
|
||||||
"blacklisted", False
|
"archived", entry.get("blacklisted", False)
|
||||||
):
|
):
|
||||||
label = entry.get("label", "")
|
label = entry.get("label", "")
|
||||||
period = int(entry.get("period", 30))
|
period = int(entry.get("period", 30))
|
||||||
|
@@ -34,7 +34,7 @@ def test_add_and_retrieve_entry():
|
|||||||
"length": 12,
|
"length": 12,
|
||||||
"username": "user",
|
"username": "user",
|
||||||
"url": "",
|
"url": "",
|
||||||
"blacklisted": False,
|
"archived": False,
|
||||||
"type": "password",
|
"type": "password",
|
||||||
"kind": "password",
|
"kind": "password",
|
||||||
"notes": "",
|
"notes": "",
|
||||||
|
@@ -63,5 +63,6 @@ def test_handle_add_totp(monkeypatch, capsys):
|
|||||||
"index": 0,
|
"index": 0,
|
||||||
"period": 30,
|
"period": 30,
|
||||||
"digits": 6,
|
"digits": 6,
|
||||||
|
"archived": False,
|
||||||
}
|
}
|
||||||
assert "ID 0" in out
|
assert "ID 0" in out
|
||||||
|
@@ -61,7 +61,7 @@ def test_handle_display_totp_codes(monkeypatch, capsys):
|
|||||||
assert "123456" in out
|
assert "123456" in out
|
||||||
|
|
||||||
|
|
||||||
def test_display_totp_codes_excludes_blacklisted(monkeypatch, capsys):
|
def test_display_totp_codes_excludes_archived(monkeypatch, capsys):
|
||||||
with TemporaryDirectory() as tmpdir:
|
with TemporaryDirectory() as tmpdir:
|
||||||
tmp_path = Path(tmpdir)
|
tmp_path = Path(tmpdir)
|
||||||
vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
|
vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
|
||||||
@@ -83,7 +83,7 @@ def test_display_totp_codes_excludes_blacklisted(monkeypatch, capsys):
|
|||||||
|
|
||||||
entry_mgr.add_totp("Visible", TEST_SEED)
|
entry_mgr.add_totp("Visible", TEST_SEED)
|
||||||
entry_mgr.add_totp("Hidden", TEST_SEED)
|
entry_mgr.add_totp("Hidden", TEST_SEED)
|
||||||
entry_mgr.modify_entry(1, blacklisted=True)
|
entry_mgr.modify_entry(1, archived=True)
|
||||||
|
|
||||||
monkeypatch.setattr(pm.entry_manager, "get_totp_code", lambda *a, **k: "123456")
|
monkeypatch.setattr(pm.entry_manager, "get_totp_code", lambda *a, **k: "123456")
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
|
@@ -30,6 +30,7 @@ def test_nostr_key_determinism():
|
|||||||
"index": idx,
|
"index": idx,
|
||||||
"label": "main",
|
"label": "main",
|
||||||
"notes": "",
|
"notes": "",
|
||||||
|
"archived": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
npub1, nsec1 = entry_mgr.get_nostr_key_pair(idx, TEST_SEED)
|
npub1, nsec1 = entry_mgr.get_nostr_key_pair(idx, TEST_SEED)
|
||||||
|
@@ -28,6 +28,7 @@ def test_add_and_retrieve_ssh_key_pair():
|
|||||||
"index": index,
|
"index": index,
|
||||||
"label": "ssh",
|
"label": "ssh",
|
||||||
"notes": "",
|
"notes": "",
|
||||||
|
"archived": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
priv1, pub1 = entry_mgr.get_ssh_key_pair(index, TEST_SEED)
|
priv1, pub1 = entry_mgr.get_ssh_key_pair(index, TEST_SEED)
|
||||||
|
@@ -35,6 +35,7 @@ def test_add_totp_and_get_code():
|
|||||||
"index": 0,
|
"index": 0,
|
||||||
"period": 30,
|
"period": 30,
|
||||||
"digits": 6,
|
"digits": 6,
|
||||||
|
"archived": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
code = entry_mgr.get_totp_code(0, TEST_SEED, timestamp=0)
|
code = entry_mgr.get_totp_code(0, TEST_SEED, timestamp=0)
|
||||||
@@ -72,6 +73,7 @@ def test_add_totp_imported(tmp_path):
|
|||||||
"secret": secret,
|
"secret": secret,
|
||||||
"period": 30,
|
"period": 30,
|
||||||
"digits": 6,
|
"digits": 6,
|
||||||
|
"archived": False,
|
||||||
}
|
}
|
||||||
code = em.get_totp_code(0, timestamp=0)
|
code = em.get_totp_code(0, timestamp=0)
|
||||||
assert code == pyotp.TOTP(secret).at(0)
|
assert code == pyotp.TOTP(secret).at(0)
|
||||||
|
Reference in New Issue
Block a user