diff --git a/src/client_server/room.rs b/src/client_server/room.rs index 5a026997..f6c3a50e 100644 --- a/src/client_server/room.rs +++ b/src/client_server/room.rs @@ -61,6 +61,16 @@ pub async fn create_room_route( ); let state_lock = mutex_state.lock().await; + if !db.globals.allow_room_creation() + && !body.from_appservice + && !db.users.is_admin(sender_user, &db.rooms, &db.globals)? + { + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Room creation has been disabled.", + )); + } + let alias: Option = body.room_alias_name .as_ref() diff --git a/src/database.rs b/src/database.rs index 110d4d0c..8a589299 100644 --- a/src/database.rs +++ b/src/database.rs @@ -61,6 +61,8 @@ pub struct Config { allow_encryption: bool, #[serde(default = "false_fn")] allow_federation: bool, + #[serde(default = "true_fn")] + allow_room_creation: bool, #[serde(default = "false_fn")] pub allow_jaeger: bool, #[serde(default = "false_fn")] diff --git a/src/database/globals.rs b/src/database/globals.rs index 2f1b45ad..c2ef1c36 100644 --- a/src/database/globals.rs +++ b/src/database/globals.rs @@ -211,6 +211,10 @@ impl Globals { self.config.allow_federation } + pub fn allow_room_creation(&self) -> bool { + self.config.allow_room_creation + } + pub fn trusted_servers(&self) -> &[Box] { &self.config.trusted_servers } diff --git a/src/database/users.rs b/src/database/users.rs index 63ed0710..ee064903 100644 --- a/src/database/users.rs +++ b/src/database/users.rs @@ -5,7 +5,8 @@ use ruma::{ events::{AnyToDeviceEvent, EventType}, identifiers::MxcUri, serde::Raw, - DeviceId, DeviceKeyAlgorithm, DeviceKeyId, MilliSecondsSinceUnixEpoch, UInt, UserId, + DeviceId, DeviceKeyAlgorithm, DeviceKeyId, MilliSecondsSinceUnixEpoch, RoomAliasId, UInt, + UserId, }; use std::{collections::BTreeMap, convert::TryFrom, mem, sync::Arc}; use tracing::warn; @@ -53,6 +54,22 @@ impl Users { .is_empty()) } + /// Check if a user is an admin + #[tracing::instrument(skip(self, user_id, rooms, globals))] + pub fn is_admin( + &self, + user_id: &UserId, + rooms: &super::rooms::Rooms, + globals: &super::globals::Globals, + ) -> Result { + let admin_room_alias_id = + RoomAliasId::try_from(format!("#admins:{}", globals.server_name())) + .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid alias."))?; + let admin_room_id = rooms.id_from_alias(&admin_room_alias_id)?.unwrap(); + + Ok(rooms.is_joined(user_id, &admin_room_id)?) + } + /// Create a new user account on this homeserver. #[tracing::instrument(skip(self, user_id, password))] pub fn create(&self, user_id: &UserId, password: Option<&str>) -> Result<()> {