state-res: Add membership check for Knock behind unstable feature

This commit is contained in:
Devin Ragotzy 2021-10-04 15:52:19 -04:00 committed by Jonas Platte
parent c48aead00e
commit 7f0913ccd7
No known key found for this signature in database
GPG Key ID: 7D261D771D915378

View File

@ -230,6 +230,7 @@ pub fn auth_check<E: Event>(
<&UserId>::try_from(state_key).map_err(|e| Error::InvalidPdu(format!("{}", e)))?; <&UserId>::try_from(state_key).map_err(|e| Error::InvalidPdu(format!("{}", e)))?;
if !valid_membership_change( if !valid_membership_change(
room_version,
target_user, target_user,
fetch_state(&EventType::RoomMember, target_user.as_str()).as_ref(), fetch_state(&EventType::RoomMember, target_user.as_str()).as_ref(),
sender, sender,
@ -375,6 +376,7 @@ pub fn auth_check<E: Event>(
/// State. /// State.
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn valid_membership_change( fn valid_membership_change(
_room_version: &RoomVersion,
target_user: &UserId, target_user: &UserId,
target_user_membership_event: Option<impl Event>, target_user_membership_event: Option<impl Event>,
sender: &UserId, sender: &UserId,
@ -400,14 +402,11 @@ fn valid_membership_change(
let third_party_invite = let third_party_invite =
from_json_str::<GetThirdPartyInvite>(content.get())?.third_party_invite; from_json_str::<GetThirdPartyInvite>(content.get())?.third_party_invite;
let sender_is_joined = {
let sender_membership = match &sender_membership_event { let sender_membership = match &sender_membership_event {
Some(pdu) => from_json_str::<GetMembership>(pdu.content().get())?.membership, Some(pdu) => from_json_str::<GetMembership>(pdu.content().get())?.membership,
None => MembershipState::Leave, None => MembershipState::Leave,
}; };
let sender_is_joined = sender_membership == MembershipState::Join;
sender_membership == MembershipState::Join
};
let target_user_current_membership = match &target_user_membership_event { let target_user_current_membership = match &target_user_membership_event {
Some(pdu) => from_json_str::<GetMembership>(pdu.content().get())?.membership, Some(pdu) => from_json_str::<GetMembership>(pdu.content().get())?.membership,
@ -557,6 +556,33 @@ fn valid_membership_change(
allow allow
} }
} }
#[cfg(feature = "unstable-pre-spec")]
MembershipState::Knock if _room_version.allow_knocking => {
// 1. If the `join_rule` is anything other than `knock`, reject.
if join_rules != JoinRule::Knock {
warn!("Join rule is not set to knock");
false
} else {
// 2. If `sender` does not match `state_key`, reject.
// 3. If the `sender`'s current membership is not `ban`, `invite`, or `join`, allow.
// 4. Otherwise, reject.
if sender != target_user {
warn!("Can't make other user join");
false
} else if matches!(
sender_membership,
MembershipState::Ban | MembershipState::Invite | MembershipState::Join
) {
warn!(
?target_user_membership_event_id,
"Membership state of ban, invite, or join are invalid",
);
false
} else {
true
}
}
}
_ => { _ => {
warn!("Unknown membership transition"); warn!("Unknown membership transition");
false false
@ -838,7 +864,7 @@ mod tests {
test_utils::{ test_utils::{
alice, charlie, member_content_ban, to_pdu_event, StateEvent, INITIAL_EVENTS, alice, charlie, member_content_ban, to_pdu_event, StateEvent, INITIAL_EVENTS,
}, },
Event, StateMap, Event, RoomVersion, StateMap,
}; };
use ruma_events::EventType; use ruma_events::EventType;
@ -873,6 +899,7 @@ mod tests {
let sender = alice(); let sender = alice();
assert!(valid_membership_change( assert!(valid_membership_change(
&RoomVersion::VERSION6,
&target_user, &target_user,
fetch_state(EventType::RoomMember, target_user.to_string()), fetch_state(EventType::RoomMember, target_user.to_string()),
&sender, &sender,
@ -917,6 +944,7 @@ mod tests {
let sender = charlie(); let sender = charlie();
assert!(!valid_membership_change( assert!(!valid_membership_change(
&RoomVersion::VERSION6,
&target_user, &target_user,
fetch_state(EventType::RoomMember, target_user.to_string()), fetch_state(EventType::RoomMember, target_user.to_string()),
&sender, &sender,