Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 119 additions & 5 deletions crates/matrix-sdk-base/src/room/members.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,13 @@ impl Room {
.transpose()?
.map(|e| e.content.ignored_users.into_keys().collect());

let active_users = self.store.get_user_ids(self.room_id(), RoomMemberships::ACTIVE).await?;

Ok(MemberRoomInfo {
power_levels: power_levels.into(),
max_power_level,
users_display_names,
active_users,
ignored_users,
})
}
Expand Down Expand Up @@ -211,13 +214,24 @@ impl RoomMember {
presence: Option<PresenceEvent>,
room_info: &MemberRoomInfo<'_>,
) -> Self {
let MemberRoomInfo { power_levels, max_power_level, users_display_names, ignored_users } =
room_info;
let MemberRoomInfo {
power_levels,
max_power_level,
users_display_names,
ignored_users,
active_users,
} = room_info;

let display_name = event.display_name();
let display_name_ambiguous = users_display_names
.get(&display_name)
.is_some_and(|s| is_display_name_ambiguous(&display_name, s));

let display_name_ambiguous = users_display_names.get(&display_name).is_some_and(|s| {
// s.filter(|n| )
if !is_display_name_ambiguous(&display_name, s) {
return false;
}
//We check of many active_users with the same surname exist
active_users.iter().filter(|u| s.contains(*u)).count() > 1
});
let is_ignored = ignored_users.as_ref().is_some_and(|s| s.contains(event.user_id()));

Self {
Expand Down Expand Up @@ -390,6 +404,7 @@ pub(crate) struct MemberRoomInfo<'a> {
pub(crate) max_power_level: i64,
pub(crate) users_display_names: HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>,
pub(crate) ignored_users: Option<BTreeSet<OwnedUserId>>,
pub(crate) active_users: Vec<OwnedUserId>,
}

/// The kind of room member updates that just happened.
Expand Down Expand Up @@ -478,9 +493,23 @@ pub fn normalize_power_level(power_level: Int, max_power_level: i64) -> Int {

#[cfg(test)]
mod tests {
use std::sync::Arc;

use matrix_sdk_test::{async_test, event_factory::EventFactory};
use proptest::prelude::*;
use ruma::{room_id, user_id};

use super::*;
use crate::{RoomState, StateChanges, StateStore, store::MemoryStore};

fn make_room_test_helper(room_type: RoomState) -> (Arc<MemoryStore>, Room) {
let store = Arc::new(MemoryStore::new());
let user_id = user_id!("@me:example.org");
let room_id = room_id!("!test:localhost");
let (sender, _receiver) = tokio::sync::broadcast::channel(1);

(store.clone(), Room::new(user_id, store, room_id, room_type, sender))
}

prop_compose! {
fn arb_int()(id in any::<i64>()) -> Int {
Expand Down Expand Up @@ -526,4 +555,89 @@ mod tests {
assert!(normalized >= 0);
assert!(normalized <= 100);
}

#[async_test]
async fn test_room_member_from_parts() {
let (store, room) = make_room_test_helper(RoomState::Joined);

let carol = user_id!("@carol:example.org");
let denis = user_id!("@denis:example.org");
let erica = user_id!("@erica:example.org");
let fred = user_id!("@fred:example.org");
let fredo = user_id!("@fredo:example.org");
let bob = user_id!("@bob:example.org");
let julie = user_id!("@julie:example.org");
let me = user_id!("@me:example.org");
let mewto = user_id!("@mewto:example.org");

let mut changes = StateChanges::new("".to_owned());

let f = EventFactory::new().room(room_id!("!test:localhost"));

{
let members = changes
.state
.entry(room.room_id().to_owned())
.or_default()
.entry(StateEventType::RoomMember)
.or_default();

let ambiguity_maps =
changes.ambiguity_maps.entry(room.room_id().to_owned()).or_default();

let display_name = DisplayName::new("Carol");
members.insert(carol.into(), f.member(carol).display_name("Carol").into());
ambiguity_maps.entry(display_name).or_default().insert(carol.to_owned());

let display_name = DisplayName::new("Fred");
members.insert(fred.into(), f.member(fred).display_name("Fred").into());
ambiguity_maps.entry(display_name.clone()).or_default().insert(fred.to_owned());
members.insert(
fredo.into(),
f.member(fredo).display_name("Fred").membership(MembershipState::Knock).into(),
);
ambiguity_maps.entry(display_name.clone()).or_default().insert(fredo.to_owned());
members.insert(
denis.into(),
f.member(denis).display_name("Fred").membership(MembershipState::Leave).into(),
);
ambiguity_maps.entry(display_name.clone()).or_default().insert(erica.to_owned());
members.insert(
erica.into(),
f.member(erica).display_name("Fred").membership(MembershipState::Ban).into(),
);

let display_name = DisplayName::new("Bob");
members.insert(
bob.into(),
f.member(bob).display_name("Bob").membership(MembershipState::Invite).into(),
);
ambiguity_maps.entry(display_name.clone()).or_default().insert(bob.to_owned());
members.insert(julie.into(), f.member(me).display_name("Bob").into());
ambiguity_maps.entry(display_name.clone()).or_default().insert(julie.to_owned());

let display_name = DisplayName::new("Me");
members.insert(me.into(), f.member(me).display_name("Me").into());
ambiguity_maps.entry(display_name.clone()).or_default().insert(me.to_owned());
members.insert(mewto.into(), f.member(mewto).display_name("Me").into());
ambiguity_maps.entry(display_name.clone()).or_default().insert(mewto.to_owned());

store.save_changes(&changes).await.unwrap();
}

assert!(!room.get_member(carol).await.unwrap().expect("Carol user").name_ambiguous());

assert!(!room.get_member(fred).await.unwrap().expect("Fred user").name_ambiguous());
assert!(!room.get_member(fredo).await.unwrap().expect("Fredo user").name_ambiguous());
assert!(!room.get_member(denis).await.unwrap().expect("Denis user").name_ambiguous());
assert!(!room.get_member(erica).await.unwrap().expect("Erica user").name_ambiguous());

assert!(!room.get_member(bob).await.unwrap().expect("Bob user").name_ambiguous());

assert!(!room.get_member(julie).await.unwrap().expect("Julie user").name_ambiguous());
assert!(!room.get_member(bob).await.unwrap().expect("Bob user").name_ambiguous());

assert!(room.get_member(me).await.unwrap().expect("Me user").name_ambiguous());
assert!(room.get_member(mewto).await.unwrap().expect("Mewto user").name_ambiguous());
}
}
Loading