ids.rs

  1use crate::Result;
  2use rpc::proto;
  3use sea_orm::{DbErr, entity::prelude::*};
  4use serde::{Deserialize, Serialize};
  5use uuid::Uuid;
  6
  7#[macro_export]
  8macro_rules! id_type {
  9    ($name:ident) => {
 10        #[derive(
 11            Clone,
 12            Copy,
 13            Debug,
 14            Default,
 15            PartialEq,
 16            Eq,
 17            PartialOrd,
 18            Ord,
 19            Hash,
 20            Serialize,
 21            Deserialize,
 22            DeriveValueType,
 23        )]
 24        #[allow(missing_docs)]
 25        #[serde(transparent)]
 26        pub struct $name(pub i32);
 27
 28        impl $name {
 29            #[allow(unused)]
 30            #[allow(missing_docs)]
 31            pub const MAX: Self = Self(i32::MAX);
 32
 33            #[allow(unused)]
 34            #[allow(missing_docs)]
 35            pub fn from_proto(value: u64) -> Self {
 36                debug_assert!(value != 0);
 37                Self(value as i32)
 38            }
 39
 40            #[allow(unused)]
 41            #[allow(missing_docs)]
 42            pub fn to_proto(self) -> u64 {
 43                self.0 as u64
 44            }
 45        }
 46
 47        impl std::fmt::Display for $name {
 48            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
 49                self.0.fmt(f)
 50            }
 51        }
 52
 53        impl sea_orm::TryFromU64 for $name {
 54            fn try_from_u64(n: u64) -> Result<Self, DbErr> {
 55                Ok(Self(n.try_into().map_err(|_| {
 56                    DbErr::ConvertFromU64(concat!(
 57                        "error converting ",
 58                        stringify!($name),
 59                        " to u64"
 60                    ))
 61                })?))
 62            }
 63        }
 64
 65        impl sea_orm::sea_query::Nullable for $name {
 66            fn null() -> Value {
 67                Value::Int(None)
 68            }
 69        }
 70    };
 71}
 72
 73id_type!(AccessTokenId);
 74id_type!(BufferId);
 75id_type!(ChannelBufferCollaboratorId);
 76id_type!(ChannelChatParticipantId);
 77id_type!(ChannelId);
 78id_type!(ChannelMemberId);
 79id_type!(ContactId);
 80id_type!(ExtensionId);
 81id_type!(FlagId);
 82id_type!(FollowerId);
 83id_type!(HostedProjectId);
 84id_type!(MessageId);
 85id_type!(NotificationId);
 86id_type!(NotificationKindId);
 87id_type!(ProjectCollaboratorId);
 88id_type!(ProjectId);
 89id_type!(ReplicaId);
 90id_type!(RoomId);
 91id_type!(RoomParticipantId);
 92id_type!(ServerId);
 93id_type!(SignupId);
 94id_type!(UserId);
 95
 96#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, DeriveValueType)]
 97pub struct SharedThreadId(pub Uuid);
 98
 99impl SharedThreadId {
100    pub fn from_proto(id: String) -> Option<Self> {
101        Uuid::parse_str(&id).ok().map(SharedThreadId)
102    }
103
104    pub fn to_proto(self) -> String {
105        self.0.to_string()
106    }
107}
108
109impl sea_orm::TryFromU64 for SharedThreadId {
110    fn try_from_u64(_n: u64) -> std::result::Result<Self, DbErr> {
111        Err(DbErr::ConvertFromU64(
112            "SharedThreadId uses UUID and cannot be converted from u64",
113        ))
114    }
115}
116
117impl sea_orm::sea_query::Nullable for SharedThreadId {
118    fn null() -> Value {
119        Value::Uuid(None)
120    }
121}
122
123impl std::fmt::Display for SharedThreadId {
124    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
125        self.0.fmt(f)
126    }
127}
128
129/// ChannelRole gives you permissions for both channels and calls.
130#[derive(
131    Eq, PartialEq, Copy, Clone, Debug, EnumIter, DeriveActiveEnum, Default, Hash, Serialize,
132)]
133#[sea_orm(rs_type = "String", db_type = "String(StringLen::None)")]
134pub enum ChannelRole {
135    /// Admin can read/write and change permissions.
136    #[sea_orm(string_value = "admin")]
137    Admin,
138    /// Member can read/write, but not change permissions.
139    #[sea_orm(string_value = "member")]
140    #[default]
141    Member,
142    /// Talker can read, but not write.
143    /// They can use microphones and the channel chat
144    #[sea_orm(string_value = "talker")]
145    Talker,
146    /// Guest can read, but not write.
147    /// They can not use microphones but can use the chat.
148    #[sea_orm(string_value = "guest")]
149    Guest,
150    /// Banned may not read.
151    #[sea_orm(string_value = "banned")]
152    Banned,
153}
154
155impl ChannelRole {
156    /// Returns true if this role is more powerful than the other role.
157    pub fn should_override(&self, other: Self) -> bool {
158        use ChannelRole::*;
159        match self {
160            Admin => matches!(other, Member | Banned | Talker | Guest),
161            Member => matches!(other, Banned | Talker | Guest),
162            Talker => matches!(other, Guest),
163            Banned => matches!(other, Guest),
164            Guest => false,
165        }
166    }
167
168    /// Returns the maximal role between the two
169    pub fn max(&self, other: Self) -> Self {
170        if self.should_override(other) {
171            *self
172        } else {
173            other
174        }
175    }
176
177    pub fn can_see_channel(&self, visibility: ChannelVisibility) -> bool {
178        use ChannelRole::*;
179        match self {
180            Admin | Member => true,
181            Guest | Talker => visibility == ChannelVisibility::Public,
182            Banned => false,
183        }
184    }
185
186    /// True if the role allows access to all descendant channels
187    pub fn can_see_all_descendants(&self) -> bool {
188        use ChannelRole::*;
189        match self {
190            Admin | Member => true,
191            Guest | Talker | Banned => false,
192        }
193    }
194
195    /// True if the role only allows access to public descendant channels
196    pub fn can_only_see_public_descendants(&self) -> bool {
197        use ChannelRole::*;
198        match self {
199            Guest | Talker => true,
200            Admin | Member | Banned => false,
201        }
202    }
203
204    /// True if the role can share screen/microphone/projects into rooms.
205    pub fn can_use_microphone(&self) -> bool {
206        use ChannelRole::*;
207        match self {
208            Admin | Member | Talker => true,
209            Guest | Banned => false,
210        }
211    }
212
213    /// True if the role can edit shared projects.
214    pub fn can_edit_projects(&self) -> bool {
215        use ChannelRole::*;
216        match self {
217            Admin | Member => true,
218            Talker | Guest | Banned => false,
219        }
220    }
221
222    /// True if the role can read shared projects.
223    pub fn can_read_projects(&self) -> bool {
224        use ChannelRole::*;
225        match self {
226            Admin | Member | Guest | Talker => true,
227            Banned => false,
228        }
229    }
230
231    pub fn requires_cla(&self) -> bool {
232        use ChannelRole::*;
233        match self {
234            Admin | Member => true,
235            Banned | Guest | Talker => false,
236        }
237    }
238}
239
240impl From<proto::ChannelRole> for ChannelRole {
241    fn from(value: proto::ChannelRole) -> Self {
242        match value {
243            proto::ChannelRole::Admin => ChannelRole::Admin,
244            proto::ChannelRole::Member => ChannelRole::Member,
245            proto::ChannelRole::Talker => ChannelRole::Talker,
246            proto::ChannelRole::Guest => ChannelRole::Guest,
247            proto::ChannelRole::Banned => ChannelRole::Banned,
248        }
249    }
250}
251
252impl From<ChannelRole> for proto::ChannelRole {
253    fn from(val: ChannelRole) -> Self {
254        match val {
255            ChannelRole::Admin => proto::ChannelRole::Admin,
256            ChannelRole::Member => proto::ChannelRole::Member,
257            ChannelRole::Talker => proto::ChannelRole::Talker,
258            ChannelRole::Guest => proto::ChannelRole::Guest,
259            ChannelRole::Banned => proto::ChannelRole::Banned,
260        }
261    }
262}
263
264impl From<ChannelRole> for i32 {
265    fn from(val: ChannelRole) -> Self {
266        let proto: proto::ChannelRole = val.into();
267        proto.into()
268    }
269}
270
271/// ChannelVisibility controls whether channels are public or private.
272#[derive(Eq, PartialEq, Copy, Clone, Debug, EnumIter, DeriveActiveEnum, Default, Hash)]
273#[sea_orm(rs_type = "String", db_type = "String(StringLen::None)")]
274pub enum ChannelVisibility {
275    /// Public channels are visible to anyone with the link. People join with the Guest role by default.
276    #[sea_orm(string_value = "public")]
277    Public,
278    /// Members channels are only visible to members of this channel or its parents.
279    #[sea_orm(string_value = "members")]
280    #[default]
281    Members,
282}
283
284impl From<proto::ChannelVisibility> for ChannelVisibility {
285    fn from(value: proto::ChannelVisibility) -> Self {
286        match value {
287            proto::ChannelVisibility::Public => ChannelVisibility::Public,
288            proto::ChannelVisibility::Members => ChannelVisibility::Members,
289        }
290    }
291}
292
293impl From<ChannelVisibility> for proto::ChannelVisibility {
294    fn from(val: ChannelVisibility) -> Self {
295        match val {
296            ChannelVisibility::Public => proto::ChannelVisibility::Public,
297            ChannelVisibility::Members => proto::ChannelVisibility::Members,
298        }
299    }
300}
301
302impl From<ChannelVisibility> for i32 {
303    fn from(val: ChannelVisibility) -> Self {
304        let proto: proto::ChannelVisibility = val.into();
305        proto.into()
306    }
307}
308
309/// Indicate whether a [Buffer] has permissions to edit.
310#[derive(PartialEq, Clone, Copy, Debug)]
311pub enum Capability {
312    /// The buffer is a mutable replica.
313    ReadWrite,
314    /// The buffer is a read-only replica.
315    ReadOnly,
316}