From 9589382cb8e892139b21260c91ebe2d4eb4db1a7 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Fri, 27 Sep 2024 16:06:14 -0700 Subject: [PATCH] save the admin bot localpart This will be used later in the run. --- src/database.rs | 7 +++++++ src/database/key_value/globals.rs | 22 ++++++++++++++++++++++ src/error.rs | 4 +++- src/service/admin.rs | 5 +++++ src/service/globals.rs | 11 +++++++++++ src/service/globals/data.rs | 2 ++ 6 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/database.rs b/src/database.rs index abfad85a..7483c93c 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1071,6 +1071,13 @@ impl KeyValueDatabase { Ok(()) })?; + // Ensure the admin bot localpart has been written once + if services().globals.saved_admin_bot_localpart()?.is_none() { + services().globals.save_admin_bot_localpart( + services().globals.admin_bot_user_id.localpart(), + )?; + } + assert_eq!( services().globals.database_version().unwrap(), latest_database_version, diff --git a/src/database/key_value/globals.rs b/src/database/key_value/globals.rs index 7934535f..7abd2f66 100644 --- a/src/database/key_value/globals.rs +++ b/src/database/key_value/globals.rs @@ -385,4 +385,26 @@ lasttimelinecount_cache: {lasttimelinecount_cache}\n" Ok(Some(server_name)) } + + fn set_admin_bot_localpart(&self, localpart: &str) -> Result<()> { + self.global.insert(b"admin_bot_localpart", localpart.as_bytes()) + } + + fn admin_bot_localpart(&self) -> Result> { + let opt_bytes = self + .global + .get(b"admin_bot_localpart") + .map_err(|_| Error::bad_database("Failed to read from globals"))?; + + // `admin_bot_localpart` has not been set yet + let Some(bytes) = opt_bytes else { + return Ok(None); + }; + + let localpart = String::from_utf8(bytes).map_err(|_| { + Error::bad_database("Invalid UTF-8 in admin_bot_localpart") + })?; + + Ok(Some(localpart)) + } } diff --git a/src/error.rs b/src/error.rs index 1ada3bbb..500a09ca 100644 --- a/src/error.rs +++ b/src/error.rs @@ -91,7 +91,9 @@ pub(crate) enum ServerNameChanged { Renamed(OwnedServerName, OwnedServerName), #[error( - "couldn't find {0} in the database, `server_name` must have changed" + "couldn't find {0} in the database, either the `server_name` changed \ + or the admin bot localpart was reconfigured without running the \ + server at least once with the original localpart" )] MissingAdminBot(OwnedUserId), diff --git a/src/service/admin.rs b/src/service/admin.rs index e46368ed..1aeec5cc 100644 --- a/src/service/admin.rs +++ b/src/service/admin.rs @@ -1283,6 +1283,8 @@ impl Service { /// Create the admin room. /// + /// This function should only be run on a fresh database. + /// /// Users in this room are considered admins by grapevine, and the room can /// be used to issue admin commands by talking to the server user inside /// it. @@ -1300,6 +1302,9 @@ impl Service { .await; services().users.create(&services().globals.admin_bot_user_id, None)?; + services().globals.save_admin_bot_localpart( + services().globals.admin_bot_user_id.localpart(), + )?; let room_version_id = services().globals.default_room_version(); let room_version = RoomVersion::try_from(&room_version_id)?; diff --git a/src/service/globals.rs b/src/service/globals.rs index 00bbd7d9..c3565338 100644 --- a/src/service/globals.rs +++ b/src/service/globals.rs @@ -656,6 +656,17 @@ impl Service { pub(crate) fn saved_server_name(&self) -> Result> { self.db.server_name() } + + pub(crate) fn save_admin_bot_localpart( + &self, + localpart: &str, + ) -> Result<()> { + self.db.set_admin_bot_localpart(localpart) + } + + pub(crate) fn saved_admin_bot_localpart(&self) -> Result> { + self.db.admin_bot_localpart() + } } fn reqwest_client_builder(config: &Config) -> Result { diff --git a/src/service/globals/data.rs b/src/service/globals/data.rs index a232f81c..1b784159 100644 --- a/src/service/globals/data.rs +++ b/src/service/globals/data.rs @@ -121,4 +121,6 @@ pub(crate) trait Data: Send + Sync { fn bump_database_version(&self, new_version: u64) -> Result<()>; fn set_server_name(&self, server_name: &ServerName) -> Result<()>; fn server_name(&self) -> Result>; + fn set_admin_bot_localpart(&self, localpart: &str) -> Result<()>; + fn admin_bot_localpart(&self) -> Result>; }