Enhance modify entry for TOTP

This commit is contained in:
thePR0M3TH3AN
2025-07-03 13:29:17 -04:00
parent 1d4838dd99
commit 1b0101f257
3 changed files with 185 additions and 70 deletions

View File

@@ -192,6 +192,13 @@ python src/main.py
5. Optionally specify the TOTP period and digit count. 5. Optionally specify the TOTP period and digit count.
6. SeedPass will display the URI and secret so you can add it to your authenticator app. 6. SeedPass will display the URI and secret so you can add it to your authenticator app.
### Modifying a 2FA Entry
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 blacklist status.
3. Enter new values or press **Enter** to keep the existing settings.
4. The updated entry is saved back to your encrypted vault.
### Managing Multiple Seeds ### Managing Multiple Seeds

View File

@@ -304,15 +304,22 @@ class EntryManager:
url: Optional[str] = None, url: Optional[str] = None,
blacklisted: Optional[bool] = None, blacklisted: Optional[bool] = None,
notes: Optional[str] = None, notes: Optional[str] = None,
*,
label: Optional[str] = None,
period: Optional[int] = None,
digits: Optional[int] = None,
) -> 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.
: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. :param username: (Optional) The new username (password entries).
:param url: (Optional) The new URL. :param url: (Optional) The new URL (password entries).
:param blacklisted: (Optional) The new blacklist status. :param blacklisted: (Optional) The new blacklist 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 TOTP entries.
:param period: (Optional) The new TOTP period in seconds.
:param digits: (Optional) The new number of digits for TOTP codes.
""" """
try: try:
data = self.vault.load_index() data = self.vault.load_index()
@@ -330,13 +337,25 @@ class EntryManager:
) )
return return
if username is not None: entry_type = entry.get("type", EntryType.PASSWORD.value)
entry["username"] = username
logger.debug(f"Updated username to '{username}' for index {index}.")
if url is not None: if entry_type == EntryType.TOTP.value:
entry["url"] = url if label is not None:
logger.debug(f"Updated URL to '{url}' for index {index}.") entry["label"] = label
logger.debug(f"Updated label to '{label}' for index {index}.")
if period is not None:
entry["period"] = period
logger.debug(f"Updated period to '{period}' for index {index}.")
if digits is not None:
entry["digits"] = digits
logger.debug(f"Updated digits to '{digits}' for index {index}.")
else:
if username is not None:
entry["username"] = username
logger.debug(f"Updated username to '{username}' for index {index}.")
if url is not None:
entry["url"] = url
logger.debug(f"Updated URL to '{url}' for index {index}.")
if blacklisted is not None: if blacklisted is not None:
entry["blacklisted"] = blacklisted entry["blacklisted"] = blacklisted

View File

@@ -1121,76 +1121,165 @@ class PasswordManager:
if not entry: if not entry:
return return
website_name = entry.get("website") entry_type = entry.get("type", EntryType.PASSWORD.value)
length = entry.get("length")
username = entry.get("username")
url = entry.get("url")
blacklisted = entry.get("blacklisted")
notes = entry.get("notes", "")
# Display current values if entry_type == EntryType.TOTP.value:
print( label = entry.get("label", "")
colored( period = int(entry.get("period", 30))
f"Modifying entry for '{website_name}' (Index: {index}):", "cyan" digits = int(entry.get("digits", 6))
) blacklisted = entry.get("blacklisted", False)
) notes = entry.get("notes", "")
print(colored(f"Current Username: {username or 'N/A'}", "cyan"))
print(colored(f"Current URL: {url or 'N/A'}", "cyan"))
print(
colored(
f"Current Blacklist Status: {'Blacklisted' if blacklisted else 'Not Blacklisted'}",
"cyan",
)
)
# Prompt for new values (optional)
new_username = (
input(
f'Enter new username (leave blank to keep "{username or "N/A"}"): '
).strip()
or username
)
new_url = (
input(f'Enter new URL (leave blank to keep "{url or "N/A"}"): ').strip()
or url
)
blacklist_input = (
input(
f'Is this password blacklisted? (Y/N, current: {"Y" if blacklisted else "N"}): '
)
.strip()
.lower()
)
if blacklist_input == "":
new_blacklisted = blacklisted
elif blacklist_input == "y":
new_blacklisted = True
elif blacklist_input == "n":
new_blacklisted = False
else:
print( print(
colored( colored(
"Invalid input for blacklist status. Keeping the current status.", f"Modifying 2FA entry '{label}' (Index: {index}):",
"yellow", "cyan",
) )
) )
new_blacklisted = blacklisted print(colored(f"Current Period: {period}s", "cyan"))
print(colored(f"Current Digits: {digits}", "cyan"))
new_notes = ( print(
input( colored(
f'Enter new notes (leave blank to keep "{notes or "N/A"}"): ' f"Current Blacklist Status: {'Blacklisted' if blacklisted else 'Not Blacklisted'}",
"cyan",
)
)
new_label = (
input(f'Enter new label (leave blank to keep "{label}"): ').strip()
or label
)
period_input = input(
f"Enter new period in seconds (current: {period}): "
).strip() ).strip()
or notes new_period = period
) if period_input:
if period_input.isdigit():
new_period = int(period_input)
else:
print(
colored("Invalid period value. Keeping current.", "yellow")
)
digits_input = input(
f"Enter new digit count (current: {digits}): "
).strip()
new_digits = digits
if digits_input:
if digits_input.isdigit():
new_digits = int(digits_input)
else:
print(
colored(
"Invalid digits value. Keeping current.",
"yellow",
)
)
blacklist_input = (
input(
f'Is this 2FA code blacklisted? (Y/N, current: {"Y" if blacklisted else "N"}): '
)
.strip()
.lower()
)
if blacklist_input == "":
new_blacklisted = blacklisted
elif blacklist_input == "y":
new_blacklisted = True
elif blacklist_input == "n":
new_blacklisted = False
else:
print(
colored(
"Invalid input for blacklist status. Keeping the current status.",
"yellow",
)
)
new_blacklisted = blacklisted
# Update the entry new_notes = (
self.entry_manager.modify_entry( input(
index, f'Enter new notes (leave blank to keep "{notes or "N/A"}"): '
new_username, ).strip()
new_url, or notes
new_blacklisted, )
new_notes,
) self.entry_manager.modify_entry(
index,
blacklisted=new_blacklisted,
notes=new_notes,
label=new_label,
period=new_period,
digits=new_digits,
)
else:
website_name = entry.get("website")
username = entry.get("username")
url = entry.get("url")
blacklisted = entry.get("blacklisted")
notes = entry.get("notes", "")
print(
colored(
f"Modifying entry for '{website_name}' (Index: {index}):",
"cyan",
)
)
print(colored(f"Current Username: {username or 'N/A'}", "cyan"))
print(colored(f"Current URL: {url or 'N/A'}", "cyan"))
print(
colored(
f"Current Blacklist Status: {'Blacklisted' if blacklisted else 'Not Blacklisted'}",
"cyan",
)
)
new_username = (
input(
f'Enter new username (leave blank to keep "{username or "N/A"}"): '
).strip()
or username
)
new_url = (
input(
f'Enter new URL (leave blank to keep "{url or "N/A"}"): '
).strip()
or url
)
blacklist_input = (
input(
f'Is this password blacklisted? (Y/N, current: {"Y" if blacklisted else "N"}): '
)
.strip()
.lower()
)
if blacklist_input == "":
new_blacklisted = blacklisted
elif blacklist_input == "y":
new_blacklisted = True
elif blacklist_input == "n":
new_blacklisted = False
else:
print(
colored(
"Invalid input for blacklist status. Keeping the current status.",
"yellow",
)
)
new_blacklisted = blacklisted
new_notes = (
input(
f'Enter new notes (leave blank to keep "{notes or "N/A"}"): '
).strip()
or notes
)
self.entry_manager.modify_entry(
index,
new_username,
new_url,
new_blacklisted,
new_notes,
)
# Mark database as dirty for background sync # Mark database as dirty for background sync
self.is_dirty = True self.is_dirty = True