Merge branch 'sliding' into 'next'
Very basic Element X support and fixes See merge request famedly/conduit!501
This commit is contained in:
commit
ad06d475de
14 changed files with 422 additions and 164 deletions
63
Cargo.lock
generated
63
Cargo.lock
generated
|
@ -422,6 +422,12 @@ version = "0.9.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913"
|
||||
|
||||
[[package]]
|
||||
name = "const_panic"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
|
@ -1167,7 +1173,6 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
|||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.3",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1178,6 +1183,7 @@ checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
|||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.0",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1212,9 +1218,9 @@ checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
|
|||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
@ -1283,25 +1289,30 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "konst"
|
||||
version = "0.2.19"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "330f0e13e6483b8c34885f7e6c9f19b1a7bd449c673fbb948a51c99d66ef74f4"
|
||||
checksum = "1d9a8bb6c7c71d151b25936b03e012a4c00daea99e3a3797c6ead66b0a0d55e2"
|
||||
dependencies = [
|
||||
"konst_macro_rules",
|
||||
"const_panic",
|
||||
"konst_kernel",
|
||||
"konst_proc_macros",
|
||||
"typewit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "konst_macro_rules"
|
||||
version = "0.2.19"
|
||||
name = "konst_kernel"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37"
|
||||
checksum = "55d2ab266022e7309df89ed712bddc753e3a3c395c3ced1bb2e4470ec2a8146d"
|
||||
dependencies = [
|
||||
"typewit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "konst_proc_macros"
|
||||
version = "0.2.11"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "984e109462d46ad18314f10e392c286c3d47bce203088a09012de1015b45b737"
|
||||
checksum = "4e28ab1dc35e09d60c2b8c90d12a9a8d9666c876c10a3739a3196db0103b6043"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
|
@ -2111,7 +2122,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/ruma/ruma?rev=38294bd5206498c02b1001227d65654eb548308b#38294bd5206498c02b1001227d65654eb548308b"
|
||||
source = "git+https://github.com/ruma/ruma?rev=07bc06038fded40d4e9180637f056d256f9a1fbc#07bc06038fded40d4e9180637f056d256f9a1fbc"
|
||||
dependencies = [
|
||||
"assign",
|
||||
"js_int",
|
||||
|
@ -2129,7 +2140,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-appservice-api"
|
||||
version = "0.8.1"
|
||||
source = "git+https://github.com/ruma/ruma?rev=38294bd5206498c02b1001227d65654eb548308b#38294bd5206498c02b1001227d65654eb548308b"
|
||||
source = "git+https://github.com/ruma/ruma?rev=07bc06038fded40d4e9180637f056d256f9a1fbc#07bc06038fded40d4e9180637f056d256f9a1fbc"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
|
@ -2140,7 +2151,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-client-api"
|
||||
version = "0.16.2"
|
||||
source = "git+https://github.com/ruma/ruma?rev=38294bd5206498c02b1001227d65654eb548308b#38294bd5206498c02b1001227d65654eb548308b"
|
||||
source = "git+https://github.com/ruma/ruma?rev=07bc06038fded40d4e9180637f056d256f9a1fbc#07bc06038fded40d4e9180637f056d256f9a1fbc"
|
||||
dependencies = [
|
||||
"assign",
|
||||
"bytes",
|
||||
|
@ -2157,13 +2168,13 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-common"
|
||||
version = "0.11.3"
|
||||
source = "git+https://github.com/ruma/ruma?rev=38294bd5206498c02b1001227d65654eb548308b#38294bd5206498c02b1001227d65654eb548308b"
|
||||
source = "git+https://github.com/ruma/ruma?rev=07bc06038fded40d4e9180637f056d256f9a1fbc#07bc06038fded40d4e9180637f056d256f9a1fbc"
|
||||
dependencies = [
|
||||
"base64 0.21.2",
|
||||
"bytes",
|
||||
"form_urlencoded",
|
||||
"http",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.0.0",
|
||||
"js_int",
|
||||
"js_option",
|
||||
"konst",
|
||||
|
@ -2185,7 +2196,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-federation-api"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/ruma/ruma?rev=38294bd5206498c02b1001227d65654eb548308b#38294bd5206498c02b1001227d65654eb548308b"
|
||||
source = "git+https://github.com/ruma/ruma?rev=07bc06038fded40d4e9180637f056d256f9a1fbc#07bc06038fded40d4e9180637f056d256f9a1fbc"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
|
@ -2196,7 +2207,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-identifiers-validation"
|
||||
version = "0.9.1"
|
||||
source = "git+https://github.com/ruma/ruma?rev=38294bd5206498c02b1001227d65654eb548308b#38294bd5206498c02b1001227d65654eb548308b"
|
||||
source = "git+https://github.com/ruma/ruma?rev=07bc06038fded40d4e9180637f056d256f9a1fbc#07bc06038fded40d4e9180637f056d256f9a1fbc"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"thiserror",
|
||||
|
@ -2205,7 +2216,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-identity-service-api"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/ruma/ruma?rev=38294bd5206498c02b1001227d65654eb548308b#38294bd5206498c02b1001227d65654eb548308b"
|
||||
source = "git+https://github.com/ruma/ruma?rev=07bc06038fded40d4e9180637f056d256f9a1fbc#07bc06038fded40d4e9180637f056d256f9a1fbc"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
|
@ -2215,7 +2226,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-macros"
|
||||
version = "0.11.3"
|
||||
source = "git+https://github.com/ruma/ruma?rev=38294bd5206498c02b1001227d65654eb548308b#38294bd5206498c02b1001227d65654eb548308b"
|
||||
source = "git+https://github.com/ruma/ruma?rev=07bc06038fded40d4e9180637f056d256f9a1fbc#07bc06038fded40d4e9180637f056d256f9a1fbc"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro-crate",
|
||||
|
@ -2230,7 +2241,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-push-gateway-api"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/ruma/ruma?rev=38294bd5206498c02b1001227d65654eb548308b#38294bd5206498c02b1001227d65654eb548308b"
|
||||
source = "git+https://github.com/ruma/ruma?rev=07bc06038fded40d4e9180637f056d256f9a1fbc#07bc06038fded40d4e9180637f056d256f9a1fbc"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
|
@ -2241,7 +2252,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-signatures"
|
||||
version = "0.13.1"
|
||||
source = "git+https://github.com/ruma/ruma?rev=38294bd5206498c02b1001227d65654eb548308b#38294bd5206498c02b1001227d65654eb548308b"
|
||||
source = "git+https://github.com/ruma/ruma?rev=07bc06038fded40d4e9180637f056d256f9a1fbc#07bc06038fded40d4e9180637f056d256f9a1fbc"
|
||||
dependencies = [
|
||||
"base64 0.21.2",
|
||||
"ed25519-dalek",
|
||||
|
@ -2257,7 +2268,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-state-res"
|
||||
version = "0.9.1"
|
||||
source = "git+https://github.com/ruma/ruma?rev=38294bd5206498c02b1001227d65654eb548308b#38294bd5206498c02b1001227d65654eb548308b"
|
||||
source = "git+https://github.com/ruma/ruma?rev=07bc06038fded40d4e9180637f056d256f9a1fbc#07bc06038fded40d4e9180637f056d256f9a1fbc"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"js_int",
|
||||
|
@ -3152,6 +3163,12 @@ version = "1.16.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||
|
||||
[[package]]
|
||||
name = "typewit"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4061a10d4d8f3081a8ccc025182afd8434302d8d4b4503ec6d8510d09df08c2d"
|
||||
|
||||
[[package]]
|
||||
name = "uncased"
|
||||
version = "0.9.9"
|
||||
|
|
|
@ -26,9 +26,9 @@ tower-http = { version = "0.4.1", features = ["add-extension", "cors", "sensitiv
|
|||
|
||||
# Used for matrix spec type definitions and helpers
|
||||
#ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
||||
ruma = { git = "https://github.com/ruma/ruma", rev = "38294bd5206498c02b1001227d65654eb548308b", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] }
|
||||
#ruma = { git = "https://github.com/timokoesters/ruma", rev = "50c1db7e0a3a21fc794b0cce3b64285a4c750c71", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
||||
#ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
||||
ruma = { git = "https://github.com/ruma/ruma", rev = "07bc06038fded40d4e9180637f056d256f9a1fbc", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] }
|
||||
#ruma = { git = "https://github.com/timokoesters/ruma", rev = "4ec9c69bb7e09391add2382b3ebac97b6e8f4c64", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] }
|
||||
#ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] }
|
||||
|
||||
# Async runtime and utilities
|
||||
tokio = { version = "1.28.1", features = ["fs", "macros", "signal", "sync"] }
|
||||
|
|
|
@ -68,7 +68,7 @@ Thanks to the contributors to Conduit and all libraries we use, for example:
|
|||
If you run into any question, feel free to
|
||||
- Ask us in `#conduit:fachschaften.org` on Matrix
|
||||
- Write an E-Mail to `conduit@koesters.xyz`
|
||||
- Send an direct message to `timo@fachschaften.org` on Matrix
|
||||
- Send an direct message to `timokoesters@fachschaften.org` on Matrix
|
||||
- [Open an issue on GitLab](https://gitlab.com/famedly/conduit/-/issues/new)
|
||||
|
||||
#### Donate
|
||||
|
|
|
@ -203,17 +203,7 @@ pub(crate) async fn get_public_rooms_filtered_helper(
|
|||
Error::bad_database("Invalid canonical alias event in database.")
|
||||
})
|
||||
})?,
|
||||
name: services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
.room_state_get(&room_id, &StateEventType::RoomName, "")?
|
||||
.map_or(Ok(None), |s| {
|
||||
serde_json::from_str(s.content.get())
|
||||
.map(|c: RoomNameEventContent| c.name)
|
||||
.map_err(|_| {
|
||||
Error::bad_database("Invalid room name event in database.")
|
||||
})
|
||||
})?,
|
||||
name: services().rooms.state_accessor.get_name(&room_id)?,
|
||||
num_joined_members: services()
|
||||
.rooms
|
||||
.state_cache
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::{service::rooms::timeline::PduCount, services, Error, Result, Ruma, RumaResponse};
|
||||
use crate::{
|
||||
service::rooms::timeline::PduCount, services, Error, PduEvent, Result, Ruma, RumaResponse,
|
||||
};
|
||||
use ruma::{
|
||||
api::client::{
|
||||
filter::{FilterDefinition, LazyLoadOptions},
|
||||
|
@ -8,6 +10,7 @@ use ruma::{
|
|||
Ephemeral, Filter, GlobalAccountData, InviteState, InvitedRoom, JoinedRoom,
|
||||
LeftRoom, Presence, RoomAccountData, RoomSummary, Rooms, State, Timeline, ToDevice,
|
||||
},
|
||||
v4::SlidingOp,
|
||||
DeviceLists, UnreadNotificationsCount,
|
||||
},
|
||||
uiaa::UiaaResponse,
|
||||
|
@ -17,7 +20,7 @@ use ruma::{
|
|||
StateEventType, TimelineEventType,
|
||||
},
|
||||
serde::Raw,
|
||||
DeviceId, OwnedDeviceId, OwnedUserId, RoomId, UserId,
|
||||
uint, DeviceId, OwnedDeviceId, OwnedUserId, RoomId, UInt, UserId,
|
||||
};
|
||||
use std::{
|
||||
collections::{hash_map::Entry, BTreeMap, HashMap, HashSet},
|
||||
|
@ -199,7 +202,7 @@ async fn sync_helper(
|
|||
let mut joined_rooms = BTreeMap::new();
|
||||
let since = body
|
||||
.since
|
||||
.clone()
|
||||
.as_ref()
|
||||
.and_then(|string| string.parse().ok())
|
||||
.unwrap_or(0);
|
||||
let sincecount = PduCount::Normal(since);
|
||||
|
@ -581,43 +584,7 @@ async fn load_joined_room(
|
|||
drop(insert_lock);
|
||||
}
|
||||
|
||||
let timeline_pdus;
|
||||
let limited;
|
||||
if services()
|
||||
.rooms
|
||||
.timeline
|
||||
.last_timeline_count(&sender_user, &room_id)?
|
||||
> sincecount
|
||||
{
|
||||
let mut non_timeline_pdus = services()
|
||||
.rooms
|
||||
.timeline
|
||||
.pdus_until(&sender_user, &room_id, PduCount::max())?
|
||||
.filter_map(|r| {
|
||||
// Filter out buggy events
|
||||
if r.is_err() {
|
||||
error!("Bad pdu in pdus_since: {:?}", r);
|
||||
}
|
||||
r.ok()
|
||||
})
|
||||
.take_while(|(pducount, _)| pducount > &sincecount);
|
||||
|
||||
// Take the last 10 events for the timeline
|
||||
timeline_pdus = non_timeline_pdus
|
||||
.by_ref()
|
||||
.take(10)
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.rev()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// They /sync response doesn't always return all messages, so we say the output is
|
||||
// limited unless there are events in non_timeline_pdus
|
||||
limited = non_timeline_pdus.next().is_some();
|
||||
} else {
|
||||
timeline_pdus = Vec::new();
|
||||
limited = false;
|
||||
}
|
||||
let (timeline_pdus, limited) = load_timeline(sender_user, room_id, sincecount, 10)?;
|
||||
|
||||
let send_notification_counts = !timeline_pdus.is_empty()
|
||||
|| services()
|
||||
|
@ -1132,6 +1099,52 @@ async fn load_joined_room(
|
|||
})
|
||||
}
|
||||
|
||||
fn load_timeline(
|
||||
sender_user: &UserId,
|
||||
room_id: &RoomId,
|
||||
sincecount: PduCount,
|
||||
limit: u64,
|
||||
) -> Result<(Vec<(PduCount, PduEvent)>, bool), Error> {
|
||||
let timeline_pdus;
|
||||
let limited;
|
||||
if services()
|
||||
.rooms
|
||||
.timeline
|
||||
.last_timeline_count(&sender_user, &room_id)?
|
||||
> sincecount
|
||||
{
|
||||
let mut non_timeline_pdus = services()
|
||||
.rooms
|
||||
.timeline
|
||||
.pdus_until(&sender_user, &room_id, PduCount::max())?
|
||||
.filter_map(|r| {
|
||||
// Filter out buggy events
|
||||
if r.is_err() {
|
||||
error!("Bad pdu in pdus_since: {:?}", r);
|
||||
}
|
||||
r.ok()
|
||||
})
|
||||
.take_while(|(pducount, _)| pducount > &sincecount);
|
||||
|
||||
// Take the last events for the timeline
|
||||
timeline_pdus = non_timeline_pdus
|
||||
.by_ref()
|
||||
.take(limit as usize)
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.rev()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// They /sync response doesn't always return all messages, so we say the output is
|
||||
// limited unless there are events in non_timeline_pdus
|
||||
limited = non_timeline_pdus.next().is_some();
|
||||
} else {
|
||||
timeline_pdus = Vec::new();
|
||||
limited = false;
|
||||
}
|
||||
Ok((timeline_pdus, limited))
|
||||
}
|
||||
|
||||
fn share_encrypted_room(
|
||||
sender_user: &UserId,
|
||||
user_id: &UserId,
|
||||
|
@ -1155,3 +1168,190 @@ fn share_encrypted_room(
|
|||
})
|
||||
.any(|encrypted| encrypted))
|
||||
}
|
||||
|
||||
pub async fn sync_events_v4_route(
|
||||
body: Ruma<sync_events::v4::Request>,
|
||||
) -> Result<sync_events::v4::Response, RumaResponse<UiaaResponse>> {
|
||||
let sender_user = body.sender_user.expect("user is authenticated");
|
||||
let sender_device = body.sender_device.expect("user is authenticated");
|
||||
let body = dbg!(body.body);
|
||||
|
||||
// Setup watchers, so if there's no response, we can wait for them
|
||||
let watcher = services().globals.watch(&sender_user, &sender_device);
|
||||
|
||||
let next_batch = services().globals.current_count()?;
|
||||
|
||||
let since = body
|
||||
.pos
|
||||
.as_ref()
|
||||
.and_then(|string| string.parse().ok())
|
||||
.unwrap_or(0);
|
||||
let sincecount = PduCount::Normal(since);
|
||||
|
||||
let initial = since == 0;
|
||||
|
||||
let all_joined_rooms = services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.rooms_joined(&sender_user)
|
||||
.filter_map(|r| r.ok())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut lists = BTreeMap::new();
|
||||
let mut todo_rooms = BTreeMap::new(); // and required state
|
||||
|
||||
for (list_id, list) in body.lists {
|
||||
if list.filters.and_then(|f| f.is_invite).unwrap_or(false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
lists.insert(
|
||||
list_id,
|
||||
sync_events::v4::SyncList {
|
||||
ops: list
|
||||
.ranges
|
||||
.into_iter()
|
||||
.map(|mut r| {
|
||||
r.0 =
|
||||
r.0.clamp(uint!(0), UInt::from(all_joined_rooms.len() as u32 - 1));
|
||||
r.1 =
|
||||
r.1.clamp(r.0, UInt::from(all_joined_rooms.len() as u32 - 1));
|
||||
let room_ids = all_joined_rooms
|
||||
[(u64::from(r.0) as usize)..=(u64::from(r.1) as usize)]
|
||||
.to_vec();
|
||||
todo_rooms.extend(room_ids.iter().cloned().map(|r| {
|
||||
let limit = list
|
||||
.room_details
|
||||
.timeline_limit
|
||||
.map_or(10, u64::from)
|
||||
.min(100);
|
||||
(r, (list.room_details.required_state.clone(), limit))
|
||||
}));
|
||||
sync_events::v4::SyncOp {
|
||||
op: SlidingOp::Sync,
|
||||
range: Some(r.clone()),
|
||||
index: None,
|
||||
room_ids,
|
||||
room_id: None,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
count: UInt::from(all_joined_rooms.len() as u32),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let mut rooms = BTreeMap::new();
|
||||
for (room_id, (required_state_request, timeline_limit)) in todo_rooms {
|
||||
let (timeline_pdus, limited) =
|
||||
load_timeline(&sender_user, &room_id, sincecount, timeline_limit)?;
|
||||
|
||||
let prev_batch = timeline_pdus
|
||||
.first()
|
||||
.map_or(Ok::<_, Error>(None), |(pdu_count, _)| {
|
||||
Ok(Some(match pdu_count {
|
||||
PduCount::Backfilled(_) => {
|
||||
error!("timeline in backfill state?!");
|
||||
"0".to_owned()
|
||||
}
|
||||
PduCount::Normal(c) => c.to_string(),
|
||||
}))
|
||||
})?;
|
||||
|
||||
let room_events: Vec<_> = timeline_pdus
|
||||
.iter()
|
||||
.map(|(_, pdu)| pdu.to_sync_room_event())
|
||||
.collect();
|
||||
|
||||
let required_state = required_state_request
|
||||
.iter()
|
||||
.map(|state| {
|
||||
services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
.room_state_get(&room_id, &state.0, &state.1)
|
||||
})
|
||||
.filter_map(|r| r.ok())
|
||||
.filter_map(|o| o)
|
||||
.map(|state| state.to_sync_state_event())
|
||||
.collect();
|
||||
|
||||
rooms.insert(
|
||||
room_id.clone(),
|
||||
sync_events::v4::SlidingSyncRoom {
|
||||
name: services().rooms.state_accessor.get_name(&room_id)?,
|
||||
initial: Some(initial),
|
||||
is_dm: None,
|
||||
invite_state: None,
|
||||
unread_notifications: UnreadNotificationsCount {
|
||||
highlight_count: None,
|
||||
notification_count: None,
|
||||
},
|
||||
timeline: room_events,
|
||||
required_state,
|
||||
prev_batch,
|
||||
limited,
|
||||
joined_count: Some(
|
||||
(services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_joined_count(&room_id)?
|
||||
.unwrap_or(0) as u32)
|
||||
.into(),
|
||||
),
|
||||
invited_count: Some(
|
||||
(services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_invited_count(&room_id)?
|
||||
.unwrap_or(0) as u32)
|
||||
.into(),
|
||||
),
|
||||
num_live: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if rooms
|
||||
.iter()
|
||||
.all(|(_, r)| r.timeline.is_empty() && r.required_state.is_empty())
|
||||
{
|
||||
// Hang a few seconds so requests are not spammed
|
||||
// Stop hanging if new info arrives
|
||||
let mut duration = body.timeout.unwrap_or(Duration::from_secs(30));
|
||||
if duration.as_secs() > 30 {
|
||||
duration = Duration::from_secs(30);
|
||||
}
|
||||
let _ = tokio::time::timeout(duration, watcher).await;
|
||||
}
|
||||
|
||||
Ok(dbg!(sync_events::v4::Response {
|
||||
initial: initial,
|
||||
txn_id: body.txn_id.clone(),
|
||||
pos: next_batch.to_string(),
|
||||
lists,
|
||||
rooms,
|
||||
extensions: sync_events::v4::Extensions {
|
||||
to_device: None,
|
||||
e2ee: sync_events::v4::E2EE {
|
||||
device_lists: DeviceLists {
|
||||
changed: Vec::new(),
|
||||
left: Vec::new(),
|
||||
},
|
||||
device_one_time_keys_count: BTreeMap::new(),
|
||||
device_unused_fallback_key_types: None,
|
||||
},
|
||||
account_data: sync_events::v4::AccountData {
|
||||
global: Vec::new(),
|
||||
rooms: BTreeMap::new(),
|
||||
},
|
||||
receipts: sync_events::v4::Receipts {
|
||||
rooms: BTreeMap::new(),
|
||||
},
|
||||
typing: sync_events::v4::Typing {
|
||||
rooms: BTreeMap::new(),
|
||||
},
|
||||
},
|
||||
delta_token: None,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use std::{collections::BTreeMap, iter::FromIterator};
|
||||
|
||||
use ruma::api::client::discovery::get_supported_versions;
|
||||
use axum::{response::IntoResponse, Json};
|
||||
use ruma::api::client::{discovery::get_supported_versions, error::ErrorKind};
|
||||
|
||||
use crate::{Result, Ruma};
|
||||
use crate::{services, Error, Result, Ruma};
|
||||
|
||||
/// # `GET /_matrix/client/versions`
|
||||
///
|
||||
|
@ -31,3 +32,18 @@ pub async fn get_supported_versions_route(
|
|||
|
||||
Ok(resp)
|
||||
}
|
||||
|
||||
/// # `GET /.well-known/matrix/client`
|
||||
pub async fn well_known_client_route(
|
||||
_body: Ruma<get_supported_versions::Request>,
|
||||
) -> Result<impl IntoResponse> {
|
||||
let client_url = match services().globals.well_known_client() {
|
||||
Some(url) => url.clone(),
|
||||
None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
|
||||
};
|
||||
|
||||
Ok(Json(serde_json::json!({
|
||||
"m.homeserver": {"base_url": client_url},
|
||||
"org.matrix.msc3575.proxy": {"url": client_url}
|
||||
})))
|
||||
}
|
||||
|
|
|
@ -123,6 +123,12 @@ where
|
|||
return Err(Error::bad_config("Federation is disabled."));
|
||||
}
|
||||
|
||||
if destination == services().globals.server_name() {
|
||||
return Err(Error::bad_config(
|
||||
"Won't send federation request to ourselves",
|
||||
));
|
||||
}
|
||||
|
||||
debug!("Preparing to send request to {destination}");
|
||||
|
||||
let mut write_destination_to_cache = false;
|
||||
|
|
|
@ -54,6 +54,7 @@ pub struct Config {
|
|||
pub allow_unstable_room_versions: bool,
|
||||
#[serde(default = "default_default_room_version")]
|
||||
pub default_room_version: RoomVersionId,
|
||||
pub well_known_client: Option<String>,
|
||||
#[serde(default = "false_fn")]
|
||||
pub allow_jaeger: bool,
|
||||
#[serde(default = "false_fn")]
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use futures_util::{stream::FuturesUnordered, StreamExt};
|
||||
use lru_cache::LruCache;
|
||||
use ruma::{
|
||||
api::federation::discovery::{ServerSigningKeys, VerifyKey},
|
||||
signatures::Ed25519KeyPair,
|
||||
|
@ -148,28 +149,36 @@ lasttimelinecount_cache: {lasttimelinecount_cache}\n"
|
|||
|
||||
fn clear_caches(&self, amount: u32) {
|
||||
if amount > 0 {
|
||||
self.pdu_cache.lock().unwrap().clear();
|
||||
let c = &mut *self.pdu_cache.lock().unwrap();
|
||||
*c = LruCache::new(c.capacity());
|
||||
}
|
||||
if amount > 1 {
|
||||
self.shorteventid_cache.lock().unwrap().clear();
|
||||
let c = &mut *self.shorteventid_cache.lock().unwrap();
|
||||
*c = LruCache::new(c.capacity());
|
||||
}
|
||||
if amount > 2 {
|
||||
self.auth_chain_cache.lock().unwrap().clear();
|
||||
let c = &mut *self.auth_chain_cache.lock().unwrap();
|
||||
*c = LruCache::new(c.capacity());
|
||||
}
|
||||
if amount > 3 {
|
||||
self.eventidshort_cache.lock().unwrap().clear();
|
||||
let c = &mut *self.eventidshort_cache.lock().unwrap();
|
||||
*c = LruCache::new(c.capacity());
|
||||
}
|
||||
if amount > 4 {
|
||||
self.statekeyshort_cache.lock().unwrap().clear();
|
||||
let c = &mut *self.statekeyshort_cache.lock().unwrap();
|
||||
*c = LruCache::new(c.capacity());
|
||||
}
|
||||
if amount > 5 {
|
||||
self.our_real_users_cache.write().unwrap().clear();
|
||||
let c = &mut *self.our_real_users_cache.write().unwrap();
|
||||
*c = HashMap::new();
|
||||
}
|
||||
if amount > 6 {
|
||||
self.appservice_in_room_cache.write().unwrap().clear();
|
||||
let c = &mut *self.appservice_in_room_cache.write().unwrap();
|
||||
*c = HashMap::new();
|
||||
}
|
||||
if amount > 7 {
|
||||
self.lasttimelinecount_cache.lock().unwrap().clear();
|
||||
let c = &mut *self.lasttimelinecount_cache.lock().unwrap();
|
||||
*c = HashMap::new();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -357,6 +357,7 @@ fn routes() -> Router {
|
|||
.put(client_server::send_state_event_for_empty_key_route),
|
||||
)
|
||||
.ruma_route(client_server::sync_events_route)
|
||||
.ruma_route(client_server::sync_events_v4_route)
|
||||
.ruma_route(client_server::get_context_route)
|
||||
.ruma_route(client_server::get_message_events_route)
|
||||
.ruma_route(client_server::search_events_route)
|
||||
|
|
|
@ -342,6 +342,10 @@ impl Service {
|
|||
r
|
||||
}
|
||||
|
||||
pub fn well_known_client(&self) -> &Option<String> {
|
||||
&self.config.well_known_client
|
||||
}
|
||||
|
||||
pub fn shutdown(&self) {
|
||||
self.shutdown.store(true, atomic::Ordering::Relaxed);
|
||||
// On shutdown
|
||||
|
|
|
@ -270,21 +270,7 @@ impl Service {
|
|||
|
||||
notifi.sender_display_name = services().users.displayname(&event.sender)?;
|
||||
|
||||
let room_name = if let Some(room_name_pdu) = services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
.room_state_get(&event.room_id, &StateEventType::RoomName, "")?
|
||||
{
|
||||
serde_json::from_str::<RoomNameEventContent>(room_name_pdu.content.get())
|
||||
.map_err(|_| {
|
||||
Error::bad_database("Invalid room name event in database.")
|
||||
})?
|
||||
.name
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
notifi.room_name = room_name;
|
||||
notifi.room_name = services().rooms.state_accessor.get_name(&event.room_id)?;
|
||||
|
||||
self.send_request(&http.url, send_event_notification::v1::Request::new(notifi))
|
||||
.await?;
|
||||
|
|
|
@ -5,11 +5,10 @@ use ruma::{
|
|||
api::{
|
||||
client::{
|
||||
error::ErrorKind,
|
||||
space::{get_hierarchy, SpaceHierarchyRoomsChunk, SpaceRoomJoinRule},
|
||||
space::{get_hierarchy, SpaceHierarchyRoomsChunk},
|
||||
},
|
||||
federation,
|
||||
},
|
||||
directory::PublicRoomJoinRule,
|
||||
events::{
|
||||
room::{
|
||||
avatar::RoomAvatarEventContent,
|
||||
|
@ -18,11 +17,11 @@ use ruma::{
|
|||
guest_access::{GuestAccess, RoomGuestAccessEventContent},
|
||||
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
|
||||
join_rules::{JoinRule, RoomJoinRulesEventContent},
|
||||
name::RoomNameEventContent,
|
||||
topic::RoomTopicEventContent,
|
||||
},
|
||||
StateEventType,
|
||||
},
|
||||
space::SpaceRoomJoinRule,
|
||||
OwnedRoomId, RoomId, UserId,
|
||||
};
|
||||
|
||||
|
@ -30,10 +29,15 @@ use tracing::{debug, error, warn};
|
|||
|
||||
use crate::{services, Error, PduEvent, Result};
|
||||
|
||||
pub enum CachedJoinRule {
|
||||
Simplified(SpaceRoomJoinRule),
|
||||
Full(JoinRule),
|
||||
}
|
||||
|
||||
pub struct CachedSpaceChunk {
|
||||
chunk: SpaceHierarchyRoomsChunk,
|
||||
children: Vec<OwnedRoomId>,
|
||||
join_rule: JoinRule,
|
||||
join_rule: CachedJoinRule,
|
||||
}
|
||||
|
||||
pub struct Service {
|
||||
|
@ -79,9 +83,15 @@ impl Service {
|
|||
.as_ref()
|
||||
{
|
||||
if let Some(cached) = cached {
|
||||
if let Some(_join_rule) =
|
||||
self.handle_join_rule(&cached.join_rule, sender_user, ¤t_room)?
|
||||
{
|
||||
let allowed = match &cached.join_rule {
|
||||
CachedJoinRule::Simplified(s) => {
|
||||
self.handle_simplified_join_rule(s, sender_user, ¤t_room)?
|
||||
}
|
||||
CachedJoinRule::Full(f) => {
|
||||
self.handle_join_rule(f, sender_user, ¤t_room)?
|
||||
}
|
||||
};
|
||||
if allowed {
|
||||
if left_to_skip > 0 {
|
||||
left_to_skip -= 1;
|
||||
} else {
|
||||
|
@ -152,7 +162,7 @@ impl Service {
|
|||
Some(CachedSpaceChunk {
|
||||
chunk,
|
||||
children: children_ids.clone(),
|
||||
join_rule,
|
||||
join_rule: CachedJoinRule::Full(join_rule),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -182,7 +192,6 @@ impl Service {
|
|||
.await
|
||||
{
|
||||
warn!("Got response from {server} for /hierarchy\n{response:?}");
|
||||
let join_rule = self.translate_pjoinrule(&response.room.join_rule)?;
|
||||
let chunk = SpaceHierarchyRoomsChunk {
|
||||
canonical_alias: response.room.canonical_alias,
|
||||
name: response.room.name,
|
||||
|
@ -192,7 +201,7 @@ impl Service {
|
|||
world_readable: response.room.world_readable,
|
||||
guest_can_join: response.room.guest_can_join,
|
||||
avatar_url: response.room.avatar_url,
|
||||
join_rule: self.translate_sjoinrule(&response.room.join_rule)?,
|
||||
join_rule: response.room.join_rule.clone(),
|
||||
room_type: response.room.room_type,
|
||||
children_state: response.room.children_state,
|
||||
};
|
||||
|
@ -202,9 +211,11 @@ impl Service {
|
|||
.map(|c| c.room_id.clone())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if let Some(_join_rule) =
|
||||
self.handle_join_rule(&join_rule, sender_user, ¤t_room)?
|
||||
{
|
||||
if self.handle_simplified_join_rule(
|
||||
&response.room.join_rule,
|
||||
sender_user,
|
||||
¤t_room,
|
||||
)? {
|
||||
if left_to_skip > 0 {
|
||||
left_to_skip -= 1;
|
||||
} else {
|
||||
|
@ -220,7 +231,7 @@ impl Service {
|
|||
Some(CachedSpaceChunk {
|
||||
chunk,
|
||||
children,
|
||||
join_rule,
|
||||
join_rule: CachedJoinRule::Simplified(response.room.join_rule),
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -273,15 +284,7 @@ impl Service {
|
|||
Error::bad_database("Invalid canonical alias event in database.")
|
||||
})
|
||||
})?,
|
||||
name: services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
.room_state_get(&room_id, &StateEventType::RoomName, "")?
|
||||
.map_or(Ok(None), |s| {
|
||||
serde_json::from_str(s.content.get())
|
||||
.map(|c: RoomNameEventContent| c.name)
|
||||
.map_err(|_| Error::bad_database("Invalid room name event in database."))
|
||||
})?,
|
||||
name: services().rooms.state_accessor.get_name(&room_id)?,
|
||||
num_joined_members: services()
|
||||
.rooms
|
||||
.state_cache
|
||||
|
@ -357,15 +360,17 @@ impl Service {
|
|||
})
|
||||
.transpose()?
|
||||
.unwrap_or(JoinRule::Invite);
|
||||
self.handle_join_rule(&join_rule, sender_user, room_id)?
|
||||
.ok_or_else(|| {
|
||||
debug!("User is not allowed to see room {room_id}");
|
||||
// This error will be caught later
|
||||
Error::BadRequest(
|
||||
ErrorKind::Forbidden,
|
||||
"User is not allowed to see the room",
|
||||
)
|
||||
})?
|
||||
|
||||
if !self.handle_join_rule(&join_rule, sender_user, room_id)? {
|
||||
debug!("User is not allowed to see room {room_id}");
|
||||
// This error will be caught later
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::Forbidden,
|
||||
"User is not allowed to see the room",
|
||||
));
|
||||
}
|
||||
|
||||
self.translate_joinrule(&join_rule)?
|
||||
},
|
||||
room_type: services()
|
||||
.rooms
|
||||
|
@ -386,20 +391,35 @@ impl Service {
|
|||
})
|
||||
}
|
||||
|
||||
fn translate_pjoinrule(&self, join_rule: &PublicRoomJoinRule) -> Result<JoinRule> {
|
||||
fn translate_joinrule(&self, join_rule: &JoinRule) -> Result<SpaceRoomJoinRule> {
|
||||
match join_rule {
|
||||
PublicRoomJoinRule::Knock => Ok(JoinRule::Knock),
|
||||
PublicRoomJoinRule::Public => Ok(JoinRule::Public),
|
||||
JoinRule::Invite => Ok(SpaceRoomJoinRule::Invite),
|
||||
JoinRule::Knock => Ok(SpaceRoomJoinRule::Knock),
|
||||
JoinRule::Private => Ok(SpaceRoomJoinRule::Private),
|
||||
JoinRule::Restricted(_) => Ok(SpaceRoomJoinRule::Restricted),
|
||||
JoinRule::KnockRestricted(_) => Ok(SpaceRoomJoinRule::KnockRestricted),
|
||||
JoinRule::Public => Ok(SpaceRoomJoinRule::Public),
|
||||
_ => Err(Error::BadServerResponse("Unknown join rule")),
|
||||
}
|
||||
}
|
||||
|
||||
fn translate_sjoinrule(&self, join_rule: &PublicRoomJoinRule) -> Result<SpaceRoomJoinRule> {
|
||||
match join_rule {
|
||||
PublicRoomJoinRule::Knock => Ok(SpaceRoomJoinRule::Knock),
|
||||
PublicRoomJoinRule::Public => Ok(SpaceRoomJoinRule::Public),
|
||||
_ => Err(Error::BadServerResponse("Unknown join rule")),
|
||||
}
|
||||
fn handle_simplified_join_rule(
|
||||
&self,
|
||||
join_rule: &SpaceRoomJoinRule,
|
||||
sender_user: &UserId,
|
||||
room_id: &RoomId,
|
||||
) -> Result<bool> {
|
||||
let allowed = match join_rule {
|
||||
SpaceRoomJoinRule::Public => true,
|
||||
SpaceRoomJoinRule::Knock => true,
|
||||
SpaceRoomJoinRule::Invite => services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.is_joined(sender_user, &room_id)?,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
Ok(allowed)
|
||||
}
|
||||
|
||||
fn handle_join_rule(
|
||||
|
@ -407,30 +427,25 @@ impl Service {
|
|||
join_rule: &JoinRule,
|
||||
sender_user: &UserId,
|
||||
room_id: &RoomId,
|
||||
) -> Result<Option<SpaceRoomJoinRule>> {
|
||||
) -> Result<bool> {
|
||||
if self.handle_simplified_join_rule(
|
||||
&self.translate_joinrule(join_rule)?,
|
||||
sender_user,
|
||||
room_id,
|
||||
)? {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
match join_rule {
|
||||
JoinRule::Public => Ok::<_, Error>(Some(SpaceRoomJoinRule::Public)),
|
||||
JoinRule::Knock => Ok(Some(SpaceRoomJoinRule::Knock)),
|
||||
JoinRule::Invite => {
|
||||
if services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.is_joined(sender_user, &room_id)?
|
||||
{
|
||||
Ok(Some(SpaceRoomJoinRule::Invite))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
JoinRule::Restricted(_r) => {
|
||||
JoinRule::Restricted(_) => {
|
||||
// TODO: Check rules
|
||||
Ok(None)
|
||||
Ok(false)
|
||||
}
|
||||
JoinRule::KnockRestricted(_r) => {
|
||||
JoinRule::KnockRestricted(_) => {
|
||||
// TODO: Check rules
|
||||
Ok(None)
|
||||
Ok(false)
|
||||
}
|
||||
_ => Ok(None),
|
||||
_ => Ok(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use ruma::{
|
|||
room::{
|
||||
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
|
||||
member::{MembershipState, RoomMemberEventContent},
|
||||
name::RoomNameEventContent,
|
||||
},
|
||||
StateEventType,
|
||||
},
|
||||
|
@ -269,4 +270,16 @@ impl Service {
|
|||
) -> Result<Option<Arc<PduEvent>>> {
|
||||
self.db.room_state_get(room_id, event_type, state_key)
|
||||
}
|
||||
|
||||
pub fn get_name(&self, room_id: &RoomId) -> Result<Option<String>> {
|
||||
services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
.room_state_get(&room_id, &StateEventType::RoomName, "")?
|
||||
.map_or(Ok(None), |s| {
|
||||
serde_json::from_str(s.content.get())
|
||||
.map(|c: RoomNameEventContent| c.name)
|
||||
.map_err(|_| Error::bad_database("Invalid room name event in database."))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue