fix(profiles): label-only rename for secretless remote-signer profiles
This commit is contained in:
parent
ca62111092
commit
6ebc364fcf
2 changed files with 66 additions and 3 deletions
|
|
@ -576,9 +576,11 @@ function RenameModal({
|
||||||
npub: target.npub,
|
npub: target.npub,
|
||||||
perform: () => renameProfile(target.npub, trimmed),
|
perform: () => renameProfile(target.npub, trimmed),
|
||||||
successMessage: (report) =>
|
successMessage: (report) =>
|
||||||
report.failed.length === 0
|
report.succeeded.length === 0 && report.failed.length === 0
|
||||||
? `Renamed to "${trimmed}" and published to ${report.succeeded.length} relay(s). It may take a minute to appear on other clients.`
|
? `Renamed to "${trimmed}" (saved on this device; external-signer profiles publish their name from the signer app).`
|
||||||
: `Renamed to "${trimmed}", but ${report.failed.length} relay(s) did not accept it. Use "Publish name" to retry.`,
|
: report.failed.length === 0
|
||||||
|
? `Renamed to "${trimmed}" and published to ${report.succeeded.length} relay(s). It may take a minute to appear on other clients.`
|
||||||
|
: `Renamed to "${trimmed}", but ${report.failed.length} relay(s) did not accept it. Use "Publish name" to retry.`,
|
||||||
onSaved,
|
onSaved,
|
||||||
onError,
|
onError,
|
||||||
onSavingChange,
|
onSavingChange,
|
||||||
|
|
|
||||||
|
|
@ -298,6 +298,39 @@ pub fn rename_profile(
|
||||||
return Err(AppError::config("The profile name cannot be empty."));
|
return Err(AppError::config("The profile name cannot be empty."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remote (secretless) profiles have no local key to sign a kind-0
|
||||||
|
// metadata event with — and the kind-0 reroute through the external
|
||||||
|
// signer is still pending (P2). The label is still useful as the local
|
||||||
|
// display name, so rename it vault-side and report zero relays rather
|
||||||
|
// than failing the whole rename outright.
|
||||||
|
let is_remote = vault
|
||||||
|
.profiles
|
||||||
|
.iter()
|
||||||
|
.find(|p| p.public_key == npub)
|
||||||
|
.is_some_and(|p| {
|
||||||
|
p.signer_mode == SignerMode::Nip46Client || p.secret_key.trim().is_empty()
|
||||||
|
});
|
||||||
|
if is_remote {
|
||||||
|
let is_active = vault.active_profile.as_deref() == Some(npub);
|
||||||
|
let stored = find_profile_mut(vault, npub)?;
|
||||||
|
stored.label = trimmed.to_string();
|
||||||
|
let summary = ProfileSummary {
|
||||||
|
label: stored.label.clone(),
|
||||||
|
npub: stored.public_key.clone(),
|
||||||
|
created_at: stored.created_at,
|
||||||
|
is_active,
|
||||||
|
picture: stored.picture.clone(),
|
||||||
|
nip05: stored.nip05.clone(),
|
||||||
|
};
|
||||||
|
return Ok((
|
||||||
|
summary,
|
||||||
|
MetadataPublishReport {
|
||||||
|
succeeded: Vec::new(),
|
||||||
|
failed: Vec::new(),
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve and sign before mutating so a locked vault or bad key changes
|
// Resolve and sign before mutating so a locked vault or bad key changes
|
||||||
// nothing on disk.
|
// nothing on disk.
|
||||||
let secret_hex = resolve_secret_key(vault, npub, key)?;
|
let secret_hex = resolve_secret_key(vault, npub, key)?;
|
||||||
|
|
@ -1230,6 +1263,34 @@ mod tests {
|
||||||
assert_eq!(err.kind(), crate::errors::ErrorKind::ProfileNotFound);
|
assert_eq!(err.kind(), crate::errors::ErrorKind::ProfileNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rename_profile_updates_label_for_secretless_remote_profiles() {
|
||||||
|
// Paired (NIP-46) profiles carry no local key, so no kind-0 can be
|
||||||
|
// signed — but the local display label must still be renameable.
|
||||||
|
use nostr::nips::nip19::ToBech32;
|
||||||
|
let mut vault = Vault::empty();
|
||||||
|
let remote = Keys::generate();
|
||||||
|
let npub = remote.public_key().to_bech32().unwrap();
|
||||||
|
store_remote_profile(&mut vault, &npub, "Remote Signer".to_string()).unwrap();
|
||||||
|
|
||||||
|
let (renamed, report) = rename_profile(
|
||||||
|
&mut vault,
|
||||||
|
&npub,
|
||||||
|
"Phone Key".to_string(),
|
||||||
|
None,
|
||||||
|
&offline_settings(),
|
||||||
|
)
|
||||||
|
.expect("remote rename must succeed locally");
|
||||||
|
assert_eq!(renamed.label, "Phone Key");
|
||||||
|
assert_eq!(vault.profiles[0].label, "Phone Key");
|
||||||
|
assert!(
|
||||||
|
vault.profiles[0].secret_key.is_empty(),
|
||||||
|
"rename must not fabricate a secret"
|
||||||
|
);
|
||||||
|
assert!(report.succeeded.is_empty());
|
||||||
|
assert!(report.failed.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_nip05_stores_identifier_and_skips_publish_without_relays() {
|
fn set_nip05_stores_identifier_and_skips_publish_without_relays() {
|
||||||
let mut vault = Vault::empty();
|
let mut vault = Vault::empty();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue