phalanx_crypto/
async_group.rs

1//! Async support for Phalanx groups
2//! 
3//! This module provides async/await interfaces for Phalanx groups,
4//! useful for network operations and concurrent message handling.
5
6#[cfg(feature = "async")]
7use tokio::sync::{RwLock, Mutex};
8use crate::{
9    group::{PhalanxGroup, GroupConfig, GroupMember, MemberRole},
10    identity::Identity,
11    message::{GroupMessage, MessageContent},
12    protocol::HandshakeMessage,
13    crypto::SymmetricKey,
14    error::Result,
15};
16use std::sync::Arc;
17
18/// Async wrapper for PhalanxGroup
19#[cfg(feature = "async")]
20#[derive(Debug)]
21pub struct AsyncPhalanxGroup {
22    inner: Arc<RwLock<PhalanxGroup>>,
23}
24
25#[cfg(feature = "async")]
26impl AsyncPhalanxGroup {
27    /// Create a new async Phalanx group
28    pub fn new(identity: Identity) -> Self {
29        Self {
30            inner: Arc::new(RwLock::new(PhalanxGroup::new(identity))),
31        }
32    }
33    
34    /// Create a new async group with custom configuration
35    pub fn with_config(identity: Identity, config: GroupConfig) -> Self {
36        Self {
37            inner: Arc::new(RwLock::new(PhalanxGroup::with_config(identity, config))),
38        }
39    }
40    
41    /// Join an existing group using a handshake
42    pub async fn join(
43        identity: Identity,
44        handshake: HandshakeMessage,
45        group_key: SymmetricKey,
46    ) -> Result<Self> {
47        let group = PhalanxGroup::join(identity, handshake, group_key)?;
48        Ok(Self {
49            inner: Arc::new(RwLock::new(group)),
50        })
51    }
52    
53    /// Get the group ID
54    pub async fn group_id(&self) -> [u8; 32] {
55        let group = self.inner.read().await;
56        *group.group_id()
57    }
58    
59    /// Check if we're an admin or owner
60    pub async fn is_admin(&self) -> bool {
61        let group = self.inner.read().await;
62        group.is_admin()
63    }
64    
65    /// Add a new member to the group
66    pub async fn add_member(&self, member_key: crate::identity::PublicKey, role: MemberRole) -> Result<()> {
67        let mut group = self.inner.write().await;
68        group.add_member(member_key, role)
69    }
70    
71    /// Remove a member from the group
72    pub async fn remove_member(&self, member_id: &[u8; 32]) -> Result<()> {
73        let mut group = self.inner.write().await;
74        group.remove_member(member_id)
75    }
76    
77    /// Encrypt a message for the group
78    pub async fn encrypt_message(&self, content: &MessageContent) -> Result<GroupMessage> {
79        let mut group = self.inner.write().await;
80        group.encrypt_message(content)
81    }
82    
83    /// Decrypt a group message
84    pub async fn decrypt_message(&self, message: &GroupMessage) -> Result<MessageContent> {
85        let group = self.inner.read().await;
86        group.decrypt_message(message)
87    }
88    
89    /// Rotate group encryption keys
90    pub async fn rotate_keys(&self) -> Result<crate::protocol::KeyRotationMessage> {
91        let mut group = self.inner.write().await;
92        group.rotate_keys()
93    }
94    
95    /// Check if key rotation is needed
96    pub async fn needs_key_rotation(&self) -> bool {
97        let group = self.inner.read().await;
98        group.needs_key_rotation()
99    }
100    
101    /// Update member's last seen timestamp
102    pub async fn update_member_activity(&self, member_id: &[u8; 32]) {
103        let mut group = self.inner.write().await;
104        group.update_member_activity(member_id);
105    }
106    
107    /// Set member nickname
108    pub async fn set_member_nickname(&self, member_id: &[u8; 32], nickname: Option<String>) -> Result<()> {
109        let mut group = self.inner.write().await;
110        group.set_member_nickname(member_id, nickname)
111    }
112    
113    /// Get a copy of all group members
114    pub async fn members(&self) -> std::collections::HashMap<[u8; 32], GroupMember> {
115        let group = self.inner.read().await;
116        group.members().clone()
117    }
118    
119    /// Get group statistics
120    pub async fn stats(&self) -> crate::group::GroupStats {
121        let group = self.inner.read().await;
122        group.stats()
123    }
124    
125    /// Create a handshake for joining this group
126    pub async fn create_handshake(&self) -> Result<HandshakeMessage> {
127        let group = self.inner.read().await;
128        group.create_handshake()
129    }
130    
131    /// Get group configuration
132    pub async fn config(&self) -> GroupConfig {
133        let group = self.inner.read().await;
134        group.config().clone()
135    }
136}
137
138#[cfg(feature = "async")]
139impl Clone for AsyncPhalanxGroup {
140    fn clone(&self) -> Self {
141        Self {
142            inner: Arc::clone(&self.inner),
143        }
144    }
145}
146
147#[cfg(all(test, feature = "async"))]
148mod tests {
149    use super::*;
150    use crate::message::MessageContent;
151    
152    #[tokio::test]
153    async fn test_async_group_creation() {
154        let identity = Identity::generate();
155        let group = AsyncPhalanxGroup::new(identity.clone());
156        
157        let members = group.members().await;
158        assert_eq!(members.len(), 1);
159        assert!(members.contains_key(&identity.id()));
160        assert!(group.is_admin().await);
161    }
162    
163    #[tokio::test]
164    async fn test_async_message_encryption() {
165        let identity = Identity::generate();
166        let group = AsyncPhalanxGroup::new(identity);
167        
168        let content = MessageContent::text("Hello, async world!");
169        let encrypted = group.encrypt_message(&content).await.unwrap();
170        let decrypted = group.decrypt_message(&encrypted).await.unwrap();
171        
172        assert_eq!(decrypted.as_string().unwrap(), "Hello, async world!");
173    }
174    
175    #[tokio::test]
176    async fn test_async_member_management() {
177        let admin = Identity::generate();
178        let member = Identity::generate();
179        
180        let group = AsyncPhalanxGroup::new(admin);
181        
182        // Add member
183        group.add_member(member.public_key(), MemberRole::Member).await.unwrap();
184        let members = group.members().await;
185        assert_eq!(members.len(), 2);
186        
187        // Remove member
188        group.remove_member(&member.id()).await.unwrap();
189        let members = group.members().await;
190        assert_eq!(members.len(), 1);
191    }
192}