feat: Implement comprehensive Nostr identity and social features
## Core Identity Management - Add secure key generation and import functionality - Implement AES-GCM encryption with PBKDF2 key derivation - Create password-protected identity storage - Add browser-compatible crypto utilities (no Buffer dependency) ## User Interface - Build identity management dialog with tabs for setup and profile - Add navbar integration with user dropdown and mobile support - Create password unlock dialog for encrypted identities - Integrate vue-sonner for toast notifications ## Nostr Protocol Integration - Implement event creation (notes, reactions, profiles, contacts) - Add reply thread detection and engagement metrics - Create social interaction composables for publishing - Support multi-relay publishing with failure handling - Add profile fetching and caching system ## Security Features - Web Crypto API with 100k PBKDF2 iterations - Secure random salt and IV generation - Automatic password prompts for encrypted storage - Legacy support for unencrypted identities ## Technical Improvements - Replace all Buffer usage with browser-native APIs - Add comprehensive error handling and validation - Implement reactive state management with Vue composables - Create reusable crypto utility functions 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
d3e8b23c86
commit
ee7eb461c4
12 changed files with 1777 additions and 21 deletions
47
src/App.vue
47
src/App.vue
|
|
@ -1,14 +1,47 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import Navbar from '@/components/layout/Navbar.vue'
|
||||
import Footer from '@/components/layout/Footer.vue'
|
||||
import ConnectionStatus from '@/components/nostr/ConnectionStatus.vue'
|
||||
import PasswordDialog from '@/components/nostr/PasswordDialog.vue'
|
||||
import { Toaster } from 'vue-sonner'
|
||||
import { useNostr } from '@/composables/useNostr'
|
||||
import { identity } from '@/composables/useIdentity'
|
||||
import { toast } from 'vue-sonner'
|
||||
|
||||
const relays = JSON.parse(import.meta.env.VITE_NOSTR_RELAYS as string)
|
||||
const { isConnected, isConnecting, error, connect, disconnect } = useNostr({ relays })
|
||||
|
||||
const showPasswordDialog = ref(false)
|
||||
|
||||
async function handlePasswordUnlock(password: string) {
|
||||
try {
|
||||
await identity.loadWithPassword(password)
|
||||
showPasswordDialog.value = false
|
||||
toast.success('Identity unlocked successfully')
|
||||
} catch (error) {
|
||||
toast.error('Failed to unlock identity. Please check your password.')
|
||||
}
|
||||
}
|
||||
|
||||
function handlePasswordCancel() {
|
||||
showPasswordDialog.value = false
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// Check if we have an encrypted identity that needs password
|
||||
if (identity.hasStoredIdentity() && identity.isStoredIdentityEncrypted()) {
|
||||
showPasswordDialog.value = true
|
||||
} else {
|
||||
// Initialize identity system for non-encrypted identities
|
||||
try {
|
||||
await identity.initialize()
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize identity:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to Nostr relays
|
||||
await connect()
|
||||
})
|
||||
|
||||
|
|
@ -39,5 +72,17 @@ onUnmounted(() => {
|
|||
|
||||
<Footer />
|
||||
</div>
|
||||
|
||||
<!-- Toast notifications -->
|
||||
<Toaster />
|
||||
|
||||
<!-- Password unlock dialog -->
|
||||
<PasswordDialog
|
||||
v-model:is-open="showPasswordDialog"
|
||||
title="Unlock Identity"
|
||||
description="Your Nostr identity is encrypted. Enter your password to unlock it."
|
||||
@password="handlePasswordUnlock"
|
||||
@cancel="handlePasswordCancel"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue