sdk&ffi: server unstable features support for MSC4028 (#3192)

Fixes https://github.com/matrix-org/matrix-rust-sdk/issues/3191

Allows support for fetching the unstable_features from `/_matrix/clients/versions`.
Specifically, to be used for checking the state of org.matrix.msc4028 through ffi to the clients.

---

* sdk: fetch unstable_features supported by homeserver

Signed-off-by: hanadi92 <hanadi.tamimi@gmail.com>

* ffi: add can_homeserver_push_encrypted_event_to_device method

Signed-off-by: hanadi92 <hanadi.tamimi@gmail.com>

* fix: use copied instead of dereferencing

Co-authored-by: Benjamin Bouvier <public@benj.me>
Signed-off-by: Hanadi <hanadi.tamimi@gmail.com>

* fix: move can_homeserver_push_encrypted_event_to_device logic to sdk

Signed-off-by: hanadi92 <hanadi.tamimi@gmail.com>

* fix: remove unused unstable features param in client builder

Signed-off-by: hanadi92 <hanadi.tamimi@gmail.com>

* fix: use assert instead of asserteq for bool check

Signed-off-by: hanadi92 <hanadi.tamimi@gmail.com>

* fix: documentation

Signed-off-by: hanadi92 <hanadi.tamimi@gmail.com>

* Apply suggestions from code review

Signed-off-by: Benjamin Bouvier <public@benj.me>

---------

Signed-off-by: hanadi92 <hanadi.tamimi@gmail.com>
Signed-off-by: Hanadi <hanadi.tamimi@gmail.com>
Signed-off-by: Benjamin Bouvier <public@benj.me>
Co-authored-by: Benjamin Bouvier <public@benj.me>
This commit is contained in:
Hanadi
2024-03-08 11:28:04 +01:00
committed by GitHub
parent b7d6fd08f1
commit 724d133cce
4 changed files with 112 additions and 1 deletions

View File

@@ -319,6 +319,13 @@ impl NotificationSettings {
}
}
/// Check whether [MSC 4028 push rule][rule] is enabled on the homeserver.
///
/// [rule]: https://github.com/matrix-org/matrix-spec-proposals/blob/giomfo/push_encrypted_events/proposals/4028-push-all-encrypted-events-except-for-muted-rooms.md
pub async fn can_homeserver_push_encrypted_event_to_device(&self) -> bool {
self.sdk_client.can_homeserver_push_encrypted_event_to_device().await.unwrap()
}
/// Set whether user mentions are enabled.
pub async fn set_user_mention_enabled(
&self,

View File

@@ -508,6 +508,7 @@ impl ClientBuilder {
http_client,
base_client,
self.server_versions,
None,
self.respect_login_well_known,
event_cache,
#[cfg(feature = "e2e-encryption")]

View File

@@ -235,6 +235,9 @@ pub(crate) struct ClientInner {
/// The Matrix versions the server supports (well-known ones only)
server_versions: OnceCell<Box<[MatrixVersion]>>,
/// The unstable features and their on/off state on the server
unstable_features: OnceCell<BTreeMap<String, bool>>,
/// Collection of locks individual client methods might want to use, either
/// to ensure that only a single call to a method happens at once or to
/// deduplicate multiple calls to a method.
@@ -292,6 +295,7 @@ impl ClientInner {
http_client: HttpClient,
base_client: BaseClient,
server_versions: Option<Box<[MatrixVersion]>>,
unstable_features: Option<BTreeMap<String, bool>>,
respect_login_well_known: bool,
event_cache: OnceCell<EventCache>,
#[cfg(feature = "e2e-encryption")] encryption_settings: EncryptionSettings,
@@ -305,6 +309,7 @@ impl ClientInner {
base_client,
locks: Default::default(),
server_versions: OnceCell::new_with(server_versions),
unstable_features: OnceCell::new_with(unstable_features),
typing_notice_times: Default::default(),
event_handlers: Default::default(),
notification_handlers: Default::default(),
@@ -1401,6 +1406,67 @@ impl Client {
Ok(server_versions)
}
/// Fetch unstable_features from homeserver
async fn request_unstable_features(&self) -> HttpResult<BTreeMap<String, bool>> {
let unstable_features: BTreeMap<String, bool> = self
.inner
.http_client
.send(
get_supported_versions::Request::new(),
None,
self.homeserver().to_string(),
None,
&[MatrixVersion::V1_0],
Default::default(),
)
.await?
.unstable_features;
Ok(unstable_features)
}
/// Get unstable features from `request_unstable_features` or cache
///
/// # Examples
///
/// ```no_run
/// # use matrix_sdk::{Client, config::SyncSettings};
/// # use url::Url;
/// # async {
/// # let homeserver = Url::parse("http://localhost:8080")?;
/// # let mut client = Client::new(homeserver).await?;
/// let unstable_features = client.unstable_features().await?;
/// let msc_x = unstable_features.get("msc_x").unwrap_or(&false);
/// # anyhow::Ok(()) };
/// ```
pub async fn unstable_features(&self) -> HttpResult<&BTreeMap<String, bool>> {
let unstable_features = self
.inner
.unstable_features
.get_or_try_init(|| self.request_unstable_features())
.await?;
Ok(unstable_features)
}
/// Check whether MSC 4028 is enabled on the homeserver.
///
/// # Examples
///
/// ```no_run
/// # use matrix_sdk::{Client, config::SyncSettings};
/// # use url::Url;
/// # async {
/// # let homeserver = Url::parse("http://localhost:8080")?;
/// # let mut client = Client::new(homeserver).await?;
/// let msc4028_enabled =
/// client.can_homeserver_push_encrypted_event_to_device().await?;
/// # anyhow::Ok(()) };
/// ```
pub async fn can_homeserver_push_encrypted_event_to_device(&self) -> HttpResult<bool> {
Ok(self.unstable_features().await?.get("org.matrix.msc4028").copied().unwrap_or(false))
}
/// Get information of all our own devices.
///
/// # Examples
@@ -2006,6 +2072,7 @@ impl Client {
self.inner.http_client.clone(),
self.inner.base_client.clone_with_in_memory_state_store(),
self.inner.server_versions.get().cloned(),
self.inner.unstable_features.get().cloned(),
self.inner.respect_login_well_known,
self.inner.event_cache.clone(),
#[cfg(feature = "e2e-encryption")]
@@ -2269,4 +2336,39 @@ pub(crate) mod tests {
assert_eq!(result.avatar_url.clone().unwrap().to_string(), "mxc://example.me/someid");
assert!(!response.limited);
}
#[async_test]
async fn test_request_unstable_features() {
let server = MockServer::start().await;
let client = logged_in_client(Some(server.uri())).await;
Mock::given(method("GET"))
.and(path("_matrix/client/versions"))
.respond_with(
ResponseTemplate::new(200).set_body_json(&*test_json::api_responses::VERSIONS),
)
.mount(&server)
.await;
let unstable_features = client.request_unstable_features().await.unwrap();
assert_eq!(unstable_features.get("org.matrix.e2e_cross_signing"), Some(&true));
assert_eq!(unstable_features, client.unstable_features().await.unwrap().clone());
}
#[async_test]
async fn test_can_homeserver_push_encrypted_event_to_device() {
let server = MockServer::start().await;
let client = logged_in_client(Some(server.uri())).await;
Mock::given(method("GET"))
.and(path("_matrix/client/versions"))
.respond_with(
ResponseTemplate::new(200).set_body_json(&*test_json::api_responses::VERSIONS),
)
.mount(&server)
.await;
let msc4028_enabled = client.can_homeserver_push_encrypted_event_to_device().await.unwrap();
assert!(msc4028_enabled);
}
}

View File

@@ -324,7 +324,8 @@ pub static VERSIONS: Lazy<JsonValue> = Lazy::new(|| {
],
"unstable_features": {
"org.matrix.label_based_filtering":true,
"org.matrix.e2e_cross_signing":true
"org.matrix.e2e_cross_signing":true,
"org.matrix.msc4028":true
}
})
});