From 8e8c6bfe07633eea75149ed067a04bc393433c15 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Thu, 5 Dec 2024 07:23:51 +0000 Subject: [PATCH] abstract supported room versions apis Signed-off-by: Jason Volk --- src/api/client/capabilities.rs | 16 ++-------- src/api/client/membership.rs | 20 +++--------- src/api/client/room/create.rs | 8 ++--- src/api/client/room/upgrade.rs | 6 +--- src/api/server/invite.rs | 6 +--- src/core/info/mod.rs | 1 + src/core/info/room_version.rs | 58 ++++++++++++++++++++++++++++++++++ src/service/admin/create.rs | 5 ++- src/service/globals/mod.rs | 43 +++---------------------- 9 files changed, 75 insertions(+), 88 deletions(-) create mode 100644 src/core/info/room_version.rs diff --git a/src/api/client/capabilities.rs b/src/api/client/capabilities.rs index 89157e47..20f9cb58 100644 --- a/src/api/client/capabilities.rs +++ b/src/api/client/capabilities.rs @@ -19,23 +19,11 @@ use crate::{Result, Ruma}; pub(crate) async fn get_capabilities_route( State(services): State, _body: Ruma, ) -> Result { - let available: BTreeMap = services - .globals - .unstable_room_versions - .iter() - .map(|unstable_room_version| (unstable_room_version.clone(), RoomVersionStability::Unstable)) - .chain( - services - .globals - .stable_room_versions - .iter() - .map(|stable_room_version| (stable_room_version.clone(), RoomVersionStability::Stable)), - ) - .collect(); + let available: BTreeMap = services.server.available_room_versions().collect(); let mut capabilities = Capabilities::default(); capabilities.room_versions = RoomVersionsCapability { - default: services.globals.default_room_version(), + default: services.server.config.default_room_version.clone(), available, }; diff --git a/src/api/client/membership.rs b/src/api/client/membership.rs index 9478e383..1cdf25a2 100644 --- a/src/api/client/membership.rs +++ b/src/api/client/membership.rs @@ -706,11 +706,7 @@ async fn join_room_by_id_helper_remote( return Err!(BadServerResponse("Remote room version is not supported by conduwuit")); }; - if !services - .globals - .supported_room_versions() - .contains(&room_version_id) - { + if !services.server.supported_room_version(&room_version_id) { return Err!(BadServerResponse( "Remote room version {room_version_id} is not supported by conduwuit" )); @@ -1122,11 +1118,7 @@ async fn join_room_by_id_helper_local( return Err!(BadServerResponse("Remote room version is not supported by conduwuit")); }; - if !services - .globals - .supported_room_versions() - .contains(&room_version_id) - { + if !services.server.supported_room_version(&room_version_id) { return Err!(BadServerResponse( "Remote room version {room_version_id} is not supported by conduwuit" )); @@ -1260,7 +1252,7 @@ async fn make_join_request( federation::membership::prepare_join_event::v1::Request { room_id: room_id.to_owned(), user_id: sender_user.to_owned(), - ver: services.globals.supported_room_versions(), + ver: services.server.supported_room_versions().collect(), }, ) .await; @@ -1616,11 +1608,7 @@ async fn remote_leave_room(services: &Services, user_id: &UserId, room_id: &Room return Err!(BadServerResponse("Remote room version is not supported by conduwuit")); }; - if !services - .globals - .supported_room_versions() - .contains(&room_version_id) - { + if !services.server.supported_room_version(&room_version_id) { return Err!(BadServerResponse( "Remote room version {room_version_id} is not supported by conduwuit" )); diff --git a/src/api/client/room/create.rs b/src/api/client/room/create.rs index 2ccb1c87..2e9852f8 100644 --- a/src/api/client/room/create.rs +++ b/src/api/client/room/create.rs @@ -116,11 +116,7 @@ pub(crate) async fn create_room_route( let room_version = match body.room_version.clone() { Some(room_version) => { - if services - .globals - .supported_room_versions() - .contains(&room_version) - { + if services.server.supported_room_version(&room_version) { room_version } else { return Err(Error::BadRequest( @@ -129,7 +125,7 @@ pub(crate) async fn create_room_route( )); } }, - None => services.globals.default_room_version(), + None => services.server.config.default_room_version.clone(), }; let create_content = match &body.creation_content { diff --git a/src/api/client/room/upgrade.rs b/src/api/client/room/upgrade.rs index ad5c356e..fafce2d1 100644 --- a/src/api/client/room/upgrade.rs +++ b/src/api/client/room/upgrade.rs @@ -47,11 +47,7 @@ pub(crate) async fn upgrade_room_route( ) -> Result { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); - if !services - .globals - .supported_room_versions() - .contains(&body.new_version) - { + if !services.server.supported_room_version(&body.new_version) { return Err(Error::BadRequest( ErrorKind::UnsupportedRoomVersion, "This server does not support that room version.", diff --git a/src/api/server/invite.rs b/src/api/server/invite.rs index 0ceb914f..f7919bb3 100644 --- a/src/api/server/invite.rs +++ b/src/api/server/invite.rs @@ -26,11 +26,7 @@ pub(crate) async fn create_invite_route( .acl_check(body.origin(), &body.room_id) .await?; - if !services - .globals - .supported_room_versions() - .contains(&body.room_version) - { + if !services.server.supported_room_version(&body.room_version) { return Err(Error::BadRequest( ErrorKind::IncompatibleRoomVersion { room_version: body.room_version.clone(), diff --git a/src/core/info/mod.rs b/src/core/info/mod.rs index e4a33b4e..22ea7d3d 100644 --- a/src/core/info/mod.rs +++ b/src/core/info/mod.rs @@ -2,6 +2,7 @@ //! etc information which can be queried by admins or used by developers. pub mod cargo; +pub mod room_version; pub mod rustc; pub mod version; diff --git a/src/core/info/room_version.rs b/src/core/info/room_version.rs new file mode 100644 index 00000000..59685b5f --- /dev/null +++ b/src/core/info/room_version.rs @@ -0,0 +1,58 @@ +//! Room version support + +use std::iter::once; + +use ruma::{api::client::discovery::get_capabilities::RoomVersionStability, RoomVersionId}; + +use crate::{at, is_equal_to}; + +/// Supported and stable room versions +pub const STABLE_ROOM_VERSIONS: &[RoomVersionId] = &[ + RoomVersionId::V6, + RoomVersionId::V7, + RoomVersionId::V8, + RoomVersionId::V9, + RoomVersionId::V10, + RoomVersionId::V11, +]; + +/// Experimental, partially supported room versions +pub const UNSTABLE_ROOM_VERSIONS: &[RoomVersionId] = + &[RoomVersionId::V2, RoomVersionId::V3, RoomVersionId::V4, RoomVersionId::V5]; + +impl crate::Server { + #[inline] + pub fn supported_room_version(&self, version: &RoomVersionId) -> bool { + self.supported_room_versions().any(is_equal_to!(*version)) + } + + #[inline] + pub fn supported_room_versions(&self) -> impl Iterator + '_ { + self.available_room_versions() + .filter(|(_, stability)| self.supported_stability(stability)) + .map(at!(0)) + } + + #[inline] + pub fn available_room_versions(&self) -> impl Iterator { + available_room_versions() + } + + #[inline] + fn supported_stability(&self, stability: &RoomVersionStability) -> bool { + self.config.allow_unstable_room_versions || *stability == RoomVersionStability::Stable + } +} + +pub fn available_room_versions() -> impl Iterator { + let unstable_room_versions = UNSTABLE_ROOM_VERSIONS + .iter() + .cloned() + .zip(once(RoomVersionStability::Unstable).cycle()); + + STABLE_ROOM_VERSIONS + .iter() + .cloned() + .zip(once(RoomVersionStability::Stable).cycle()) + .chain(unstable_room_versions) +} diff --git a/src/service/admin/create.rs b/src/service/admin/create.rs index 1631f1cb..897d412d 100644 --- a/src/service/admin/create.rs +++ b/src/service/admin/create.rs @@ -25,6 +25,7 @@ use crate::Services; /// used to issue admin commands by talking to the server user inside it. pub async fn create_admin_room(services: &Services) -> Result<()> { let room_id = RoomId::new(services.globals.server_name()); + let room_version = &services.server.config.default_room_version; let _short_id = services .rooms @@ -38,8 +39,6 @@ pub async fn create_admin_room(services: &Services) -> Result<()> { let server_user = &services.globals.server_user; services.users.create(server_user, None)?; - let room_version = services.globals.default_room_version(); - let create_content = { use RoomVersionId::*; match room_version { @@ -58,7 +57,7 @@ pub async fn create_admin_room(services: &Services) -> Result<()> { &RoomCreateEventContent { federate: true, predecessor: None, - room_version, + room_version: room_version.clone(), ..create_content }, ), diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index 4fb1ce2d..fefff3b5 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -10,9 +10,7 @@ use std::{ use conduit::{error, Config, Result}; use data::Data; use regex::RegexSet; -use ruma::{ - OwnedEventId, OwnedRoomAliasId, OwnedServerName, OwnedUserId, RoomAliasId, RoomVersionId, ServerName, UserId, -}; +use ruma::{OwnedEventId, OwnedRoomAliasId, OwnedServerName, OwnedUserId, RoomAliasId, ServerName, UserId}; use tokio::sync::Mutex; use crate::service; @@ -22,8 +20,6 @@ pub struct Service { pub config: Config, jwt_decoding_key: Option, - pub stable_room_versions: Vec, - pub unstable_room_versions: Vec, pub bad_event_ratelimiter: Arc>>, pub bad_query_ratelimiter: Arc>>, pub stateres_mutex: Arc>, @@ -45,18 +41,6 @@ impl crate::Service for Service { .as_ref() .map(|secret| jsonwebtoken::DecodingKey::from_secret(secret.as_bytes())); - // Supported and stable room versions - let stable_room_versions = vec![ - RoomVersionId::V6, - RoomVersionId::V7, - RoomVersionId::V8, - RoomVersionId::V9, - RoomVersionId::V10, - RoomVersionId::V11, - ]; - // Experimental, partially supported room versions - let unstable_room_versions = vec![RoomVersionId::V2, RoomVersionId::V3, RoomVersionId::V4, RoomVersionId::V5]; - let turn_secret = config .turn_secret_file .as_ref() @@ -86,8 +70,6 @@ impl crate::Service for Service { db, config: config.clone(), jwt_decoding_key, - stable_room_versions, - unstable_room_versions, bad_event_ratelimiter: Arc::new(RwLock::new(HashMap::new())), bad_query_ratelimiter: Arc::new(RwLock::new(HashMap::new())), stateres_mutex: Arc::new(Mutex::new(())), @@ -99,9 +81,9 @@ impl crate::Service for Service { registration_token, }; - if !s - .supported_room_versions() - .contains(&s.config.default_room_version) + if !args + .server + .supported_room_version(&config.default_room_version) { error!(config=?s.config.default_room_version, fallback=?conduit::config::default_default_room_version(), "Room version in config isn't supported, falling back to default version"); s.config.default_room_version = conduit::config::default_default_room_version(); @@ -173,11 +155,6 @@ impl Service { pub fn allow_room_creation(&self) -> bool { self.config.allow_room_creation } - pub fn allow_unstable_room_versions(&self) -> bool { self.config.allow_unstable_room_versions } - - #[inline] - pub fn default_room_version(&self) -> RoomVersionId { self.config.default_room_version.clone() } - pub fn new_user_displayname_suffix(&self) -> &String { &self.config.new_user_displayname_suffix } pub fn allow_check_for_updates(&self) -> bool { self.config.allow_check_for_updates } @@ -232,18 +209,6 @@ impl Service { pub fn block_non_admin_invites(&self) -> bool { self.config.block_non_admin_invites } - pub fn supported_room_versions(&self) -> Vec { - if self.config.allow_unstable_room_versions { - self.stable_room_versions - .clone() - .into_iter() - .chain(self.unstable_room_versions.clone()) - .collect() - } else { - self.stable_room_versions.clone() - } - } - /// checks if `user_id` is local to us via server_name comparison #[inline] pub fn user_is_local(&self, user_id: &UserId) -> bool { self.server_is_ours(user_id.server_name()) }