feat: first steps towards joining rooms over federation
This commit is contained in:
		
							parent
							
								
									f40f1d9f75
								
							
						
					
					
						commit
						04eee089e0
					
				
					 10 changed files with 291 additions and 143 deletions
				
			
		
							
								
								
									
										27
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										27
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							|  | @ -267,6 +267,7 @@ checksum = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" | |||
| name = "conduit" | ||||
| version = "0.1.0" | ||||
| dependencies = [ | ||||
|  "base64 0.12.3", | ||||
|  "directories", | ||||
|  "http", | ||||
|  "image", | ||||
|  | @ -1559,7 +1560,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma" | ||||
| 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 = [ | ||||
|  "ruma-api", | ||||
|  "ruma-client-api", | ||||
|  | @ -1573,7 +1574,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-api" | ||||
| 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 = [ | ||||
|  "http", | ||||
|  "percent-encoding", | ||||
|  | @ -1588,7 +1589,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-api-macros" | ||||
| 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 = [ | ||||
|  "proc-macro-crate", | ||||
|  "proc-macro2", | ||||
|  | @ -1599,7 +1600,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-client-api" | ||||
| 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 = [ | ||||
|  "assign", | ||||
|  "http", | ||||
|  | @ -1617,7 +1618,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-common" | ||||
| 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 = [ | ||||
|  "js_int", | ||||
|  "ruma-identifiers", | ||||
|  | @ -1630,7 +1631,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-events" | ||||
| 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 = [ | ||||
|  "js_int", | ||||
|  "ruma-common", | ||||
|  | @ -1645,7 +1646,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-events-macros" | ||||
| 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 = [ | ||||
|  "proc-macro-crate", | ||||
|  "proc-macro2", | ||||
|  | @ -1656,7 +1657,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-federation-api" | ||||
| 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 = [ | ||||
|  "js_int", | ||||
|  "ruma-api", | ||||
|  | @ -1671,7 +1672,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-identifiers" | ||||
| 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 = [ | ||||
|  "rand", | ||||
|  "ruma-identifiers-macros", | ||||
|  | @ -1683,7 +1684,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-identifiers-macros" | ||||
| 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 = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  | @ -1694,7 +1695,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-identifiers-validation" | ||||
| 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 = [ | ||||
|  "ruma-serde", | ||||
|  "serde", | ||||
|  | @ -1705,7 +1706,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-serde" | ||||
| 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 = [ | ||||
|  "form_urlencoded", | ||||
|  "itoa", | ||||
|  | @ -1717,7 +1718,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-signatures" | ||||
| 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 = [ | ||||
|  "base64 0.12.3", | ||||
|  "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/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"] } | ||||
| tokio = "0.2.22" # Used for long polling | ||||
| sled = "0.32.0" # Used for storing data permanently | ||||
| log = "0.4.8" # Used for emitting log entries | ||||
| 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 | ||||
| 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 | ||||
| base64 = "0.12.3" # Used to encode server public key | ||||
| 
 | ||||
| [features] | ||||
| default = ["conduit_bin"] | ||||
|  |  | |||
|  | @ -1,9 +1,9 @@ | |||
| use super::State; | ||||
| use crate::{ConduitResult, Database, Error, Ruma}; | ||||
| use ruma::api::client::{ | ||||
| use crate::{ConduitResult, Database, Error, Ruma, server_server}; | ||||
| use ruma::api::{federation, client::{ | ||||
|     error::ErrorKind, | ||||
|     r0::alias::{create_alias, delete_alias, get_alias}, | ||||
| }; | ||||
| }}; | ||||
| 
 | ||||
| #[cfg(feature = "conduit_bin")] | ||||
| use rocket::{delete, get, put}; | ||||
|  | @ -43,12 +43,25 @@ pub fn delete_alias_route( | |||
|     feature = "conduit_bin", | ||||
|     get("/_matrix/client/r0/directory/room/<_>", data = "<body>") | ||||
| )] | ||||
| pub fn get_alias_route( | ||||
| pub async fn get_alias_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<get_alias::IncomingRequest>, | ||||
| ) -> ConduitResult<get_alias::Response> { | ||||
|     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 | ||||
|  |  | |||
|  | @ -1,7 +1,8 @@ | |||
| use super::State; | ||||
| use crate::{ConduitResult, Database, Error, Result, Ruma}; | ||||
| use crate::{server_server, ConduitResult, Database, Error, Result, Ruma}; | ||||
| use ruma::{ | ||||
|     api::client::{ | ||||
|     api::{ | ||||
|         client::{ | ||||
|             error::ErrorKind, | ||||
|             r0::{ | ||||
|                 directory::{ | ||||
|  | @ -11,6 +12,8 @@ use ruma::{ | |||
|                 room, | ||||
|             }, | ||||
|         }, | ||||
|         federation, | ||||
|     }, | ||||
|     events::{ | ||||
|         room::{avatar, canonical_alias, guest_access, history_visibility, name, topic}, | ||||
|         EventType, | ||||
|  | @ -29,6 +32,46 @@ pub async fn get_public_rooms_filtered_route( | |||
|     db: State<'_, Database>, | ||||
|     body: Ruma<get_public_rooms_filtered::IncomingRequest>, | ||||
| ) -> 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 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.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 chunk = all_rooms | ||||
|  |  | |||
|  | @ -1,16 +1,24 @@ | |||
| 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::{ | ||||
|     api::client::{ | ||||
|     api::{ | ||||
|         client::{ | ||||
|             error::ErrorKind, | ||||
|         r0::membership::{ | ||||
|             r0::{ | ||||
|                 alias, | ||||
|                 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}, | ||||
|     Raw, RoomId, | ||||
|     EventId, Raw, RoomId, RoomVersionId, | ||||
| }; | ||||
| use std::{collections::BTreeMap, convert::TryFrom}; | ||||
| 
 | ||||
|  | @ -21,13 +29,81 @@ use rocket::{get, post}; | |||
|     feature = "conduit_bin", | ||||
|     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>, | ||||
|     body: Ruma<join_room_by_id::IncomingRequest>, | ||||
| ) -> ConduitResult<join_room_by_id::Response> { | ||||
|     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 { | ||||
|         membership: member::MembershipState::Join, | ||||
|  | @ -61,16 +137,28 @@ pub fn join_room_by_id_route( | |||
|     feature = "conduit_bin", | ||||
|     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>, | ||||
|     db2: State<'_, Database>, | ||||
|     body: Ruma<join_room_by_id_or_alias::Request>, | ||||
| ) -> ConduitResult<join_room_by_id_or_alias::Response> { | ||||
|     let room_id = RoomId::try_from(body.room_id_or_alias.clone()).or_else(|alias| { | ||||
|         Ok::<_, Error>(db.rooms.id_from_alias(&alias)?.ok_or(Error::BadRequest( | ||||
|             ErrorKind::NotFound, | ||||
|             "Room not found (TODO: Federation).", | ||||
|         ))?) | ||||
|     })?; | ||||
|     let room_id = match RoomId::try_from(body.room_id_or_alias.clone()) { | ||||
|         Ok(room_id) => room_id, | ||||
|         Err(room_alias) => { | ||||
|             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 { | ||||
|         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 { | ||||
|         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()) | ||||
| } | ||||
|  |  | |||
|  | @ -92,13 +92,6 @@ pub fn create_room_route( | |||
|         &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
 | ||||
|     let mut users = BTreeMap::new(); | ||||
|     users.insert(sender_id.clone(), 100.into()); | ||||
|  | @ -142,6 +135,14 @@ pub fn create_room_route( | |||
|     )?; | ||||
| 
 | ||||
|     // 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
 | ||||
|     db.rooms.append_pdu( | ||||
|         PduBuilder { | ||||
|  |  | |||
|  | @ -27,6 +27,13 @@ pub enum Error { | |||
|         #[from] | ||||
|         source: image::error::ImageError, | ||||
|     }, | ||||
|     #[error("Could not connect to server.")] | ||||
|     ReqwestError { | ||||
|         #[from] | ||||
|         source: reqwest::Error, | ||||
|     }, | ||||
|     #[error("{0}")] | ||||
|     BadServerResponse(&'static str), | ||||
|     #[error("{0}")] | ||||
|     BadConfig(&'static str), | ||||
|     #[error("{0}")] | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| pub mod client_server; | ||||
| pub mod server_server; | ||||
| mod database; | ||||
| mod error; | ||||
| mod pdu; | ||||
|  |  | |||
							
								
								
									
										14
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/main.rs
									
									
									
									
									
								
							|  | @ -1,13 +1,13 @@ | |||
| #![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 error; | ||||
| mod pdu; | ||||
| mod ruma_wrapper; | ||||
| //mod server_server;
 | ||||
| mod utils; | ||||
| 
 | ||||
| pub use database::Database; | ||||
|  | @ -110,10 +110,10 @@ fn setup_rocket() -> rocket::Rocket { | |||
|                 client_server::get_key_changes_route, | ||||
|                 client_server::get_pushers_route, | ||||
|                 client_server::set_pushers_route, | ||||
|                 //server_server::well_known_server,
 | ||||
|                 //server_server::get_server_version,
 | ||||
|                 //server_server::get_server_keys,
 | ||||
|                 //server_server::get_server_keys_deprecated,
 | ||||
|                 server_server::well_known_server, | ||||
|                 server_server::get_server_version, | ||||
|                 server_server::get_server_keys, | ||||
|                 server_server::get_server_keys_deprecated, | ||||
|             ], | ||||
|         ) | ||||
|         .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 log::error; | ||||
| use rocket::{get, response::content::Json, State}; | ||||
| use ruma::api::Endpoint; | ||||
| use ruma::api::client::error::Error; | ||||
| 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 std::{ | ||||
|     collections::BTreeMap, | ||||
|     convert::TryFrom, | ||||
|     fmt::Debug, | ||||
|     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()) | ||||
| } | ||||
| 
 | ||||
| pub async fn send_request<T: Endpoint>( | ||||
| pub async fn send_request<T: OutgoingRequest>( | ||||
|     db: &crate::Database, | ||||
|     destination: String, | ||||
|     request: T, | ||||
| ) -> Option<T::Response> { | ||||
|     let mut http_request: http::Request<_> = request.try_into().unwrap(); | ||||
| 
 | ||||
| ) -> Result<T::IncomingResponse> | ||||
| where | ||||
|     T: Debug, | ||||
| { | ||||
|     let actual_destination = "https://".to_owned() | ||||
|         + &request_well_known(db, &destination) | ||||
|             .await | ||||
|             .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(); | ||||
| 
 | ||||
|     if !http_request.body().is_empty() { | ||||
|         request_map.insert( | ||||
|             "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("uri".to_owned(), T::METADATA.path.into()); | ||||
|     request_map.insert("origin".to_owned(), db.globals.server_name().into()); | ||||
|     request_map.insert( | ||||
|         "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()); | ||||
| 
 | ||||
|     let mut request_json = request_map.into(); | ||||
|     ruma::signatures::sign_json( | ||||
|         db.globals.server_name(), | ||||
|         db.globals.server_name().as_str(), | ||||
|         db.globals.keypair(), | ||||
|         &mut request_json, | ||||
|     ) | ||||
|  | @ -72,14 +86,15 @@ pub async fn send_request<T: Endpoint>( | |||
|         .as_object() | ||||
|         .unwrap() | ||||
|         .values() | ||||
|         .next() | ||||
|         .unwrap() | ||||
|         .as_object() | ||||
|         .map(|v| { | ||||
|             v.as_object() | ||||
|                 .unwrap() | ||||
|                 .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 { | ||||
|         for s in signature_server { | ||||
|             http_request.headers_mut().insert( | ||||
|                 AUTHORIZATION, | ||||
|                 HeaderValue::from_str(&format!( | ||||
|  | @ -91,12 +106,12 @@ pub async fn send_request<T: Endpoint>( | |||
|                 .unwrap(), | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     let reqwest_response = db | ||||
|         .globals | ||||
|         .reqwest_client() | ||||
|         .execute(http_request.into()) | ||||
|         .await; | ||||
|     let reqwest_request = reqwest::Request::try_from(http_request) | ||||
|         .expect("all http requests are valid reqwest requests"); | ||||
| 
 | ||||
|     let reqwest_response = db.globals.reqwest_client().execute(reqwest_request).await; | ||||
| 
 | ||||
|     // Because reqwest::Response -> http::Response is complicated:
 | ||||
|     match reqwest_response { | ||||
|  | @ -117,59 +132,56 @@ pub async fn send_request<T: Endpoint>( | |||
|                 .unwrap() | ||||
|                 .into_iter() | ||||
|                 .collect(); | ||||
|             Some( | ||||
|                 <T::Response>::try_from(http_response.body(body).unwrap()) | ||||
|                     .ok() | ||||
|                     .unwrap(), | ||||
|             Ok( | ||||
|                 T::IncomingResponse::try_from(http_response.body(body).unwrap()) | ||||
|                     .expect("TODO: error handle other server errors"), | ||||
|             ) | ||||
|         } | ||||
|         Err(e) => { | ||||
|             error!("{}", e); | ||||
|             None | ||||
|         } | ||||
|         Err(e) => Err(e.into()), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[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> { | ||||
|     rocket::response::content::Json( | ||||
|         json!({ "m.server": "matrixtesting.koesters.xyz:14004"}).to_string(), | ||||
|     ) | ||||
|     rocket::response::content::Json(json!({ "m.server": "pc.koesters.xyz:59003"}).to_string()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(feature = "conduit_bin",get("/_matrix/federation/v1/version"))] | ||||
| pub fn get_server_version() -> MatrixResult<get_server_version::Response, Error> { | ||||
|     MatrixResult(Ok(get_server_version::Response { | ||||
| #[cfg_attr(feature = "conduit_bin", get("/_matrix/federation/v1/version"))] | ||||
| pub fn get_server_version() -> ConduitResult<get_server_version::Response> { | ||||
|     Ok(get_server_version::Response { | ||||
|         server: Some(get_server_version::Server { | ||||
|             name: Some("Conduit".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> { | ||||
|     let mut verify_keys = BTreeMap::new(); | ||||
|     verify_keys.insert( | ||||
|         format!("ed25519:{}", db.globals.keypair().version()), | ||||
|         get_server_keys::VerifyKey { | ||||
|         VerifyKey { | ||||
|             key: base64::encode_config(db.globals.keypair().public_key(), base64::STANDARD_NO_PAD), | ||||
|         }, | ||||
|     ); | ||||
|     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_key: ServerKey { | ||||
|                 server_name: db.globals.server_name().to_owned(), | ||||
|                 verify_keys, | ||||
|                 old_verify_keys: BTreeMap::new(), | ||||
|                 signatures: BTreeMap::new(), | ||||
|                 valid_until_ts: SystemTime::now() + Duration::from_secs(60 * 2), | ||||
|             }, | ||||
|         }) | ||||
|         .unwrap() | ||||
|         .body(), | ||||
|     ) | ||||
|     .unwrap(); | ||||
|     ruma::signatures::sign_json( | ||||
|         db.globals.server_name(), | ||||
|         db.globals.server_name().as_str(), | ||||
|         db.globals.keypair(), | ||||
|         &mut response, | ||||
|     ) | ||||
|  | @ -177,7 +189,7 @@ pub fn get_server_keys(db: State<'_, Database>) -> Json<String> { | |||
|     Json(response.to_string()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(feature = "conduit_bin",get("/_matrix/key/v2/server/<_key_id>"))] | ||||
| pub fn get_server_keys_deprecated(db: State<'_, Database>, _key_id: String) -> Json<String> { | ||||
| #[cfg_attr(feature = "conduit_bin", get("/_matrix/key/v2/server/<_>"))] | ||||
| pub fn get_server_keys_deprecated(db: State<'_, Database>) -> Json<String> { | ||||
|     get_server_keys(db) | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue