fix: membership deserializing
parent
51aa6448bc
commit
84f4ce73e5
|
@ -877,9 +877,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.92"
|
version = "0.2.93"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714"
|
checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked-hash-map"
|
name = "linked-hash-map"
|
||||||
|
@ -2125,7 +2125,7 @@ checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "state-res"
|
name = "state-res"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/ruma/state-res?rev=af450d0fe2b0e1c890284d0bc3b9d6d4008ac475#af450d0fe2b0e1c890284d0bc3b9d6d4008ac475"
|
source = "git+https://github.com/timokoesters/state-res?rev=1ec42ea2fc0b0728bf027a5899839ad94bb3091b#1ec42ea2fc0b0728bf027a5899839ad94bb3091b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
|
@ -2578,9 +2578,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.4"
|
version = "0.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"matches",
|
"matches",
|
||||||
]
|
]
|
||||||
|
@ -2760,9 +2760,9 @@ checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wildmatch"
|
name = "wildmatch"
|
||||||
version = "2.0.0"
|
version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07ae7ce410f81ba679081aac1d4874f3b1c328535b630209aa5b4cdaaf895e20"
|
checksum = "d6c48bd20df7e4ced539c12f570f937c6b4884928a87fee70a479d72f031d4e0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
|
|
|
@ -23,11 +23,8 @@ ruma = { git = "https://github.com/ruma/ruma", rev = "a310ccc318a4eb51062923d570
|
||||||
#ruma = { path = "../ruma/ruma", features = ["unstable-exhaustive-types", "rand", "client-api", "federation-api", "push-gateway-api", "unstable-pre-spec", "unstable-synapse-quirks"] }
|
#ruma = { path = "../ruma/ruma", features = ["unstable-exhaustive-types", "rand", "client-api", "federation-api", "push-gateway-api", "unstable-pre-spec", "unstable-synapse-quirks"] }
|
||||||
|
|
||||||
# Used when doing state resolution
|
# Used when doing state resolution
|
||||||
state-res = { git = "https://github.com/ruma/state-res", rev = "af450d0fe2b0e1c890284d0bc3b9d6d4008ac475", features = ["unstable-pre-spec"] }
|
state-res = { git = "https://github.com/timokoesters/state-res", rev = "1ec42ea2fc0b0728bf027a5899839ad94bb3091b", features = ["unstable-pre-spec"] }
|
||||||
# TODO: remove the gen-eventid feature
|
#state-res = { path = "../state-res", features = ["unstable-pre-spec"] }
|
||||||
#state-res = { git = "https://github.com/ruma/state-res", branch = "main", features = ["unstable-pre-spec", "gen-eventid"] }
|
|
||||||
#state-res = { git = "https://github.com/ruma/state-res", rev = "1621a491a9e867a1ad4dff9f2f92b0c1e2d44aa0", features = ["unstable-pre-spec", "gen-eventid"] }
|
|
||||||
#state-res = { path = "../state-res", features = ["unstable-pre-spec", "gen-eventid"] }
|
|
||||||
|
|
||||||
# Used for long polling and federation sender, should be the same as rocket::tokio
|
# Used for long polling and federation sender, should be the same as rocket::tokio
|
||||||
tokio = "1.2.0"
|
tokio = "1.2.0"
|
||||||
|
|
|
@ -604,12 +604,16 @@ async fn join_room_by_id_helper(
|
||||||
db.rooms.update_membership(
|
db.rooms.update_membership(
|
||||||
&pdu.room_id,
|
&pdu.room_id,
|
||||||
&target_user_id,
|
&target_user_id,
|
||||||
serde_json::from_value::<member::MemberEventContent>(pdu.content.clone())
|
serde_json::from_value::<member::MembershipState>(
|
||||||
.map_err(|_| {
|
pdu.content
|
||||||
Error::BadRequest(
|
.get("membership")
|
||||||
ErrorKind::InvalidParam,
|
.ok_or_else(|| {
|
||||||
"Invalid member event content.",
|
Error::BadServerResponse("Invalid member event content")
|
||||||
|
})?
|
||||||
|
.clone(),
|
||||||
)
|
)
|
||||||
|
.map_err(|_| {
|
||||||
|
Error::BadServerResponse("Invalid membership state content.")
|
||||||
})?,
|
})?,
|
||||||
&pdu.sender,
|
&pdu.sender,
|
||||||
&db.account_data,
|
&db.account_data,
|
||||||
|
|
|
@ -91,11 +91,25 @@ pub async fn create_room_route(
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// 3. Power levels
|
// 3. Power levels
|
||||||
|
|
||||||
|
// Figure out preset. We need it for preset specific events
|
||||||
|
let preset = body
|
||||||
|
.preset
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| match &body.visibility {
|
||||||
|
room::Visibility::Private => create_room::RoomPreset::PrivateChat,
|
||||||
|
room::Visibility::Public => create_room::RoomPreset::PublicChat,
|
||||||
|
room::Visibility::_Custom(_) => create_room::RoomPreset::PrivateChat, // Room visibility should not be custom
|
||||||
|
});
|
||||||
|
|
||||||
let mut users = BTreeMap::new();
|
let mut users = BTreeMap::new();
|
||||||
users.insert(sender_user.clone(), 100.into());
|
users.insert(sender_user.clone(), 100.into());
|
||||||
|
|
||||||
|
if preset == create_room::RoomPreset::TrustedPrivateChat {
|
||||||
for invite_ in &body.invite {
|
for invite_ in &body.invite {
|
||||||
users.insert(invite_.clone(), 100.into());
|
users.insert(invite_.clone(), 100.into());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let power_levels_content = if let Some(power_levels) = &body.power_level_content_override {
|
let power_levels_content = if let Some(power_levels) = &body.power_level_content_override {
|
||||||
serde_json::from_str(power_levels.json().get()).map_err(|_| {
|
serde_json::from_str(power_levels.json().get()).map_err(|_| {
|
||||||
|
@ -133,16 +147,6 @@ pub async fn create_room_route(
|
||||||
|
|
||||||
// 4. Events set by preset
|
// 4. Events set by preset
|
||||||
|
|
||||||
// Figure out preset. We need it for preset specific events
|
|
||||||
let preset = body
|
|
||||||
.preset
|
|
||||||
.clone()
|
|
||||||
.unwrap_or_else(|| match &body.visibility {
|
|
||||||
room::Visibility::Private => create_room::RoomPreset::PrivateChat,
|
|
||||||
room::Visibility::Public => create_room::RoomPreset::PublicChat,
|
|
||||||
room::Visibility::_Custom(s) => create_room::RoomPreset::_Custom(s.into()),
|
|
||||||
});
|
|
||||||
|
|
||||||
// 4.1 Join Rules
|
// 4.1 Join Rules
|
||||||
db.rooms.build_and_append_pdu(
|
db.rooms.build_and_append_pdu(
|
||||||
PduBuilder {
|
PduBuilder {
|
||||||
|
|
|
@ -108,7 +108,7 @@ impl Database {
|
||||||
pub async fn load_or_create(config: Config) -> Result<Self> {
|
pub async fn load_or_create(config: Config) -> Result<Self> {
|
||||||
let db = sled::Config::default()
|
let db = sled::Config::default()
|
||||||
.path(&config.database_path)
|
.path(&config.database_path)
|
||||||
.cache_capacity(config.cache_capacity as u64)
|
.cache_capacity(config.cache_capacity as usize)
|
||||||
.use_compression(true)
|
.use_compression(true)
|
||||||
.open()?;
|
.open()?;
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,7 @@ pub async fn send_push_notice(
|
||||||
let mut notify = None;
|
let mut notify = None;
|
||||||
let mut tweaks = Vec::new();
|
let mut tweaks = Vec::new();
|
||||||
|
|
||||||
for action in ruleset.get_actions(&pdu.to_sync_state_event(), &ctx) {
|
for action in ruleset.get_actions(&pdu.to_sync_room_event(), &ctx) {
|
||||||
let n = match action {
|
let n = match action {
|
||||||
Action::DontNotify => false,
|
Action::DontNotify => false,
|
||||||
// TODO: Implement proper support for coalesce
|
// TODO: Implement proper support for coalesce
|
||||||
|
|
|
@ -465,7 +465,7 @@ impl Rooms {
|
||||||
/// Returns the pdu.
|
/// Returns the pdu.
|
||||||
///
|
///
|
||||||
/// This does __NOT__ check the outliers `Tree`.
|
/// This does __NOT__ check the outliers `Tree`.
|
||||||
pub fn get_pdu_from_id(&self, pdu_id: &IVec) -> Result<Option<PduEvent>> {
|
pub fn get_pdu_from_id(&self, pdu_id: &[u8]) -> Result<Option<PduEvent>> {
|
||||||
self.pduid_pdu.get(pdu_id)?.map_or(Ok(None), |pdu| {
|
self.pduid_pdu.get(pdu_id)?.map_or(Ok(None), |pdu| {
|
||||||
Ok(Some(
|
Ok(Some(
|
||||||
serde_json::from_slice(&pdu)
|
serde_json::from_slice(&pdu)
|
||||||
|
@ -671,11 +671,21 @@ impl Rooms {
|
||||||
self.update_membership(
|
self.update_membership(
|
||||||
&pdu.room_id,
|
&pdu.room_id,
|
||||||
&target_user_id,
|
&target_user_id,
|
||||||
serde_json::from_value::<member::MemberEventContent>(pdu.content.clone())
|
serde_json::from_value::<member::MembershipState>(
|
||||||
|
pdu.content
|
||||||
|
.get("membership")
|
||||||
|
.ok_or_else(|| {
|
||||||
|
Error::BadRequest(
|
||||||
|
ErrorKind::InvalidParam,
|
||||||
|
"Invalid member event content",
|
||||||
|
)
|
||||||
|
})?
|
||||||
|
.clone(),
|
||||||
|
)
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
Error::BadRequest(
|
Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"Invalid member event content.",
|
"Invalid membership state content.",
|
||||||
)
|
)
|
||||||
})?,
|
})?,
|
||||||
&pdu.sender,
|
&pdu.sender,
|
||||||
|
@ -895,19 +905,14 @@ impl Rooms {
|
||||||
.scan_prefix(&old_shortstatehash)
|
.scan_prefix(&old_shortstatehash)
|
||||||
.filter_map(|pdu| pdu.map_err(|e| error!("{}", e)).ok())
|
.filter_map(|pdu| pdu.map_err(|e| error!("{}", e)).ok())
|
||||||
// Chop the old_shortstatehash out leaving behind the short state key
|
// Chop the old_shortstatehash out leaving behind the short state key
|
||||||
.map(|(k, v)| {
|
.map(|(k, v)| (k[old_shortstatehash.len()..].to_vec(), v))
|
||||||
(
|
.collect::<HashMap<Vec<u8>, IVec>>()
|
||||||
k.subslice(old_shortstatehash.len(), k.len() - old_shortstatehash.len()),
|
|
||||||
v,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect::<HashMap<IVec, IVec>>()
|
|
||||||
} else {
|
} else {
|
||||||
HashMap::new()
|
HashMap::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(state_key) = &new_pdu.state_key {
|
if let Some(state_key) = &new_pdu.state_key {
|
||||||
let mut new_state: HashMap<IVec, IVec> = old_state;
|
let mut new_state: HashMap<Vec<u8>, IVec> = old_state;
|
||||||
|
|
||||||
let mut new_state_key = new_pdu.kind.as_ref().as_bytes().to_vec();
|
let mut new_state_key = new_pdu.kind.as_ref().as_bytes().to_vec();
|
||||||
new_state_key.push(0xff);
|
new_state_key.push(0xff);
|
||||||
|
@ -935,7 +940,7 @@ impl Rooms {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
new_state.insert(shortstatekey.into(), shorteventid.into());
|
new_state.insert(shortstatekey, shorteventid.into());
|
||||||
|
|
||||||
let new_state_hash = self.calculate_hash(
|
let new_state_hash = self.calculate_hash(
|
||||||
&new_state
|
&new_state
|
||||||
|
@ -1377,13 +1382,11 @@ impl Rooms {
|
||||||
&self,
|
&self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
member_content: member::MemberEventContent,
|
membership: member::MembershipState,
|
||||||
sender: &UserId,
|
sender: &UserId,
|
||||||
account_data: &super::account_data::AccountData,
|
account_data: &super::account_data::AccountData,
|
||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let membership = member_content.membership;
|
|
||||||
|
|
||||||
let mut roomserver_id = room_id.as_bytes().to_vec();
|
let mut roomserver_id = room_id.as_bytes().to_vec();
|
||||||
roomserver_id.push(0xff);
|
roomserver_id.push(0xff);
|
||||||
roomserver_id.extend_from_slice(user_id.server_name().as_bytes());
|
roomserver_id.extend_from_slice(user_id.server_name().as_bytes());
|
||||||
|
@ -1633,7 +1636,7 @@ impl Rooms {
|
||||||
&'a self,
|
&'a self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
search_string: &str,
|
search_string: &str,
|
||||||
) -> Result<(impl Iterator<Item = IVec> + 'a, Vec<String>)> {
|
) -> Result<(impl Iterator<Item = Vec<u8>> + 'a, Vec<String>)> {
|
||||||
let mut prefix = room_id.as_bytes().to_vec();
|
let mut prefix = room_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
|
@ -1661,7 +1664,7 @@ impl Rooms {
|
||||||
.0
|
.0
|
||||||
+ 1; // +1 because the pdu id starts AFTER the separator
|
+ 1; // +1 because the pdu id starts AFTER the separator
|
||||||
|
|
||||||
let pdu_id = key.subslice(pduid_index, key.len() - pduid_index);
|
let pdu_id = key[pduid_index..].to_vec();
|
||||||
|
|
||||||
Ok::<_, Error>(pdu_id)
|
Ok::<_, Error>(pdu_id)
|
||||||
})
|
})
|
||||||
|
@ -1700,7 +1703,7 @@ impl Rooms {
|
||||||
.0
|
.0
|
||||||
+ 1; // +1 because the room id starts AFTER the separator
|
+ 1; // +1 because the room id starts AFTER the separator
|
||||||
|
|
||||||
let room_id = key.subslice(roomid_index, key.len() - roomid_index);
|
let room_id = key[roomid_index..].to_vec();
|
||||||
|
|
||||||
Ok::<_, Error>(room_id)
|
Ok::<_, Error>(room_id)
|
||||||
})
|
})
|
||||||
|
|
|
@ -47,7 +47,7 @@ impl Sending {
|
||||||
let mut futures = FuturesUnordered::new();
|
let mut futures = FuturesUnordered::new();
|
||||||
|
|
||||||
// Retry requests we could not finish yet
|
// Retry requests we could not finish yet
|
||||||
let mut current_transactions = HashMap::<OutgoingKind, Vec<IVec>>::new();
|
let mut current_transactions = HashMap::<OutgoingKind, Vec<Vec<u8>>>::new();
|
||||||
|
|
||||||
for (key, outgoing_kind, pdu) in servercurrentpdus
|
for (key, outgoing_kind, pdu) in servercurrentpdus
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -55,7 +55,7 @@ impl Sending {
|
||||||
.filter_map(|(key, _)| {
|
.filter_map(|(key, _)| {
|
||||||
Self::parse_servercurrentpdus(&key)
|
Self::parse_servercurrentpdus(&key)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|(k, p)| (key, k, p))
|
.map(|(k, p)| (key, k, p.to_vec()))
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
if pdu.is_empty() {
|
if pdu.is_empty() {
|
||||||
|
@ -150,7 +150,7 @@ impl Sending {
|
||||||
.keys()
|
.keys()
|
||||||
.filter_map(|r| r.ok())
|
.filter_map(|r| r.ok())
|
||||||
.map(|k| {
|
.map(|k| {
|
||||||
k.subslice(prefix.len(), k.len() - prefix.len())
|
k[prefix.len()..].to_vec()
|
||||||
})
|
})
|
||||||
.take(30)
|
.take(30)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -211,7 +211,11 @@ impl Sending {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
Some(event) = &mut subscriber => {
|
Some(event) = &mut subscriber => {
|
||||||
if let sled::Event::Insert { key, .. } = event {
|
for (_tree, key, value_opt) in &event {
|
||||||
|
if value_opt.is_none() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let servernamepduid = key.clone();
|
let servernamepduid = key.clone();
|
||||||
|
|
||||||
let exponential_backoff = |(tries, instant): &(u32, Instant)| {
|
let exponential_backoff = |(tries, instant): &(u32, Instant)| {
|
||||||
|
@ -265,7 +269,7 @@ impl Sending {
|
||||||
futures.push(
|
futures.push(
|
||||||
Self::handle_event(
|
Self::handle_event(
|
||||||
outgoing_kind,
|
outgoing_kind,
|
||||||
vec![pdu_id],
|
vec![pdu_id.to_vec()],
|
||||||
&db,
|
&db,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -310,7 +314,7 @@ impl Sending {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
fn calculate_hash(keys: &[IVec]) -> Vec<u8> {
|
fn calculate_hash(keys: &[Vec<u8>]) -> Vec<u8> {
|
||||||
// We only hash the pdu's event ids, not the whole pdu
|
// We only hash the pdu's event ids, not the whole pdu
|
||||||
let bytes = keys.join(&0xff);
|
let bytes = keys.join(&0xff);
|
||||||
let hash = digest::digest(&digest::SHA256, &bytes);
|
let hash = digest::digest(&digest::SHA256, &bytes);
|
||||||
|
@ -320,7 +324,7 @@ impl Sending {
|
||||||
#[tracing::instrument(skip(db))]
|
#[tracing::instrument(skip(db))]
|
||||||
async fn handle_event(
|
async fn handle_event(
|
||||||
kind: OutgoingKind,
|
kind: OutgoingKind,
|
||||||
pdu_ids: Vec<IVec>,
|
pdu_ids: Vec<Vec<u8>>,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
) -> std::result::Result<OutgoingKind, (OutgoingKind, Error)> {
|
) -> std::result::Result<OutgoingKind, (OutgoingKind, Error)> {
|
||||||
match &kind {
|
match &kind {
|
||||||
|
|
|
@ -2,7 +2,6 @@ use argon2::{Config, Variant};
|
||||||
use cmp::Ordering;
|
use cmp::Ordering;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use ruma::serde::{try_from_json_map, CanonicalJsonError, CanonicalJsonObject};
|
use ruma::serde::{try_from_json_map, CanonicalJsonError, CanonicalJsonObject};
|
||||||
use sled::IVec;
|
|
||||||
use std::{
|
use std::{
|
||||||
cmp,
|
cmp,
|
||||||
convert::TryInto,
|
convert::TryInto,
|
||||||
|
@ -70,10 +69,10 @@ pub fn calculate_hash(password: &str) -> Result<String, argon2::Error> {
|
||||||
argon2::hash_encoded(password.as_bytes(), salt.as_bytes(), &hashing_config)
|
argon2::hash_encoded(password.as_bytes(), salt.as_bytes(), &hashing_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn common_elements(
|
pub fn common_elements<'a>(
|
||||||
mut iterators: impl Iterator<Item = impl Iterator<Item = IVec>>,
|
mut iterators: impl Iterator<Item = impl Iterator<Item = Vec<u8>>>,
|
||||||
check_order: impl Fn(&IVec, &IVec) -> Ordering,
|
check_order: impl Fn(&[u8], &[u8]) -> Ordering,
|
||||||
) -> Option<impl Iterator<Item = IVec>> {
|
) -> Option<impl Iterator<Item = Vec<u8>>> {
|
||||||
let first_iterator = iterators.next()?;
|
let first_iterator = iterators.next()?;
|
||||||
let mut other_iterators = iterators.map(|i| i.peekable()).collect::<Vec<_>>();
|
let mut other_iterators = iterators.map(|i| i.peekable()).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue