fix(sdk): Restrict when m.room.member represents a LatestEvent candidate.
This patch relies on `MembershipChange` to decide when a `m.room.member` represents a `LatestEvent` candidate. It was a mistale to rely on the `membership` strictly, because the `prev_content` must be taken into account. Thus, this patch adds the following cases to `Knocked`, `Joined` and `Invited`: `InvitationAccepted` and `KnockedAccepted`. Moreover, this patch excludes other cases, including `ProfileChanged`, which was a bug previously! When the user had a new display name, it was considered as a `LatestEvent` candidate.
This commit is contained in:
@@ -25,7 +25,7 @@ use ruma::{
|
||||
AnyMessageLikeEventContent, AnySyncStateEvent, AnySyncTimelineEvent, SyncStateEvent,
|
||||
relation::Replacement,
|
||||
room::{
|
||||
member::MembershipState,
|
||||
member::MembershipChange,
|
||||
message::{MessageType, Relation, RoomMessageEventContent},
|
||||
power_levels::RoomPowerLevels,
|
||||
redaction::RoomRedactionEventContent,
|
||||
@@ -701,14 +701,14 @@ fn filter_any_sync_state_event(
|
||||
power_levels: Option<&RoomPowerLevels>,
|
||||
) -> ControlFlow<(), FilterContinue> {
|
||||
match event {
|
||||
AnySyncStateEvent::RoomMember(member) => {
|
||||
match member.membership() {
|
||||
MembershipState::Knock => {
|
||||
AnySyncStateEvent::RoomMember(SyncStateEvent::Original(member)) => {
|
||||
match member.membership_change() {
|
||||
MembershipChange::Knocked => {
|
||||
let can_accept_or_decline_knocks = match power_levels {
|
||||
Some(room_power_levels) => {
|
||||
room_power_levels.user_can_invite(own_user_id)
|
||||
|| room_power_levels
|
||||
.user_can_kick_user(own_user_id, member.state_key())
|
||||
.user_can_kick_user(own_user_id, &member.state_key)
|
||||
}
|
||||
None => false,
|
||||
};
|
||||
@@ -716,39 +716,28 @@ fn filter_any_sync_state_event(
|
||||
// The current user can act on the knock changes, so they should be
|
||||
// displayed
|
||||
if can_accept_or_decline_knocks {
|
||||
// We can only decide whether the user can accept or decline knocks if the
|
||||
// event isn't redacted.
|
||||
return if matches!(member, SyncStateEvent::Original(_)) {
|
||||
filter_break()
|
||||
} else {
|
||||
filter_continue()
|
||||
};
|
||||
return filter_break();
|
||||
}
|
||||
|
||||
filter_continue()
|
||||
}
|
||||
|
||||
// A member is joining or is being invited…
|
||||
MembershipState::Join | MembershipState::Invite => {
|
||||
// A member has joined one way or another.
|
||||
MembershipChange::Joined
|
||||
| MembershipChange::Invited
|
||||
| MembershipChange::InvitationAccepted
|
||||
| MembershipChange::KnockAccepted => {
|
||||
// This member _is_ the current user, not someone else! This is a valid state
|
||||
// event:
|
||||
//
|
||||
// - the user is joining a room: we want a `LatestEventValue` to get a first
|
||||
// value!
|
||||
// - the user is joining a room (for the first time or again): we want a
|
||||
// `LatestEventValue` to get a first value!
|
||||
// - the user is being invited: we want a `LatestEventValue` to represent the
|
||||
// invitation!
|
||||
match member {
|
||||
// We can only decide whether the user is joining or is being invited if the
|
||||
// event isn't redacted.
|
||||
SyncStateEvent::Original(state) => {
|
||||
if state.state_key.deref() == own_user_id {
|
||||
filter_break()
|
||||
} else {
|
||||
filter_continue()
|
||||
}
|
||||
}
|
||||
|
||||
_ => filter_continue(),
|
||||
if member.state_key.deref() == own_user_id {
|
||||
filter_break()
|
||||
} else {
|
||||
filter_continue()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -765,10 +754,13 @@ mod filter_tests {
|
||||
use std::ops::Not;
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use matrix_sdk_test::event_factory::EventFactory;
|
||||
use matrix_sdk_test::event_factory::{EventFactory, PreviousMembership};
|
||||
use ruma::{
|
||||
event_id,
|
||||
events::{room::message::RoomMessageEventContent, rtc::notification::NotificationType},
|
||||
events::{
|
||||
room::{member::MembershipState, message::RoomMessageEventContent},
|
||||
rtc::notification::NotificationType,
|
||||
},
|
||||
owned_user_id, user_id,
|
||||
};
|
||||
|
||||
@@ -1023,12 +1015,12 @@ mod filter_tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_knocked_state_event_without_power_levels() {
|
||||
fn test_knocked_without_power_levels() {
|
||||
assert_latest_event_content!(
|
||||
event | event_factory | {
|
||||
event_factory
|
||||
.member(user_id!("@other_mnt_io:server.name"))
|
||||
.membership(ruma::events::room::member::MembershipState::Knock)
|
||||
.membership(MembershipState::Knock)
|
||||
.into_event()
|
||||
}
|
||||
is not a candidate
|
||||
@@ -1036,12 +1028,9 @@ mod filter_tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_knocked_state_event_with_power_levels() {
|
||||
fn test_knocked_with_power_levels() {
|
||||
use ruma::{
|
||||
events::room::{
|
||||
member::MembershipState,
|
||||
power_levels::{RoomPowerLevels, RoomPowerLevelsSource},
|
||||
},
|
||||
events::room::power_levels::{RoomPowerLevels, RoomPowerLevelsSource},
|
||||
room_version_rules::AuthorizationRules,
|
||||
};
|
||||
|
||||
@@ -1119,9 +1108,37 @@ mod filter_tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_join_state_event() {
|
||||
use ruma::events::room::member::MembershipState;
|
||||
fn test_knock_accepted() {
|
||||
// The current user was knocking and now is invited.
|
||||
assert_latest_event_content!(
|
||||
event | event_factory | {
|
||||
event_factory
|
||||
.member(user_id!("@mnt_io:matrix.org"))
|
||||
.membership(MembershipState::Invite)
|
||||
.previous(MembershipState::Knock)
|
||||
.into_event()
|
||||
}
|
||||
is a candidate
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_knock_accepted_from_someone_else() {
|
||||
// The current user sees an accepted knock but for someone else.
|
||||
assert_latest_event_content!(
|
||||
event | event_factory | {
|
||||
event_factory
|
||||
.member(user_id!("@other_mnt_io:server.name"))
|
||||
.membership(MembershipState::Invite)
|
||||
.previous(MembershipState::Knock)
|
||||
.into_event()
|
||||
}
|
||||
is not a candidate
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_joined() {
|
||||
// The current user is joining the room.
|
||||
assert_latest_event_content!(
|
||||
event | event_factory | {
|
||||
@@ -1135,7 +1152,22 @@ mod filter_tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_join_state_event_for_someone_else() {
|
||||
fn test_joined_from_left() {
|
||||
// The current user was left and now joins again.
|
||||
assert_latest_event_content!(
|
||||
event | event_factory | {
|
||||
event_factory
|
||||
.member(user_id!("@mnt_io:matrix.org"))
|
||||
.membership(MembershipState::Join)
|
||||
.previous(MembershipState::Leave)
|
||||
.into_event()
|
||||
}
|
||||
is a candidate
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_joined_for_someone_else() {
|
||||
use ruma::events::room::member::MembershipState;
|
||||
|
||||
// The current user sees a join but for someone else.
|
||||
@@ -1151,10 +1183,7 @@ mod filter_tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invite_state_event() {
|
||||
use ruma::events::room::member::MembershipState;
|
||||
|
||||
// The current user is receiving an invite.
|
||||
fn test_invited() {
|
||||
assert_latest_event_content!(
|
||||
event | event_factory | {
|
||||
event_factory
|
||||
@@ -1167,9 +1196,22 @@ mod filter_tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invite_state_event_for_someone_else() {
|
||||
use ruma::events::room::member::MembershipState;
|
||||
fn test_invited_from_left() {
|
||||
// The current user was left and now is invited again.
|
||||
assert_latest_event_content!(
|
||||
event | event_factory | {
|
||||
event_factory
|
||||
.member(user_id!("@mnt_io:matrix.org"))
|
||||
.membership(MembershipState::Invite)
|
||||
.previous(MembershipState::Leave)
|
||||
.into_event()
|
||||
}
|
||||
is a candidate
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invited_for_someone_else() {
|
||||
// The current user sees an invite but for someone else.
|
||||
assert_latest_event_content!(
|
||||
event | event_factory | {
|
||||
@@ -1182,6 +1224,51 @@ mod filter_tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invitation_accepted() {
|
||||
// The current user was invited and now is joined.
|
||||
assert_latest_event_content!(
|
||||
event | event_factory | {
|
||||
event_factory
|
||||
.member(user_id!("@mnt_io:matrix.org"))
|
||||
.membership(MembershipState::Join)
|
||||
.previous(MembershipState::Invite)
|
||||
.into_event()
|
||||
}
|
||||
is a candidate
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invitation_accepted_from_someone_else() {
|
||||
// The current user sees an accepted invitation but for someone else.
|
||||
assert_latest_event_content!(
|
||||
event | event_factory | {
|
||||
event_factory
|
||||
.member(user_id!("@other_mnt_io:server.name"))
|
||||
.membership(MembershipState::Join)
|
||||
.previous(MembershipState::Invite)
|
||||
.into_event()
|
||||
}
|
||||
is not a candidate
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_profile_changed() {
|
||||
// The current user has a new display name.
|
||||
assert_latest_event_content!(
|
||||
event | event_factory | {
|
||||
event_factory
|
||||
.member(user_id!("@mnt_io:matrix.org"))
|
||||
.membership(MembershipState::Join)
|
||||
.previous(PreviousMembership::new(MembershipState::Join).display_name("Coucou"))
|
||||
.into_event()
|
||||
}
|
||||
is not a candidate
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_room_message_verification_request() {
|
||||
use ruma::{OwnedDeviceId, events::room::message};
|
||||
|
||||
Reference in New Issue
Block a user