Prevent guests from screen-sharing, unmuting or screen sharing

Conrad Irwin created

Change summary

crates/call/src/room.rs                      |  5 +
crates/collab/src/db/ids.rs                  |  8 ++
crates/collab/src/db/queries/projects.rs     |  7 ++
crates/collab_ui/src/collab_titlebar_item.rs | 64 +++++++++++++--------
crates/live_kit_server/src/token.rs          |  1 
5 files changed, 60 insertions(+), 25 deletions(-)

Detailed changes

crates/call/src/room.rs 🔗

@@ -1251,6 +1251,11 @@ impl Room {
             .unwrap_or(false)
     }
 
+    pub fn can_publish(&self) -> bool {
+        self.local_participant().role == proto::ChannelRole::Member
+            || self.local_participant().role == proto::ChannelRole::Admin
+    }
+
     pub fn is_speaking(&self) -> bool {
         self.live_kit
             .as_ref()

crates/collab/src/db/ids.rs 🔗

@@ -132,6 +132,14 @@ impl ChannelRole {
             Admin | Member | Banned => false,
         }
     }
+
+    pub fn can_share_projects(&self) -> bool {
+        use ChannelRole::*;
+        match self {
+            Admin | Member => true,
+            Guest | Banned => false,
+        }
+    }
 }
 
 impl From<proto::ChannelRole> for ChannelRole {

crates/collab/src/db/queries/projects.rs 🔗

@@ -46,6 +46,13 @@ impl Database {
             if participant.room_id != room_id {
                 return Err(anyhow!("shared project on unexpected room"))?;
             }
+            if !participant
+                .role
+                .unwrap_or(ChannelRole::Member)
+                .can_share_projects()
+            {
+                return Err(anyhow!("guests cannot share projects"))?;
+            }
 
             let project = project::ActiveModel {
                 room_id: ActiveValue::set(participant.room_id),

crates/collab_ui/src/collab_titlebar_item.rs 🔗

@@ -173,8 +173,9 @@ impl Render for CollabTitlebarItem {
                         let is_muted = room.is_muted(cx);
                         let is_deafened = room.is_deafened().unwrap_or(false);
                         let is_screen_sharing = room.is_screen_sharing();
+                        let can_publish = room.can_publish();
 
-                        this.when(is_local, |this| {
+                        this.when(is_local && can_publish, |this| {
                             this.child(
                                 Button::new(
                                     "toggle_sharing",
@@ -203,20 +204,22 @@ impl Render for CollabTitlebarItem {
                                         .detach_and_log_err(cx);
                                 }),
                         )
-                        .child(
-                            IconButton::new(
-                                "mute-microphone",
-                                if is_muted {
-                                    ui::Icon::MicMute
-                                } else {
-                                    ui::Icon::Mic
-                                },
+                        .when(can_publish, |this| {
+                            this.child(
+                                IconButton::new(
+                                    "mute-microphone",
+                                    if is_muted {
+                                        ui::Icon::MicMute
+                                    } else {
+                                        ui::Icon::Mic
+                                    },
+                                )
+                                .style(ButtonStyle::Subtle)
+                                .icon_size(IconSize::Small)
+                                .selected(is_muted)
+                                .on_click(move |_, cx| crate::toggle_mute(&Default::default(), cx)),
                             )
-                            .style(ButtonStyle::Subtle)
-                            .icon_size(IconSize::Small)
-                            .selected(is_muted)
-                            .on_click(move |_, cx| crate::toggle_mute(&Default::default(), cx)),
-                        )
+                        })
                         .child(
                             IconButton::new(
                                 "mute-sound",
@@ -230,19 +233,30 @@ impl Render for CollabTitlebarItem {
                             .icon_size(IconSize::Small)
                             .selected(is_deafened)
                             .tooltip(move |cx| {
-                                Tooltip::with_meta("Deafen Audio", None, "Mic will be muted", cx)
+                                if can_publish {
+                                    Tooltip::with_meta(
+                                        "Deafen Audio",
+                                        None,
+                                        "Mic will be muted",
+                                        cx,
+                                    )
+                                } else {
+                                    Tooltip::text("Deafen Audio", cx)
+                                }
                             })
-                            .on_click(move |_, cx| crate::toggle_mute(&Default::default(), cx)),
-                        )
-                        .child(
-                            IconButton::new("screen-share", ui::Icon::Screen)
-                                .style(ButtonStyle::Subtle)
-                                .icon_size(IconSize::Small)
-                                .selected(is_screen_sharing)
-                                .on_click(move |_, cx| {
-                                    crate::toggle_screen_sharing(&Default::default(), cx)
-                                }),
+                            .on_click(move |_, cx| crate::toggle_deafen(&Default::default(), cx)),
                         )
+                        .when(can_publish, |this| {
+                            this.child(
+                                IconButton::new("screen-share", ui::Icon::Screen)
+                                    .style(ButtonStyle::Subtle)
+                                    .icon_size(IconSize::Small)
+                                    .selected(is_screen_sharing)
+                                    .on_click(move |_, cx| {
+                                        crate::toggle_screen_sharing(&Default::default(), cx)
+                                    }),
+                            )
+                        })
                     })
                     .map(|el| {
                         let status = self.client.status();

crates/live_kit_server/src/token.rs 🔗

@@ -62,6 +62,7 @@ impl<'a> VideoGrant<'a> {
         Self {
             room: Some(Cow::Borrowed(room)),
             room_join: Some(true),
+            can_publish: Some(false),
             can_subscribe: Some(true),
             ..Default::default()
         }