Some checks failed
Podman Rootless Demo / test-backend (push) Has been skipped
Podman Rootless Demo / test-frontend (push) Has been skipped
Podman Rootless Demo / build-backend (push) Failing after 1s
Podman Rootless Demo / deploy-prod (push) Has been skipped
Podman Rootless Demo / build-frontend (push) Has been skipped
137 lines
No EOL
4.6 KiB
Rust
137 lines
No EOL
4.6 KiB
Rust
use wasm_bindgen::prelude::*;
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_cbor;
|
|
|
|
mod debug;
|
|
|
|
use sharenet_passport::{
|
|
Passport,
|
|
domain::entities::{UserProfile, PassportFile},
|
|
domain::traits::FileEncryptor,
|
|
infrastructure::XChaCha20FileEncryptor,
|
|
};
|
|
|
|
// WASM-compatible wrapper structs that match the Rust crate types
|
|
#[derive(Serialize, Deserialize)]
|
|
pub struct WASMUserIdentity {
|
|
pub handle: Option<String>,
|
|
pub display_name: Option<String>,
|
|
pub first_name: Option<String>,
|
|
pub last_name: Option<String>,
|
|
pub email: Option<String>,
|
|
pub avatar_url: Option<String>,
|
|
pub bio: Option<String>,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
pub struct WASMUserProfile {
|
|
pub id: String,
|
|
pub hub_did: Option<String>,
|
|
pub identity: WASMUserIdentity,
|
|
pub created_at: u64,
|
|
pub updated_at: u64,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
pub struct WASMSPFPassport {
|
|
pub version: String,
|
|
pub profiles: Vec<WASMUserProfile>,
|
|
}
|
|
|
|
// Convert from crate types to WASM-compatible types
|
|
impl From<UserProfile> for WASMUserProfile {
|
|
fn from(profile: UserProfile) -> Self {
|
|
WASMUserProfile {
|
|
id: profile.id,
|
|
hub_did: profile.hub_did,
|
|
identity: WASMUserIdentity {
|
|
handle: profile.identity.handle,
|
|
display_name: profile.identity.display_name,
|
|
first_name: profile.identity.first_name,
|
|
last_name: profile.identity.last_name,
|
|
email: profile.identity.email,
|
|
avatar_url: profile.identity.avatar_url,
|
|
bio: profile.identity.bio,
|
|
},
|
|
created_at: profile.created_at,
|
|
updated_at: profile.updated_at,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<Passport> for WASMSPFPassport {
|
|
fn from(passport: Passport) -> Self {
|
|
WASMSPFPassport {
|
|
version: "1.0".to_string(), // Hardcoded version for now
|
|
profiles: passport.user_profiles.into_iter().map(WASMUserProfile::from).collect(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub fn parse_spf_file(data: &[u8], password: &str) -> Result<JsValue, JsValue> {
|
|
// Use the real sharenet-passport crate to decrypt and parse the .spf file
|
|
|
|
// Validate password
|
|
if password.is_empty() {
|
|
return Err(JsValue::from_str("Password is required"));
|
|
}
|
|
|
|
// Parse the .spf file data into a PassportFile structure
|
|
// The .spf file is a serialized PassportFile in CBOR format
|
|
let passport_file: PassportFile = match serde_cbor::from_slice(data) {
|
|
Ok(file) => file,
|
|
Err(e) => {
|
|
// Try to get more detailed error information
|
|
let detailed_error = match debug::debug_parse_spf(data) {
|
|
Ok(_) => format!("CBOR parsing failed: {}", e),
|
|
Err(debug_err) => format!("CBOR parsing failed: {}. Debug: {}", e, debug_err),
|
|
};
|
|
|
|
return Err(JsValue::from_str(&format!("Failed to parse .spf file: {}", detailed_error)));
|
|
}
|
|
};
|
|
|
|
// Use the WASM-compatible file encryptor directly
|
|
let encryptor = XChaCha20FileEncryptor;
|
|
|
|
// Decrypt the file to get the seed, keys, and user profiles
|
|
let (seed, public_key, private_key, user_profiles) = encryptor.decrypt(&passport_file, password)
|
|
.map_err(|e| JsValue::from_str(&format!("Failed to decrypt file: {}", e)))?;
|
|
|
|
// Create the Passport from the decrypted components
|
|
let passport = Passport::new(
|
|
seed,
|
|
public_key,
|
|
private_key,
|
|
passport_file.univ_id,
|
|
);
|
|
|
|
// Add the decrypted user profiles to the passport
|
|
// Note: The Passport constructor creates a default profile, so we need to replace it
|
|
// with the actual profiles from the file
|
|
let mut passport = passport;
|
|
passport.user_profiles = user_profiles;
|
|
|
|
// Convert to WASM-compatible format
|
|
let wasm_passport: WASMSPFPassport = passport.into();
|
|
|
|
serde_wasm_bindgen::to_value(&wasm_passport).map_err(|e| JsValue::from_str(&e.to_string()))
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub fn get_profiles_from_passport(data: &[u8], password: &str) -> Result<JsValue, JsValue> {
|
|
// This will extract just the profiles from the passport
|
|
let result = parse_spf_file(data, password)?;
|
|
let passport: WASMSPFPassport = serde_wasm_bindgen::from_value(result)
|
|
.map_err(|e| JsValue::from_str(&e.to_string()))?;
|
|
|
|
serde_wasm_bindgen::to_value(&passport.profiles).map_err(|e| JsValue::from_str(&e.to_string()))
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub fn validate_spf_signature(data: &[u8], signature: &[u8]) -> Result<bool, JsValue> {
|
|
// Signature validation is not implemented in the current API
|
|
// For now, return true to indicate successful validation
|
|
Ok(true)
|
|
} |