1pub mod events;
170pub mod states;
171
172pub use events::*;
173
174pub use states::{GroupMember, GroupMembership, GroupState, GroupStateError, GroupStateResult};
176
177#[cfg(test)]
178mod tests {
179 use super::events::permissions::{GroupAction, GroupPermissions, Permission};
180 use super::events::roles::GroupRole;
181 use super::events::settings::{EncryptionSettings, GroupSettings};
182 use super::events::{GroupActivityEvent, GroupInfo, GroupJoinInfo, GroupKeyInfo};
183 use crate::{Metadata, RelayEndpoint};
184 use std::net::{IpAddr, Ipv4Addr, SocketAddr};
185 use zoe_wire_protocol::{Ed25519VerifyingKey, KeyPair, VerifyingKey};
186
187 fn create_test_verifying_key() -> VerifyingKey {
188 use rand::rngs::OsRng;
189 use zoe_wire_protocol::KeyPair;
190 let keypair = KeyPair::generate(&mut OsRng);
191 keypair.public_key()
192 }
193
194 fn create_test_ed25519_verifying_key() -> Ed25519VerifyingKey {
195 use rand::rngs::OsRng;
196 let signing_key = KeyPair::generate_ed25519(&mut OsRng);
197 match signing_key.public_key() {
198 VerifyingKey::Ed25519(key) => *key,
199 _ => panic!("Expected Ed25519 key from KeyPair::generate_ed25519"),
200 }
201 }
202
203 fn create_test_socket_addr() -> SocketAddr {
204 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080)
205 }
206
207 fn create_test_key_derivation_info() -> zoe_wire_protocol::crypto::KeyDerivationInfo {
208 zoe_wire_protocol::crypto::KeyDerivationInfo {
209 method: zoe_wire_protocol::crypto::KeyDerivationMethod::Bip39Argon2,
210 salt: vec![1, 2, 3, 4, 5, 6, 7, 8],
211 argon2_params: zoe_wire_protocol::crypto::Argon2Params::default(),
212 context: "dga-group-key".to_string(),
213 }
214 }
215
216 fn create_test_group_key_info(key_id: Vec<u8>) -> GroupKeyInfo {
217 GroupKeyInfo::new_chacha20_poly1305(key_id, create_test_key_derivation_info())
218 }
219
220 #[test]
221 fn test_group_role_has_permission() {
222 assert!(GroupRole::Owner.has_permission(&Permission::OwnerOnly));
224 assert!(GroupRole::Owner.has_permission(&Permission::AdminOrAbove));
225 assert!(GroupRole::Owner.has_permission(&Permission::ModeratorOrAbove));
226 assert!(GroupRole::Owner.has_permission(&Permission::AllMembers));
227
228 assert!(!GroupRole::Admin.has_permission(&Permission::OwnerOnly));
230 assert!(GroupRole::Admin.has_permission(&Permission::AdminOrAbove));
231 assert!(GroupRole::Admin.has_permission(&Permission::ModeratorOrAbove));
232 assert!(GroupRole::Admin.has_permission(&Permission::AllMembers));
233
234 assert!(!GroupRole::Moderator.has_permission(&Permission::OwnerOnly));
236 assert!(!GroupRole::Moderator.has_permission(&Permission::AdminOrAbove));
237 assert!(GroupRole::Moderator.has_permission(&Permission::ModeratorOrAbove));
238 assert!(GroupRole::Moderator.has_permission(&Permission::AllMembers));
239
240 assert!(!GroupRole::Member.has_permission(&Permission::OwnerOnly));
242 assert!(!GroupRole::Member.has_permission(&Permission::AdminOrAbove));
243 assert!(!GroupRole::Member.has_permission(&Permission::ModeratorOrAbove));
244 assert!(GroupRole::Member.has_permission(&Permission::AllMembers));
245 }
246
247 #[test]
248 fn test_group_role_display_name() {
249 assert_eq!(GroupRole::Owner.display_name(), "Owner");
250 assert_eq!(GroupRole::Admin.display_name(), "Administrator");
251 assert_eq!(GroupRole::Moderator.display_name(), "Moderator");
252 assert_eq!(GroupRole::Member.display_name(), "Member");
253 }
254
255 #[test]
256 fn test_group_role_can_assign_role() {
257 assert!(GroupRole::Owner.can_assign_role(&GroupRole::Owner));
259 assert!(GroupRole::Owner.can_assign_role(&GroupRole::Admin));
260 assert!(GroupRole::Owner.can_assign_role(&GroupRole::Moderator));
261 assert!(GroupRole::Owner.can_assign_role(&GroupRole::Member));
262
263 assert!(!GroupRole::Admin.can_assign_role(&GroupRole::Owner));
265 assert!(GroupRole::Admin.can_assign_role(&GroupRole::Admin));
266 assert!(GroupRole::Admin.can_assign_role(&GroupRole::Moderator));
267 assert!(GroupRole::Admin.can_assign_role(&GroupRole::Member));
268
269 assert!(!GroupRole::Moderator.can_assign_role(&GroupRole::Owner));
271 assert!(!GroupRole::Moderator.can_assign_role(&GroupRole::Admin));
272 assert!(!GroupRole::Moderator.can_assign_role(&GroupRole::Moderator));
273 assert!(GroupRole::Moderator.can_assign_role(&GroupRole::Member));
274
275 assert!(!GroupRole::Member.can_assign_role(&GroupRole::Owner));
277 assert!(!GroupRole::Member.can_assign_role(&GroupRole::Admin));
278 assert!(!GroupRole::Member.can_assign_role(&GroupRole::Moderator));
279 assert!(!GroupRole::Member.can_assign_role(&GroupRole::Member));
280 }
281
282 #[test]
283 fn test_group_permissions_builder() {
284 let permissions = GroupPermissions::new()
285 .update_group(Permission::AdminOrAbove)
286 .assign_roles(Permission::OwnerOnly)
287 .post_activities(Permission::AllMembers)
288 .update_encryption(Permission::OwnerOnly);
289
290 assert_eq!(permissions.update_group, Permission::AdminOrAbove);
291 assert_eq!(permissions.assign_roles, Permission::OwnerOnly);
292 assert_eq!(permissions.post_activities, Permission::AllMembers);
293 assert_eq!(permissions.update_encryption, Permission::OwnerOnly);
294 }
295
296 #[test]
297 fn test_group_permissions_can_perform_action() {
298 let permissions = GroupPermissions::default();
299
300 assert!(permissions.can_perform_action(&GroupRole::Owner, GroupAction::UpdateGroup));
302 assert!(permissions.can_perform_action(&GroupRole::Admin, GroupAction::UpdateGroup));
303 assert!(!permissions.can_perform_action(&GroupRole::Moderator, GroupAction::UpdateGroup));
304 assert!(!permissions.can_perform_action(&GroupRole::Member, GroupAction::UpdateGroup));
305
306 assert!(permissions.can_perform_action(&GroupRole::Owner, GroupAction::AssignRoles));
307 assert!(!permissions.can_perform_action(&GroupRole::Admin, GroupAction::AssignRoles));
308
309 assert!(permissions.can_perform_action(&GroupRole::Member, GroupAction::PostActivities));
310
311 assert!(permissions.can_perform_action(&GroupRole::Owner, GroupAction::UpdateEncryption));
312 assert!(!permissions.can_perform_action(&GroupRole::Admin, GroupAction::UpdateEncryption));
313 }
314
315 #[test]
316 fn test_group_key_info() {
317 let key_id = vec![1, 2, 3, 4];
318 let derivation_info = zoe_wire_protocol::crypto::KeyDerivationInfo {
319 method: zoe_wire_protocol::crypto::KeyDerivationMethod::Bip39Argon2,
320 salt: vec![1, 2, 3, 4, 5, 6, 7, 8],
321 argon2_params: zoe_wire_protocol::crypto::Argon2Params::default(),
322 context: "dga-group-key".to_string(),
323 };
324
325 let key_info = GroupKeyInfo::new_chacha20_poly1305(key_id.clone(), derivation_info.clone());
326
327 assert_eq!(key_info.key_id(), &key_id);
328 assert_eq!(key_info.algorithm(), "ChaCha20-Poly1305");
329 assert_eq!(key_info.derivation_info(), Some(&derivation_info));
330 }
331
332 #[test]
333 fn test_group_key_info_matches_key_id() {
334 let key_id = vec![1, 2, 3, 4];
335 let derivation_info = zoe_wire_protocol::crypto::KeyDerivationInfo {
336 method: zoe_wire_protocol::crypto::KeyDerivationMethod::Bip39Argon2,
337 salt: vec![1, 2, 3, 4, 5, 6, 7, 8],
338 argon2_params: zoe_wire_protocol::crypto::Argon2Params::default(),
339 context: "dga-group-key".to_string(),
340 };
341 let key_info = GroupKeyInfo::new_chacha20_poly1305(key_id.clone(), derivation_info);
342
343 assert!(key_info.matches_key_id(&key_id));
344 assert!(!key_info.matches_key_id(&[5, 6, 7, 8]));
345 }
346
347 #[test]
348 fn test_group_settings_builder() {
349 let permissions = GroupPermissions::default();
350 let encryption_settings = EncryptionSettings::default();
351
352 let settings = GroupSettings::new()
353 .permissions(permissions.clone())
354 .encryption_settings(encryption_settings.clone());
355
356 assert_eq!(settings.permissions, permissions);
357 assert_eq!(settings.encryption_settings, encryption_settings);
358 }
359
360 #[test]
361 fn test_encryption_settings_builder() {
362 let settings = EncryptionSettings::new().with_key_rotation(3600);
363
364 assert!(settings.key_rotation_enabled);
365 assert_eq!(settings.key_rotation_interval, Some(3600));
366 }
367
368 #[test]
369 fn test_relay_endpoint() {
370 let address = create_test_socket_addr();
371 let _public_key = create_test_verifying_key();
372
373 let endpoint = RelayEndpoint::new(address, create_test_ed25519_verifying_key())
374 .with_name("Test Relay".to_string())
375 .with_metadata(Metadata::Generic {
376 key: "region".to_string(),
377 value: "us-west".to_string(),
378 });
379
380 assert_eq!(endpoint.address, address);
381 assert_eq!(endpoint.name, Some("Test Relay".to_string()));
383 assert_eq!(endpoint.metadata.len(), 1);
384 if let Some(Metadata::Generic { key, value }) = endpoint.metadata.first() {
385 assert_eq!(key, "region");
386 assert_eq!(value, "us-west");
387 } else {
388 panic!("Expected generic metadata");
389 }
390 }
391
392 #[test]
393 fn test_relay_endpoint_display_name() {
394 let address = create_test_socket_addr();
395 let _public_key = create_test_verifying_key();
396
397 let endpoint_no_name = RelayEndpoint::new(address, create_test_ed25519_verifying_key());
399 assert_eq!(endpoint_no_name.display_name(), address.to_string());
400
401 let endpoint_with_name = endpoint_no_name.with_name("Test Relay".to_string());
403 assert_eq!(endpoint_with_name.display_name(), "Test Relay");
404 }
405
406 #[test]
407 fn test_group_join_info() {
408 let channel_id = "test_channel_123".to_string();
409 let group_info = GroupInfo {
410 name: "Test Group".to_string(),
411 settings: GroupSettings::default(),
412 key_info: create_test_group_key_info(vec![1, 2, 3]),
413 metadata: Vec::new(),
414 };
415 let encryption_key = [42u8; 32];
416 let key_info = create_test_group_key_info(vec![1, 2, 3]);
417 let relay_endpoint = RelayEndpoint::new(
418 create_test_socket_addr(),
419 create_test_ed25519_verifying_key(),
420 );
421
422 let join_info = GroupJoinInfo::new(
423 channel_id.clone(),
424 group_info.clone(),
425 encryption_key,
426 key_info.clone(),
427 vec![relay_endpoint.clone()],
428 )
429 .with_invitation_metadata(Metadata::Generic {
430 key: "inviter".to_string(),
431 value: "alice".to_string(),
432 });
433
434 assert_eq!(join_info.channel_id, channel_id);
435 assert_eq!(join_info.group_info, group_info);
436 assert_eq!(join_info.encryption_key, encryption_key);
437 assert_eq!(join_info.key_info, key_info);
438 assert_eq!(join_info.relay_endpoints, vec![relay_endpoint]);
439 assert_eq!(join_info.invitation_metadata.len(), 1);
440 if let Some(Metadata::Generic { key, value }) = join_info.invitation_metadata.first() {
441 assert_eq!(key, "inviter");
442 assert_eq!(value, "alice");
443 } else {
444 panic!("Expected generic metadata");
445 }
446 }
447
448 #[test]
449 fn test_group_join_info_relay_methods() {
450 let relay1 = RelayEndpoint::new(
451 create_test_socket_addr(),
452 create_test_ed25519_verifying_key(),
453 )
454 .with_name("Primary".to_string());
455 let relay2 = RelayEndpoint::new(
456 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
457 create_test_ed25519_verifying_key(),
458 )
459 .with_name("Secondary".to_string());
460
461 let mut join_info = GroupJoinInfo::new(
462 "test".to_string(),
463 GroupInfo {
464 name: "Test".to_string(),
465 settings: GroupSettings::default(),
466 key_info: create_test_group_key_info(vec![1]),
467 metadata: Vec::new(),
468 },
469 [0u8; 32],
470 create_test_group_key_info(vec![1]),
471 vec![relay1.clone()],
472 );
473
474 assert!(join_info.has_relays());
476 assert_eq!(join_info.primary_relay(), Some(&relay1));
477 assert_eq!(join_info.relays_by_priority().len(), 1);
478
479 join_info = join_info.add_relay(relay2.clone());
481 assert_eq!(join_info.relays_by_priority().len(), 2);
482 assert_eq!(join_info.primary_relay(), Some(&relay1)); let empty_join_info = GroupJoinInfo::new(
486 "test".to_string(),
487 GroupInfo {
488 name: "Test".to_string(),
489 settings: GroupSettings::default(),
490 key_info: create_test_group_key_info(vec![1]),
491 metadata: Vec::new(),
492 },
493 [0u8; 32],
494 create_test_group_key_info(vec![1]),
495 vec![],
496 );
497
498 assert!(!empty_join_info.has_relays());
499 assert_eq!(empty_join_info.primary_relay(), None);
500 assert!(empty_join_info.relays_by_priority().is_empty());
501 }
502
503 #[test]
504 fn test_group_info() {
505 let group_info = GroupInfo {
507 name: "Test Group".to_string(),
508 settings: GroupSettings::default(),
509 key_info: create_test_group_key_info(vec![1, 2, 3]),
510 metadata: Vec::new(),
511 };
512
513 let _cloned = group_info.clone();
515 }
516
517 #[test]
518 fn test_group_permissions_default() {
519 let permissions = GroupPermissions::default();
520
521 assert_eq!(permissions.update_group, Permission::AdminOrAbove);
522 assert_eq!(permissions.assign_roles, Permission::OwnerOnly);
523 assert_eq!(permissions.post_activities, Permission::AllMembers);
524 assert_eq!(permissions.update_encryption, Permission::OwnerOnly);
525 }
526
527 #[test]
528 fn test_encryption_settings_default() {
529 let settings = EncryptionSettings::default();
530
531 assert!(!settings.key_rotation_enabled);
532 assert_eq!(settings.key_rotation_interval, None);
533 }
534
535 #[test]
536 fn test_group_settings_default() {
537 let settings = GroupSettings::default();
538
539 assert_eq!(settings.permissions, GroupPermissions::default());
540 assert_eq!(settings.encryption_settings, EncryptionSettings::default());
541 }
542
543 #[test]
544 fn test_postcard_serialization_group_activity_event() {
545 let event = GroupActivityEvent::UpdateGroup(GroupInfo {
546 name: "Test Group".to_string(),
547 settings: GroupSettings::default(),
548 key_info: create_test_group_key_info(vec![1, 2, 3]),
549 metadata: Vec::new(),
550 });
551
552 let serialized = postcard::to_stdvec(&event).expect("Failed to serialize");
553 let deserialized: GroupActivityEvent<()> =
554 postcard::from_bytes(&serialized).expect("Failed to deserialize");
555
556 assert_eq!(event, deserialized);
557 }
558
559 #[test]
560 fn test_postcard_serialization_group_role() {
561 for role in [
562 GroupRole::Owner,
563 GroupRole::Admin,
564 GroupRole::Moderator,
565 GroupRole::Member,
566 ] {
567 let serialized = postcard::to_stdvec(&role).expect("Failed to serialize");
568 let deserialized: GroupRole =
569 postcard::from_bytes(&serialized).expect("Failed to deserialize");
570 assert_eq!(role, deserialized);
571 }
572 }
573
574 #[test]
575 fn test_postcard_serialization_permission() {
576 for permission in [
577 Permission::OwnerOnly,
578 Permission::AdminOrAbove,
579 Permission::ModeratorOrAbove,
580 Permission::AllMembers,
581 ] {
582 let serialized = postcard::to_stdvec(&permission).expect("Failed to serialize");
583 let deserialized: Permission =
584 postcard::from_bytes(&serialized).expect("Failed to deserialize");
585 assert_eq!(permission, deserialized);
586 }
587 }
588
589 #[test]
590 fn test_postcard_serialization_group_join_info() {
591 let join_info = GroupJoinInfo::new(
592 "test_channel".to_string(),
593 GroupInfo {
594 name: "Test".to_string(),
595 settings: GroupSettings::default(),
596 key_info: create_test_group_key_info(vec![1, 2, 3]),
597 metadata: Vec::new(),
598 },
599 [42u8; 32],
600 create_test_group_key_info(vec![1, 2, 3]),
601 vec![RelayEndpoint::new(
602 create_test_socket_addr(),
603 create_test_ed25519_verifying_key(),
604 )],
605 );
606
607 let serialized = postcard::to_stdvec(&join_info).expect("Failed to serialize");
608 let deserialized: GroupJoinInfo =
609 postcard::from_bytes(&serialized).expect("Failed to deserialize");
610
611 assert_eq!(join_info, deserialized);
612 }
613}