feat: first steps towards joining rooms over federation
parent
f40f1d9f75
commit
04eee089e0
|
@ -267,6 +267,7 @@ checksum = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd"
|
||||||
name = "conduit"
|
name = "conduit"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"base64 0.12.3",
|
||||||
"directories",
|
"directories",
|
||||||
"http",
|
"http",
|
||||||
"image",
|
"image",
|
||||||
|
@ -1559,7 +1560,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma"
|
name = "ruma"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ruma-api",
|
"ruma-api",
|
||||||
"ruma-client-api",
|
"ruma-client-api",
|
||||||
|
@ -1573,7 +1574,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-api"
|
name = "ruma-api"
|
||||||
version = "0.17.0-alpha.1"
|
version = "0.17.0-alpha.1"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
|
@ -1588,7 +1589,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-api-macros"
|
name = "ruma-api-macros"
|
||||||
version = "0.17.0-alpha.1"
|
version = "0.17.0-alpha.1"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -1599,7 +1600,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-client-api"
|
name = "ruma-client-api"
|
||||||
version = "0.10.0-alpha.1"
|
version = "0.10.0-alpha.1"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assign",
|
"assign",
|
||||||
"http",
|
"http",
|
||||||
|
@ -1617,7 +1618,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-common"
|
name = "ruma-common"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-identifiers",
|
"ruma-identifiers",
|
||||||
|
@ -1630,7 +1631,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-events"
|
name = "ruma-events"
|
||||||
version = "0.22.0-alpha.1"
|
version = "0.22.0-alpha.1"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
|
@ -1645,7 +1646,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-events-macros"
|
name = "ruma-events-macros"
|
||||||
version = "0.22.0-alpha.1"
|
version = "0.22.0-alpha.1"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -1656,7 +1657,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-federation-api"
|
name = "ruma-federation-api"
|
||||||
version = "0.0.3"
|
version = "0.0.3"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-api",
|
"ruma-api",
|
||||||
|
@ -1671,7 +1672,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-identifiers"
|
name = "ruma-identifiers"
|
||||||
version = "0.17.4"
|
version = "0.17.4"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
"ruma-identifiers-macros",
|
"ruma-identifiers-macros",
|
||||||
|
@ -1683,7 +1684,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-identifiers-macros"
|
name = "ruma-identifiers-macros"
|
||||||
version = "0.17.4"
|
version = "0.17.4"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1694,7 +1695,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-identifiers-validation"
|
name = "ruma-identifiers-validation"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ruma-serde",
|
"ruma-serde",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -1705,7 +1706,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-serde"
|
name = "ruma-serde"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"itoa",
|
"itoa",
|
||||||
|
@ -1717,7 +1718,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-signatures"
|
name = "ruma-signatures"
|
||||||
version = "0.6.0-dev.1"
|
version = "0.6.0-dev.1"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014"
|
source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.12.3",
|
"base64 0.12.3",
|
||||||
"ring",
|
"ring",
|
||||||
|
|
|
@ -16,9 +16,10 @@ edition = "2018"
|
||||||
#rocket = { git = "https://github.com/SergioBenitez/Rocket.git", rev = "8d779caa22c63b15a6c3ceb75d8f6d4971b2eb67", features = ["tls"] } # Used to handle requests
|
#rocket = { git = "https://github.com/SergioBenitez/Rocket.git", rev = "8d779caa22c63b15a6c3ceb75d8f6d4971b2eb67", features = ["tls"] } # Used to handle requests
|
||||||
rocket = { git = "https://github.com/timokoesters/Rocket.git", branch = "empty_parameters", features = ["tls"] }
|
rocket = { git = "https://github.com/timokoesters/Rocket.git", branch = "empty_parameters", features = ["tls"] }
|
||||||
|
|
||||||
tokio = "0.2.22" # Used for long polling
|
#ruma = { git = "https://github.com/ruma/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"], rev = "987d48666cf166cf12100b5dbc61b5e3385c4014" } # Used for matrix spec type definitions and helpers
|
||||||
ruma = { git = "https://github.com/ruma/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"], rev = "987d48666cf166cf12100b5dbc61b5e3385c4014" } # Used for matrix spec type definitions and helpers
|
ruma = { git = "https://github.com/timokoesters/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"], branch = "timo-fixes" } # Used for matrix spec type definitions and helpers
|
||||||
#ruma = { path = "../ruma/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"] }
|
#ruma = { path = "../ruma/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"] }
|
||||||
|
tokio = "0.2.22" # Used for long polling
|
||||||
sled = "0.32.0" # Used for storing data permanently
|
sled = "0.32.0" # Used for storing data permanently
|
||||||
log = "0.4.8" # Used for emitting log entries
|
log = "0.4.8" # Used for emitting log entries
|
||||||
http = "0.2.1" # Used for rocket<->ruma conversions
|
http = "0.2.1" # Used for rocket<->ruma conversions
|
||||||
|
@ -31,6 +32,7 @@ rust-argon2 = "0.8.2" # Used to hash passwords
|
||||||
reqwest = "0.10.6" # Used to send requests
|
reqwest = "0.10.6" # Used to send requests
|
||||||
thiserror = "1.0.19" # Used for conduit::Error type
|
thiserror = "1.0.19" # Used for conduit::Error type
|
||||||
image = { version = "0.23.4", default-features = false, features = ["jpeg", "png", "gif"] } # Used to generate thumbnails for images
|
image = { version = "0.23.4", default-features = false, features = ["jpeg", "png", "gif"] } # Used to generate thumbnails for images
|
||||||
|
base64 = "0.12.3" # Used to encode server public key
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["conduit_bin"]
|
default = ["conduit_bin"]
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use super::State;
|
use super::State;
|
||||||
use crate::{ConduitResult, Database, Error, Ruma};
|
use crate::{ConduitResult, Database, Error, Ruma, server_server};
|
||||||
use ruma::api::client::{
|
use ruma::api::{federation, client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
r0::alias::{create_alias, delete_alias, get_alias},
|
r0::alias::{create_alias, delete_alias, get_alias},
|
||||||
};
|
}};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
#[cfg(feature = "conduit_bin")]
|
||||||
use rocket::{delete, get, put};
|
use rocket::{delete, get, put};
|
||||||
|
@ -43,12 +43,25 @@ pub fn delete_alias_route(
|
||||||
feature = "conduit_bin",
|
feature = "conduit_bin",
|
||||||
get("/_matrix/client/r0/directory/room/<_>", data = "<body>")
|
get("/_matrix/client/r0/directory/room/<_>", data = "<body>")
|
||||||
)]
|
)]
|
||||||
pub fn get_alias_route(
|
pub async fn get_alias_route(
|
||||||
db: State<'_, Database>,
|
db: State<'_, Database>,
|
||||||
body: Ruma<get_alias::IncomingRequest>,
|
body: Ruma<get_alias::IncomingRequest>,
|
||||||
) -> ConduitResult<get_alias::Response> {
|
) -> ConduitResult<get_alias::Response> {
|
||||||
if body.room_alias.server_name() != db.globals.server_name() {
|
if body.room_alias.server_name() != db.globals.server_name() {
|
||||||
todo!("ask remote server");
|
let response = server_server::send_request(
|
||||||
|
&db,
|
||||||
|
body.room_alias.server_name().to_string(),
|
||||||
|
federation::query::get_room_information::v1::Request {
|
||||||
|
room_alias: body.room_alias.to_string(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(get_alias::Response {
|
||||||
|
room_id: response.room_id,
|
||||||
|
servers: response.servers,
|
||||||
|
}
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let room_id = db
|
let room_id = db
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
use super::State;
|
use super::State;
|
||||||
use crate::{ConduitResult, Database, Error, Result, Ruma};
|
use crate::{server_server, ConduitResult, Database, Error, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::{
|
||||||
error::ErrorKind,
|
client::{
|
||||||
r0::{
|
error::ErrorKind,
|
||||||
directory::{
|
r0::{
|
||||||
self, get_public_rooms, get_public_rooms_filtered, get_room_visibility,
|
directory::{
|
||||||
set_room_visibility,
|
self, get_public_rooms, get_public_rooms_filtered, get_room_visibility,
|
||||||
|
set_room_visibility,
|
||||||
|
},
|
||||||
|
room,
|
||||||
},
|
},
|
||||||
room,
|
|
||||||
},
|
},
|
||||||
|
federation,
|
||||||
},
|
},
|
||||||
events::{
|
events::{
|
||||||
room::{avatar, canonical_alias, guest_access, history_visibility, name, topic},
|
room::{avatar, canonical_alias, guest_access, history_visibility, name, topic},
|
||||||
|
@ -29,6 +32,46 @@ pub async fn get_public_rooms_filtered_route(
|
||||||
db: State<'_, Database>,
|
db: State<'_, Database>,
|
||||||
body: Ruma<get_public_rooms_filtered::IncomingRequest>,
|
body: Ruma<get_public_rooms_filtered::IncomingRequest>,
|
||||||
) -> ConduitResult<get_public_rooms_filtered::Response> {
|
) -> ConduitResult<get_public_rooms_filtered::Response> {
|
||||||
|
if let Some(other_server) = body
|
||||||
|
.server
|
||||||
|
.clone()
|
||||||
|
.filter(|server| server != &db.globals.server_name().as_str())
|
||||||
|
{
|
||||||
|
let response = server_server::send_request(
|
||||||
|
&db,
|
||||||
|
other_server,
|
||||||
|
federation::directory::get_public_rooms::v1::Request {
|
||||||
|
limit: body.limit,
|
||||||
|
since: body.since.clone(),
|
||||||
|
room_network: federation::directory::get_public_rooms::v1::RoomNetwork::Matrix,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(get_public_rooms_filtered::Response {
|
||||||
|
chunk: response
|
||||||
|
.chunk
|
||||||
|
.into_iter()
|
||||||
|
.map(|c| {
|
||||||
|
// Convert ruma::api::federation::directory::get_public_rooms::v1::PublicRoomsChunk
|
||||||
|
// to ruma::api::client::r0::directory::PublicRoomsChunk
|
||||||
|
Ok::<_, Error>(
|
||||||
|
serde_json::from_str(
|
||||||
|
&serde_json::to_string(&c)
|
||||||
|
.expect("PublicRoomsChunk::to_string always works"),
|
||||||
|
)
|
||||||
|
.expect("federation and client-server PublicRoomsChunk are the same type"),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.filter_map(|r| r.ok())
|
||||||
|
.collect(),
|
||||||
|
prev_batch: response.prev_batch,
|
||||||
|
next_batch: response.next_batch,
|
||||||
|
total_room_count_estimate: response.total_room_count_estimate,
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
let limit = body.limit.map_or(10, u64::from);
|
let limit = body.limit.map_or(10, u64::from);
|
||||||
let mut since = 0_u64;
|
let mut since = 0_u64;
|
||||||
|
|
||||||
|
@ -169,26 +212,6 @@ pub async fn get_public_rooms_filtered_route(
|
||||||
|
|
||||||
all_rooms.sort_by(|l, r| r.num_joined_members.cmp(&l.num_joined_members));
|
all_rooms.sort_by(|l, r| r.num_joined_members.cmp(&l.num_joined_members));
|
||||||
|
|
||||||
/*
|
|
||||||
all_rooms.extend_from_slice(
|
|
||||||
&server_server::send_request(
|
|
||||||
&db,
|
|
||||||
"privacytools.io".to_owned(),
|
|
||||||
ruma::api::federation::v1::get_public_rooms::Request {
|
|
||||||
limit: Some(20_u32.into()),
|
|
||||||
since: None,
|
|
||||||
room_network: ruma::api::federation::v1::get_public_rooms::RoomNetwork::Matrix,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
?
|
|
||||||
.chunk
|
|
||||||
.into_iter()
|
|
||||||
.map(|c| serde_json::from_str(&serde_json::to_string(&c)?)?)
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
|
|
||||||
let total_room_count_estimate = (all_rooms.len() as u32).into();
|
let total_room_count_estimate = (all_rooms.len() as u32).into();
|
||||||
|
|
||||||
let chunk = all_rooms
|
let chunk = all_rooms
|
||||||
|
|
|
@ -1,16 +1,24 @@
|
||||||
use super::State;
|
use super::State;
|
||||||
use crate::{pdu::PduBuilder, ConduitResult, Database, Error, Ruma};
|
use crate::{
|
||||||
|
client_server, pdu::PduBuilder, server_server, utils, ConduitResult, Database, Error, Ruma,
|
||||||
|
};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::{
|
||||||
error::ErrorKind,
|
client::{
|
||||||
r0::membership::{
|
error::ErrorKind,
|
||||||
ban_user, forget_room, get_member_events, invite_user, join_room_by_id,
|
r0::{
|
||||||
join_room_by_id_or_alias, joined_members, joined_rooms, kick_user, leave_room,
|
alias,
|
||||||
unban_user,
|
membership::{
|
||||||
|
ban_user, forget_room, get_member_events, invite_user, join_room_by_id,
|
||||||
|
join_room_by_id_or_alias, joined_members, joined_rooms, kick_user, leave_room,
|
||||||
|
unban_user,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
federation,
|
||||||
},
|
},
|
||||||
events::{room::member, EventType},
|
events::{room::member, EventType},
|
||||||
Raw, RoomId,
|
EventId, Raw, RoomId, RoomVersionId,
|
||||||
};
|
};
|
||||||
use std::{collections::BTreeMap, convert::TryFrom};
|
use std::{collections::BTreeMap, convert::TryFrom};
|
||||||
|
|
||||||
|
@ -21,13 +29,81 @@ use rocket::{get, post};
|
||||||
feature = "conduit_bin",
|
feature = "conduit_bin",
|
||||||
post("/_matrix/client/r0/rooms/<_>/join", data = "<body>")
|
post("/_matrix/client/r0/rooms/<_>/join", data = "<body>")
|
||||||
)]
|
)]
|
||||||
pub fn join_room_by_id_route(
|
pub async fn join_room_by_id_route(
|
||||||
db: State<'_, Database>,
|
db: State<'_, Database>,
|
||||||
body: Ruma<join_room_by_id::IncomingRequest>,
|
body: Ruma<join_room_by_id::IncomingRequest>,
|
||||||
) -> ConduitResult<join_room_by_id::Response> {
|
) -> ConduitResult<join_room_by_id::Response> {
|
||||||
let sender_id = body.sender_id.as_ref().expect("user is authenticated");
|
let sender_id = body.sender_id.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
// TODO: Ask a remote server if we don't have this room
|
// Ask a remote server if we don't have this room
|
||||||
|
if !db.rooms.exists(&body.room_id)? && body.room_id.server_name() != db.globals.server_name() {
|
||||||
|
let make_join_response = server_server::send_request(
|
||||||
|
&db,
|
||||||
|
body.room_id.server_name().to_string(),
|
||||||
|
federation::membership::create_join_event_template::v1::Request {
|
||||||
|
room_id: body.room_id.clone(),
|
||||||
|
user_id: sender_id.clone(),
|
||||||
|
ver: vec![RoomVersionId::Version5, RoomVersionId::Version6],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut join_event_stub_value =
|
||||||
|
serde_json::from_str::<serde_json::Value>(make_join_response.event.json().get())
|
||||||
|
.map_err(|_| {
|
||||||
|
Error::BadServerResponse("Invalid make_join event json received from server.")
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let join_event_stub =
|
||||||
|
join_event_stub_value
|
||||||
|
.as_object_mut()
|
||||||
|
.ok_or(Error::BadServerResponse(
|
||||||
|
"Invalid make join event object received from server.",
|
||||||
|
))?;
|
||||||
|
|
||||||
|
join_event_stub.insert(
|
||||||
|
"origin".to_owned(),
|
||||||
|
db.globals.server_name().to_owned().to_string().into(),
|
||||||
|
);
|
||||||
|
join_event_stub.insert(
|
||||||
|
"origin_server_ts".to_owned(),
|
||||||
|
utils::millis_since_unix_epoch().into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Generate event id
|
||||||
|
let event_id = EventId::try_from(&*format!(
|
||||||
|
"${}",
|
||||||
|
ruma::signatures::reference_hash(&join_event_stub_value)
|
||||||
|
.expect("ruma can calculate reference hashes")
|
||||||
|
))
|
||||||
|
.expect("ruma's reference hashes are valid event ids");
|
||||||
|
|
||||||
|
// We don't leave the event id into the pdu because that's only allowed in v1 or v2 rooms
|
||||||
|
let join_event_stub = join_event_stub_value.as_object_mut().unwrap();
|
||||||
|
join_event_stub.remove("event_id");
|
||||||
|
|
||||||
|
ruma::signatures::hash_and_sign_event(
|
||||||
|
db.globals.server_name().as_str(),
|
||||||
|
db.globals.keypair(),
|
||||||
|
&mut join_event_stub_value,
|
||||||
|
)
|
||||||
|
.expect("event is valid, we just created it");
|
||||||
|
|
||||||
|
let send_join_response = server_server::send_request(
|
||||||
|
&db,
|
||||||
|
body.room_id.server_name().to_string(),
|
||||||
|
federation::membership::create_join_event::v2::Request {
|
||||||
|
room_id: body.room_id.clone(),
|
||||||
|
event_id,
|
||||||
|
pdu_stub: serde_json::from_value::<Raw<_>>(join_event_stub_value)
|
||||||
|
.expect("Raw::from_value always works"),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
dbg!(send_join_response);
|
||||||
|
todo!("Take send_join_response and 'create' the room using that data");
|
||||||
|
}
|
||||||
|
|
||||||
let event = member::MemberEventContent {
|
let event = member::MemberEventContent {
|
||||||
membership: member::MembershipState::Join,
|
membership: member::MembershipState::Join,
|
||||||
|
@ -61,16 +137,28 @@ pub fn join_room_by_id_route(
|
||||||
feature = "conduit_bin",
|
feature = "conduit_bin",
|
||||||
post("/_matrix/client/r0/join/<_>", data = "<body>")
|
post("/_matrix/client/r0/join/<_>", data = "<body>")
|
||||||
)]
|
)]
|
||||||
pub fn join_room_by_id_or_alias_route(
|
pub async fn join_room_by_id_or_alias_route(
|
||||||
db: State<'_, Database>,
|
db: State<'_, Database>,
|
||||||
|
db2: State<'_, Database>,
|
||||||
body: Ruma<join_room_by_id_or_alias::Request>,
|
body: Ruma<join_room_by_id_or_alias::Request>,
|
||||||
) -> ConduitResult<join_room_by_id_or_alias::Response> {
|
) -> ConduitResult<join_room_by_id_or_alias::Response> {
|
||||||
let room_id = RoomId::try_from(body.room_id_or_alias.clone()).or_else(|alias| {
|
let room_id = match RoomId::try_from(body.room_id_or_alias.clone()) {
|
||||||
Ok::<_, Error>(db.rooms.id_from_alias(&alias)?.ok_or(Error::BadRequest(
|
Ok(room_id) => room_id,
|
||||||
ErrorKind::NotFound,
|
Err(room_alias) => {
|
||||||
"Room not found (TODO: Federation).",
|
client_server::get_alias_route(
|
||||||
))?)
|
db,
|
||||||
})?;
|
Ruma {
|
||||||
|
body: alias::get_alias::IncomingRequest { room_alias },
|
||||||
|
sender_id: body.sender_id.clone(),
|
||||||
|
device_id: body.device_id.clone(),
|
||||||
|
json_body: None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.0
|
||||||
|
.room_id
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let body = Ruma {
|
let body = Ruma {
|
||||||
sender_id: body.sender_id.clone(),
|
sender_id: body.sender_id.clone(),
|
||||||
|
@ -83,7 +171,7 @@ pub fn join_room_by_id_or_alias_route(
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(join_room_by_id_or_alias::Response {
|
Ok(join_room_by_id_or_alias::Response {
|
||||||
room_id: join_room_by_id_route(db, body)?.0.room_id,
|
room_id: join_room_by_id_route(db2, body).await?.0.room_id,
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,13 +92,6 @@ pub fn create_room_route(
|
||||||
&db.account_data,
|
&db.account_data,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Figure out preset. We need it for power levels and preset specific events
|
|
||||||
let visibility = body.visibility.unwrap_or(room::Visibility::Private);
|
|
||||||
let preset = body.preset.unwrap_or_else(|| match visibility {
|
|
||||||
room::Visibility::Private => create_room::RoomPreset::PrivateChat,
|
|
||||||
room::Visibility::Public => create_room::RoomPreset::PublicChat,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 3. Power levels
|
// 3. Power levels
|
||||||
let mut users = BTreeMap::new();
|
let mut users = BTreeMap::new();
|
||||||
users.insert(sender_id.clone(), 100.into());
|
users.insert(sender_id.clone(), 100.into());
|
||||||
|
@ -142,6 +135,14 @@ pub 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 visibility = body.visibility.unwrap_or(room::Visibility::Private);
|
||||||
|
let preset = body.preset.unwrap_or_else(|| match visibility {
|
||||||
|
room::Visibility::Private => create_room::RoomPreset::PrivateChat,
|
||||||
|
room::Visibility::Public => create_room::RoomPreset::PublicChat,
|
||||||
|
});
|
||||||
|
|
||||||
// 4.1 Join Rules
|
// 4.1 Join Rules
|
||||||
db.rooms.append_pdu(
|
db.rooms.append_pdu(
|
||||||
PduBuilder {
|
PduBuilder {
|
||||||
|
|
|
@ -27,6 +27,13 @@ pub enum Error {
|
||||||
#[from]
|
#[from]
|
||||||
source: image::error::ImageError,
|
source: image::error::ImageError,
|
||||||
},
|
},
|
||||||
|
#[error("Could not connect to server.")]
|
||||||
|
ReqwestError {
|
||||||
|
#[from]
|
||||||
|
source: reqwest::Error,
|
||||||
|
},
|
||||||
|
#[error("{0}")]
|
||||||
|
BadServerResponse(&'static str),
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
BadConfig(&'static str),
|
BadConfig(&'static str),
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod client_server;
|
pub mod client_server;
|
||||||
|
pub mod server_server;
|
||||||
mod database;
|
mod database;
|
||||||
mod error;
|
mod error;
|
||||||
mod pdu;
|
mod pdu;
|
||||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -1,13 +1,13 @@
|
||||||
#![warn(rust_2018_idioms)]
|
#![warn(rust_2018_idioms)]
|
||||||
|
|
||||||
pub mod push_rules;
|
pub mod server_server;
|
||||||
|
pub mod client_server;
|
||||||
|
|
||||||
mod client_server;
|
mod push_rules;
|
||||||
mod database;
|
mod database;
|
||||||
mod error;
|
mod error;
|
||||||
mod pdu;
|
mod pdu;
|
||||||
mod ruma_wrapper;
|
mod ruma_wrapper;
|
||||||
//mod server_server;
|
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
pub use database::Database;
|
pub use database::Database;
|
||||||
|
@ -110,10 +110,10 @@ fn setup_rocket() -> rocket::Rocket {
|
||||||
client_server::get_key_changes_route,
|
client_server::get_key_changes_route,
|
||||||
client_server::get_pushers_route,
|
client_server::get_pushers_route,
|
||||||
client_server::set_pushers_route,
|
client_server::set_pushers_route,
|
||||||
//server_server::well_known_server,
|
server_server::well_known_server,
|
||||||
//server_server::get_server_version,
|
server_server::get_server_version,
|
||||||
//server_server::get_server_keys,
|
server_server::get_server_keys,
|
||||||
//server_server::get_server_keys_deprecated,
|
server_server::get_server_keys_deprecated,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.attach(AdHoc::on_attach("Config", |mut rocket| async {
|
.attach(AdHoc::on_attach("Config", |mut rocket| async {
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
use crate::{Database, MatrixResult};
|
use crate::{ConduitResult, Database, Result};
|
||||||
use http::header::{HeaderValue, AUTHORIZATION};
|
use http::header::{HeaderValue, AUTHORIZATION};
|
||||||
use log::error;
|
|
||||||
use rocket::{get, response::content::Json, State};
|
use rocket::{get, response::content::Json, State};
|
||||||
use ruma::api::Endpoint;
|
|
||||||
use ruma::api::client::error::Error;
|
|
||||||
use ruma::api::federation::discovery::{
|
use ruma::api::federation::discovery::{
|
||||||
get_server_keys::v2 as get_server_keys, get_server_version::v1 as get_server_version,
|
get_server_keys, get_server_version::v1 as get_server_version, ServerKey, VerifyKey,
|
||||||
};
|
};
|
||||||
|
use ruma::api::OutgoingRequest;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{
|
use std::{
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
|
fmt::Debug,
|
||||||
time::{Duration, SystemTime},
|
time::{Duration, SystemTime},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,36 +32,51 @@ pub async fn request_well_known(db: &crate::Database, destination: &str) -> Opti
|
||||||
Some(body.get("m.server")?.as_str()?.to_owned())
|
Some(body.get("m.server")?.as_str()?.to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_request<T: Endpoint>(
|
pub async fn send_request<T: OutgoingRequest>(
|
||||||
db: &crate::Database,
|
db: &crate::Database,
|
||||||
destination: String,
|
destination: String,
|
||||||
request: T,
|
request: T,
|
||||||
) -> Option<T::Response> {
|
) -> Result<T::IncomingResponse>
|
||||||
let mut http_request: http::Request<_> = request.try_into().unwrap();
|
where
|
||||||
|
T: Debug,
|
||||||
|
{
|
||||||
let actual_destination = "https://".to_owned()
|
let actual_destination = "https://".to_owned()
|
||||||
+ &request_well_known(db, &destination)
|
+ &request_well_known(db, &destination)
|
||||||
.await
|
.await
|
||||||
.unwrap_or(destination.clone() + ":8448");
|
.unwrap_or(destination.clone() + ":8448");
|
||||||
*http_request.uri_mut() = (actual_destination + T::METADATA.path).parse().unwrap();
|
|
||||||
|
let mut http_request = request
|
||||||
|
.try_into_http_request(&actual_destination, Some(""))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut request_map = serde_json::Map::new();
|
let mut request_map = serde_json::Map::new();
|
||||||
|
|
||||||
if !http_request.body().is_empty() {
|
if !http_request.body().is_empty() {
|
||||||
request_map.insert(
|
request_map.insert(
|
||||||
"content".to_owned(),
|
"content".to_owned(),
|
||||||
serde_json::to_value(http_request.body()).unwrap(),
|
serde_json::from_slice(http_request.body()).unwrap(),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
request_map.insert("method".to_owned(), T::METADATA.method.to_string().into());
|
request_map.insert("method".to_owned(), T::METADATA.method.to_string().into());
|
||||||
request_map.insert("uri".to_owned(), T::METADATA.path.into());
|
request_map.insert(
|
||||||
request_map.insert("origin".to_owned(), db.globals.server_name().into());
|
"uri".to_owned(),
|
||||||
|
http_request
|
||||||
|
.uri()
|
||||||
|
.path_and_query()
|
||||||
|
.expect("all requests have a path")
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
request_map.insert(
|
||||||
|
"origin".to_owned(),
|
||||||
|
db.globals.server_name().as_str().into(),
|
||||||
|
);
|
||||||
request_map.insert("destination".to_owned(), destination.into());
|
request_map.insert("destination".to_owned(), destination.into());
|
||||||
|
|
||||||
let mut request_json = request_map.into();
|
let mut request_json = request_map.into();
|
||||||
ruma::signatures::sign_json(
|
ruma::signatures::sign_json(
|
||||||
db.globals.server_name(),
|
db.globals.server_name().as_str(),
|
||||||
db.globals.keypair(),
|
db.globals.keypair(),
|
||||||
&mut request_json,
|
&mut request_json,
|
||||||
)
|
)
|
||||||
|
@ -72,31 +86,32 @@ pub async fn send_request<T: Endpoint>(
|
||||||
.as_object()
|
.as_object()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.values()
|
.values()
|
||||||
.next()
|
.map(|v| {
|
||||||
.unwrap()
|
v.as_object()
|
||||||
.as_object()
|
.unwrap()
|
||||||
.unwrap()
|
.iter()
|
||||||
.iter()
|
.map(|(k, v)| (k, v.as_str().unwrap()))
|
||||||
.map(|(k, v)| (k, v.as_str().unwrap()));
|
});
|
||||||
|
|
||||||
for s in signatures {
|
for signature_server in signatures {
|
||||||
http_request.headers_mut().insert(
|
for s in signature_server {
|
||||||
AUTHORIZATION,
|
http_request.headers_mut().insert(
|
||||||
HeaderValue::from_str(&format!(
|
AUTHORIZATION,
|
||||||
"X-Matrix origin={},key=\"{}\",sig=\"{}\"",
|
HeaderValue::from_str(&format!(
|
||||||
db.globals.server_name(),
|
"X-Matrix origin={},key=\"{}\",sig=\"{}\"",
|
||||||
s.0,
|
db.globals.server_name(),
|
||||||
s.1
|
s.0,
|
||||||
))
|
s.1
|
||||||
.unwrap(),
|
))
|
||||||
);
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let reqwest_response = db
|
let reqwest_request = reqwest::Request::try_from(http_request)
|
||||||
.globals
|
.expect("all http requests are valid reqwest requests");
|
||||||
.reqwest_client()
|
|
||||||
.execute(http_request.into())
|
let reqwest_response = db.globals.reqwest_client().execute(reqwest_request).await;
|
||||||
.await;
|
|
||||||
|
|
||||||
// Because reqwest::Response -> http::Response is complicated:
|
// Because reqwest::Response -> http::Response is complicated:
|
||||||
match reqwest_response {
|
match reqwest_response {
|
||||||
|
@ -117,59 +132,56 @@ pub async fn send_request<T: Endpoint>(
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
Some(
|
Ok(
|
||||||
<T::Response>::try_from(http_response.body(body).unwrap())
|
T::IncomingResponse::try_from(http_response.body(body).unwrap())
|
||||||
.ok()
|
.expect("TODO: error handle other server errors"),
|
||||||
.unwrap(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => Err(e.into()),
|
||||||
error!("{}", e);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "conduit_bin",get("/.well-known/matrix/server"))]
|
#[cfg_attr(feature = "conduit_bin", get("/.well-known/matrix/server"))]
|
||||||
pub fn well_known_server() -> Json<String> {
|
pub fn well_known_server() -> Json<String> {
|
||||||
rocket::response::content::Json(
|
rocket::response::content::Json(json!({ "m.server": "pc.koesters.xyz:59003"}).to_string())
|
||||||
json!({ "m.server": "matrixtesting.koesters.xyz:14004"}).to_string(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "conduit_bin",get("/_matrix/federation/v1/version"))]
|
#[cfg_attr(feature = "conduit_bin", get("/_matrix/federation/v1/version"))]
|
||||||
pub fn get_server_version() -> MatrixResult<get_server_version::Response, Error> {
|
pub fn get_server_version() -> ConduitResult<get_server_version::Response> {
|
||||||
MatrixResult(Ok(get_server_version::Response {
|
Ok(get_server_version::Response {
|
||||||
server: Some(get_server_version::Server {
|
server: Some(get_server_version::Server {
|
||||||
name: Some("Conduit".to_owned()),
|
name: Some("Conduit".to_owned()),
|
||||||
version: Some(env!("CARGO_PKG_VERSION").to_owned()),
|
version: Some(env!("CARGO_PKG_VERSION").to_owned()),
|
||||||
}),
|
}),
|
||||||
}))
|
}
|
||||||
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "conduit_bin",get("/_matrix/key/v2/server"))]
|
#[cfg_attr(feature = "conduit_bin", get("/_matrix/key/v2/server"))]
|
||||||
pub fn get_server_keys(db: State<'_, Database>) -> Json<String> {
|
pub fn get_server_keys(db: State<'_, Database>) -> Json<String> {
|
||||||
let mut verify_keys = BTreeMap::new();
|
let mut verify_keys = BTreeMap::new();
|
||||||
verify_keys.insert(
|
verify_keys.insert(
|
||||||
format!("ed25519:{}", db.globals.keypair().version()),
|
format!("ed25519:{}", db.globals.keypair().version()),
|
||||||
get_server_keys::VerifyKey {
|
VerifyKey {
|
||||||
key: base64::encode_config(db.globals.keypair().public_key(), base64::STANDARD_NO_PAD),
|
key: base64::encode_config(db.globals.keypair().public_key(), base64::STANDARD_NO_PAD),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let mut response = serde_json::from_slice(
|
let mut response = serde_json::from_slice(
|
||||||
http::Response::try_from(get_server_keys::Response {
|
http::Response::try_from(get_server_keys::v2::Response {
|
||||||
server_name: db.globals.server_name().to_owned(),
|
server_key: ServerKey {
|
||||||
verify_keys,
|
server_name: db.globals.server_name().to_owned(),
|
||||||
old_verify_keys: BTreeMap::new(),
|
verify_keys,
|
||||||
signatures: BTreeMap::new(),
|
old_verify_keys: BTreeMap::new(),
|
||||||
valid_until_ts: SystemTime::now() + Duration::from_secs(60 * 2),
|
signatures: BTreeMap::new(),
|
||||||
|
valid_until_ts: SystemTime::now() + Duration::from_secs(60 * 2),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.body(),
|
.body(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ruma::signatures::sign_json(
|
ruma::signatures::sign_json(
|
||||||
db.globals.server_name(),
|
db.globals.server_name().as_str(),
|
||||||
db.globals.keypair(),
|
db.globals.keypair(),
|
||||||
&mut response,
|
&mut response,
|
||||||
)
|
)
|
||||||
|
@ -177,7 +189,7 @@ pub fn get_server_keys(db: State<'_, Database>) -> Json<String> {
|
||||||
Json(response.to_string())
|
Json(response.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "conduit_bin",get("/_matrix/key/v2/server/<_key_id>"))]
|
#[cfg_attr(feature = "conduit_bin", get("/_matrix/key/v2/server/<_>"))]
|
||||||
pub fn get_server_keys_deprecated(db: State<'_, Database>, _key_id: String) -> Json<String> {
|
pub fn get_server_keys_deprecated(db: State<'_, Database>) -> Json<String> {
|
||||||
get_server_keys(db)
|
get_server_keys(db)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue