From 8513547e92b65f8edd3bc75b04526b3dca105a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 3 Feb 2025 09:13:02 +0100 Subject: [PATCH] feat(ffi): Add FFI bindings for `Room::forget`. Also make sure rooms the user has been banned from can also be forgotten, not only left ones. --- bindings/matrix-sdk-ffi/src/room.rs | 10 +++ crates/matrix-sdk/src/room/mod.rs | 9 ++- .../matrix-sdk/tests/integration/room/left.rs | 63 ++++++++++++++++++- 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/bindings/matrix-sdk-ffi/src/room.rs b/bindings/matrix-sdk-ffi/src/room.rs index 818ac3ff3..a734ce9fe 100644 --- a/bindings/matrix-sdk-ffi/src/room.rs +++ b/bindings/matrix-sdk-ffi/src/room.rs @@ -1033,6 +1033,16 @@ impl Room { } }))) } + + /// Forget this room. + /// + /// This communicates to the homeserver that it should forget the room. + /// + /// Only left or banned-from rooms can be forgotten. + pub async fn forget(&self) -> Result<(), ClientError> { + self.inner.forget().await?; + Ok(()) + } } /// A listener for receiving new live location shares in a room. diff --git a/crates/matrix-sdk/src/room/mod.rs b/crates/matrix-sdk/src/room/mod.rs index c351d6e05..43488c0cc 100644 --- a/crates/matrix-sdk/src/room/mod.rs +++ b/crates/matrix-sdk/src/room/mod.rs @@ -2896,11 +2896,14 @@ impl Room { /// /// This communicates to the homeserver that it should forget the room. /// - /// Only left rooms can be forgotten. + /// Only left or banned-from rooms can be forgotten. pub async fn forget(&self) -> Result<()> { let state = self.state(); - if state != RoomState::Left { - return Err(Error::WrongRoomState(WrongRoomState::new("Left", state))); + match state { + RoomState::Joined | RoomState::Invited | RoomState::Knocked => { + return Err(Error::WrongRoomState(WrongRoomState::new("Left / Banned", state))); + } + RoomState::Left | RoomState::Banned => {} } let request = forget_room::v3::Request::new(self.inner.room_id().to_owned()); diff --git a/crates/matrix-sdk/tests/integration/room/left.rs b/crates/matrix-sdk/tests/integration/room/left.rs index 723b8572f..6c351b075 100644 --- a/crates/matrix-sdk/tests/integration/room/left.rs +++ b/crates/matrix-sdk/tests/integration/room/left.rs @@ -2,7 +2,7 @@ use std::time::Duration; use assert_matches2::assert_matches; use matrix_sdk::config::SyncSettings; -use matrix_sdk_base::RoomState; +use matrix_sdk_base::{RoomInfoNotableUpdateReasons, RoomState}; use matrix_sdk_test::{ async_test, test_json, GlobalAccountDataTestEvent, LeftRoomBuilder, SyncResponseBuilder, DEFAULT_TEST_ROOM_ID, @@ -77,6 +77,67 @@ async fn test_forget_non_direct_room() { } } +#[async_test] +async fn test_forget_banned_room() { + let (client, server) = logged_in_client_with_server().await; + let user_id = client.user_id().unwrap(); + + let event_cache = client.event_cache(); + event_cache.subscribe().unwrap(); + event_cache.enable_storage().unwrap(); + + Mock::given(method("POST")) + .and(path_regex(r"^/_matrix/client/r0/rooms/.*/forget$")) + .and(header("authorization", "Bearer 1234")) + .respond_with(ResponseTemplate::new(200).set_body_json(&*test_json::EMPTY)) + .named("forget") + .expect(1) + .mount(&server) + .await; + + Mock::given(method("PUT")) + .and(path(format!("/_matrix/client/r0/user/{user_id}/account_data/m.direct"))) + .and(header("authorization", "Bearer 1234")) + .respond_with(ResponseTemplate::new(200).set_body_json(&*test_json::EMPTY)) + .named("set_mdirect") + .expect(0) + .mount(&server) + .await; + + mock_sync(&server, &*test_json::LEAVE_SYNC, None).await; + + let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); + let _response = client.sync_once(sync_settings).await.unwrap(); + + // Let the event cache process updates. + yield_now().await; + + { + // There is some data in the cache store. + let event_cache_store = client.event_cache_store().lock().await.unwrap(); + let room_data = event_cache_store.reload_linked_chunk(&DEFAULT_TEST_ROOM_ID).await.unwrap(); + assert!(!room_data.is_empty()); + } + + // Make the room banned + let room = client.get_room(&DEFAULT_TEST_ROOM_ID).unwrap(); + let mut room_info = room.clone_info(); + room_info.mark_as_banned(); + room.set_room_info(room_info, RoomInfoNotableUpdateReasons::MEMBERSHIP); + assert_eq!(room.state(), RoomState::Banned); + + room.forget().await.unwrap(); + + assert!(client.get_room(&DEFAULT_TEST_ROOM_ID).is_none()); + + { + // Data in the event cache store has been removed. + let event_cache_store = client.event_cache_store().lock().await.unwrap(); + let room_data = event_cache_store.reload_linked_chunk(&DEFAULT_TEST_ROOM_ID).await.unwrap(); + assert!(room_data.is_empty()); + } +} + #[async_test] async fn test_forget_direct_room() { let (client, server) = logged_in_client_with_server().await;