mirror of
https://gitlab.computer.surgery/matrix/grapevine.git
synced 2025-12-17 07:41:23 +01:00
save server_name separately in the database
And use it to assert that the configured `server_name` doesn't change after creating the database. This prevents us from relying on the admin bot for this.
This commit is contained in:
parent
43018e5793
commit
ea5605bbc3
4 changed files with 72 additions and 2 deletions
|
|
@ -6,7 +6,7 @@ use lru_cache::LruCache;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::federation::discovery::{OldVerifyKey, ServerSigningKeys},
|
api::federation::discovery::{OldVerifyKey, ServerSigningKeys},
|
||||||
signatures::Ed25519KeyPair,
|
signatures::Ed25519KeyPair,
|
||||||
DeviceId, ServerName, UserId,
|
DeviceId, OwnedServerName, ServerName, UserId,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -361,4 +361,28 @@ lasttimelinecount_cache: {lasttimelinecount_cache}\n"
|
||||||
self.global.insert(b"version", &new_version.to_be_bytes())?;
|
self.global.insert(b"version", &new_version.to_be_bytes())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_server_name(&self, server_name: &ServerName) -> Result<()> {
|
||||||
|
self.global.insert(b"server_name", server_name.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn server_name(&self) -> Result<Option<OwnedServerName>> {
|
||||||
|
let opt_bytes = self
|
||||||
|
.global
|
||||||
|
.get(b"server_name")
|
||||||
|
.map_err(|_| Error::bad_database("Failed to read from globals"))?;
|
||||||
|
|
||||||
|
// `server_name` has not been set yet
|
||||||
|
let Some(bytes) = opt_bytes else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let utf8 = String::from_utf8(bytes)
|
||||||
|
.map_err(|_| Error::bad_database("Invalid UTF-8 in server_name"))?;
|
||||||
|
|
||||||
|
let server_name = OwnedServerName::try_from(utf8)
|
||||||
|
.map_err(|_| Error::bad_database("Invalid server_name"))?;
|
||||||
|
|
||||||
|
Ok(Some(server_name))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,9 @@ pub(crate) enum ServeCommand {
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub(crate) enum ServerNameChanged {
|
pub(crate) enum ServerNameChanged {
|
||||||
|
#[error("failed to read saved server_name")]
|
||||||
|
ReadSavedServerName(#[source] crate::utils::error::Error),
|
||||||
|
|
||||||
#[error("failed to check if there are any users")]
|
#[error("failed to check if there are any users")]
|
||||||
NonZeroUsers(#[source] crate::utils::error::Error),
|
NonZeroUsers(#[source] crate::utils::error::Error),
|
||||||
|
|
||||||
|
|
@ -83,6 +86,9 @@ pub(crate) enum ServerNameChanged {
|
||||||
|
|
||||||
#[error("`server_name` in the database and config file differ")]
|
#[error("`server_name` in the database and config file differ")]
|
||||||
Renamed,
|
Renamed,
|
||||||
|
|
||||||
|
#[error("failed to save the configured server_name")]
|
||||||
|
SaveServerName(#[source] crate::utils::error::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Observability initialization errors
|
/// Observability initialization errors
|
||||||
|
|
|
||||||
|
|
@ -307,6 +307,10 @@ impl Service {
|
||||||
|
|
||||||
/// Check if `server_name` in the DB and config differ, return error if so
|
/// Check if `server_name` in the DB and config differ, return error if so
|
||||||
///
|
///
|
||||||
|
/// This function will save the currently configured `server_name` if the
|
||||||
|
/// check passes, so that future calls to this function will continue to
|
||||||
|
/// check against the first-configured value.
|
||||||
|
///
|
||||||
/// Matrix resource ownership is based on the server name; changing it
|
/// Matrix resource ownership is based on the server name; changing it
|
||||||
/// requires recreating the database from scratch. This check needs to be
|
/// requires recreating the database from scratch. This check needs to be
|
||||||
/// done before background tasks are started to avoid data races.
|
/// done before background tasks are started to avoid data races.
|
||||||
|
|
@ -317,6 +321,20 @@ impl Service {
|
||||||
) -> Result<(), crate::error::ServerNameChanged> {
|
) -> Result<(), crate::error::ServerNameChanged> {
|
||||||
use crate::error::ServerNameChanged as Error;
|
use crate::error::ServerNameChanged as Error;
|
||||||
|
|
||||||
|
let config = &*services().globals.config.server_name;
|
||||||
|
|
||||||
|
let opt_saved =
|
||||||
|
self.saved_server_name().map_err(Error::ReadSavedServerName)?;
|
||||||
|
|
||||||
|
// Check against saved server name
|
||||||
|
if let Some(saved) = opt_saved {
|
||||||
|
if saved == config {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(Error::Renamed);
|
||||||
|
}
|
||||||
|
|
||||||
let non_zero_users = services()
|
let non_zero_users = services()
|
||||||
.users
|
.users
|
||||||
.count()
|
.count()
|
||||||
|
|
@ -328,10 +346,18 @@ impl Service {
|
||||||
.exists(&self.admin_bot_user_id)
|
.exists(&self.admin_bot_user_id)
|
||||||
.map_err(Error::AdminBotExists)?;
|
.map_err(Error::AdminBotExists)?;
|
||||||
|
|
||||||
|
// Fall back to checking against the admin bot user ID
|
||||||
if non_zero_users && !admin_bot_exists {
|
if non_zero_users && !admin_bot_exists {
|
||||||
return Err(Error::Renamed);
|
return Err(Error::Renamed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the server_name wasn't saved and the admin bot user ID check
|
||||||
|
// didn't fail, save the current server_name
|
||||||
|
services()
|
||||||
|
.globals
|
||||||
|
.save_server_name(config)
|
||||||
|
.map_err(Error::SaveServerName)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -618,6 +644,18 @@ impl Service {
|
||||||
self.shutdown.store(true, atomic::Ordering::Relaxed);
|
self.shutdown.store(true, atomic::Ordering::Relaxed);
|
||||||
self.rotate.fire();
|
self.rotate.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn save_server_name(
|
||||||
|
&self,
|
||||||
|
server_name: &ServerName,
|
||||||
|
) -> Result<()> {
|
||||||
|
self.db.set_server_name(server_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Named this way to avoid conflicts with the existing `fn server_name`
|
||||||
|
pub(crate) fn saved_server_name(&self) -> Result<Option<OwnedServerName>> {
|
||||||
|
self.db.server_name()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reqwest_client_builder(config: &Config) -> Result<reqwest::ClientBuilder> {
|
fn reqwest_client_builder(config: &Config) -> Result<reqwest::ClientBuilder> {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use ruma::{
|
||||||
api::federation::discovery::{OldVerifyKey, ServerSigningKeys, VerifyKey},
|
api::federation::discovery::{OldVerifyKey, ServerSigningKeys, VerifyKey},
|
||||||
serde::Base64,
|
serde::Base64,
|
||||||
signatures::Ed25519KeyPair,
|
signatures::Ed25519KeyPair,
|
||||||
DeviceId, MilliSecondsSinceUnixEpoch, ServerName, UserId,
|
DeviceId, MilliSecondsSinceUnixEpoch, OwnedServerName, ServerName, UserId,
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
|
@ -119,4 +119,6 @@ pub(crate) trait Data: Send + Sync {
|
||||||
) -> Result<Option<SigningKeys>>;
|
) -> Result<Option<SigningKeys>>;
|
||||||
fn database_version(&self) -> Result<u64>;
|
fn database_version(&self) -> Result<u64>;
|
||||||
fn bump_database_version(&self, new_version: u64) -> Result<()>;
|
fn bump_database_version(&self, new_version: u64) -> Result<()>;
|
||||||
|
fn set_server_name(&self, server_name: &ServerName) -> Result<()>;
|
||||||
|
fn server_name(&self) -> Result<Option<OwnedServerName>>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue