abstract supported room versions apis

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-12-05 07:23:51 +00:00
parent f0a1aaf7bc
commit 8e8c6bfe07
9 changed files with 75 additions and 88 deletions

View file

@ -19,23 +19,11 @@ use crate::{Result, Ruma};
pub(crate) async fn get_capabilities_route( pub(crate) async fn get_capabilities_route(
State(services): State<crate::State>, _body: Ruma<get_capabilities::v3::Request>, State(services): State<crate::State>, _body: Ruma<get_capabilities::v3::Request>,
) -> Result<get_capabilities::v3::Response> { ) -> Result<get_capabilities::v3::Response> {
let available: BTreeMap<RoomVersionId, RoomVersionStability> = services let available: BTreeMap<RoomVersionId, RoomVersionStability> = services.server.available_room_versions().collect();
.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 mut capabilities = Capabilities::default(); let mut capabilities = Capabilities::default();
capabilities.room_versions = RoomVersionsCapability { capabilities.room_versions = RoomVersionsCapability {
default: services.globals.default_room_version(), default: services.server.config.default_room_version.clone(),
available, available,
}; };

View file

@ -706,11 +706,7 @@ async fn join_room_by_id_helper_remote(
return Err!(BadServerResponse("Remote room version is not supported by conduwuit")); return Err!(BadServerResponse("Remote room version is not supported by conduwuit"));
}; };
if !services if !services.server.supported_room_version(&room_version_id) {
.globals
.supported_room_versions()
.contains(&room_version_id)
{
return Err!(BadServerResponse( return Err!(BadServerResponse(
"Remote room version {room_version_id} is not supported by conduwuit" "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")); return Err!(BadServerResponse("Remote room version is not supported by conduwuit"));
}; };
if !services if !services.server.supported_room_version(&room_version_id) {
.globals
.supported_room_versions()
.contains(&room_version_id)
{
return Err!(BadServerResponse( return Err!(BadServerResponse(
"Remote room version {room_version_id} is not supported by conduwuit" "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 { federation::membership::prepare_join_event::v1::Request {
room_id: room_id.to_owned(), room_id: room_id.to_owned(),
user_id: sender_user.to_owned(), user_id: sender_user.to_owned(),
ver: services.globals.supported_room_versions(), ver: services.server.supported_room_versions().collect(),
}, },
) )
.await; .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")); return Err!(BadServerResponse("Remote room version is not supported by conduwuit"));
}; };
if !services if !services.server.supported_room_version(&room_version_id) {
.globals
.supported_room_versions()
.contains(&room_version_id)
{
return Err!(BadServerResponse( return Err!(BadServerResponse(
"Remote room version {room_version_id} is not supported by conduwuit" "Remote room version {room_version_id} is not supported by conduwuit"
)); ));

View file

@ -116,11 +116,7 @@ pub(crate) async fn create_room_route(
let room_version = match body.room_version.clone() { let room_version = match body.room_version.clone() {
Some(room_version) => { Some(room_version) => {
if services if services.server.supported_room_version(&room_version) {
.globals
.supported_room_versions()
.contains(&room_version)
{
room_version room_version
} else { } else {
return Err(Error::BadRequest( 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 { let create_content = match &body.creation_content {

View file

@ -47,11 +47,7 @@ pub(crate) async fn upgrade_room_route(
) -> Result<upgrade_room::v3::Response> { ) -> Result<upgrade_room::v3::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let sender_user = body.sender_user.as_ref().expect("user is authenticated");
if !services if !services.server.supported_room_version(&body.new_version) {
.globals
.supported_room_versions()
.contains(&body.new_version)
{
return Err(Error::BadRequest( return Err(Error::BadRequest(
ErrorKind::UnsupportedRoomVersion, ErrorKind::UnsupportedRoomVersion,
"This server does not support that room version.", "This server does not support that room version.",

View file

@ -26,11 +26,7 @@ pub(crate) async fn create_invite_route(
.acl_check(body.origin(), &body.room_id) .acl_check(body.origin(), &body.room_id)
.await?; .await?;
if !services if !services.server.supported_room_version(&body.room_version) {
.globals
.supported_room_versions()
.contains(&body.room_version)
{
return Err(Error::BadRequest( return Err(Error::BadRequest(
ErrorKind::IncompatibleRoomVersion { ErrorKind::IncompatibleRoomVersion {
room_version: body.room_version.clone(), room_version: body.room_version.clone(),

View file

@ -2,6 +2,7 @@
//! etc information which can be queried by admins or used by developers. //! etc information which can be queried by admins or used by developers.
pub mod cargo; pub mod cargo;
pub mod room_version;
pub mod rustc; pub mod rustc;
pub mod version; pub mod version;

View file

@ -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<Item = RoomVersionId> + '_ {
self.available_room_versions()
.filter(|(_, stability)| self.supported_stability(stability))
.map(at!(0))
}
#[inline]
pub fn available_room_versions(&self) -> impl Iterator<Item = (RoomVersionId, RoomVersionStability)> {
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<Item = (RoomVersionId, RoomVersionStability)> {
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)
}

View file

@ -25,6 +25,7 @@ use crate::Services;
/// used to issue admin commands by talking to the server user inside it. /// used to issue admin commands by talking to the server user inside it.
pub async fn create_admin_room(services: &Services) -> Result<()> { pub async fn create_admin_room(services: &Services) -> Result<()> {
let room_id = RoomId::new(services.globals.server_name()); let room_id = RoomId::new(services.globals.server_name());
let room_version = &services.server.config.default_room_version;
let _short_id = services let _short_id = services
.rooms .rooms
@ -38,8 +39,6 @@ pub async fn create_admin_room(services: &Services) -> Result<()> {
let server_user = &services.globals.server_user; let server_user = &services.globals.server_user;
services.users.create(server_user, None)?; services.users.create(server_user, None)?;
let room_version = services.globals.default_room_version();
let create_content = { let create_content = {
use RoomVersionId::*; use RoomVersionId::*;
match room_version { match room_version {
@ -58,7 +57,7 @@ pub async fn create_admin_room(services: &Services) -> Result<()> {
&RoomCreateEventContent { &RoomCreateEventContent {
federate: true, federate: true,
predecessor: None, predecessor: None,
room_version, room_version: room_version.clone(),
..create_content ..create_content
}, },
), ),

View file

@ -10,9 +10,7 @@ use std::{
use conduit::{error, Config, Result}; use conduit::{error, Config, Result};
use data::Data; use data::Data;
use regex::RegexSet; use regex::RegexSet;
use ruma::{ use ruma::{OwnedEventId, OwnedRoomAliasId, OwnedServerName, OwnedUserId, RoomAliasId, ServerName, UserId};
OwnedEventId, OwnedRoomAliasId, OwnedServerName, OwnedUserId, RoomAliasId, RoomVersionId, ServerName, UserId,
};
use tokio::sync::Mutex; use tokio::sync::Mutex;
use crate::service; use crate::service;
@ -22,8 +20,6 @@ pub struct Service {
pub config: Config, pub config: Config,
jwt_decoding_key: Option<jsonwebtoken::DecodingKey>, jwt_decoding_key: Option<jsonwebtoken::DecodingKey>,
pub stable_room_versions: Vec<RoomVersionId>,
pub unstable_room_versions: Vec<RoomVersionId>,
pub bad_event_ratelimiter: Arc<RwLock<HashMap<OwnedEventId, RateLimitState>>>, pub bad_event_ratelimiter: Arc<RwLock<HashMap<OwnedEventId, RateLimitState>>>,
pub bad_query_ratelimiter: Arc<RwLock<HashMap<OwnedServerName, RateLimitState>>>, pub bad_query_ratelimiter: Arc<RwLock<HashMap<OwnedServerName, RateLimitState>>>,
pub stateres_mutex: Arc<Mutex<()>>, pub stateres_mutex: Arc<Mutex<()>>,
@ -45,18 +41,6 @@ impl crate::Service for Service {
.as_ref() .as_ref()
.map(|secret| jsonwebtoken::DecodingKey::from_secret(secret.as_bytes())); .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 let turn_secret = config
.turn_secret_file .turn_secret_file
.as_ref() .as_ref()
@ -86,8 +70,6 @@ impl crate::Service for Service {
db, db,
config: config.clone(), config: config.clone(),
jwt_decoding_key, jwt_decoding_key,
stable_room_versions,
unstable_room_versions,
bad_event_ratelimiter: Arc::new(RwLock::new(HashMap::new())), bad_event_ratelimiter: Arc::new(RwLock::new(HashMap::new())),
bad_query_ratelimiter: Arc::new(RwLock::new(HashMap::new())), bad_query_ratelimiter: Arc::new(RwLock::new(HashMap::new())),
stateres_mutex: Arc::new(Mutex::new(())), stateres_mutex: Arc::new(Mutex::new(())),
@ -99,9 +81,9 @@ impl crate::Service for Service {
registration_token, registration_token,
}; };
if !s if !args
.supported_room_versions() .server
.contains(&s.config.default_room_version) .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"); 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(); 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_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 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 } 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 block_non_admin_invites(&self) -> bool { self.config.block_non_admin_invites }
pub fn supported_room_versions(&self) -> Vec<RoomVersionId> {
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 /// checks if `user_id` is local to us via server_name comparison
#[inline] #[inline]
pub fn user_is_local(&self, user_id: &UserId) -> bool { self.server_is_ours(user_id.server_name()) } pub fn user_is_local(&self, user_id: &UserId) -> bool { self.server_is_ours(user_id.server_name()) }