diff --git a/src/cli/serve.rs b/src/cli/serve.rs index f2152e55..ab65396b 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -84,15 +84,7 @@ pub(crate) async fn run(args: ServeArgs) -> Result<(), error::ServeCommand> { .map_err(Error::InitializeServices)?, ))); - // Matrix resource ownership is based on the server name; changing it - // requires recreating the database from scratch. This check needs to be - // done before background tasks are started to avoid data races. - if services().users.count().map(|x| x > 0).map_err(Error::NonZeroUsers)? { - let admin_bot = services().globals.admin_bot_user_id.as_ref(); - if !services().users.exists(admin_bot).map_err(Error::AdminBotExists)? { - return Err(Error::Renamed); - } - } + services().globals.err_if_server_name_changed()?; db.apply_migrations().await.map_err(Error::DatabaseError)?; diff --git a/src/error.rs b/src/error.rs index 2ad565a3..106484df 100644 --- a/src/error.rs +++ b/src/error.rs @@ -65,6 +65,16 @@ pub(crate) enum ServeCommand { #[error("failed to initialize services")] InitializeServices(#[source] crate::utils::error::Error), + #[error("`server_name` change check failed")] + ServerNameChanged(#[from] ServerNameChanged), +} + +/// Error generated if `server_name` has changed or if checking this failed +// Missing docs are allowed here since that kind of information should be +// encoded in the error messages themselves anyway. +#[allow(missing_docs)] +#[derive(Error, Debug)] +pub(crate) enum ServerNameChanged { #[error("failed to check if there are any users")] NonZeroUsers(#[source] crate::utils::error::Error), diff --git a/src/service/globals.rs b/src/service/globals.rs index 9a280a23..a1662c9e 100644 --- a/src/service/globals.rs +++ b/src/service/globals.rs @@ -305,6 +305,37 @@ impl Service { Ok(s) } + /// Check if `server_name` in the DB and config differ, return error if so + /// + /// Matrix resource ownership is based on the server name; changing it + /// requires recreating the database from scratch. This check needs to be + /// done before background tasks are started to avoid data races. + // Allowed because this function calls `services()` + #[allow(clippy::unused_self)] + pub(crate) fn err_if_server_name_changed( + &self, + ) -> Result<(), crate::error::ServerNameChanged> { + use crate::error::ServerNameChanged as Error; + + if services() + .users + .count() + .map(|x| x > 0) + .map_err(Error::NonZeroUsers)? + { + let admin_bot = self.admin_bot_user_id.as_ref(); + if !services() + .users + .exists(admin_bot) + .map_err(Error::AdminBotExists)? + { + return Err(Error::Renamed); + } + } + + Ok(()) + } + /// Returns this server's keypair. pub(crate) fn keypair(&self) -> &ruma::signatures::Ed25519KeyPair { &self.keypair