sdk: create new users_with_power_levels fn (#3182)

It maps user ids to users' power levels.

Also, make sure it just returns an empty map if this info is not available, instead of crashing. 

Then use it in the FFI side to output updated data for the `RoomInfo`.

---

* sdk: create new `users_with_power_levels` fn which maps user ids to users' power levels

Also, make sure it just returns an empty map if this info is not available, instead of crashing.

* Update crates/matrix-sdk/src/room/mod.rs

Co-authored-by: Benjamin Bouvier <public@benj.me>
Signed-off-by: Jorge Martin Espinosa <angel.arasthel@gmail.com>

* Improve tests

---------

Signed-off-by: Jorge Martin Espinosa <angel.arasthel@gmail.com>
Co-authored-by: Benjamin Bouvier <public@benj.me>
This commit is contained in:
Jorge Martin Espinosa
2024-03-04 16:37:16 +01:00
committed by GitHub
parent 4b56ca1841
commit 0c98e26a05
4 changed files with 242 additions and 6 deletions

View File

@@ -54,10 +54,10 @@ impl RoomInfo {
) -> matrix_sdk::Result<Self> {
let unread_notification_counts = room.unread_notification_counts();
let power_levels = room.room_power_levels().await?;
let power_levels_map = room.users_with_power_levels().await;
let mut user_power_levels = HashMap::<String, i64>::new();
for (id, level) in power_levels.users.iter() {
user_power_levels.insert(id.to_string(), (*level).into());
for (id, level) in power_levels_map.iter() {
user_power_levels.insert(id.to_string(), *level);
}
Ok(Self {

View File

@@ -1,6 +1,12 @@
//! High-level room API
use std::{borrow::Borrow, collections::BTreeMap, ops::Deref, sync::Arc, time::Duration};
use std::{
borrow::Borrow,
collections::{BTreeMap, HashMap},
ops::Deref,
sync::Arc,
time::Duration,
};
use eyeball::SharedObservable;
use futures_core::Stream;
@@ -1589,8 +1595,6 @@ impl Room {
/// Run /keys/query requests for all the non-tracked users.
#[cfg(feature = "e2e-encryption")]
async fn query_keys_for_untracked_users(&self) -> Result<()> {
use std::collections::HashMap;
let olm = self.client.olm_machine().await;
let olm = olm.as_ref().expect("Olm machine wasn't started");
@@ -1874,6 +1878,19 @@ impl Room {
Ok(event.for_user(user_id).into())
}
/// Gets a map with the `UserId` of users with power levels other than `0`
/// and this power level.
pub async fn users_with_power_levels(&self) -> HashMap<OwnedUserId, i64> {
let power_levels = self.room_power_levels().await.ok();
let mut user_power_levels = HashMap::<OwnedUserId, i64>::new();
if let Some(power_levels) = power_levels {
for (id, level) in power_levels.users.into_iter() {
user_power_levels.insert(id, level.into());
}
}
user_power_levels
}
/// Sets the name of this room.
pub async fn set_name(&self, name: String) -> Result<send_state_event::v3::Response> {
self.send_state_event(RoomNameEventContent::new(name)).await

View File

@@ -787,3 +787,33 @@ async fn get_power_level_for_user() {
room.get_user_power_level(user_id!("@non-existing:localhost")).await.unwrap();
assert_eq!(power_level_unknown, 0);
}
#[async_test]
async fn get_users_with_power_levels() {
let (client, server) = logged_in_client_with_server().await;
mock_sync(&server, &*test_json::sync::SYNC_ADMIN_AND_MOD, None).await;
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_room(&DEFAULT_TEST_ROOM_ID).unwrap();
let users_with_power_levels = room.users_with_power_levels().await;
assert_eq!(users_with_power_levels.len(), 2);
assert_eq!(users_with_power_levels[user_id!("@admin:localhost")], 100);
assert_eq!(users_with_power_levels[user_id!("@mod:localhost")], 50);
}
#[async_test]
async fn get_users_with_power_levels_is_empty_if_power_level_info_is_not_available() {
let (client, server) = logged_in_client_with_server().await;
mock_sync(&server, &*test_json::INVITE_SYNC, None).await;
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
// The room doesn't have any power level info
let room = client.get_room(room_id!("!696r7674:example.com")).unwrap();
assert!(room.users_with_power_levels().await.is_empty());
}

View File

@@ -1525,3 +1525,192 @@ pub static VOIP_SYNC: Lazy<JsonValue> = Lazy::new(|| {
}
})
});
pub static SYNC_ADMIN_AND_MOD: Lazy<JsonValue> = Lazy::new(|| {
json!({
"device_one_time_keys_count": {},
"next_batch": "s526_47314_0_7_1_1_1_11444_1",
"device_lists": {
"changed": [
"@admin:example.org"
],
"left": []
},
"rooms": {
"invite": {},
"join": {
*DEFAULT_TEST_ROOM_ID: {
"summary": {
"m.heroes": [
"@example2:localhost"
],
"m.joined_member_count": 2,
"m.invited_member_count": 0
},
"account_data": {
"events": []
},
"ephemeral": {
"events": []
},
"state": {
"events": [
{
"content": {
"join_rule": "public"
},
"event_id": "$15139375514WsgmR:localhost",
"origin_server_ts": 151393755000000_u64,
"sender": "@admin:localhost",
"state_key": "",
"type": "m.room.join_rules",
"unsigned": {
"age": 7034220
}
},
{
"content": {
"avatar_url": null,
"displayname": "admin",
"membership": "join"
},
"event_id": "$151800140517rfvjc:localhost",
"membership": "join",
"origin_server_ts": 151800140000000_u64,
"sender": "@admin:localhost",
"state_key": "@admin:localhost",
"type": "m.room.member",
"unsigned": {
"age": 297036,
"replaces_state": "$151800111315tsynI:localhost"
}
},
{
"content": {
"avatar_url": null,
"displayname": "mod",
"membership": "join"
},
"event_id": "$151800140518rfvjc:localhost",
"membership": "join",
"origin_server_ts": 1518001450000000_u64,
"sender": "@mod:localhost",
"state_key": "@mod:localhost",
"type": "m.room.member",
"unsigned": {
"age": 297035,
}
},
{
"content": {
"history_visibility": "shared"
},
"event_id": "$15139375515VaJEY:localhost",
"origin_server_ts": 151393755000000_u64,
"sender": "@admin:localhost",
"state_key": "",
"type": "m.room.history_visibility",
"unsigned": {
"age": 703422
}
},
{
"content": {
"creator": "@example:localhost"
},
"event_id": "$15139375510KUZHi:localhost",
"origin_server_ts": 151393755000000_u64,
"sender": "@admin:localhost",
"state_key": "",
"type": "m.room.create",
"unsigned": {
"age": 703422
}
},
{
"content": {
"topic": "room topic"
},
"event_id": "$151957878228ssqrJ:localhost",
"origin_server_ts": 151957878000000_u64,
"sender": "@admin:localhost",
"state_key": "",
"type": "m.room.topic",
"unsigned": {
"age": 1392989709,
"prev_content": {
"topic": "test"
},
"prev_sender": "@example:localhost",
"replaces_state": "$151957069225EVYKm:localhost"
}
},
{
"content": {
"ban": 50,
"events": {
"m.room.avatar": 50,
"m.room.canonical_alias": 50,
"m.room.history_visibility": 100,
"m.room.name": 50,
"m.room.power_levels": 100
},
"events_default": 0,
"invite": 0,
"kick": 50,
"redact": 50,
"state_default": 50,
"users": {
"@admin:localhost": 100,
"@mod:localhost": 50
},
"users_default": 0
},
"event_id": "$15139375512JaHAW:localhost",
"origin_server_ts": 151393755000000_u64,
"sender": "@admin:localhost",
"state_key": "",
"type": "m.room.power_levels",
"unsigned": {
"age": 703422
}
}
]
},
"timeline": {
"events": [
{
"content": {
"body": "baba",
"format": "org.matrix.custom.html",
"formatted_body": "<strong>baba</strong>",
"msgtype": "m.text"
},
"event_id": "$152037280074GZeOm:localhost",
"origin_server_ts": 152037280000000_u64,
"sender": "@admin:localhost",
"type": "m.room.message",
"unsigned": {
"age": 598971425
}
}
],
"limited": true,
"prev_batch": "t392-516_47314_0_7_1_1_1_11444_1"
},
"unread_notifications": {
"highlight_count": 0,
"notification_count": 11
}
}
},
"leave": {}
},
"to_device": {
"events": []
},
"presence": {
"events": []
}
})
});