Integrate state-res and rename to ruma-state-res
This commit is contained in:
parent
6609829735
commit
addc67051e
@ -1,30 +0,0 @@
|
|||||||
name: Rust Nightly
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
pull_request:
|
|
||||||
branches: [main]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
name: Check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: nightly
|
|
||||||
profile: minimal
|
|
||||||
override: true
|
|
||||||
components: rustfmt, clippy
|
|
||||||
- name: Check formatting
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: fmt
|
|
||||||
args: -- --check
|
|
||||||
- name: Catch common mistakes
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: clippy
|
|
||||||
args: --all-features --all-targets -- -D warnings
|
|
@ -1,28 +0,0 @@
|
|||||||
name: Rust Stable
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
pull_request:
|
|
||||||
branches: [main]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
name: Check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: stable
|
|
||||||
profile: minimal
|
|
||||||
override: true
|
|
||||||
- name: Run tests
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
- name: Run tests (unstable-pre-spec)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --features unstable-pre-spec
|
|
2
crates/ruma-state-res/.gitignore
vendored
2
crates/ruma-state-res/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
/target
|
|
||||||
Cargo.lock
|
|
@ -1,32 +1,28 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "state-res"
|
name = "ruma-state-res"
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Devin R <devin.ragotzy@gmail.com>"]
|
authors = ["Devin R <devin.ragotzy@gmail.com>"]
|
||||||
edition = "2018"
|
|
||||||
categories = ["api-bindings", "web-programming"]
|
categories = ["api-bindings", "web-programming"]
|
||||||
|
keywords = ["matrix", "chat", "state resolution", "ruma"]
|
||||||
description = "An abstraction for Matrix state resolution."
|
description = "An abstraction for Matrix state resolution."
|
||||||
homepage = "https://www.ruma.io/"
|
homepage = "https://www.ruma.io/"
|
||||||
keywords = ["matrix", "chat", "state resolution", "ruma"]
|
repository = "https://github.com/ruma/ruma"
|
||||||
license = "MIT"
|
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://github.com/ruma/state-res"
|
license = "MIT"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
unstable-pre-spec = ["ruma/unstable-pre-spec"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
itertools = "0.10.0"
|
itertools = "0.10.0"
|
||||||
|
ruma = { version = "0.0.3", path = "../ruma", features = ["events", "signatures"] }
|
||||||
serde = { version = "1.0.118", features = ["derive"] }
|
serde = { version = "1.0.118", features = ["derive"] }
|
||||||
serde_json = "1.0.60"
|
serde_json = "1.0.60"
|
||||||
maplit = "1.0.2"
|
maplit = "1.0.2"
|
||||||
thiserror = "1.0.22"
|
thiserror = "1.0.22"
|
||||||
log = "0.4.11"
|
log = "0.4.11"
|
||||||
|
|
||||||
[features]
|
|
||||||
unstable-pre-spec = ["ruma/unstable-pre-spec"]
|
|
||||||
|
|
||||||
[dependencies.ruma]
|
|
||||||
git = "https://github.com/ruma/ruma"
|
|
||||||
rev = "8c286e78d41770fe431e7304cc2fe23e383793df"
|
|
||||||
features = ["events", "signatures"]
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.3.3"
|
criterion = "0.3.3"
|
||||||
rand = "0.7.3"
|
rand = "0.7.3"
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
Copyright (c) 2020 Devin Ragotzy
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
@ -25,8 +25,8 @@ use ruma::{
|
|||||||
},
|
},
|
||||||
EventId, RoomId, RoomVersionId, UserId,
|
EventId, RoomId, RoomVersionId, UserId,
|
||||||
};
|
};
|
||||||
|
use ruma_state_res::{Error, Event, EventMap, Result, StateMap, StateResolution};
|
||||||
use serde_json::{json, Value as JsonValue};
|
use serde_json::{json, Value as JsonValue};
|
||||||
use state_res::{Error, Event, Result, StateMap, StateResolution};
|
|
||||||
|
|
||||||
static mut SERVER_TIMESTAMP: u64 = 0;
|
static mut SERVER_TIMESTAMP: u64 = 0;
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ fn resolution_shallow_auth_chain(c: &mut Criterion) {
|
|||||||
let (state_at_bob, state_at_charlie, _) = store.set_up();
|
let (state_at_bob, state_at_charlie, _) = store.set_up();
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut ev_map: state_res::EventMap<Arc<StateEvent>> = store.0.clone();
|
let mut ev_map: EventMap<Arc<StateEvent>> = store.0.clone();
|
||||||
let state_sets = vec![state_at_bob.clone(), state_at_charlie.clone()];
|
let state_sets = vec![state_at_bob.clone(), state_at_charlie.clone()];
|
||||||
let _ = match StateResolution::resolve::<StateEvent>(
|
let _ = match StateResolution::resolve::<StateEvent>(
|
||||||
&room_id(),
|
&room_id(),
|
||||||
@ -202,10 +202,7 @@ impl<E: Event> TestStore<E> {
|
|||||||
for ids in event_ids {
|
for ids in event_ids {
|
||||||
// TODO state store `auth_event_ids` returns self in the event ids list
|
// TODO state store `auth_event_ids` returns self in the event ids list
|
||||||
// when an event returns `auth_event_ids` self is not contained
|
// when an event returns `auth_event_ids` self is not contained
|
||||||
let chain = self
|
let chain = self.auth_event_ids(room_id, &ids)?.into_iter().collect::<BTreeSet<_>>();
|
||||||
.auth_event_ids(room_id, &ids)?
|
|
||||||
.into_iter()
|
|
||||||
.collect::<BTreeSet<_>>();
|
|
||||||
chains.push(chain);
|
chains.push(chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,8 +247,7 @@ impl TestStore<StateEvent> {
|
|||||||
&[cre.clone()],
|
&[cre.clone()],
|
||||||
&[cre.clone()],
|
&[cre.clone()],
|
||||||
);
|
);
|
||||||
self.0
|
self.0.insert(alice_mem.event_id().clone(), Arc::clone(&alice_mem));
|
||||||
.insert(alice_mem.event_id().clone(), Arc::clone(&alice_mem));
|
|
||||||
|
|
||||||
let join_rules = to_pdu_event(
|
let join_rules = to_pdu_event(
|
||||||
"IJR",
|
"IJR",
|
||||||
@ -262,8 +258,7 @@ impl TestStore<StateEvent> {
|
|||||||
&[cre.clone(), alice_mem.event_id().clone()],
|
&[cre.clone(), alice_mem.event_id().clone()],
|
||||||
&[alice_mem.event_id().clone()],
|
&[alice_mem.event_id().clone()],
|
||||||
);
|
);
|
||||||
self.0
|
self.0.insert(join_rules.event_id().clone(), join_rules.clone());
|
||||||
.insert(join_rules.event_id().clone(), join_rules.clone());
|
|
||||||
|
|
||||||
// Bob and Charlie join at the same time, so there is a fork
|
// Bob and Charlie join at the same time, so there is a fork
|
||||||
// this will be represented in the state_sets when we resolve
|
// this will be represented in the state_sets when we resolve
|
||||||
@ -287,8 +282,7 @@ impl TestStore<StateEvent> {
|
|||||||
&[cre, join_rules.event_id().clone()],
|
&[cre, join_rules.event_id().clone()],
|
||||||
&[join_rules.event_id().clone()],
|
&[join_rules.event_id().clone()],
|
||||||
);
|
);
|
||||||
self.0
|
self.0.insert(charlie_mem.event_id().clone(), charlie_mem.clone());
|
||||||
.insert(charlie_mem.event_id().clone(), charlie_mem.clone());
|
|
||||||
|
|
||||||
let state_at_bob = [&create_event, &alice_mem, &join_rules, &bob_mem]
|
let state_at_bob = [&create_event, &alice_mem, &join_rules, &bob_mem]
|
||||||
.iter()
|
.iter()
|
||||||
@ -300,16 +294,10 @@ impl TestStore<StateEvent> {
|
|||||||
.map(|e| ((e.kind(), e.state_key().unwrap()), e.event_id().clone()))
|
.map(|e| ((e.kind(), e.state_key().unwrap()), e.event_id().clone()))
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let expected = [
|
let expected = [&create_event, &alice_mem, &join_rules, &bob_mem, &charlie_mem]
|
||||||
&create_event,
|
.iter()
|
||||||
&alice_mem,
|
.map(|e| ((e.kind(), e.state_key().unwrap()), e.event_id().clone()))
|
||||||
&join_rules,
|
.collect::<StateMap<_>>();
|
||||||
&bob_mem,
|
|
||||||
&charlie_mem,
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.map(|e| ((e.kind(), e.state_key().unwrap()), e.event_id().clone()))
|
|
||||||
.collect::<StateMap<_>>();
|
|
||||||
|
|
||||||
(state_at_bob, state_at_charlie, expected)
|
(state_at_bob, state_at_charlie, expected)
|
||||||
}
|
}
|
||||||
@ -379,21 +367,9 @@ where
|
|||||||
SERVER_TIMESTAMP += 1;
|
SERVER_TIMESTAMP += 1;
|
||||||
ts
|
ts
|
||||||
};
|
};
|
||||||
let id = if id.contains('$') {
|
let id = if id.contains('$') { id.to_string() } else { format!("${}:foo", id) };
|
||||||
id.to_string()
|
let auth_events = auth_events.iter().map(AsRef::as_ref).map(event_id).collect::<Vec<_>>();
|
||||||
} else {
|
let prev_events = prev_events.iter().map(AsRef::as_ref).map(event_id).collect::<Vec<_>>();
|
||||||
format!("${}:foo", id)
|
|
||||||
};
|
|
||||||
let auth_events = auth_events
|
|
||||||
.iter()
|
|
||||||
.map(AsRef::as_ref)
|
|
||||||
.map(event_id)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let prev_events = prev_events
|
|
||||||
.iter()
|
|
||||||
.map(AsRef::as_ref)
|
|
||||||
.map(event_id)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let state_key = state_key.map(ToString::to_string);
|
let state_key = state_key.map(ToString::to_string);
|
||||||
Arc::new(StateEvent {
|
Arc::new(StateEvent {
|
||||||
@ -557,11 +533,10 @@ pub mod event {
|
|||||||
},
|
},
|
||||||
EventId, RoomId, RoomVersionId, ServerName, ServerSigningKeyId, UInt, UserId,
|
EventId, RoomId, RoomVersionId, ServerName, ServerSigningKeyId, UInt, UserId,
|
||||||
};
|
};
|
||||||
|
use ruma_state_res::Event;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
|
|
||||||
use state_res::Event;
|
|
||||||
|
|
||||||
impl Event for StateEvent {
|
impl Event for StateEvent {
|
||||||
fn event_id(&self) -> &EventId {
|
fn event_id(&self) -> &EventId {
|
||||||
self.event_id()
|
self.event_id()
|
||||||
@ -632,10 +607,7 @@ pub mod event {
|
|||||||
id: EventId,
|
id: EventId,
|
||||||
json: serde_json::Value,
|
json: serde_json::Value,
|
||||||
) -> Result<Self, serde_json::Error> {
|
) -> Result<Self, serde_json::Error> {
|
||||||
Ok(Self {
|
Ok(Self { event_id: id, rest: Pdu::RoomV3Pdu(serde_json::from_value(json)?) })
|
||||||
event_id: id,
|
|
||||||
rest: Pdu::RoomV3Pdu(serde_json::from_value(json)?),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_id_canon_obj(
|
pub fn from_id_canon_obj(
|
||||||
|
@ -1 +0,0 @@
|
|||||||
imports_granularity="Crate"
|
|
@ -169,10 +169,7 @@ pub fn auth_check<E: Event>(
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// 3. If event does not have m.room.create in auth_events reject
|
// 3. If event does not have m.room.create in auth_events reject
|
||||||
if auth_events
|
if auth_events.get(&(EventType::RoomCreate, "".to_string())).is_none() {
|
||||||
.get(&(EventType::RoomCreate, "".to_string()))
|
|
||||||
.is_none()
|
|
||||||
{
|
|
||||||
log::warn!("no m.room.create event in auth chain");
|
log::warn!("no m.room.create event in auth chain");
|
||||||
|
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
@ -275,11 +272,12 @@ pub fn auth_check<E: Event>(
|
|||||||
log::info!("power levels event allowed");
|
log::info!("power levels event allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Room version 3: Redaction events are always accepted (provided the event is allowed by `events` and
|
// Room version 3: Redaction events are always accepted (provided the event is allowed by
|
||||||
// `events_default` in the power levels). However, servers should not apply or send redaction's
|
// `events` and `events_default` in the power levels). However, servers should not apply or
|
||||||
// to clients until both the redaction event and original event have been seen, and are valid.
|
// send redaction's to clients until both the redaction event and original event have been
|
||||||
// Servers should only apply redaction's to events where the sender's domains match,
|
// seen, and are valid. Servers should only apply redaction's to events where the sender's
|
||||||
// or the sender of the redaction has the appropriate permissions per the power levels.
|
// domains match, or the sender of the redaction has the appropriate permissions per the
|
||||||
|
// power levels.
|
||||||
|
|
||||||
if room_version.extra_redaction_checks
|
if room_version.extra_redaction_checks
|
||||||
&& incoming_event.kind() == EventType::RoomRedaction
|
&& incoming_event.kind() == EventType::RoomRedaction
|
||||||
@ -310,10 +308,7 @@ pub fn valid_membership_change<E: Event>(
|
|||||||
auth_events: &StateMap<Arc<E>>,
|
auth_events: &StateMap<Arc<E>>,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
let target_membership = serde_json::from_value::<MembershipState>(
|
let target_membership = serde_json::from_value::<MembershipState>(
|
||||||
content
|
content.get("membership").expect("we should test before that this field exists").clone(),
|
||||||
.get("membership")
|
|
||||||
.expect("we should test before that this field exists")
|
|
||||||
.clone(),
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let third_party_invite = content
|
let third_party_invite = content
|
||||||
@ -327,10 +322,7 @@ pub fn valid_membership_change<E: Event>(
|
|||||||
let sender = auth_events.get(&key);
|
let sender = auth_events.get(&key);
|
||||||
let sender_membership = sender.map_or(Ok::<_, Error>(MembershipState::Leave), |pdu| {
|
let sender_membership = sender.map_or(Ok::<_, Error>(MembershipState::Leave), |pdu| {
|
||||||
Ok(serde_json::from_value::<MembershipState>(
|
Ok(serde_json::from_value::<MembershipState>(
|
||||||
pdu.content()
|
pdu.content().get("membership").expect("we assume existing events are valid").clone(),
|
||||||
.get("membership")
|
|
||||||
.expect("we assume existing events are valid")
|
|
||||||
.clone(),
|
|
||||||
)?)
|
)?)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@ -339,10 +331,7 @@ pub fn valid_membership_change<E: Event>(
|
|||||||
|
|
||||||
let current_membership = current.map_or(Ok::<_, Error>(MembershipState::Leave), |pdu| {
|
let current_membership = current.map_or(Ok::<_, Error>(MembershipState::Leave), |pdu| {
|
||||||
Ok(serde_json::from_value::<MembershipState>(
|
Ok(serde_json::from_value::<MembershipState>(
|
||||||
pdu.content()
|
pdu.content().get("membership").expect("we assume existing events are valid").clone(),
|
||||||
.get("membership")
|
|
||||||
.expect("we assume existing events are valid")
|
|
||||||
.clone(),
|
|
||||||
)?)
|
)?)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@ -436,9 +425,7 @@ pub fn valid_membership_change<E: Event>(
|
|||||||
);
|
);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
let allow = sender_power
|
let allow = sender_power.filter(|&p| p >= &power_levels.invite).is_some();
|
||||||
.filter(|&p| p >= &power_levels.invite)
|
|
||||||
.is_some();
|
|
||||||
if !allow {
|
if !allow {
|
||||||
warn!("User does not have enough power to invite");
|
warn!("User does not have enough power to invite");
|
||||||
}
|
}
|
||||||
@ -521,10 +508,7 @@ pub fn can_send_event<E: Event>(event: &Arc<E>, auth_events: &StateMap<Arc<E>>)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if event
|
if event.state_key().as_ref().map_or(false, |k| k.starts_with('@'))
|
||||||
.state_key()
|
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |k| k.starts_with('@'))
|
|
||||||
&& event.state_key().as_deref() != Some(event.sender().as_str())
|
&& event.state_key().as_deref() != Some(event.sender().as_str())
|
||||||
{
|
{
|
||||||
return false; // permission required to post in this room
|
return false; // permission required to post in this room
|
||||||
@ -539,9 +523,7 @@ pub fn check_power_levels<E: Event>(
|
|||||||
power_event: &Arc<E>,
|
power_event: &Arc<E>,
|
||||||
auth_events: &StateMap<Arc<E>>,
|
auth_events: &StateMap<Arc<E>>,
|
||||||
) -> Option<bool> {
|
) -> Option<bool> {
|
||||||
let power_event_state_key = power_event
|
let power_event_state_key = power_event.state_key().expect("power events have state keys");
|
||||||
.state_key()
|
|
||||||
.expect("power events have state keys");
|
|
||||||
let key = (power_event.kind(), power_event_state_key);
|
let key = (power_event.kind(), power_event_state_key);
|
||||||
let current_state = if let Some(current_state) = auth_events.get(&key) {
|
let current_state = if let Some(current_state) = auth_events.get(&key) {
|
||||||
current_state
|
current_state
|
||||||
@ -647,15 +629,8 @@ pub fn check_power_levels<E: Event>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let levels = [
|
let levels =
|
||||||
"users_default",
|
["users_default", "events_default", "state_default", "ban", "redact", "kick", "invite"];
|
||||||
"events_default",
|
|
||||||
"state_default",
|
|
||||||
"ban",
|
|
||||||
"redact",
|
|
||||||
"kick",
|
|
||||||
"invite",
|
|
||||||
];
|
|
||||||
let old_state = serde_json::to_value(old_state).unwrap();
|
let old_state = serde_json::to_value(old_state).unwrap();
|
||||||
let new_state = serde_json::to_value(new_state).unwrap();
|
let new_state = serde_json::to_value(new_state).unwrap();
|
||||||
for lvl_name in &levels {
|
for lvl_name in &levels {
|
||||||
@ -701,10 +676,7 @@ pub fn check_redaction<E: Event>(
|
|||||||
// If the domain of the event_id of the event being redacted is the same as the
|
// If the domain of the event_id of the event being redacted is the same as the
|
||||||
// domain of the event_id of the m.room.redaction, allow
|
// domain of the event_id of the m.room.redaction, allow
|
||||||
if redaction_event.event_id().server_name()
|
if redaction_event.event_id().server_name()
|
||||||
== redaction_event
|
== redaction_event.redacts().as_ref().and_then(|id| id.server_name())
|
||||||
.redacts()
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|id| id.server_name())
|
|
||||||
{
|
{
|
||||||
log::info!("redaction event allowed via room version 1 rules");
|
log::info!("redaction event allowed via room version 1 rules");
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
@ -863,7 +835,8 @@ pub fn verify_third_party_invite<E: Event>(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any signature in signed matches any public key in the m.room.third_party_invite event, allow
|
// If any signature in signed matches any public key in the m.room.third_party_invite event,
|
||||||
|
// allow
|
||||||
if let Ok(tpid_ev) = serde_json::from_value::<
|
if let Ok(tpid_ev) = serde_json::from_value::<
|
||||||
ruma::events::room::third_party_invite::ThirdPartyInviteEventContent,
|
ruma::events::room::third_party_invite::ThirdPartyInviteEventContent,
|
||||||
>(current_tpid.content())
|
>(current_tpid.content())
|
||||||
|
@ -45,7 +45,8 @@ impl StateResolution {
|
|||||||
/// * `state_sets` - The incoming state to resolve. Each `StateMap` represents a possible fork
|
/// * `state_sets` - The incoming state to resolve. Each `StateMap` represents a possible fork
|
||||||
/// in the state of a room.
|
/// in the state of a room.
|
||||||
///
|
///
|
||||||
/// * `auth_events` - The full recursive set of `auth_events` for each event in the `state_sets`.
|
/// * `auth_events` - The full recursive set of `auth_events` for each event in the
|
||||||
|
/// `state_sets`.
|
||||||
///
|
///
|
||||||
/// * `event_map` - The `EventMap` acts as a local cache of state, any event that is not found
|
/// * `event_map` - The `EventMap` acts as a local cache of state, any event that is not found
|
||||||
/// in the `event_map` will cause an unrecoverable `Error` in `resolve`.
|
/// in the `event_map` will cause an unrecoverable `Error` in `resolve`.
|
||||||
@ -77,11 +78,8 @@ impl StateResolution {
|
|||||||
|
|
||||||
// add the auth_diff to conflicting now we have a full set of conflicting events
|
// add the auth_diff to conflicting now we have a full set of conflicting events
|
||||||
auth_diff.extend(conflicting.values().cloned().flatten());
|
auth_diff.extend(conflicting.values().cloned().flatten());
|
||||||
let mut all_conflicted = auth_diff
|
let mut all_conflicted =
|
||||||
.into_iter()
|
auth_diff.into_iter().collect::<BTreeSet<_>>().into_iter().collect::<Vec<_>>();
|
||||||
.collect::<BTreeSet<_>>()
|
|
||||||
.into_iter()
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
log::info!("full conflicted set is {} events", all_conflicted.len());
|
log::info!("full conflicted set is {} events", all_conflicted.len());
|
||||||
|
|
||||||
@ -122,10 +120,7 @@ impl StateResolution {
|
|||||||
|
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"AUTHED {:?}",
|
"AUTHED {:?}",
|
||||||
resolved_control
|
resolved_control.iter().map(|(key, id)| (key, id.to_string())).collect::<Vec<_>>()
|
||||||
.iter()
|
|
||||||
.map(|(key, id)| (key, id.to_string()))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// At this point the control_events have been resolved we now have to
|
// At this point the control_events have been resolved we now have to
|
||||||
@ -133,7 +128,8 @@ impl StateResolution {
|
|||||||
sorted_control_levels.dedup();
|
sorted_control_levels.dedup();
|
||||||
let deduped_power_ev = sorted_control_levels;
|
let deduped_power_ev = sorted_control_levels;
|
||||||
|
|
||||||
// This removes the control events that passed auth and more importantly those that failed auth
|
// This removes the control events that passed auth and more importantly those that failed
|
||||||
|
// auth
|
||||||
let events_to_resolve = all_conflicted
|
let events_to_resolve = all_conflicted
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|id| !deduped_power_ev.contains(id))
|
.filter(|id| !deduped_power_ev.contains(id))
|
||||||
@ -142,10 +138,7 @@ impl StateResolution {
|
|||||||
|
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"LEFT {:?}",
|
"LEFT {:?}",
|
||||||
events_to_resolve
|
events_to_resolve.iter().map(ToString::to_string).collect::<Vec<_>>()
|
||||||
.iter()
|
|
||||||
.map(ToString::to_string)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// This "epochs" power level event
|
// This "epochs" power level event
|
||||||
@ -158,10 +151,7 @@ impl StateResolution {
|
|||||||
|
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"SORTED LEFT {:?}",
|
"SORTED LEFT {:?}",
|
||||||
sorted_left_events
|
sorted_left_events.iter().map(ToString::to_string).collect::<Vec<_>>()
|
||||||
.iter()
|
|
||||||
.map(ToString::to_string)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut resolved_state = StateResolution::iterative_auth_check(
|
let mut resolved_state = StateResolution::iterative_auth_check(
|
||||||
@ -189,20 +179,14 @@ impl StateResolution {
|
|||||||
) -> (StateMap<EventId>, StateMap<Vec<EventId>>) {
|
) -> (StateMap<EventId>, StateMap<Vec<EventId>>) {
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
log::info!(
|
log::info!("seperating {} sets of events into conflicted/unconflicted", state_sets.len());
|
||||||
"seperating {} sets of events into conflicted/unconflicted",
|
|
||||||
state_sets.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut unconflicted_state = StateMap::new();
|
let mut unconflicted_state = StateMap::new();
|
||||||
let mut conflicted_state = StateMap::new();
|
let mut conflicted_state = StateMap::new();
|
||||||
|
|
||||||
for key in state_sets.iter().flat_map(|map| map.keys()).dedup() {
|
for key in state_sets.iter().flat_map(|map| map.keys()).dedup() {
|
||||||
let mut event_ids = state_sets
|
let mut event_ids =
|
||||||
.iter()
|
state_sets.iter().map(|state_set| state_set.get(key)).dedup().collect::<Vec<_>>();
|
||||||
.map(|state_set| state_set.get(key))
|
|
||||||
.dedup()
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
if event_ids.len() == 1 {
|
if event_ids.len() == 1 {
|
||||||
if let Some(Some(id)) = event_ids.pop() {
|
if let Some(Some(id)) = event_ids.pop() {
|
||||||
@ -241,12 +225,7 @@ impl StateResolution {
|
|||||||
let rest = chains.iter().skip(1).flatten().cloned().collect();
|
let rest = chains.iter().skip(1).flatten().cloned().collect();
|
||||||
let common = chain.intersection(&rest).collect::<Vec<_>>();
|
let common = chain.intersection(&rest).collect::<Vec<_>>();
|
||||||
|
|
||||||
Ok(chains
|
Ok(chains.into_iter().flatten().filter(|id| !common.contains(&id)).dedup().collect())
|
||||||
.into_iter()
|
|
||||||
.flatten()
|
|
||||||
.filter(|id| !common.contains(&id))
|
|
||||||
.dedup()
|
|
||||||
.collect())
|
|
||||||
} else {
|
} else {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
@ -326,10 +305,8 @@ impl StateResolution {
|
|||||||
// TODO make the BTreeSet conversion cleaner ??
|
// TODO make the BTreeSet conversion cleaner ??
|
||||||
// outdegree_map is an event referring to the events before it, the
|
// outdegree_map is an event referring to the events before it, the
|
||||||
// more outdegree's the more recent the event.
|
// more outdegree's the more recent the event.
|
||||||
let mut outdegree_map: BTreeMap<EventId, BTreeSet<EventId>> = graph
|
let mut outdegree_map: BTreeMap<EventId, BTreeSet<EventId>> =
|
||||||
.iter()
|
graph.iter().map(|(k, v)| (k.clone(), v.iter().cloned().collect())).collect();
|
||||||
.map(|(k, v)| (k.clone(), v.iter().cloned().collect()))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// The number of events that depend on the given event (the eventId key)
|
// The number of events that depend on the given event (the eventId key)
|
||||||
let mut reverse_graph = BTreeMap::new();
|
let mut reverse_graph = BTreeMap::new();
|
||||||
@ -346,10 +323,7 @@ impl StateResolution {
|
|||||||
|
|
||||||
reverse_graph.entry(node).or_insert(btreeset![]);
|
reverse_graph.entry(node).or_insert(btreeset![]);
|
||||||
for edge in edges {
|
for edge in edges {
|
||||||
reverse_graph
|
reverse_graph.entry(edge).or_insert(btreeset![]).insert(node);
|
||||||
.entry(edge)
|
|
||||||
.or_insert(btreeset![])
|
|
||||||
.insert(node);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,11 +365,7 @@ impl StateResolution {
|
|||||||
|
|
||||||
// TODO store.auth_event_ids returns "self" with the event ids is this ok
|
// 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 ?
|
// event.auth_event_ids does not include its own event id ?
|
||||||
for aid in event
|
for aid in event.as_ref().map(|pdu| pdu.auth_events()).unwrap_or_default() {
|
||||||
.as_ref()
|
|
||||||
.map(|pdu| pdu.auth_events())
|
|
||||||
.unwrap_or_default()
|
|
||||||
{
|
|
||||||
if let Ok(aev) = StateResolution::get_or_load_event(room_id, &aid, event_map) {
|
if let Ok(aev) = StateResolution::get_or_load_event(room_id, &aid, event_map) {
|
||||||
if is_type_and_key(&aev, EventType::RoomPowerLevels, "") {
|
if is_type_and_key(&aev, EventType::RoomPowerLevels, "") {
|
||||||
pl = Some(aev);
|
pl = Some(aev);
|
||||||
@ -444,10 +414,7 @@ impl StateResolution {
|
|||||||
|
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"performing auth checks on {:?}",
|
"performing auth checks on {:?}",
|
||||||
events_to_check
|
events_to_check.iter().map(ToString::to_string).collect::<Vec<_>>()
|
||||||
.iter()
|
|
||||||
.map(ToString::to_string)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut resolved_state = unconflicted_state.clone();
|
let mut resolved_state = unconflicted_state.clone();
|
||||||
@ -461,7 +428,8 @@ impl StateResolution {
|
|||||||
let mut auth_events = BTreeMap::new();
|
let mut auth_events = BTreeMap::new();
|
||||||
for aid in &event.auth_events() {
|
for aid in &event.auth_events() {
|
||||||
if let Ok(ev) = StateResolution::get_or_load_event(room_id, aid, event_map) {
|
if let Ok(ev) = StateResolution::get_or_load_event(room_id, aid, event_map) {
|
||||||
// TODO synapse check "rejected_reason", I'm guessing this is redacted_because in ruma ??
|
// TODO synapse check "rejected_reason", I'm guessing this is redacted_because
|
||||||
|
// in ruma ??
|
||||||
auth_events.insert(
|
auth_events.insert(
|
||||||
(
|
(
|
||||||
ev.kind(),
|
ev.kind(),
|
||||||
@ -499,8 +467,8 @@ impl StateResolution {
|
|||||||
.filter_map(|id| StateResolution::get_or_load_event(room_id, id, event_map).ok())
|
.filter_map(|id| StateResolution::get_or_load_event(room_id, id, event_map).ok())
|
||||||
.next_back();
|
.next_back();
|
||||||
|
|
||||||
// The key for this is (eventType + a state_key of the signed token not sender) so search
|
// The key for this is (eventType + a state_key of the signed token not sender) so
|
||||||
// for it
|
// search for it
|
||||||
let current_third_party = auth_events.iter().find_map(|(_, pdu)| {
|
let current_third_party = auth_events.iter().find_map(|(_, pdu)| {
|
||||||
if pdu.kind() == EventType::RoomThirdPartyInvite {
|
if pdu.kind() == EventType::RoomThirdPartyInvite {
|
||||||
Some(pdu.clone()) // TODO no clone, auth_events is borrowed while moved
|
Some(pdu.clone()) // TODO no clone, auth_events is borrowed while moved
|
||||||
@ -520,10 +488,7 @@ impl StateResolution {
|
|||||||
resolved_state.insert((event.kind(), state_key), event_id.clone());
|
resolved_state.insert((event.kind(), state_key), event_id.clone());
|
||||||
} else {
|
} else {
|
||||||
// synapse passes here on AuthError. We do not add this event to resolved_state.
|
// synapse passes here on AuthError. We do not add this event to resolved_state.
|
||||||
log::warn!(
|
log::warn!("event {} failed the authentication check", event_id.to_string());
|
||||||
"event {} failed the authentication check",
|
|
||||||
event_id.to_string()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: if these functions are ever made async here
|
// TODO: if these functions are ever made async here
|
||||||
@ -658,9 +623,8 @@ impl StateResolution {
|
|||||||
graph.entry(eid.clone()).or_insert_with(Vec::new);
|
graph.entry(eid.clone()).or_insert_with(Vec::new);
|
||||||
// prefer the store to event as the store filters dedups the events
|
// prefer the store to event as the store filters dedups the events
|
||||||
// otherwise it seems we can loop forever
|
// otherwise it seems we can loop forever
|
||||||
for aid in &StateResolution::get_or_load_event(room_id, &eid, event_map)
|
for aid in
|
||||||
.unwrap()
|
&StateResolution::get_or_load_event(room_id, &eid, event_map).unwrap().auth_events()
|
||||||
.auth_events()
|
|
||||||
{
|
{
|
||||||
if auth_diff.contains(aid) {
|
if auth_diff.contains(aid) {
|
||||||
if !graph.contains_key(aid) {
|
if !graph.contains_key(aid) {
|
||||||
|
@ -65,12 +65,7 @@ impl RoomVersion {
|
|||||||
RoomVersionId::Version4 => Self::version_4(),
|
RoomVersionId::Version4 => Self::version_4(),
|
||||||
RoomVersionId::Version5 => Self::version_5(),
|
RoomVersionId::Version5 => Self::version_5(),
|
||||||
RoomVersionId::Version6 => Self::version_6(),
|
RoomVersionId::Version6 => Self::version_6(),
|
||||||
ver => {
|
ver => return Err(Error::Unsupported(format!("found version `{}`", ver.as_str()))),
|
||||||
return Err(Error::Unsupported(format!(
|
|
||||||
"found version `{}`",
|
|
||||||
ver.as_str()
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use state_res::{event_auth::valid_membership_change, StateMap};
|
use ruma_state_res::{event_auth::valid_membership_change, StateMap};
|
||||||
// use state_res::event_auth:::{
|
// use ruma_state_res::event_auth:::{
|
||||||
// auth_check, auth_types_for_event, can_federate, check_power_levels, check_redaction,
|
// auth_check, auth_types_for_event, can_federate, check_power_levels, check_redaction,
|
||||||
// };
|
// };
|
||||||
|
|
||||||
@ -12,10 +12,7 @@ use utils::{alice, charlie, event_id, member_content_ban, to_pdu_event, INITIAL_
|
|||||||
fn test_ban_pass() {
|
fn test_ban_pass() {
|
||||||
let events = INITIAL_EVENTS();
|
let events = INITIAL_EVENTS();
|
||||||
|
|
||||||
let prev = events
|
let prev = events.values().find(|ev| ev.event_id().as_str().contains("IMC")).map(Arc::clone);
|
||||||
.values()
|
|
||||||
.find(|ev| ev.event_id().as_str().contains("IMC"))
|
|
||||||
.map(Arc::clone);
|
|
||||||
|
|
||||||
let auth_events = events
|
let auth_events = events
|
||||||
.values()
|
.values()
|
||||||
@ -47,10 +44,7 @@ fn test_ban_pass() {
|
|||||||
fn test_ban_fail() {
|
fn test_ban_fail() {
|
||||||
let events = INITIAL_EVENTS();
|
let events = INITIAL_EVENTS();
|
||||||
|
|
||||||
let prev = events
|
let prev = events.values().find(|ev| ev.event_id().as_str().contains("IMC")).map(Arc::clone);
|
||||||
.values()
|
|
||||||
.find(|ev| ev.event_id().as_str().contains("IMC"))
|
|
||||||
.map(Arc::clone);
|
|
||||||
|
|
||||||
let auth_events = events
|
let auth_events = events
|
||||||
.values()
|
.values()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use ruma::{events::EventType, EventId};
|
use ruma::{events::EventType, EventId};
|
||||||
use state_res::{is_power_event, room_version::RoomVersion, StateMap};
|
use ruma_state_res::{is_power_event, room_version::RoomVersion, StateMap, StateResolution};
|
||||||
|
|
||||||
mod utils;
|
mod utils;
|
||||||
use utils::{room_id, INITIAL_EVENTS};
|
use utils::{room_id, INITIAL_EVENTS};
|
||||||
@ -35,7 +35,7 @@ fn test_event_sort() {
|
|||||||
// This is a TODO in conduit
|
// This is a TODO in conduit
|
||||||
// TODO these events are not guaranteed to be sorted but they are resolved, do
|
// TODO these events are not guaranteed to be sorted but they are resolved, do
|
||||||
// we need the auth_chain
|
// we need the auth_chain
|
||||||
let sorted_power_events = state_res::StateResolution::reverse_topological_power_sort(
|
let sorted_power_events = StateResolution::reverse_topological_power_sort(
|
||||||
&room_id(),
|
&room_id(),
|
||||||
&power_events,
|
&power_events,
|
||||||
&mut events,
|
&mut events,
|
||||||
@ -44,7 +44,7 @@ fn test_event_sort() {
|
|||||||
|
|
||||||
// This is a TODO in conduit
|
// This is a TODO in conduit
|
||||||
// TODO we may be able to skip this since they are resolved according to spec
|
// TODO we may be able to skip this since they are resolved according to spec
|
||||||
let resolved_power = state_res::StateResolution::iterative_auth_check(
|
let resolved_power = StateResolution::iterative_auth_check(
|
||||||
&room_id(),
|
&room_id(),
|
||||||
&RoomVersion::version_6(),
|
&RoomVersion::version_6(),
|
||||||
&sorted_power_events,
|
&sorted_power_events,
|
||||||
@ -60,12 +60,8 @@ fn test_event_sort() {
|
|||||||
|
|
||||||
let power_level = resolved_power.get(&(EventType::RoomPowerLevels, "".to_string()));
|
let power_level = resolved_power.get(&(EventType::RoomPowerLevels, "".to_string()));
|
||||||
|
|
||||||
let sorted_event_ids = state_res::StateResolution::mainline_sort(
|
let sorted_event_ids =
|
||||||
&room_id(),
|
StateResolution::mainline_sort(&room_id(), &events_to_sort, power_level, &mut events);
|
||||||
&events_to_sort,
|
|
||||||
power_level,
|
|
||||||
&mut events,
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
@ -78,10 +74,7 @@ fn test_event_sort() {
|
|||||||
"$START:foo",
|
"$START:foo",
|
||||||
"$END:foo"
|
"$END:foo"
|
||||||
],
|
],
|
||||||
sorted_event_ids
|
sorted_event_ids.iter().map(|id| id.to_string()).collect::<Vec<_>>()
|
||||||
.iter()
|
|
||||||
.map(|id| id.to_string())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
use std::{collections::BTreeMap, sync::Arc};
|
use std::{collections::BTreeMap, sync::Arc};
|
||||||
|
|
||||||
use ruma::{events::EventType, EventId, RoomVersionId};
|
use ruma::{events::EventType, EventId, RoomVersionId};
|
||||||
|
use ruma_state_res::{EventMap, StateMap, StateResolution};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use state_res::{EventMap, StateMap, StateResolution};
|
|
||||||
|
|
||||||
mod utils;
|
mod utils;
|
||||||
use utils::{
|
use utils::{
|
||||||
@ -21,16 +21,9 @@ fn ban_with_auth_chains() {
|
|||||||
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let expected_state_ids = vec!["PA", "MB"]
|
let expected_state_ids = vec!["PA", "MB"].into_iter().map(event_id).collect::<Vec<_>>();
|
||||||
.into_iter()
|
|
||||||
.map(event_id)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
do_check(
|
do_check(&ban.values().cloned().collect::<Vec<_>>(), edges, expected_state_ids);
|
||||||
&ban.values().cloned().collect::<Vec<_>>(),
|
|
||||||
edges,
|
|
||||||
expected_state_ids,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -96,23 +89,12 @@ fn ban_with_auth_chains2() {
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
);
|
);
|
||||||
|
|
||||||
let expected = vec![
|
let expected =
|
||||||
"$CREATE:foo",
|
vec!["$CREATE:foo", "$IJR:foo", "$PA:foo", "$IMA:foo", "$IMB:foo", "$IMC:foo", "$MB:foo"];
|
||||||
"$IJR:foo",
|
|
||||||
"$PA:foo",
|
|
||||||
"$IMA:foo",
|
|
||||||
"$IMB:foo",
|
|
||||||
"$IMC:foo",
|
|
||||||
"$MB:foo",
|
|
||||||
];
|
|
||||||
|
|
||||||
for id in expected.iter().map(|i| event_id(i)) {
|
for id in expected.iter().map(|i| event_id(i)) {
|
||||||
// make sure our resolved events are equal to the expected list
|
// make sure our resolved events are equal to the expected list
|
||||||
assert!(
|
assert!(resolved.values().any(|eid| eid == &id) || init.contains_key(&id), "{}", id)
|
||||||
resolved.values().any(|eid| eid == &id) || init.contains_key(&id),
|
|
||||||
"{}",
|
|
||||||
id
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
assert_eq!(expected.len(), resolved.len())
|
assert_eq!(expected.len(), resolved.len())
|
||||||
}
|
}
|
||||||
@ -128,11 +110,7 @@ fn join_rule_with_auth_chain() {
|
|||||||
|
|
||||||
let expected_state_ids = vec!["JR"].into_iter().map(event_id).collect::<Vec<_>>();
|
let expected_state_ids = vec!["JR"].into_iter().map(event_id).collect::<Vec<_>>();
|
||||||
|
|
||||||
do_check(
|
do_check(&join_rule.values().cloned().collect::<Vec<_>>(), edges, expected_state_ids);
|
||||||
&join_rule.values().cloned().collect::<Vec<_>>(),
|
|
||||||
edges,
|
|
||||||
expected_state_ids,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
@ -5,8 +5,8 @@ use ruma::{
|
|||||||
events::{room::join_rules::JoinRule, EventType},
|
events::{room::join_rules::JoinRule, EventType},
|
||||||
EventId, RoomVersionId,
|
EventId, RoomVersionId,
|
||||||
};
|
};
|
||||||
|
use ruma_state_res::{EventMap, StateMap, StateResolution};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use state_res::{StateMap, StateResolution};
|
|
||||||
use tracing_subscriber as tracer;
|
use tracing_subscriber as tracer;
|
||||||
|
|
||||||
mod utils;
|
mod utils;
|
||||||
@ -48,19 +48,13 @@ fn ban_vs_power_level() {
|
|||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
let edges = vec![
|
let edges = vec![vec!["END", "MB", "MA", "PA", "START"], vec!["END", "PA", "PB"]]
|
||||||
vec!["END", "MB", "MA", "PA", "START"],
|
|
||||||
vec!["END", "PA", "PB"],
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let expected_state_ids = vec!["PA", "MA", "MB"]
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(event_id)
|
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let expected_state_ids = vec!["PA", "MA", "MB"].into_iter().map(event_id).collect::<Vec<_>>();
|
||||||
|
|
||||||
do_check(events, edges, expected_state_ids)
|
do_check(events, edges, expected_state_ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,18 +87,13 @@ fn topic_basic() {
|
|||||||
to_init_pdu_event("T3", bob(), EventType::RoomTopic, Some(""), json!({})),
|
to_init_pdu_event("T3", bob(), EventType::RoomTopic, Some(""), json!({})),
|
||||||
];
|
];
|
||||||
|
|
||||||
let edges = vec![
|
let edges =
|
||||||
vec!["END", "PA2", "T2", "PA1", "T1", "START"],
|
vec![vec!["END", "PA2", "T2", "PA1", "T1", "START"], vec!["END", "T3", "PB", "PA1"]]
|
||||||
vec!["END", "T3", "PB", "PA1"],
|
.into_iter()
|
||||||
]
|
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
||||||
.into_iter()
|
.collect::<Vec<_>>();
|
||||||
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let expected_state_ids = vec!["PA2", "T2"]
|
let expected_state_ids = vec!["PA2", "T2"].into_iter().map(event_id).collect::<Vec<_>>();
|
||||||
.into_iter()
|
|
||||||
.map(event_id)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
do_check(events, edges, expected_state_ids)
|
do_check(events, edges, expected_state_ids)
|
||||||
}
|
}
|
||||||
@ -130,19 +119,13 @@ fn topic_reset() {
|
|||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
let edges = vec![
|
let edges = vec![vec!["END", "MB", "T2", "PA", "T1", "START"], vec!["END", "T1"]]
|
||||||
vec!["END", "MB", "T2", "PA", "T1", "START"],
|
|
||||||
vec!["END", "T1"],
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let expected_state_ids = vec!["T1", "MB", "PA"]
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(event_id)
|
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let expected_state_ids = vec!["T1", "MB", "PA"].into_iter().map(event_id).collect::<Vec<_>>();
|
||||||
|
|
||||||
do_check(events, edges, expected_state_ids)
|
do_check(events, edges, expected_state_ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,10 +233,7 @@ fn topic_setting() {
|
|||||||
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let expected_state_ids = vec!["T4", "PA2"]
|
let expected_state_ids = vec!["T4", "PA2"].into_iter().map(event_id).collect::<Vec<_>>();
|
||||||
.into_iter()
|
|
||||||
.map(event_id)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
do_check(events, edges, expected_state_ids)
|
do_check(events, edges, expected_state_ids)
|
||||||
}
|
}
|
||||||
@ -265,7 +245,7 @@ fn test_event_map_none() {
|
|||||||
// build up the DAG
|
// build up the DAG
|
||||||
let (state_at_bob, state_at_charlie, expected) = store.set_up();
|
let (state_at_bob, state_at_charlie, expected) = store.set_up();
|
||||||
|
|
||||||
let mut ev_map: state_res::EventMap<Arc<StateEvent>> = store.0.clone();
|
let mut ev_map: EventMap<Arc<StateEvent>> = store.0.clone();
|
||||||
let state_sets = vec![state_at_bob, state_at_charlie];
|
let state_sets = vec![state_at_bob, state_at_charlie];
|
||||||
let resolved = match StateResolution::resolve::<StateEvent>(
|
let resolved = match StateResolution::resolve::<StateEvent>(
|
||||||
&room_id(),
|
&room_id(),
|
||||||
@ -317,9 +297,7 @@ impl TestStore<StateEvent> {
|
|||||||
pub fn set_up(&mut self) -> (StateMap<EventId>, StateMap<EventId>, StateMap<EventId>) {
|
pub fn set_up(&mut self) -> (StateMap<EventId>, StateMap<EventId>, StateMap<EventId>) {
|
||||||
// to activate logging use `RUST_LOG=debug cargo t one_test_only`
|
// to activate logging use `RUST_LOG=debug cargo t one_test_only`
|
||||||
let _ = LOGGER.call_once(|| {
|
let _ = LOGGER.call_once(|| {
|
||||||
tracer::fmt()
|
tracer::fmt().with_env_filter(tracer::EnvFilter::from_default_env()).init()
|
||||||
.with_env_filter(tracer::EnvFilter::from_default_env())
|
|
||||||
.init()
|
|
||||||
});
|
});
|
||||||
let create_event = to_pdu_event::<EventId>(
|
let create_event = to_pdu_event::<EventId>(
|
||||||
"CREATE",
|
"CREATE",
|
||||||
@ -342,8 +320,7 @@ impl TestStore<StateEvent> {
|
|||||||
&[cre.clone()],
|
&[cre.clone()],
|
||||||
&[cre.clone()],
|
&[cre.clone()],
|
||||||
);
|
);
|
||||||
self.0
|
self.0.insert(alice_mem.event_id().clone(), Arc::clone(&alice_mem));
|
||||||
.insert(alice_mem.event_id().clone(), Arc::clone(&alice_mem));
|
|
||||||
|
|
||||||
let join_rules = to_pdu_event(
|
let join_rules = to_pdu_event(
|
||||||
"IJR",
|
"IJR",
|
||||||
@ -354,8 +331,7 @@ impl TestStore<StateEvent> {
|
|||||||
&[cre.clone(), alice_mem.event_id().clone()],
|
&[cre.clone(), alice_mem.event_id().clone()],
|
||||||
&[alice_mem.event_id().clone()],
|
&[alice_mem.event_id().clone()],
|
||||||
);
|
);
|
||||||
self.0
|
self.0.insert(join_rules.event_id().clone(), join_rules.clone());
|
||||||
.insert(join_rules.event_id().clone(), join_rules.clone());
|
|
||||||
|
|
||||||
// Bob and Charlie join at the same time, so there is a fork
|
// Bob and Charlie join at the same time, so there is a fork
|
||||||
// this will be represented in the state_sets when we resolve
|
// this will be represented in the state_sets when we resolve
|
||||||
@ -379,8 +355,7 @@ impl TestStore<StateEvent> {
|
|||||||
&[cre, join_rules.event_id().clone()],
|
&[cre, join_rules.event_id().clone()],
|
||||||
&[join_rules.event_id().clone()],
|
&[join_rules.event_id().clone()],
|
||||||
);
|
);
|
||||||
self.0
|
self.0.insert(charlie_mem.event_id().clone(), charlie_mem.clone());
|
||||||
.insert(charlie_mem.event_id().clone(), charlie_mem.clone());
|
|
||||||
|
|
||||||
let state_at_bob = [&create_event, &alice_mem, &join_rules, &bob_mem]
|
let state_at_bob = [&create_event, &alice_mem, &join_rules, &bob_mem]
|
||||||
.iter()
|
.iter()
|
||||||
@ -392,16 +367,10 @@ impl TestStore<StateEvent> {
|
|||||||
.map(|e| ((e.kind(), e.state_key()), e.event_id().clone()))
|
.map(|e| ((e.kind(), e.state_key()), e.event_id().clone()))
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let expected = [
|
let expected = [&create_event, &alice_mem, &join_rules, &bob_mem, &charlie_mem]
|
||||||
&create_event,
|
.iter()
|
||||||
&alice_mem,
|
.map(|e| ((e.kind(), e.state_key()), e.event_id().clone()))
|
||||||
&join_rules,
|
.collect::<StateMap<_>>();
|
||||||
&bob_mem,
|
|
||||||
&charlie_mem,
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.map(|e| ((e.kind(), e.state_key()), e.event_id().clone()))
|
|
||||||
.collect::<StateMap<_>>();
|
|
||||||
|
|
||||||
(state_at_bob, state_at_charlie, expected)
|
(state_at_bob, state_at_charlie, expected)
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ use ruma::{
|
|||||||
},
|
},
|
||||||
EventId, RoomId, RoomVersionId, UserId,
|
EventId, RoomId, RoomVersionId, UserId,
|
||||||
};
|
};
|
||||||
|
use ruma_state_res::{auth_types_for_event, Error, Event, Result, StateMap, StateResolution};
|
||||||
use serde_json::{json, Value as JsonValue};
|
use serde_json::{json, Value as JsonValue};
|
||||||
use state_res::{Error, Event, Result, StateMap, StateResolution};
|
|
||||||
use tracing_subscriber as tracer;
|
use tracing_subscriber as tracer;
|
||||||
|
|
||||||
pub use event::StateEvent;
|
pub use event::StateEvent;
|
||||||
@ -35,20 +35,13 @@ pub fn do_check(
|
|||||||
expected_state_ids: Vec<EventId>,
|
expected_state_ids: Vec<EventId>,
|
||||||
) {
|
) {
|
||||||
// to activate logging use `RUST_LOG=debug cargo t`
|
// to activate logging use `RUST_LOG=debug cargo t`
|
||||||
let _ = LOGGER.call_once(|| {
|
let _ = LOGGER
|
||||||
tracer::fmt()
|
.call_once(|| tracer::fmt().with_env_filter(tracer::EnvFilter::from_default_env()).init());
|
||||||
.with_env_filter(tracer::EnvFilter::from_default_env())
|
|
||||||
.init()
|
|
||||||
});
|
|
||||||
|
|
||||||
let init_events = INITIAL_EVENTS();
|
let init_events = INITIAL_EVENTS();
|
||||||
|
|
||||||
let mut store = TestStore(
|
let mut store = TestStore(
|
||||||
init_events
|
init_events.values().chain(events).map(|ev| (ev.event_id().clone(), ev.clone())).collect(),
|
||||||
.values()
|
|
||||||
.chain(events)
|
|
||||||
.map(|ev| (ev.event_id().clone(), ev.clone()))
|
|
||||||
.collect(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// This will be lexi_topo_sorted for resolution
|
// This will be lexi_topo_sorted for resolution
|
||||||
@ -140,7 +133,7 @@ pub fn do_check(
|
|||||||
let key = fake_event.state_key();
|
let key = fake_event.state_key();
|
||||||
state_after.insert((ty, key), event_id.clone());
|
state_after.insert((ty, key), event_id.clone());
|
||||||
|
|
||||||
let auth_types = state_res::auth_types_for_event(
|
let auth_types = auth_types_for_event(
|
||||||
&fake_event.kind(),
|
&fake_event.kind(),
|
||||||
fake_event.sender(),
|
fake_event.sender(),
|
||||||
Some(fake_event.state_key()),
|
Some(fake_event.state_key()),
|
||||||
@ -181,10 +174,7 @@ pub fn do_check(
|
|||||||
let ev = event_map.get(&node).expect(&format!(
|
let ev = event_map.get(&node).expect(&format!(
|
||||||
"{} not found in {:?}",
|
"{} not found in {:?}",
|
||||||
node.to_string(),
|
node.to_string(),
|
||||||
event_map
|
event_map.keys().map(ToString::to_string).collect::<Vec<_>>(),
|
||||||
.keys()
|
|
||||||
.map(ToString::to_string)
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
));
|
));
|
||||||
|
|
||||||
let key = (ev.kind(), ev.state_key());
|
let key = (ev.kind(), ev.state_key());
|
||||||
@ -265,10 +255,7 @@ impl<E: Event> TestStore<E> {
|
|||||||
for ids in event_ids {
|
for ids in event_ids {
|
||||||
// TODO state store `auth_event_ids` returns self in the event ids list
|
// TODO state store `auth_event_ids` returns self in the event ids list
|
||||||
// when an event returns `auth_event_ids` self is not contained
|
// when an event returns `auth_event_ids` self is not contained
|
||||||
let chain = self
|
let chain = self.auth_event_ids(room_id, &ids)?.into_iter().collect::<BTreeSet<_>>();
|
||||||
.auth_event_ids(room_id, &ids)?
|
|
||||||
.into_iter()
|
|
||||||
.collect::<BTreeSet<_>>();
|
|
||||||
chains.push(chain);
|
chains.push(chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,12 +263,7 @@ impl<E: Event> TestStore<E> {
|
|||||||
let rest = chains.iter().skip(1).flatten().cloned().collect();
|
let rest = chains.iter().skip(1).flatten().cloned().collect();
|
||||||
let common = chain.intersection(&rest).collect::<Vec<_>>();
|
let common = chain.intersection(&rest).collect::<Vec<_>>();
|
||||||
|
|
||||||
Ok(chains
|
Ok(chains.into_iter().flatten().filter(|id| !common.contains(&id)).dedup().collect())
|
||||||
.into_iter()
|
|
||||||
.flatten()
|
|
||||||
.filter(|id| !common.contains(&id))
|
|
||||||
.dedup()
|
|
||||||
.collect())
|
|
||||||
} else {
|
} else {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
@ -350,11 +332,7 @@ pub fn to_init_pdu_event(
|
|||||||
SERVER_TIMESTAMP += 1;
|
SERVER_TIMESTAMP += 1;
|
||||||
ts
|
ts
|
||||||
};
|
};
|
||||||
let id = if id.contains('$') {
|
let id = if id.contains('$') { id.to_string() } else { format!("${}:foo", id) };
|
||||||
id.to_string()
|
|
||||||
} else {
|
|
||||||
format!("${}:foo", id)
|
|
||||||
};
|
|
||||||
|
|
||||||
let state_key = state_key.map(ToString::to_string);
|
let state_key = state_key.map(ToString::to_string);
|
||||||
Arc::new(StateEvent {
|
Arc::new(StateEvent {
|
||||||
@ -397,21 +375,9 @@ where
|
|||||||
SERVER_TIMESTAMP += 1;
|
SERVER_TIMESTAMP += 1;
|
||||||
ts
|
ts
|
||||||
};
|
};
|
||||||
let id = if id.contains('$') {
|
let id = if id.contains('$') { id.to_string() } else { format!("${}:foo", id) };
|
||||||
id.to_string()
|
let auth_events = auth_events.iter().map(AsRef::as_ref).map(event_id).collect::<Vec<_>>();
|
||||||
} else {
|
let prev_events = prev_events.iter().map(AsRef::as_ref).map(event_id).collect::<Vec<_>>();
|
||||||
format!("${}:foo", id)
|
|
||||||
};
|
|
||||||
let auth_events = auth_events
|
|
||||||
.iter()
|
|
||||||
.map(AsRef::as_ref)
|
|
||||||
.map(event_id)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let prev_events = prev_events
|
|
||||||
.iter()
|
|
||||||
.map(AsRef::as_ref)
|
|
||||||
.map(event_id)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let state_key = state_key.map(ToString::to_string);
|
let state_key = state_key.map(ToString::to_string);
|
||||||
Arc::new(StateEvent {
|
Arc::new(StateEvent {
|
||||||
@ -440,11 +406,8 @@ where
|
|||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn INITIAL_EVENTS() -> BTreeMap<EventId, Arc<StateEvent>> {
|
pub fn INITIAL_EVENTS() -> BTreeMap<EventId, Arc<StateEvent>> {
|
||||||
// this is always called so we can init the logger here
|
// this is always called so we can init the logger here
|
||||||
let _ = LOGGER.call_once(|| {
|
let _ = LOGGER
|
||||||
tracer::fmt()
|
.call_once(|| tracer::fmt().with_env_filter(tracer::EnvFilter::from_default_env()).init());
|
||||||
.with_env_filter(tracer::EnvFilter::from_default_env())
|
|
||||||
.init()
|
|
||||||
});
|
|
||||||
|
|
||||||
vec![
|
vec![
|
||||||
to_pdu_event::<EventId>(
|
to_pdu_event::<EventId>(
|
||||||
@ -544,11 +507,10 @@ pub mod event {
|
|||||||
},
|
},
|
||||||
EventId, RoomId, RoomVersionId, ServerName, UInt, UserId,
|
EventId, RoomId, RoomVersionId, ServerName, UInt, UserId,
|
||||||
};
|
};
|
||||||
|
use ruma_state_res::Event;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
|
|
||||||
use state_res::Event;
|
|
||||||
|
|
||||||
impl Event for StateEvent {
|
impl Event for StateEvent {
|
||||||
fn event_id(&self) -> &EventId {
|
fn event_id(&self) -> &EventId {
|
||||||
self.event_id()
|
self.event_id()
|
||||||
@ -612,10 +574,7 @@ pub mod event {
|
|||||||
id: EventId,
|
id: EventId,
|
||||||
json: serde_json::Value,
|
json: serde_json::Value,
|
||||||
) -> Result<Self, serde_json::Error> {
|
) -> Result<Self, serde_json::Error> {
|
||||||
Ok(Self {
|
Ok(Self { event_id: id, rest: Pdu::RoomV3Pdu(serde_json::from_value(json)?) })
|
||||||
event_id: id,
|
|
||||||
rest: Pdu::RoomV3Pdu(serde_json::from_value(json)?),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_id_canon_obj(
|
pub fn from_id_canon_obj(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user