mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 07:18:47 +00:00
Backup to Nostr after password change
This commit is contained in:
@@ -206,7 +206,9 @@ def handle_display_npub(password_manager: PasswordManager):
|
||||
print(colored(f"Error: Failed to display npub: {e}", "red"))
|
||||
|
||||
|
||||
def handle_post_to_nostr(password_manager: PasswordManager):
|
||||
def handle_post_to_nostr(
|
||||
password_manager: PasswordManager, alt_summary: str | None = None
|
||||
):
|
||||
"""
|
||||
Handles the action of posting the encrypted password index to Nostr.
|
||||
"""
|
||||
@@ -216,7 +218,8 @@ def handle_post_to_nostr(password_manager: PasswordManager):
|
||||
if encrypted_data:
|
||||
# Post to Nostr
|
||||
success = password_manager.nostr_client.publish_json_to_nostr(
|
||||
encrypted_data
|
||||
encrypted_data,
|
||||
alt_summary=alt_summary,
|
||||
)
|
||||
if success:
|
||||
print(colored("\N{WHITE HEAVY CHECK MARK} Sync complete.", "green"))
|
||||
|
@@ -16,6 +16,7 @@ from nostr_sdk import (
|
||||
Filter,
|
||||
Kind,
|
||||
KindStandard,
|
||||
Tag,
|
||||
)
|
||||
from datetime import timedelta
|
||||
|
||||
@@ -86,9 +87,23 @@ class NostrClient:
|
||||
logger.info(f"NostrClient connected to relays: {self.relays}")
|
||||
|
||||
def publish_json_to_nostr(
|
||||
self, encrypted_json: bytes, to_pubkey: str | None = None
|
||||
self,
|
||||
encrypted_json: bytes,
|
||||
to_pubkey: str | None = None,
|
||||
alt_summary: str | None = None,
|
||||
) -> bool:
|
||||
"""Builds and publishes a Kind 1 text note or direct message."""
|
||||
"""Builds and publishes a Kind 1 text note or direct message.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
encrypted_json : bytes
|
||||
The encrypted index data to publish.
|
||||
to_pubkey : str | None, optional
|
||||
If provided, send as a direct message to this public key.
|
||||
alt_summary : str | None, optional
|
||||
If provided, include an ``alt`` tag so uploads can be
|
||||
associated with a specific event like a password change.
|
||||
"""
|
||||
try:
|
||||
content = base64.b64encode(encrypted_json).decode("utf-8")
|
||||
|
||||
@@ -98,11 +113,10 @@ class NostrClient:
|
||||
self.relays, receiver, content
|
||||
)
|
||||
else:
|
||||
event = (
|
||||
EventBuilder.text_note(content)
|
||||
.build(self.keys.public_key())
|
||||
.sign_with_keys(self.keys)
|
||||
)
|
||||
builder = EventBuilder.text_note(content)
|
||||
if alt_summary:
|
||||
builder = builder.tags([Tag.alt(alt_summary)])
|
||||
event = builder.build(self.keys.public_key()).sign_with_keys(self.keys)
|
||||
event_output = self.publish_event(event)
|
||||
|
||||
event_id_hex = (
|
||||
|
@@ -1318,9 +1318,21 @@ class PasswordManager:
|
||||
|
||||
print(colored("Master password changed successfully.", "green"))
|
||||
|
||||
# All data has been re-encrypted with the new password. Since no
|
||||
# entries changed, avoid pushing the database to Nostr here.
|
||||
# Subsequent entry modifications will trigger a push when needed.
|
||||
# Push a fresh backup to Nostr so the newly encrypted index is
|
||||
# stored remotely. Include a tag to mark the password change.
|
||||
try:
|
||||
encrypted_data = self.get_encrypted_data()
|
||||
if encrypted_data:
|
||||
summary = f"password-change-{int(time.time())}"
|
||||
self.nostr_client.publish_json_to_nostr(
|
||||
encrypted_data,
|
||||
alt_summary=summary,
|
||||
)
|
||||
except Exception as nostr_error:
|
||||
logging.error(
|
||||
f"Failed to post updated index to Nostr after password change: {nostr_error}"
|
||||
)
|
||||
logging.error(traceback.format_exc())
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to change password: {e}")
|
||||
logging.error(traceback.format_exc())
|
||||
|
@@ -15,7 +15,7 @@ from password_manager.vault import Vault
|
||||
from password_manager.manager import PasswordManager
|
||||
|
||||
|
||||
def test_change_password_does_not_trigger_nostr_backup(monkeypatch):
|
||||
def test_change_password_triggers_nostr_backup(monkeypatch):
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
fp = Path(tmpdir)
|
||||
enc_mgr = EncryptionManager(Fernet.generate_key(), fp)
|
||||
@@ -46,4 +46,4 @@ def test_change_password_does_not_trigger_nostr_backup(monkeypatch):
|
||||
mock_instance = MockClient.return_value
|
||||
pm.nostr_client = mock_instance
|
||||
pm.change_password()
|
||||
mock_instance.publish_json_to_nostr.assert_not_called()
|
||||
mock_instance.publish_json_to_nostr.assert_called_once()
|
||||
|
@@ -10,7 +10,9 @@ import main
|
||||
def test_handle_post_success(capsys):
|
||||
pm = SimpleNamespace(
|
||||
get_encrypted_data=lambda: b"data",
|
||||
nostr_client=SimpleNamespace(publish_json_to_nostr=lambda data: True),
|
||||
nostr_client=SimpleNamespace(
|
||||
publish_json_to_nostr=lambda data, alt_summary=None: True
|
||||
),
|
||||
)
|
||||
main.handle_post_to_nostr(pm)
|
||||
out = capsys.readouterr().out
|
||||
@@ -20,7 +22,9 @@ def test_handle_post_success(capsys):
|
||||
def test_handle_post_failure(capsys):
|
||||
pm = SimpleNamespace(
|
||||
get_encrypted_data=lambda: b"data",
|
||||
nostr_client=SimpleNamespace(publish_json_to_nostr=lambda data: False),
|
||||
nostr_client=SimpleNamespace(
|
||||
publish_json_to_nostr=lambda data, alt_summary=None: False
|
||||
),
|
||||
)
|
||||
main.handle_post_to_nostr(pm)
|
||||
out = capsys.readouterr().out
|
||||
|
@@ -35,7 +35,7 @@ def setup_pm(tmp_path, monkeypatch):
|
||||
relays=list(DEFAULT_RELAYS),
|
||||
close_client_pool=lambda: None,
|
||||
initialize_client_pool=lambda: None,
|
||||
publish_json_to_nostr=lambda data: None,
|
||||
publish_json_to_nostr=lambda data, alt_summary=None: None,
|
||||
key_manager=SimpleNamespace(get_npub=lambda: "npub"),
|
||||
)
|
||||
|
||||
|
Reference in New Issue
Block a user