Add ability to join a room from a channel ID

co-authored-by: max <max@zed.dev>
This commit is contained in:
Mikayla Maki 2023-07-31 15:27:10 -07:00
parent 4b94bfa045
commit 92fa879b0c
No known key found for this signature in database
16 changed files with 485 additions and 105 deletions

View file

@ -1337,32 +1337,65 @@ impl Database {
&self,
room_id: RoomId,
user_id: UserId,
channel_id: Option<ChannelId>,
connection: ConnectionId,
) -> Result<RoomGuard<proto::Room>> {
self.room_transaction(room_id, |tx| async move {
let result = room_participant::Entity::update_many()
.filter(
Condition::all()
.add(room_participant::Column::RoomId.eq(room_id))
.add(room_participant::Column::UserId.eq(user_id))
.add(room_participant::Column::AnsweringConnectionId.is_null()),
)
.set(room_participant::ActiveModel {
if let Some(channel_id) = channel_id {
channel_member::Entity::find()
.filter(
channel_member::Column::ChannelId
.eq(channel_id)
.and(channel_member::Column::UserId.eq(user_id))
.and(channel_member::Column::Accepted.eq(true)),
)
.one(&*tx)
.await?
.ok_or_else(|| anyhow!("no such channel membership"))?;
room_participant::ActiveModel {
room_id: ActiveValue::set(room_id),
user_id: ActiveValue::set(user_id),
answering_connection_id: ActiveValue::set(Some(connection.id as i32)),
answering_connection_server_id: ActiveValue::set(Some(ServerId(
connection.owner_id as i32,
))),
answering_connection_lost: ActiveValue::set(false),
// Redundant for the channel join use case, used for channel and call invitations
calling_user_id: ActiveValue::set(user_id),
calling_connection_id: ActiveValue::set(connection.id as i32),
calling_connection_server_id: ActiveValue::set(Some(ServerId(
connection.owner_id as i32,
))),
..Default::default()
})
.exec(&*tx)
}
.insert(&*tx)
.await?;
if result.rows_affected == 0 {
Err(anyhow!("room does not exist or was already joined"))?
} else {
let room = self.get_room(room_id, &tx).await?;
Ok(room)
let result = room_participant::Entity::update_many()
.filter(
Condition::all()
.add(room_participant::Column::RoomId.eq(room_id))
.add(room_participant::Column::UserId.eq(user_id))
.add(room_participant::Column::AnsweringConnectionId.is_null()),
)
.set(room_participant::ActiveModel {
answering_connection_id: ActiveValue::set(Some(connection.id as i32)),
answering_connection_server_id: ActiveValue::set(Some(ServerId(
connection.owner_id as i32,
))),
answering_connection_lost: ActiveValue::set(false),
..Default::default()
})
.exec(&*tx)
.await?;
if result.rows_affected == 0 {
Err(anyhow!("room does not exist or was already joined"))?;
}
}
let room = self.get_room(room_id, &tx).await?;
Ok(room)
})
.await
}
@ -3071,6 +3104,14 @@ impl Database {
.insert(&*tx)
.await?;
room::ActiveModel {
channel_id: ActiveValue::Set(Some(channel.id)),
live_kit_room: ActiveValue::Set(format!("channel-{}", channel.id)),
..Default::default()
}
.insert(&*tx)
.await?;
Ok(channel.id)
})
.await
@ -3163,6 +3204,7 @@ impl Database {
self.transaction(|tx| async move {
let tx = tx;
// Breadth first list of all edges in this user's channels
let sql = r#"
WITH RECURSIVE channel_tree(child_id, parent_id, depth) AS (
SELECT channel_id as child_id, CAST(NULL as INTEGER) as parent_id, 0
@ -3173,23 +3215,52 @@ impl Database {
FROM channel_parents, channel_tree
WHERE channel_parents.parent_id = channel_tree.child_id
)
SELECT channel_tree.child_id as id, channels.name, channel_tree.parent_id
SELECT channel_tree.child_id, channel_tree.parent_id
FROM channel_tree
JOIN channels ON channels.id = channel_tree.child_id
ORDER BY channel_tree.depth;
ORDER BY child_id, parent_id IS NOT NULL
"#;
#[derive(FromQueryResult, Debug, PartialEq)]
pub struct ChannelParent {
pub child_id: ChannelId,
pub parent_id: Option<ChannelId>,
}
let stmt = Statement::from_sql_and_values(
self.pool.get_database_backend(),
sql,
vec![user_id.into()],
);
Ok(channel_parent::Entity::find()
let mut parents_by_child_id = HashMap::default();
let mut parents = channel_parent::Entity::find()
.from_raw_sql(stmt)
.into_model::<Channel>()
.all(&*tx)
.await?)
.into_model::<ChannelParent>()
.stream(&*tx).await?;
while let Some(parent) = parents.next().await {
let parent = parent?;
parents_by_child_id.insert(parent.child_id, parent.parent_id);
}
drop(parents);
let mut channels = Vec::with_capacity(parents_by_child_id.len());
let mut rows = channel::Entity::find()
.filter(channel::Column::Id.is_in(parents_by_child_id.keys().copied()))
.stream(&*tx).await?;
while let Some(row) = rows.next().await {
let row = row?;
channels.push(Channel {
id: row.id,
name: row.name,
parent_id: parents_by_child_id.get(&row.id).copied().flatten(),
});
}
drop(rows);
Ok(channels)
})
.await
}
@ -3210,6 +3281,22 @@ impl Database {
.await
}
pub async fn get_channel_room(&self, channel_id: ChannelId) -> Result<RoomId> {
self.transaction(|tx| async move {
let tx = tx;
let room = channel::Model {
id: channel_id,
..Default::default()
}
.find_related(room::Entity)
.one(&*tx)
.await?
.ok_or_else(|| anyhow!("invalid channel"))?;
Ok(room.id)
})
.await
}
async fn transaction<F, Fut, T>(&self, f: F) -> Result<T>
where
F: Send + Fn(TransactionHandle) -> Fut,