feat: bitcoin-ui CSS fix, HTTPS proxy support, deploy script improvements
Bitcoin UI: - Replace cdn.tailwindcss.com with locally bundled tailwind.css (CSP blocks external scripts) - Make all asset paths relative for nginx proxy compatibility - Add bitcoin-ui build/deploy to deploy-to-target.sh (was missing entirely) - Use --network host (bitcoin-ui proxies Bitcoin RPC at 127.0.0.1:8332) HTTPS mixed content fix: - Add HTTPS_PROXY_PATHS in AppSession.vue — when parent page is HTTPS, iframe loads through nginx proxy instead of direct HTTP port - Prevents browser blocking HTTP iframes inside HTTPS pages - All Tailscale servers use HTTPS, this was breaking all app iframes Deploy & first-boot improvements: - first-boot-containers.sh auto-detects disk size for pruning vs txindex - first-boot-containers.sh checks fallback source path for UI containers - Added mempool-electrs to APP_PORTS mapping - ElectrumX container creation in first-boot - Podman doctor/fix/uptime skills added Also includes: session persistence, identity management, LND transactions, ElectrumX status UI, nostr-provider improvements, Web5 enhancements Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
07e46dce56
commit
30164fd12a
@@ -1,7 +1,7 @@
|
||||
//! RPC handlers for multi-identity management.
|
||||
|
||||
use super::RpcHandler;
|
||||
use crate::identity_manager::{IdentityManager, IdentityPurpose};
|
||||
use crate::identity_manager::{IdentityManager, IdentityProfile, IdentityPurpose};
|
||||
use crate::network::did_dht;
|
||||
use anyhow::{Context, Result};
|
||||
use nostr_sdk::ToBech32;
|
||||
@@ -43,6 +43,7 @@ impl RpcHandler {
|
||||
"is_default": is_default,
|
||||
"nostr_pubkey": id.nostr_pubkey,
|
||||
"nostr_npub": id.nostr_npub,
|
||||
"profile": id.profile,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
@@ -650,6 +651,94 @@ impl RpcHandler {
|
||||
}))
|
||||
}
|
||||
|
||||
/// Update profile metadata for an identity.
|
||||
pub(super) async fn handle_identity_update_profile(
|
||||
&self,
|
||||
params: Option<serde_json::Value>,
|
||||
) -> Result<serde_json::Value> {
|
||||
let params = params.unwrap_or_default();
|
||||
let id = params.get("id").and_then(|v| v.as_str())
|
||||
.ok_or_else(|| anyhow::anyhow!("Missing required parameter: id"))?;
|
||||
validate_identity_id(id)?;
|
||||
|
||||
let profile = IdentityProfile {
|
||||
display_name: params.get("display_name").and_then(|v| v.as_str()).map(String::from),
|
||||
about: params.get("about").and_then(|v| v.as_str()).map(String::from),
|
||||
picture: params.get("picture").and_then(|v| v.as_str()).map(String::from),
|
||||
banner: params.get("banner").and_then(|v| v.as_str()).map(String::from),
|
||||
website: params.get("website").and_then(|v| v.as_str()).map(String::from),
|
||||
nip05: params.get("nip05").and_then(|v| v.as_str()).map(String::from),
|
||||
lud16: params.get("lud16").and_then(|v| v.as_str()).map(String::from),
|
||||
};
|
||||
|
||||
let manager = IdentityManager::new(&self.config.data_dir).await?;
|
||||
manager.update_profile(id, profile).await?;
|
||||
|
||||
Ok(serde_json::json!({ "ok": true }))
|
||||
}
|
||||
|
||||
/// Publish kind 0 (metadata) profile to the local Nostr relay.
|
||||
pub(super) async fn handle_identity_publish_profile(
|
||||
&self,
|
||||
params: Option<serde_json::Value>,
|
||||
) -> Result<serde_json::Value> {
|
||||
let params = params.unwrap_or_default();
|
||||
let id = params.get("id").and_then(|v| v.as_str())
|
||||
.ok_or_else(|| anyhow::anyhow!("Missing required parameter: id"))?;
|
||||
validate_identity_id(id)?;
|
||||
|
||||
let relay_url = params.get("relay")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("ws://localhost:18081");
|
||||
|
||||
let manager = IdentityManager::new(&self.config.data_dir).await?;
|
||||
let event_id = manager.publish_profile(id, relay_url).await?;
|
||||
|
||||
Ok(serde_json::json!({
|
||||
"event_id": event_id,
|
||||
"relay": relay_url,
|
||||
"published": true,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Export private keys for an identity — REQUIRES password verification.
|
||||
pub(super) async fn handle_identity_export_keys(
|
||||
&self,
|
||||
params: Option<serde_json::Value>,
|
||||
) -> Result<serde_json::Value> {
|
||||
let params = params.unwrap_or_default();
|
||||
let id = params
|
||||
.get("id")
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or_else(|| anyhow::anyhow!("Missing required parameter: id"))?;
|
||||
let password = params
|
||||
.get("password")
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or_else(|| anyhow::anyhow!("Missing required parameter: password"))?;
|
||||
validate_identity_id(id)?;
|
||||
|
||||
// Verify password against auth system
|
||||
if !self.auth_manager.verify_password(password).await? {
|
||||
anyhow::bail!("Invalid password");
|
||||
}
|
||||
|
||||
let manager = IdentityManager::new(&self.config.data_dir).await?;
|
||||
let keys = manager.export_keys(id).await?;
|
||||
let record = manager.get(id).await?;
|
||||
|
||||
Ok(serde_json::json!({
|
||||
"id": record.id,
|
||||
"name": record.name,
|
||||
"pubkey": record.pubkey_hex,
|
||||
"did": record.did,
|
||||
"nostr_pubkey": record.nostr_pubkey,
|
||||
"nostr_npub": record.nostr_npub,
|
||||
"ed25519_secret_hex": keys["ed25519_secret_hex"],
|
||||
"nostr_secret_hex": keys["nostr_secret_hex"],
|
||||
"nostr_nsec": keys["nostr_nsec"],
|
||||
}))
|
||||
}
|
||||
|
||||
/// identity.dht-status — Check if an identity's did:dht is published and resolvable.
|
||||
pub(super) async fn handle_identity_dht_status(
|
||||
&self,
|
||||
|
||||
Reference in New Issue
Block a user