sharenet_passport_creator/sharenet-passport-cli/src/cli/interface.rs

163 lines
No EOL
5.7 KiB
Rust

use sharenet_passport::{
application::use_cases::*,
infrastructure::*,
ApplicationError,
FileStorage,
};
use rpassword::prompt_password;
use hex;
pub struct CliInterface;
impl CliInterface {
pub fn new() -> Self {
Self
}
pub fn handle_create(&self, output: &str) -> Result<(), ApplicationError> {
let password = prompt_password("Enter password for new passport: ").unwrap();
let confirm_password = prompt_password("Confirm password: ").unwrap();
if password != confirm_password {
return Err(ApplicationError::UseCaseError("Passwords do not match".to_string()));
}
let use_case = CreatePassportUseCase::new(
Bip39MnemonicGenerator,
Ed25519KeyDeriver,
XChaCha20FileEncryptor,
FileSystemStorage,
);
let (passport, recovery_phrase) = use_case.execute(&password, output)?;
println!("✅ Passport created successfully!");
println!("📄 Saved to: {}", output);
println!("🔑 Public Key: {}", hex::encode(&passport.public_key().0));
println!("🆔 DID: {}", passport.did().as_str());
println!("\n📝 IMPORTANT: Save your recovery phrase in a secure location!");
println!("Recovery phrase: {}", recovery_phrase.to_string());
Ok(())
}
pub fn handle_import_recovery(&self, output: &str) -> Result<(), ApplicationError> {
println!("Enter your 24-word recovery phrase:");
let mut recovery_words = Vec::new();
for i in 1..=24 {
let word = prompt_password(&format!("Word {}: ", i)).unwrap();
recovery_words.push(word);
}
let password = prompt_password("Enter new password for passport file: ").unwrap();
let confirm_password = prompt_password("Confirm password: ").unwrap();
if password != confirm_password {
return Err(ApplicationError::UseCaseError("Passwords do not match".to_string()));
}
let use_case = ImportFromRecoveryUseCase::new(
Bip39MnemonicGenerator,
Ed25519KeyDeriver,
XChaCha20FileEncryptor,
FileSystemStorage,
);
let passport = use_case.execute(&recovery_words, &password, output)?;
println!("✅ Passport imported successfully!");
println!("📄 Saved to: {}", output);
println!("🔑 Public Key: {}", hex::encode(&passport.public_key().0));
println!("🆔 DID: {}", passport.did().as_str());
Ok(())
}
pub fn handle_import_file(&self, input: &str, output: Option<&str>) -> Result<(), ApplicationError> {
let password = prompt_password("Enter password for passport file: ").unwrap();
let use_case = ImportFromFileUseCase::new(
XChaCha20FileEncryptor,
FileSystemStorage,
);
let passport = use_case.execute(input, &password, output)?;
println!("✅ Passport imported successfully!");
if let Some(output_path) = output {
println!("📄 Re-encrypted to: {}", output_path);
}
println!("🔑 Public Key: {}", hex::encode(&passport.public_key().0));
println!("🆔 DID: {}", passport.did().as_str());
Ok(())
}
pub fn handle_export(&self, input: &str, output: &str) -> Result<(), ApplicationError> {
let password = prompt_password("Enter password for passport file: ").unwrap();
let new_password = prompt_password("Enter new password for exported file: ").unwrap();
let confirm_password = prompt_password("Confirm new password: ").unwrap();
if new_password != confirm_password {
return Err(ApplicationError::UseCaseError("Passwords do not match".to_string()));
}
// First import to get the passport
let import_use_case = ImportFromFileUseCase::new(
XChaCha20FileEncryptor,
FileSystemStorage,
);
let passport = import_use_case.execute(input, &password, None)?;
// Then export with new password
let export_use_case = ExportPassportUseCase::new(
XChaCha20FileEncryptor,
FileSystemStorage,
);
export_use_case.execute(&passport, &new_password, output)?;
println!("✅ Passport exported successfully!");
println!("📄 Saved to: {}", output);
Ok(())
}
pub fn handle_info(&self, file: &str) -> Result<(), ApplicationError> {
let passport_file = FileSystemStorage.load(file)
.map_err(|e| ApplicationError::UseCaseError(format!("Failed to load file: {}", e)))?;
println!("📄 Passport File Information:");
println!(" File: {}", file);
println!(" Version: {}", passport_file.version);
println!(" Created: {}", passport_file.created_at);
println!(" DID: {}", passport_file.did);
println!(" Public Key: {}", hex::encode(&passport_file.public_key));
println!(" KDF: {}", passport_file.kdf);
println!(" Cipher: {}", passport_file.cipher);
Ok(())
}
pub fn handle_sign(&self, file: &str, message: &str) -> Result<(), ApplicationError> {
let password = prompt_password("Enter password for passport file: ").unwrap();
let import_use_case = ImportFromFileUseCase::new(
XChaCha20FileEncryptor,
FileSystemStorage,
);
let passport = import_use_case.execute(file, &password, None)?;
let sign_use_case = SignCardUseCase::new();
let signature = sign_use_case.execute(&passport, message)?;
println!("✅ Message signed successfully!");
println!("📝 Message: {}", message);
println!("🔏 Signature: {}", hex::encode(&signature));
Ok(())
}
}