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