WIP: require sharing projects on a given Room

This commit is contained in:
Antonio Scandurra 2022-09-30 18:21:47 +02:00
parent 074b8f18d1
commit 964a5d2db7
6 changed files with 105 additions and 65 deletions

View file

@ -611,8 +611,34 @@ impl Server {
async fn leave_room(self: Arc<Server>, message: TypedEnvelope<proto::LeaveRoom>) -> Result<()> {
let room_id = message.payload.id;
let mut store = self.store().await;
let room = store.leave_room(room_id, message.sender_id)?;
self.room_updated(room);
let left_room = store.leave_room(room_id, message.sender_id)?;
for project in left_room.unshared_projects {
for connection_id in project.connection_ids() {
self.peer.send(
connection_id,
proto::UnshareProject {
project_id: project.id.to_proto(),
},
)?;
}
}
for project in left_room.left_projects {
if project.remove_collaborator {
for connection_id in project.connection_ids {
self.peer.send(
connection_id,
proto::RemoveProjectCollaborator {
project_id: project.id.to_proto(),
peer_id: message.sender_id.0,
},
)?;
}
}
}
self.room_updated(left_room.room);
Ok(())
}
@ -696,13 +722,12 @@ impl Server {
.await
.user_id_for_connection(request.sender_id)?;
let project_id = self.app_state.db.register_project(user_id).await?;
self.store()
.await
.share_project(request.sender_id, project_id)?;
let mut store = self.store().await;
let room = store.share_project(request.payload.room_id, project_id, request.sender_id)?;
response.send(proto::ShareProjectResponse {
project_id: project_id.to_proto(),
})?;
self.room_updated(room);
Ok(())
}
@ -712,15 +737,14 @@ impl Server {
message: TypedEnvelope<proto::UnshareProject>,
) -> Result<()> {
let project_id = ProjectId::from_proto(message.payload.project_id);
let project = self
.store()
.await
.unshare_project(project_id, message.sender_id)?;
let mut store = self.store().await;
let (room, project) = store.unshare_project(project_id, message.sender_id)?;
broadcast(
message.sender_id,
project.guest_connection_ids(),
|conn_id| self.peer.send(conn_id, message.payload.clone()),
);
self.room_updated(room);
Ok(())
}
@ -882,7 +906,7 @@ impl Server {
let project;
{
let mut store = self.store().await;
project = store.leave_project(sender_id, project_id)?;
project = store.leave_project(project_id, sender_id)?;
tracing::info!(
%project_id,
host_user_id = %project.host_user_id,

View file

@ -44,6 +44,8 @@ pub struct Call {
#[derive(Serialize)]
pub struct Project {
pub id: ProjectId,
pub room_id: RoomId,
pub host_connection_id: ConnectionId,
pub host: Collaborator,
pub guests: HashMap<ConnectionId, Collaborator>,
@ -90,12 +92,19 @@ pub struct RemovedConnectionState {
}
pub struct LeftProject {
pub id: ProjectId,
pub host_user_id: UserId,
pub host_connection_id: ConnectionId,
pub connection_ids: Vec<ConnectionId>,
pub remove_collaborator: bool,
}
pub struct LeftRoom<'a> {
pub room: &'a proto::Room,
pub unshared_projects: Vec<Project>,
pub left_projects: Vec<LeftProject>,
}
#[derive(Copy, Clone)]
pub struct Metrics {
pub connections: usize,
@ -199,9 +208,9 @@ impl Store {
// Unshare and leave all projects.
for project_id in connection_projects {
if let Ok(project) = self.unshare_project(project_id, connection_id) {
if let Ok((_, project)) = self.unshare_project(project_id, connection_id) {
result.hosted_projects.insert(project_id, project);
} else if self.leave_project(connection_id, project_id).is_ok() {
} else if self.leave_project(project_id, connection_id).is_ok() {
result.guest_project_ids.insert(project_id);
}
}
@ -424,11 +433,7 @@ impl Store {
Ok((room, recipient_connection_ids))
}
pub fn leave_room(
&mut self,
room_id: RoomId,
connection_id: ConnectionId,
) -> Result<&proto::Room> {
pub fn leave_room(&mut self, room_id: RoomId, connection_id: ConnectionId) -> Result<LeftRoom> {
let connection = self
.connections
.get_mut(&connection_id)
@ -454,7 +459,22 @@ impl Store {
.retain(|participant| participant.peer_id != connection_id.0);
connected_user.active_call = None;
Ok(room)
let mut unshared_projects = Vec::new();
let mut left_projects = Vec::new();
for project_id in connection.projects.clone() {
if let Ok((_, project)) = self.unshare_project(project_id, connection_id) {
unshared_projects.push(project);
} else if let Ok(project) = self.leave_project(project_id, connection_id) {
left_projects.push(project);
}
}
let room = self.rooms.get(&room_id).unwrap();
Ok(LeftRoom {
room,
unshared_projects,
left_projects,
})
}
pub fn room(&self, room_id: RoomId) -> Option<&proto::Room> {
@ -564,17 +584,32 @@ impl Store {
pub fn share_project(
&mut self,
host_connection_id: ConnectionId,
room_id: RoomId,
project_id: ProjectId,
) -> Result<()> {
host_connection_id: ConnectionId,
) -> Result<&proto::Room> {
let connection = self
.connections
.get_mut(&host_connection_id)
.ok_or_else(|| anyhow!("no such connection"))?;
let room = self
.rooms
.get_mut(&room_id)
.ok_or_else(|| anyhow!("no such room"))?;
let participant = room
.participants
.iter_mut()
.find(|participant| participant.peer_id == host_connection_id.0)
.ok_or_else(|| anyhow!("no such room"))?;
participant.project_ids.push(project_id.to_proto());
connection.projects.insert(project_id);
self.projects.insert(
project_id,
Project {
id: project_id,
room_id,
host_connection_id,
host: Collaborator {
user_id: connection.user_id,
@ -588,14 +623,15 @@ impl Store {
language_servers: Default::default(),
},
);
Ok(())
Ok(room)
}
pub fn unshare_project(
&mut self,
project_id: ProjectId,
connection_id: ConnectionId,
) -> Result<Project> {
) -> Result<(&proto::Room, Project)> {
match self.projects.entry(project_id) {
btree_map::Entry::Occupied(e) => {
if e.get().host_connection_id == connection_id {
@ -611,7 +647,20 @@ impl Store {
}
}
Ok(project)
let room = self
.rooms
.get_mut(&project.room_id)
.ok_or_else(|| anyhow!("no such room"))?;
let participant = room
.participants
.iter_mut()
.find(|participant| participant.peer_id == connection_id.0)
.ok_or_else(|| anyhow!("no such room"))?;
participant
.project_ids
.retain(|id| *id != project_id.to_proto());
Ok((room, project))
} else {
Err(anyhow!("no such project"))?
}
@ -731,8 +780,8 @@ impl Store {
pub fn leave_project(
&mut self,
connection_id: ConnectionId,
project_id: ProjectId,
connection_id: ConnectionId,
) -> Result<LeftProject> {
let project = self
.projects
@ -752,6 +801,7 @@ impl Store {
}
Ok(LeftProject {
id: project.id,
host_connection_id: project.host_connection_id,
host_user_id: project.host.user_id,
connection_ids: project.connection_ids(),