mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
Switching to a saved nsec profile silently failed: switchProfile -> requestLogin -> the
nsec provider was called with no passphrase, so it threw "secret-required" and the switch
was caught+logged with no user feedback. It never prompted for the PIN.
Now handleProfileSwitchRequest detects an nsec target and, before switching, prepares the
stored-key unlock:
- evaluateStoredNsecSwitch(meta, target) (pure) gates on a persisted nsec key for THIS
account (via getStoredSessionActorMetadata); errors clearly otherwise ("log in with its
nsec", "different account's key saved").
- showPasswordPrompt (js/ui/promptDialog.js) collects the PIN/passphrase in a styled
dialog (Promise<string|null>, stacks above modals).
- switchProfile(pubkey, { unlockStored: true, passphrase }) — authService.switchProfile
now forwards unlockStored/passphrase to requestLogin, which routes to the nsec
provider's unlockStoredSessionActor to restore the signer and activate the account.
- Wrong PIN -> "Incorrect PIN/passphrase" toast (decrypt-failed).
So NIP-07 -> nsec switching works fluently. NIP-46 switching is unchanged (follow-up to
verify/extend); multiple-nsec accounts still share one stored slot (follow-up).
Tests: tests/stored-nsec-switch.test.mjs (6), tests/password-prompt.test.mjs (6). Build +
lint clean; auth suites 25/25.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
25 lines
1.0 KiB
JavaScript
25 lines
1.0 KiB
JavaScript
// Decide whether switching to a saved nsec account can proceed via the stored key.
|
|
// Pure so the branching is unit-testable; the coordinator handles the prompt + I/O.
|
|
//
|
|
// { action: "prompt" } → stored nsec key matches; ask for the PIN
|
|
// { action: "error", reason: "no-stored-key" } → no persisted nsec key on this device
|
|
// { action: "error", reason: "pubkey-mismatch" } → the saved key is a different account
|
|
|
|
function normalizeHex(value) {
|
|
return typeof value === "string" && /^[0-9a-f]{64}$/i.test(value.trim())
|
|
? value.trim().toLowerCase()
|
|
: "";
|
|
}
|
|
|
|
export function evaluateStoredNsecSwitch(meta, targetPubkey) {
|
|
if (!meta || meta.hasEncryptedKey !== true || meta.source !== "nsec") {
|
|
return { action: "error", reason: "no-stored-key" };
|
|
}
|
|
const stored = normalizeHex(meta.pubkey);
|
|
const target = normalizeHex(targetPubkey);
|
|
if (stored && target && stored !== target) {
|
|
return { action: "error", reason: "pubkey-mismatch" };
|
|
}
|
|
return { action: "prompt" };
|
|
}
|