pub use offline_protocol_mls::{
EncryptedMessage, GroupId, GroupInfo, GroupMetadata, KeyPackageBundle, MlsError, MlsManager,
MlsMessageType, MlsStorage, Result as MlsResult, StorageError, WelcomeMessage,
};
pub use offline_protocol_mls::storage::InMemoryStorage;
use crate::{Error, Result};
use std::sync::Arc;
pub mod metadata_keys {
pub const ENCRYPTED: &str = "mls_encrypted";
pub const GROUP_ID: &str = "mls_group_id";
pub const EPOCH: &str = "mls_epoch";
pub const MESSAGE_TYPE: &str = "mls_message_type";
}
pub trait MlsProtocolExt {
fn encrypt_message(
&self,
mls_manager: &MlsManager,
recipient: &str,
plaintext: &[u8],
) -> Result<String>;
fn decrypt_message(
&self,
mls_manager: &MlsManager,
encrypted_content: &str,
) -> Result<Option<Vec<u8>>>;
}
pub fn encode_for_transport(encrypted: &EncryptedMessage) -> Result<String> {
encrypted
.to_base64()
.map_err(|e| Error::Other(format!("Failed to encode encrypted message: {}", e)))
}
pub fn decode_from_transport(encoded: &str) -> Result<EncryptedMessage> {
EncryptedMessage::from_base64(encoded)
.map_err(|e| Error::Other(format!("Failed to decode encrypted message: {}", e)))
}
pub fn create_manager(
user_id: impl Into<String>,
storage: Arc<dyn MlsStorage>,
) -> Result<MlsManager> {
MlsManager::new(user_id, storage)
.map_err(|e| Error::Other(format!("Failed to create MLS manager: {}", e)))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_manager() {
let storage = Arc::new(InMemoryStorage::new());
let manager = create_manager("test_user", storage).unwrap();
assert_eq!(manager.user_id(), "test_user");
}
#[test]
fn test_encode_decode_roundtrip() {
let encrypted = EncryptedMessage {
group_id: GroupId::new("test-group").unwrap(),
message_type: MlsMessageType::Application,
epoch: 1,
ciphertext: vec![1, 2, 3, 4],
sender_id: "alice".to_string(),
timestamp_ms: 1234567890,
};
let encoded = encode_for_transport(&encrypted).unwrap();
let decoded = decode_from_transport(&encoded).unwrap();
assert_eq!(encrypted.group_id, decoded.group_id);
assert_eq!(encrypted.epoch, decoded.epoch);
assert_eq!(encrypted.ciphertext, decoded.ciphertext);
}
}