elif_http/websocket/channel/
types.rs

1//! Core types for the WebSocket channel system
2
3use super::super::types::ConnectionId;
4use super::password::SecurePasswordHash;
5use serde::{Deserialize, Serialize};
6use std::fmt;
7use std::time::SystemTime;
8use uuid::Uuid;
9
10/// Unique identifier for channels
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12pub struct ChannelId(pub Uuid);
13
14impl ChannelId {
15    pub fn new() -> Self {
16        Self(Uuid::new_v4())
17    }
18
19    /// Create a channel ID from a string name (deterministic)
20    /// 
21    /// Uses UUID v5 with SHA-1 hashing to generate a stable, deterministic UUID
22    /// that will be the same across Rust versions and platforms.
23    pub fn from_name(name: &str) -> Self {
24        // Use UUID v5 with a namespace for channel names
25        // Using OID namespace as it's appropriate for application-specific identifiers
26        const CHANNEL_NAMESPACE: Uuid = Uuid::from_bytes([
27            0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
28            0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
29        ]); // This is the standard OID namespace UUID
30        
31        Self(Uuid::new_v5(&CHANNEL_NAMESPACE, name.as_bytes()))
32    }
33}
34
35impl Default for ChannelId {
36    fn default() -> Self {
37        Self::new()
38    }
39}
40
41impl fmt::Display for ChannelId {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        write!(f, "{}", self.0)
44    }
45}
46
47/// Channel visibility and access control
48#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
49pub enum ChannelType {
50    /// Public channel - anyone can join
51    Public,
52    /// Private channel - invitation required
53    Private,
54    /// Protected channel - password required with secure Argon2 hashing
55    Protected { 
56        #[serde(serialize_with = "serialize_password_hash")]
57        #[serde(deserialize_with = "deserialize_password_hash")]
58        password_hash: SecurePasswordHash 
59    },
60}
61
62// Custom serialization for SecurePasswordHash
63fn serialize_password_hash<S>(hash: &SecurePasswordHash, serializer: S) -> Result<S::Ok, S::Error>
64where
65    S: serde::Serializer,
66{
67    serializer.serialize_str(hash.as_str())
68}
69
70// Custom deserialization for SecurePasswordHash  
71fn deserialize_password_hash<'de, D>(deserializer: D) -> Result<SecurePasswordHash, D::Error>
72where
73    D: serde::Deserializer<'de>,
74{
75    let hash_string = String::deserialize(deserializer)?;
76    SecurePasswordHash::from_hash_string(hash_string)
77        .map_err(serde::de::Error::custom)
78}
79
80impl ChannelType {
81    /// Create a protected channel type with a securely hashed password
82    pub fn protected_with_password(password: &str) -> Result<Self, super::password::PasswordError> {
83        let password_hash = SecurePasswordHash::hash_password(password)?;
84        Ok(Self::Protected { password_hash })
85    }
86}
87
88/// Channel permissions for members
89#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
90pub struct ChannelPermissions {
91    /// Can send messages to the channel
92    pub can_send_messages: bool,
93    /// Can invite other users to the channel
94    pub can_invite: bool,
95    /// Can kick members from the channel (moderator)
96    pub can_kick: bool,
97    /// Can modify channel settings (admin)
98    pub can_modify: bool,
99}
100
101impl Default for ChannelPermissions {
102    fn default() -> Self {
103        Self {
104            can_send_messages: true,
105            can_invite: false,
106            can_kick: false,
107            can_modify: false,
108        }
109    }
110}
111
112impl ChannelPermissions {
113    pub fn moderator() -> Self {
114        Self {
115            can_send_messages: true,
116            can_invite: true,
117            can_kick: true,
118            can_modify: false,
119        }
120    }
121
122    pub fn admin() -> Self {
123        Self {
124            can_send_messages: true,
125            can_invite: true,
126            can_kick: true,
127            can_modify: true,
128        }
129    }
130}
131
132/// Channel member information
133#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct ChannelMember {
135    pub connection_id: ConnectionId,
136    pub joined_at: SystemTime,
137    pub permissions: ChannelPermissions,
138    pub nickname: Option<String>,
139}
140
141/// Channel metadata and configuration
142#[derive(Debug, Clone, Serialize, Deserialize)]
143pub struct ChannelMetadata {
144    pub name: String,
145    pub description: Option<String>,
146    pub created_at: SystemTime,
147    pub created_by: Option<ConnectionId>,
148    pub channel_type: ChannelType,
149    pub max_members: Option<usize>,
150    pub message_history_limit: Option<usize>,
151}
152
153/// Channel statistics
154#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct ChannelStats {
156    pub id: ChannelId,
157    pub name: String,
158    pub member_count: usize,
159    pub message_count: usize,
160    pub channel_type: ChannelType,
161    pub created_at: SystemTime,
162    pub is_empty: bool,
163}
164
165/// Channel manager statistics
166#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct ChannelManagerStats {
168    pub total_channels: usize,
169    pub total_connections_in_channels: usize,
170    pub public_channels: usize,
171    pub private_channels: usize,
172    pub protected_channels: usize,
173    pub empty_channels: usize,
174}