Add secure nsec key generation and encryption for web UI (v0.36.7)
Some checks failed
Go / build-and-release (push) Has been cancelled
Some checks failed
Go / build-and-release (push) Has been cancelled
- Add nsec-crypto.js library with Argon2id+AES-GCM encryption - Generate new nsec keys using secure system entropy - Encrypt nsec with password (~3 sec Argon2id derivation in Web Worker) - Add unlock flow for returning users with encrypted keys - Add deriving modal with live timer during key derivation - Auto-create default profile for new users with ORLY logo avatar - Fix NIP-42 auth race condition in websocket-auth.js - Improve header user profile display (avatar fills height, no truncation) - Add instant light/dark theme colors in HTML head - Add background box around username/nip05 in settings drawer - Update CLAUDE.md with nsec-crypto library documentation Files modified: - app/web/src/nsec-crypto.js: New encryption library - app/web/src/LoginModal.svelte: Key gen, encryption, unlock UI - app/web/src/nostr.js: Default profile creation - app/web/src/App.svelte: Header and drawer styling - app/web/public/index.html: Instant theme colors - CLAUDE.md: Library documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -495,14 +495,73 @@ export async function fetchUserProfile(pubkey) {
|
||||
|
||||
return profile;
|
||||
} else {
|
||||
throw new Error("No profile found");
|
||||
// No profile found - create a default profile for new users
|
||||
console.log("No profile found for pubkey, creating default:", pubkey);
|
||||
return await createDefaultProfile(pubkey);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch profile:", error);
|
||||
throw error;
|
||||
// Try to create default profile on error too
|
||||
try {
|
||||
return await createDefaultProfile(pubkey);
|
||||
} catch (e) {
|
||||
console.error("Failed to create default profile:", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default profile for new users
|
||||
* @param {string} pubkey - The user's public key (hex)
|
||||
* @returns {Promise<Object>} - The created profile
|
||||
*/
|
||||
async function createDefaultProfile(pubkey) {
|
||||
// Generate name from first 6 chars of pubkey
|
||||
const shortId = pubkey.slice(0, 6);
|
||||
const defaultName = `testuser${shortId}`;
|
||||
|
||||
// Get the current origin for the logo URL
|
||||
const logoUrl = `${window.location.origin}/orly.png`;
|
||||
|
||||
const profileContent = {
|
||||
name: defaultName,
|
||||
display_name: defaultName,
|
||||
picture: logoUrl,
|
||||
about: "New ORLY user"
|
||||
};
|
||||
|
||||
const profile = {
|
||||
name: defaultName,
|
||||
displayName: defaultName,
|
||||
picture: logoUrl,
|
||||
about: "New ORLY user",
|
||||
pubkey: pubkey
|
||||
};
|
||||
|
||||
// Try to publish the profile if we have a signer
|
||||
if (nostrClient.signer) {
|
||||
try {
|
||||
const event = {
|
||||
kind: 0,
|
||||
content: JSON.stringify(profileContent),
|
||||
tags: [],
|
||||
created_at: Math.floor(Date.now() / 1000)
|
||||
};
|
||||
|
||||
// Sign and publish using the websocket-auth client
|
||||
const signedEvent = await nostrClient.signer.signEvent(event);
|
||||
await nostrClient.publish(signedEvent);
|
||||
console.log("Default profile published:", signedEvent.id);
|
||||
} catch (e) {
|
||||
console.warn("Failed to publish default profile:", e);
|
||||
// Still return the profile even if publishing fails
|
||||
}
|
||||
}
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
// Fetch events
|
||||
export async function fetchEvents(filters, options = {}) {
|
||||
console.log(`Starting event fetch with filters:`, JSON.stringify(filters, null, 2));
|
||||
|
||||
Reference in New Issue
Block a user