matrix_sdk/room/
privacy_settings.rsuse matrix_sdk_base::Room as BaseRoom;
use ruma::{
api::client::{
directory::{get_room_visibility, set_room_visibility},
room::Visibility,
state::send_state_event,
},
assign,
events::{
room::{
canonical_alias::RoomCanonicalAliasEventContent,
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
join_rules::{JoinRule, RoomJoinRulesEventContent},
},
EmptyStateKey,
},
OwnedRoomAliasId, RoomAliasId,
};
use crate::{Client, Result};
#[derive(Debug)]
pub struct RoomPrivacySettings<'a> {
room: &'a BaseRoom,
client: &'a Client,
}
impl<'a> RoomPrivacySettings<'a> {
pub(crate) fn new(room: &'a BaseRoom, client: &'a Client) -> Self {
Self { room, client }
}
pub async fn publish_room_alias_in_room_directory(
&'a self,
alias: &RoomAliasId,
) -> Result<bool> {
if self.client.is_room_alias_available(alias).await? {
self.client.create_room_alias(alias, self.room.room_id()).await?;
return Ok(true);
}
Ok(false)
}
pub async fn remove_room_alias_from_room_directory(
&'a self,
alias: &RoomAliasId,
) -> Result<bool> {
if self.client.resolve_room_alias(alias).await.is_ok() {
self.client.remove_room_alias(alias).await?;
return Ok(true);
}
Ok(false)
}
pub async fn update_canonical_alias(
&'a self,
alias: Option<OwnedRoomAliasId>,
alt_aliases: Vec<OwnedRoomAliasId>,
) -> Result<()> {
let content = assign!(
RoomCanonicalAliasEventContent::new(),
{ alias, alt_aliases }
);
let request = send_state_event::v3::Request::new(
self.room.room_id().to_owned(),
&EmptyStateKey,
&content,
)?;
self.client.send(request).await?;
Ok(())
}
pub async fn update_room_history_visibility(
&'a self,
new_value: HistoryVisibility,
) -> Result<()> {
let request = send_state_event::v3::Request::new(
self.room.room_id().to_owned(),
&EmptyStateKey,
&RoomHistoryVisibilityEventContent::new(new_value),
)?;
self.client.send(request).await?;
Ok(())
}
pub async fn update_join_rule(&'a self, new_rule: JoinRule) -> Result<()> {
let request = send_state_event::v3::Request::new(
self.room.room_id().to_owned(),
&EmptyStateKey,
&RoomJoinRulesEventContent::new(new_rule),
)?;
self.client.send(request).await?;
Ok(())
}
pub async fn get_room_visibility(&'a self) -> Result<Visibility> {
let request = get_room_visibility::v3::Request::new(self.room.room_id().to_owned());
let response = self.client.send(request).await?;
Ok(response.visibility)
}
pub async fn update_room_visibility(&'a self, visibility: Visibility) -> Result<()> {
let request =
set_room_visibility::v3::Request::new(self.room.room_id().to_owned(), visibility);
self.client.send(request).await?;
Ok(())
}
}
#[cfg(all(test, not(target_arch = "wasm32")))]
mod tests {
use std::ops::Not;
use matrix_sdk_test::{async_test, JoinedRoomBuilder, StateTestEvent};
use ruma::{
api::client::room::Visibility,
event_id,
events::{
room::{history_visibility::HistoryVisibility, join_rules::JoinRule},
StateEventType,
},
owned_room_alias_id, room_id,
};
use crate::test_utils::mocks::MatrixMockServer;
#[async_test]
async fn test_publish_room_alias_to_room_directory() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let room = server.sync_joined_room(&client, room_id).await;
let room_alias = owned_room_alias_id!("#a:b.c");
server
.mock_room_directory_resolve_alias()
.for_alias(room_alias.to_string())
.not_found()
.mock_once()
.mount()
.await;
server.mock_room_directory_create_room_alias().ok().mock_once().mount().await;
let published = room
.privacy_settings()
.publish_room_alias_in_room_directory(&room_alias)
.await
.expect("we should get a result value, not an error");
assert!(published);
}
#[async_test]
async fn test_publish_room_alias_to_room_directory_when_alias_exists() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let room = server.sync_joined_room(&client, room_id).await;
let room_alias = owned_room_alias_id!("#a:b.c");
server
.mock_room_directory_resolve_alias()
.for_alias(room_alias.to_string())
.ok(room_id.as_ref(), Vec::new())
.mock_once()
.mount()
.await;
server.mock_room_directory_create_room_alias().ok().never().mount().await;
let published = room
.privacy_settings()
.publish_room_alias_in_room_directory(&room_alias)
.await
.expect("we should get a result value, not an error");
assert!(published.not());
}
#[async_test]
async fn test_remove_room_alias() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let joined_room_builder =
JoinedRoomBuilder::new(room_id).add_state_event(StateTestEvent::Alias);
let room = server.sync_room(&client, joined_room_builder).await;
let room_alias = owned_room_alias_id!("#a:b.c");
server
.mock_room_directory_resolve_alias()
.for_alias(room_alias.to_string())
.ok(room_id.as_ref(), Vec::new())
.mock_once()
.mount()
.await;
server.mock_room_directory_remove_room_alias().ok().mock_once().mount().await;
let removed = room
.privacy_settings()
.remove_room_alias_from_room_directory(&room_alias)
.await
.expect("we should get a result value, not an error");
assert!(removed);
}
#[async_test]
async fn test_remove_room_alias_if_it_does_not_exist() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let joined_room_builder =
JoinedRoomBuilder::new(room_id).add_state_event(StateTestEvent::Alias);
let room = server.sync_room(&client, joined_room_builder).await;
let room_alias = owned_room_alias_id!("#a:b.c");
server
.mock_room_directory_resolve_alias()
.for_alias(room_alias.to_string())
.not_found()
.mock_once()
.mount()
.await;
server.mock_room_directory_remove_room_alias().ok().never().mount().await;
let removed = room
.privacy_settings()
.remove_room_alias_from_room_directory(&room_alias)
.await
.expect("we should get a result value, not an error");
assert!(removed.not());
}
#[async_test]
async fn test_update_canonical_alias_with_some_value() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let room = server.sync_joined_room(&client, room_id).await;
server
.mock_room_send_state()
.for_type(StateEventType::RoomCanonicalAlias)
.ok(event_id!("$a:b.c"))
.mock_once()
.mount()
.await;
let room_alias = owned_room_alias_id!("#a:b.c");
let ret = room
.privacy_settings()
.update_canonical_alias(Some(room_alias.clone()), Vec::new())
.await;
assert!(ret.is_ok());
}
#[async_test]
async fn test_update_canonical_alias_with_no_value() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let room = server.sync_joined_room(&client, room_id).await;
server
.mock_room_send_state()
.for_type(StateEventType::RoomCanonicalAlias)
.ok(event_id!("$a:b.c"))
.mock_once()
.mount()
.await;
let ret = room.privacy_settings().update_canonical_alias(None, Vec::new()).await;
assert!(ret.is_ok());
}
#[async_test]
async fn test_update_room_history_visibility() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let room = server.sync_joined_room(&client, room_id).await;
server
.mock_room_send_state()
.for_type(StateEventType::RoomHistoryVisibility)
.ok(event_id!("$a:b.c"))
.mock_once()
.mount()
.await;
let ret =
room.privacy_settings().update_room_history_visibility(HistoryVisibility::Joined).await;
assert!(ret.is_ok());
}
#[async_test]
async fn test_update_join_rule() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let room = server.sync_joined_room(&client, room_id).await;
server
.mock_room_send_state()
.for_type(StateEventType::RoomJoinRules)
.ok(event_id!("$a:b.c"))
.mock_once()
.mount()
.await;
let ret = room.privacy_settings().update_join_rule(JoinRule::Public).await;
assert!(ret.is_ok());
}
#[async_test]
async fn test_get_room_visibility() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let room = server.sync_joined_room(&client, room_id).await;
server
.mock_room_send_state()
.for_type(StateEventType::RoomJoinRules)
.ok(event_id!("$a:b.c"))
.mock_once()
.mount()
.await;
let ret = room.privacy_settings().update_join_rule(JoinRule::Public).await;
assert!(ret.is_ok());
}
#[async_test]
async fn test_update_room_visibility() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let room = server.sync_joined_room(&client, room_id).await;
server.mock_room_directory_set_room_visibility().ok().mock_once().mount().await;
let ret = room.privacy_settings().update_room_visibility(Visibility::Private).await;
assert!(ret.is_ok());
}
}