qualia_client_core/api/
connect.rs1#![allow(non_snake_case)]
4
5use super::*;
6
7#[cfg(not(target_arch = "wasm32"))]
8fn resolve_front_door_did(front_door_did: &str) -> Result<String, String> {
9 if !front_door_did.is_empty() {
10 return Ok(front_door_did.to_string());
11 }
12 crate::domains::list_domains()
13 .first()
14 .map(|d| d.front_door_did.clone())
15 .ok_or_else(|| "no domain yet — create one in Domains & Mail first".to_string())
16}
17
18#[cfg(not(target_arch = "wasm32"))]
19fn build_signed_identifier(
20 front_door_did: String,
21 relation_type: String,
22 domain: &str,
23) -> Result<crate::connection_identifier::ConnectionIdentifier, String> {
24 let id = crate::node_identity::NodeIdentity::load_or_create()?;
25 let fdd = resolve_front_door_did(&front_door_did)?;
26 let rendezvous = if domain.is_empty() {
27 vec![]
28 } else {
29 vec![crate::connection_identifier::RendezvousHint {
30 kind: "domain".into(),
31 value: domain.to_string(),
32 }]
33 };
34 let now = mail_now_unix();
35 let mut ci = crate::connection_identifier::ConnectionIdentifier {
36 version: crate::connection_identifier::CI_VERSION,
37 front_door_did: fdd,
38 identity_pubkey_hex: String::new(),
39 wireguard_pubkey_hex: id.wireguard_pubkey_hex(),
40 overlay_addr: id.overlay_addr(),
41 rendezvous,
42 relation_type,
43 display_name: crate::user_profile::load_profile().display_name,
44 created_at: now,
45 expires_at: now + 7 * 24 * 3600,
46 nonce: uuid::Uuid::new_v4().to_string(),
47 signature_hex: String::new(),
48 };
49 ci.sign(&id.signing_key());
50 Ok(ci)
51}
52
53#[cfg(not(target_arch = "wasm32"))]
55pub fn generate_connection_identifier(
56 front_door_did: String,
57 relation_type: String,
58) -> Result<serde_json::Value, String> {
59 let ci = build_signed_identifier(front_door_did, relation_type, "")?;
60 serde_json::to_value(ci).map_err(|e| e.to_string())
61}
62
63#[cfg(not(target_arch = "wasm32"))]
65pub fn generate_magic_link(
66 front_door_did: String,
67 relation_type: String,
68 domain: String,
69) -> Result<serde_json::Value, String> {
70 let ci = build_signed_identifier(front_door_did, relation_type, &domain)?;
71 let deep = crate::magic_link::to_deep_link(&ci)?;
72 let https = if domain.is_empty() {
73 String::new()
74 } else {
75 crate::magic_link::to_https_link(&ci, &domain)?
76 };
77 let mailto = crate::magic_link::to_mailto(&ci, "Connect with me on Webizen")?;
78 Ok(serde_json::json!({ "deep_link": deep, "https_link": https, "mailto": mailto }))
79}
80
81#[cfg(not(target_arch = "wasm32"))]
85pub fn accept_connection(link: String) -> Result<serde_json::Value, String> {
86 let ci = crate::magic_link::from_link(&link)?;
87 ci.verify()?;
88 if ci.is_expired(mail_now_unix()) {
89 return Err("this connection link has expired".into());
90 }
91 let peer = crate::social_peers::SocialPeer {
92 did: ci.front_door_did.clone(),
93 display_name: ci.display_name.clone(),
94 wireguard_pubkey_hex: ci.wireguard_pubkey_hex.clone(),
95 overlay_addr: ci.overlay_addr.clone(),
96 endpoint: ci
97 .rendezvous
98 .iter()
99 .find(|r| r.kind == "domain" || r.kind == "edge")
100 .map(|r| r.value.clone()),
101 relation_type: ci.relation_type.clone(),
102 added_at: mail_now_unix(),
103 active: true,
104 envelope_pubkey_hex: None,
106 };
107 crate::social_peers::register_peer(peer.clone())?;
108 serde_json::to_value(peer).map_err(|e| e.to_string())
109}
110
111pub fn list_social_peers() -> Result<serde_json::Value, String> {
113 serde_json::to_value(crate::social_peers::list_peers()).map_err(|e| e.to_string())
114}
115
116pub fn set_social_peer_active(did: String, active: bool) -> Result<serde_json::Value, String> {
118 crate::social_peers::set_peer_active(&did, active)?;
119 list_social_peers()
120}
121
122pub fn set_social_peer_endpoint(
124 did: String,
125 endpoint: Option<String>,
126) -> Result<serde_json::Value, String> {
127 crate::social_peers::set_peer_endpoint(&did, endpoint.as_deref())?;
128 list_social_peers()
129}
130
131pub fn mesh_dialability() -> Result<serde_json::Value, String> {
134 let peers = crate::social_peers::list_peers();
135 serde_json::to_value(crate::social_mesh::dialability(&peers)).map_err(|e| e.to_string())
136}