Room topic reset test fails
This commit is contained in:
parent
5842ddf36e
commit
a0db51b3bd
@ -180,7 +180,14 @@ pub fn auth_check(
|
||||
}
|
||||
|
||||
if event.kind() == EventType::RoomPowerLevels {
|
||||
if !check_power_levels(room_version, event, &auth_events)? {
|
||||
tracing::info!("starting m.room.power_levels check");
|
||||
if let Some(required_pwr_lvl) = check_power_levels(room_version, event, &auth_events) {
|
||||
if !required_pwr_lvl {
|
||||
tracing::warn!("power level was not allowed");
|
||||
return Some(false);
|
||||
}
|
||||
} else {
|
||||
tracing::warn!("power level was not allowed");
|
||||
return Some(false);
|
||||
}
|
||||
tracing::info!("power levels event allowed");
|
||||
@ -372,6 +379,13 @@ fn can_send_event(event: &StateEvent, auth_events: &StateMap<StateEvent>) -> Opt
|
||||
let send_level = get_send_level(event.kind(), event.state_key(), ple);
|
||||
let user_level = get_user_power_level(event.sender(), auth_events);
|
||||
|
||||
tracing::debug!(
|
||||
"{} snd {} usr {}",
|
||||
event.event_id().unwrap().to_string(),
|
||||
send_level,
|
||||
user_level
|
||||
);
|
||||
|
||||
if user_level < send_level {
|
||||
return Some(false);
|
||||
}
|
||||
@ -394,16 +408,17 @@ fn check_power_levels(
|
||||
) -> Option<bool> {
|
||||
use itertools::Itertools;
|
||||
|
||||
let key = (power_event.kind(), power_event.state_key()?);
|
||||
let key = (power_event.kind(), power_event.state_key().unwrap());
|
||||
let current_state = auth_events.get(&key)?;
|
||||
|
||||
let user_content = power_event
|
||||
.deserialize_content::<room::power_levels::PowerLevelsEventContent>()
|
||||
.ok()?;
|
||||
.unwrap();
|
||||
let current_content = current_state
|
||||
.deserialize_content::<room::power_levels::PowerLevelsEventContent>()
|
||||
.ok()?;
|
||||
.unwrap();
|
||||
|
||||
tracing::info!("validation of power event finished");
|
||||
// validation of users is done in Ruma, synapse for loops validating user_ids and integers here
|
||||
|
||||
let user_level = get_user_power_level(power_event.sender(), auth_events);
|
||||
@ -424,6 +439,8 @@ fn check_power_levels(
|
||||
event_levels_to_check.push(ev_id);
|
||||
}
|
||||
|
||||
tracing::debug!("events to check {:?}", event_levels_to_check);
|
||||
|
||||
// TODO validate MSC2209 depending on room version check "notifications".
|
||||
// synapse does this very differently with the loops (see comments below)
|
||||
// but since we have a validated JSON event we can check the levels directly
|
||||
@ -435,6 +452,7 @@ fn check_power_levels(
|
||||
let old_level_too_big = old_level > user_level;
|
||||
let new_level_too_big = new_level > user_level;
|
||||
if old_level_too_big || new_level_too_big {
|
||||
tracing::info!("m.room.power_level cannot add ops > than own");
|
||||
return Some(false); // cannot add ops greater than own
|
||||
}
|
||||
}
|
||||
@ -456,6 +474,7 @@ fn check_power_levels(
|
||||
}
|
||||
if user != power_event.sender() {
|
||||
if old_level.map(|int| (*int).into()) == Some(user_level) {
|
||||
tracing::info!("m.room.power_level cannot remove ops == to own");
|
||||
return Some(false); // cannot remove ops level == to own
|
||||
}
|
||||
}
|
||||
@ -463,6 +482,7 @@ fn check_power_levels(
|
||||
let old_level_too_big = old_level.map(|int| (*int).into()) > Some(user_level);
|
||||
let new_level_too_big = new_level.map(|int| (*int).into()) > Some(user_level);
|
||||
if old_level_too_big || new_level_too_big {
|
||||
tracing::info!("m.room.power_level failed to add ops > than own");
|
||||
return Some(false); // cannot add ops greater than own
|
||||
}
|
||||
}
|
||||
@ -480,6 +500,7 @@ fn check_power_levels(
|
||||
let old_level_too_big = old_level.map(|int| (*int).into()) > Some(user_level);
|
||||
let new_level_too_big = new_level.map(|int| (*int).into()) > Some(user_level);
|
||||
if old_level_too_big || new_level_too_big {
|
||||
tracing::info!("m.room.power_level failed to add ops > than own");
|
||||
return Some(false); // cannot add ops greater than own
|
||||
}
|
||||
}
|
||||
@ -579,21 +600,30 @@ fn get_send_level(
|
||||
state_key: Option<String>,
|
||||
power_lvl: Option<&StateEvent>,
|
||||
) -> i64 {
|
||||
tracing::debug!("{:?} {:?}", e_type, state_key);
|
||||
if let Some(ple) = power_lvl {
|
||||
if state_key.is_some() {
|
||||
if let Ok(content) =
|
||||
serde_json::from_value::<room::power_levels::PowerLevelsEventContent>(ple.content())
|
||||
{
|
||||
if let Some(_specific_ev) = content.events.get(&e_type) {
|
||||
// this is done differently in synapse the `specific_ev` is set and if `users_default` is
|
||||
// found it is used
|
||||
if let Ok(content) =
|
||||
serde_json::from_value::<room::power_levels::PowerLevelsEventContent>(ple.content())
|
||||
{
|
||||
let mut lvl: i64 = content
|
||||
.events
|
||||
.get(&e_type)
|
||||
.cloned()
|
||||
.unwrap_or(js_int::int!(50))
|
||||
.into();
|
||||
let state_def: i64 = content.state_default.into();
|
||||
let event_def: i64 = content.events_default.into();
|
||||
if state_key.is_some() {
|
||||
if state_def > lvl {
|
||||
lvl = event_def;
|
||||
}
|
||||
content.users_default.into()
|
||||
} else {
|
||||
return 50;
|
||||
}
|
||||
if event_def > lvl {
|
||||
lvl = event_def;
|
||||
}
|
||||
return lvl;
|
||||
} else {
|
||||
return 0;
|
||||
return 50;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
|
41
src/lib.rs
41
src/lib.rs
@ -140,7 +140,13 @@ impl StateResolution {
|
||||
// TODO make sure each conflicting event is in event_map??
|
||||
// synapse says `full_set = {eid for eid in full_conflicted_set if eid in event_map}`
|
||||
all_conflicted.retain(|id| event_map.contains_key(id));
|
||||
|
||||
println!(
|
||||
"ALL {:?}",
|
||||
all_conflicted
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
// get only the power events with a state_key: "" or ban/kick event (sender != state_key)
|
||||
let power_events = all_conflicted
|
||||
.iter()
|
||||
@ -148,7 +154,7 @@ impl StateResolution {
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
tracing::debug!(
|
||||
println!(
|
||||
"POWER {:?}",
|
||||
power_events
|
||||
.iter()
|
||||
@ -165,7 +171,7 @@ impl StateResolution {
|
||||
&all_conflicted,
|
||||
);
|
||||
|
||||
tracing::debug!(
|
||||
println!(
|
||||
"SRTD {:?}",
|
||||
sorted_power_levels
|
||||
.iter()
|
||||
@ -203,7 +209,7 @@ impl StateResolution {
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
tracing::debug!(
|
||||
println!(
|
||||
"LEFT {:?}",
|
||||
events_to_resolve
|
||||
.iter()
|
||||
@ -218,7 +224,7 @@ impl StateResolution {
|
||||
let sorted_left_events =
|
||||
self.mainline_sort(room_id, &events_to_resolve, power_event, &event_map, store);
|
||||
|
||||
tracing::debug!(
|
||||
println!(
|
||||
"SORTED LEFT {:?}",
|
||||
sorted_left_events
|
||||
.iter()
|
||||
@ -324,7 +330,7 @@ impl StateResolution {
|
||||
let mut event_to_pl = BTreeMap::new();
|
||||
for (idx, event_id) in graph.keys().enumerate() {
|
||||
let pl = self.get_power_level_for_sender(room_id, &event_id, event_map, store);
|
||||
tracing::debug!("{} power level {}", event_id.to_string(), pl);
|
||||
println!("{} power level {}", event_id.to_string(), pl);
|
||||
|
||||
event_to_pl.insert(event_id.clone(), pl);
|
||||
|
||||
@ -424,16 +430,17 @@ impl StateResolution {
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
event_id: &EventId,
|
||||
_event_map: &EventMap<StateEvent>, // TODO use event_map over store ??
|
||||
event_map: &EventMap<StateEvent>, // TODO use event_map over store ??
|
||||
store: &dyn StateStore,
|
||||
) -> i64 {
|
||||
tracing::info!("fetch event senders ({}) power level", event_id.to_string());
|
||||
|
||||
let event = event_map.get(event_id);
|
||||
let mut pl = None;
|
||||
// TODO store.auth_event_ids returns "self" with the event ids is this ok
|
||||
// event.auth_event_ids does not include its own event id ?
|
||||
for aid in store.auth_event_ids(room_id, &[event_id.clone()]).unwrap() {
|
||||
if let Ok(aev) = store.get_event(&aid) {
|
||||
for aid in event_map.get(event_id).unwrap().auth_event_ids() {
|
||||
println!("aid {}", aid.to_string());
|
||||
if let Some(aev) = event_map.get(&aid) {
|
||||
if aev.is_type_and_key(EventType::RoomPowerLevels, "") {
|
||||
pl = Some(aev);
|
||||
break;
|
||||
@ -442,8 +449,10 @@ impl StateResolution {
|
||||
}
|
||||
|
||||
if pl.is_none() {
|
||||
for aid in store.auth_event_ids(room_id, &[event_id.clone()]).unwrap() {
|
||||
if let Ok(aev) = store.get_event(&aid) {
|
||||
for aid in event_map.get(event_id).unwrap().auth_event_ids() {
|
||||
println!("aid NONE {}", aid.to_string());
|
||||
|
||||
if let Some(aev) = event_map.get(&aid) {
|
||||
if aev.is_type_and_key(EventType::RoomCreate, "") {
|
||||
if let Ok(content) = aev
|
||||
.deserialize_content::<ruma::events::room::create::CreateEventContent>()
|
||||
@ -467,7 +476,12 @@ impl StateResolution {
|
||||
})
|
||||
.flatten()
|
||||
{
|
||||
content.users_default.into()
|
||||
if let Some(ev) = event {
|
||||
if let Some(user) = content.users.get(ev.sender()) {
|
||||
return (*user).into();
|
||||
}
|
||||
}
|
||||
content.state_default.into()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
@ -510,6 +524,7 @@ impl StateResolution {
|
||||
}
|
||||
}
|
||||
|
||||
tracing::debug!("event to check {:?}", event.event_id().unwrap().to_string());
|
||||
if !event_auth::auth_check(room_version, &event, auth_events)
|
||||
.ok_or("Auth check failed due to deserialization most likely".to_string())
|
||||
.unwrap()
|
||||
|
@ -35,8 +35,8 @@ impl StateEvent {
|
||||
.contains(&content.membership)
|
||||
{
|
||||
return event.sender.as_str()
|
||||
// TODO does None here mean the same as state_key = ""
|
||||
!= event.state_key.as_deref().unwrap_or("");
|
||||
// TODO is None here a failure
|
||||
!= event.state_key.as_deref().unwrap_or("NOT A STATE KEY");
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,32 +44,9 @@ impl StateEvent {
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
Pdu::RoomV3Pdu(event) => event.state_key == Some("".into()),
|
||||
},
|
||||
Self::Sync(any_event) => match any_event {
|
||||
PduStub::RoomV1PduStub(event) => match event.kind {
|
||||
EventType::RoomPowerLevels
|
||||
| EventType::RoomJoinRules
|
||||
| EventType::RoomCreate => event.state_key == Some("".into()),
|
||||
EventType::RoomMember => {
|
||||
if let Ok(content) =
|
||||
serde_json::from_value::<MemberEventContent>(event.content.clone())
|
||||
{
|
||||
if [MembershipState::Leave, MembershipState::Ban]
|
||||
.contains(&content.membership)
|
||||
{
|
||||
return event.sender.as_str()
|
||||
// TODO does None here mean the same as state_key = ""
|
||||
!= event.state_key.as_deref().unwrap_or("");
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
PduStub::RoomV3PduStub(event) => event.state_key == Some("".into()),
|
||||
Pdu::RoomV3Pdu(event) => panic!(),
|
||||
},
|
||||
Self::Sync(any_event) => panic!(),
|
||||
}
|
||||
}
|
||||
pub fn deserialize_content<C: serde::de::DeserializeOwned>(
|
||||
|
@ -286,10 +286,10 @@ fn INITIAL_EDGES() -> Vec<EventId> {
|
||||
fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids: Vec<EventId>) {
|
||||
use itertools::Itertools;
|
||||
|
||||
// to activate logging use `RUST_LOG=debug cargo t`
|
||||
tracer::fmt()
|
||||
.with_env_filter(tracer::EnvFilter::from_default_env())
|
||||
.init();
|
||||
// to activate logging use `RUST_LOG=debug cargo t one_test_only`
|
||||
// tracer::fmt()
|
||||
// .with_env_filter(tracer::EnvFilter::from_default_env())
|
||||
// .init();
|
||||
|
||||
let mut resolver = StateResolution::default();
|
||||
// TODO what do we fill this with, everything ??
|
||||
@ -519,6 +519,59 @@ fn ban_vs_power_level() {
|
||||
}
|
||||
|
||||
// #[test]
|
||||
fn topic_basic() {
|
||||
let events = &[
|
||||
to_init_pdu_event("T1", alice(), EventType::RoomTopic, Some(""), json!({})),
|
||||
to_init_pdu_event(
|
||||
"PA1",
|
||||
alice(),
|
||||
EventType::RoomPowerLevels,
|
||||
Some(""),
|
||||
json!({"users": {alice(): 100, bobo(): 50}}),
|
||||
),
|
||||
to_init_pdu_event("T2", alice(), EventType::RoomTopic, Some(""), json!({})),
|
||||
to_init_pdu_event(
|
||||
"PA2",
|
||||
alice(),
|
||||
EventType::RoomPowerLevels,
|
||||
Some(""),
|
||||
json!({"users": {alice(): 100, bobo(): 0}}),
|
||||
),
|
||||
to_init_pdu_event(
|
||||
"PAB",
|
||||
bobo(),
|
||||
EventType::RoomPowerLevels,
|
||||
Some(""),
|
||||
json!({"users": {alice(): 100, bobo(): 50}}),
|
||||
),
|
||||
to_init_pdu_event("T3", bobo(), EventType::RoomTopic, Some(""), json!({})),
|
||||
];
|
||||
|
||||
let edges = vec![
|
||||
vec!["END", "PA2", "T2", "PA1", "T1", "START"],
|
||||
vec!["END", "T3", "PB", "PA1"],
|
||||
]
|
||||
.into_iter()
|
||||
.map(|list| {
|
||||
list.into_iter()
|
||||
.map(|s| format!("${}:foo", s))
|
||||
.map(EventId::try_from)
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.unwrap()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let expected_state_ids = vec!["PA2", "T2"]
|
||||
.into_iter()
|
||||
.map(|s| format!("${}:foo", s))
|
||||
.map(EventId::try_from)
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.unwrap();
|
||||
|
||||
do_check(events, edges, expected_state_ids)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn topic_reset() {
|
||||
let events = &[
|
||||
to_init_pdu_event("T1", alice(), EventType::RoomTopic, Some(""), json!({})),
|
||||
|
Loading…
x
Reference in New Issue
Block a user