phalanx_crypto/
async_group.rs1#[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#[cfg(feature = "async")]
20#[derive(Debug)]
21pub struct AsyncPhalanxGroup {
22 inner: Arc<RwLock<PhalanxGroup>>,
23}
24
25#[cfg(feature = "async")]
26impl AsyncPhalanxGroup {
27 pub fn new(identity: Identity) -> Self {
29 Self {
30 inner: Arc::new(RwLock::new(PhalanxGroup::new(identity))),
31 }
32 }
33
34 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 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 pub async fn group_id(&self) -> [u8; 32] {
55 let group = self.inner.read().await;
56 *group.group_id()
57 }
58
59 pub async fn is_admin(&self) -> bool {
61 let group = self.inner.read().await;
62 group.is_admin()
63 }
64
65 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 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 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 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 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 pub async fn needs_key_rotation(&self) -> bool {
97 let group = self.inner.read().await;
98 group.needs_key_rotation()
99 }
100
101 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 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 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 pub async fn stats(&self) -> crate::group::GroupStats {
121 let group = self.inner.read().await;
122 group.stats()
123 }
124
125 pub async fn create_handshake(&self) -> Result<HandshakeMessage> {
127 let group = self.inner.read().await;
128 group.create_handshake()
129 }
130
131 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 group.add_member(member.public_key(), MemberRole::Member).await.unwrap();
184 let members = group.members().await;
185 assert_eq!(members.len(), 2);
186
187 group.remove_member(&member.id()).await.unwrap();
189 let members = group.members().await;
190 assert_eq!(members.len(), 1);
191 }
192}