ids.rs

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