From 40699c395ab0c1530aecba811f5ef2ade065d99a Mon Sep 17 00:00:00 2001 From: mikoto Date: Mon, 10 Jun 2024 16:07:47 +0200 Subject: [PATCH] PoC --- conduit-example.toml | 4 ++- src/api/client_server/account.rs | 27 ++++++++++++++- src/api/client_server/membership.rs | 2 +- src/config/mod.rs | 2 ++ src/database/mod.rs | 7 ++++ src/service/globals/mod.rs | 51 +++++++++++++++++++++++++++-- 6 files changed, 88 insertions(+), 5 deletions(-) diff --git a/conduit-example.toml b/conduit-example.toml index 74cbb074..558e62ab 100644 --- a/conduit-example.toml +++ b/conduit-example.toml @@ -42,7 +42,7 @@ allow_registration = true # an account. YOU NEED TO EDIT THIS. # - Insert a password that users will have to enter on registration # - Start the line with '#' to remove the condition -registration_token = "" +# registration_token = "" allow_check_for_updates = true allow_federation = true @@ -58,6 +58,8 @@ trusted_servers = ["matrix.org"] #max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time +join_by_default = ["home", "!oN47OFomZSVRQVCLLw"] + # Controls the log verbosity. See also [here][0]. # # [0]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives diff --git a/src/api/client_server/account.rs b/src/api/client_server/account.rs index 47ccdc83..d89c60f7 100644 --- a/src/api/client_server/account.rs +++ b/src/api/client_server/account.rs @@ -1,5 +1,8 @@ use super::{DEVICE_ID_LENGTH, SESSION_ID_LENGTH, TOKEN_LENGTH}; -use crate::{api::client_server, services, utils, Error, Result, Ruma}; +use crate::{ + api::client_server::{self, membership::join_room_by_id_helper}, + services, utils, Error, Result, Ruma, +}; use ruma::{ api::client::{ account::{ @@ -287,6 +290,28 @@ pub async fn register_route(body: Ruma) -> Result, room_id: &RoomId, reason: Option, diff --git a/src/config/mod.rs b/src/config/mod.rs index 378ab929..9d2b9e44 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -59,6 +59,8 @@ pub struct Config { pub allow_unstable_room_versions: bool, #[serde(default = "default_default_room_version")] pub default_room_version: RoomVersionId, + #[serde(default = "Vec::new")] + pub join_by_default: Vec, #[serde(default)] pub well_known: WellKnownConfig, #[serde(default = "false_fn")] diff --git a/src/database/mod.rs b/src/database/mod.rs index 5171d4bb..577182c5 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -969,6 +969,13 @@ impl KeyValueDatabase { // This data is probably outdated db.presenceid_presence.clear()?; + // Can only return an error during the first call + services().globals.join_by_default().map_err(|e| { + tracing::error!("Invalid room ID or alias in join-by-default rooms: {}", e); + + Error::bad_config("Invalid room ID or alias in join-by-default rooms.") + })?; + services().admin.start_handler(); // Set emergency access for the conduit user diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index 3325e518..70a3d47c 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -1,9 +1,11 @@ mod data; pub use data::{Data, SigningKeys}; + use ruma::{ serde::Base64, MilliSecondsSinceUnixEpoch, OwnedDeviceId, OwnedEventId, OwnedRoomAliasId, OwnedRoomId, OwnedServerName, OwnedUserId, RoomAliasId, }; +use tokio::sync::OnceCell; use crate::api::server_server::DestinationResponse; @@ -17,7 +19,7 @@ use ruma::{ DeviceId, RoomVersionId, ServerName, UserId, }; use std::{ - collections::{BTreeMap, HashMap}, + collections::{BTreeMap, BTreeSet, HashMap}, error::Error as StdError, fs, future::{self, Future}, @@ -33,7 +35,7 @@ use std::{ }; use tokio::sync::{broadcast, watch::Receiver, Mutex, RwLock, Semaphore}; use tower_service::Service as TowerService; -use tracing::{error, info}; +use tracing::{error, info, warn}; use base64::{engine::general_purpose, Engine as _}; @@ -68,6 +70,7 @@ pub struct Service { pub roomid_mutex_state: RwLock>>>, pub roomid_mutex_federation: RwLock>>>, // this lock will be held longer pub roomid_federationhandletime: RwLock>, + join_by_default: OnceCell>, server_user: OwnedUserId, admin_alias: OwnedRoomAliasId, pub stateres_mutex: Arc>, @@ -221,6 +224,7 @@ impl Service { roomid_mutex_insert: RwLock::new(HashMap::new()), roomid_mutex_federation: RwLock::new(HashMap::new()), roomid_federationhandletime: RwLock::new(HashMap::new()), + join_by_default: OnceCell::new(), stateres_mutex: Arc::new(Mutex::new(())), sync_receivers: RwLock::new(HashMap::new()), rotate: RotationHandler::new(), @@ -505,6 +509,49 @@ impl Service { self.config.well_known_client() } + pub fn join_by_default(&self) -> Result<&BTreeSet> { + if let Some(set) = self.join_by_default.get() { + return Ok(set); + } + + let server_name = self.config.server_name.as_str(); + let mut join_by_default = BTreeSet::new(); + + for s in self.config.join_by_default.iter().cloned() { + let next = s + .chars() + .next() + .ok_or_else(|| Error::bad_config("Invalid room ID for join-by-default."))?; + + let room_id = if next == '!' { + let id = s.split(':').next().unwrap_or(&s); + + OwnedRoomId::from_str(&format!("{id}:{server_name}",)) + .map_err(|_| Error::bad_config("Invalid room ID for join-by-default rooms."))? + } else { + let id = s.split(':').next().unwrap_or(&s).trim_start_matches('#'); + + let alias = OwnedRoomAliasId::from_str(&format!("#{id}:{server_name}",)) + .map_err(|_| Error::bad_config("Invalid room alias for join-by-default."))?; + + let Some(room_id) = services().rooms.alias.resolve_local_alias(&alias)? else { + warn!("Could not resolve Room ID for join-by-default rooms locally."); + continue; + }; + + room_id + }; + + join_by_default.insert(room_id); + } + + self.join_by_default + .set(join_by_default) + .expect("join_by_default should be set once"); + + self.join_by_default() + } + pub fn shutdown(&self) { self.shutdown.store(true, atomic::Ordering::Relaxed); // On shutdown