fix: avoid panics when admin room is not available

This commit is contained in:
Matthias Ahouansou 2024-03-03 22:42:24 +00:00
parent e06e15d4ec
commit da5975d727
3 changed files with 235 additions and 231 deletions

View file

@ -149,8 +149,7 @@ pub async fn register_route(body: Ruma<register::v3::Request>) -> Result<registe
return Err(Error::Uiaa(uiaainfo)); return Err(Error::Uiaa(uiaainfo));
} }
// Success! // Success!
} else { } else if let Some(json) = body.json_body {
if let Some(json) = body.json_body {
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH)); uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
services().uiaa.create( services().uiaa.create(
&UserId::parse_with_server_name("", services().globals.server_name()) &UserId::parse_with_server_name("", services().globals.server_name())
@ -160,7 +159,7 @@ pub async fn register_route(body: Ruma<register::v3::Request>) -> Result<registe
&json, &json,
)?; )?;
return Err(Error::Uiaa(uiaainfo)); return Err(Error::Uiaa(uiaainfo));
} } else {
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json.")); return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
} }
} }
@ -240,11 +239,12 @@ pub async fn register_route(body: Ruma<register::v3::Request>) -> Result<registe
// If this is the first real user, grant them admin privileges // If this is the first real user, grant them admin privileges
// Note: the server user, @conduit:servername, is generated first // Note: the server user, @conduit:servername, is generated first
if !is_guest if !is_guest {
&& services() if let Some(admin_room) = services().admin.get_admin_room()? {
if services()
.rooms .rooms
.state_cache .state_cache
.room_joined_count(&services().admin.get_admin_room())? .room_joined_count(&admin_room)?
== Some(1) == Some(1)
{ {
services() services()
@ -254,6 +254,8 @@ pub async fn register_route(body: Ruma<register::v3::Request>) -> Result<registe
warn!("Granting {} admin privileges as the first user", user_id); warn!("Granting {} admin privileges as the first user", user_id);
} }
}
}
Ok(register::v3::Response { Ok(register::v3::Response {
access_token: Some(token), access_token: Some(token),

View file

@ -214,9 +214,9 @@ impl Service {
let conduit_user = UserId::parse(format!("@conduit:{}", services().globals.server_name())) let conduit_user = UserId::parse(format!("@conduit:{}", services().globals.server_name()))
.expect("@conduit:server_name is valid"); .expect("@conduit:server_name is valid");
let conduit_room = services().admin.get_admin_room(); if let Ok(Some(conduit_room)) = services().admin.get_admin_room() {
let send_message = |message: RoomMessageEventContent,
let send_message = |message: RoomMessageEventContent, mutex_lock: &MutexGuard<'_, ()>| { mutex_lock: &MutexGuard<'_, ()>| {
services() services()
.rooms .rooms
.timeline .timeline
@ -262,6 +262,7 @@ impl Service {
} }
} }
} }
}
pub fn process_message(&self, room_message: String) { pub fn process_message(&self, room_message: String) {
self.sender self.sender
@ -1097,9 +1098,8 @@ impl Service {
/// Gets the room ID of the admin room /// Gets the room ID of the admin room
/// ///
/// If the room does not exist, this function panics, since it should have been created on first run /// Errors are propagated from the database, and will have None if there is no admin room
// ^ was the case before this function when the following code was re-used in multiple places pub(crate) fn get_admin_room(&self) -> Result<Option<OwnedRoomId>> {
pub(crate) fn get_admin_room(&self) -> OwnedRoomId {
let admin_room_alias: Box<RoomAliasId> = let admin_room_alias: Box<RoomAliasId> =
format!("#admins:{}", services().globals.server_name()) format!("#admins:{}", services().globals.server_name())
.try_into() .try_into()
@ -1109,8 +1109,6 @@ impl Service {
.rooms .rooms
.alias .alias
.resolve_local_alias(&admin_room_alias) .resolve_local_alias(&admin_room_alias)
.expect("Room ID should be valid unicode, since this server created it")
.expect("Admin room must exist")
} }
/// Invite the user to the conduit admin room. /// Invite the user to the conduit admin room.
@ -1121,8 +1119,7 @@ impl Service {
user_id: &UserId, user_id: &UserId,
displayname: String, displayname: String,
) -> Result<()> { ) -> Result<()> {
let room_id = services().admin.get_admin_room(); if let Some(room_id) = services().admin.get_admin_room()? {
let mutex_state = Arc::clone( let mutex_state = Arc::clone(
services() services()
.globals .globals
@ -1226,6 +1223,9 @@ impl Service {
)?; )?;
Ok(()) Ok(())
} else {
Ok(())
}
} }
} }

View file

@ -448,7 +448,6 @@ impl Service {
.search .search
.index_pdu(shortroomid, &pdu_id, &body)?; .index_pdu(shortroomid, &pdu_id, &body)?;
let admin_room = services().admin.get_admin_room();
let server_user = format!("@conduit:{}", services().globals.server_name()); let server_user = format!("@conduit:{}", services().globals.server_name());
let to_conduit = body.starts_with(&format!("{server_user}: ")) let to_conduit = body.starts_with(&format!("{server_user}: "))
@ -461,11 +460,13 @@ impl Service {
let from_conduit = pdu.sender == server_user let from_conduit = pdu.sender == server_user
&& services().globals.emergency_password().is_none(); && services().globals.emergency_password().is_none();
if let Some(admin_room) = services().admin.get_admin_room()? {
if to_conduit && !from_conduit && admin_room == pdu.room_id { if to_conduit && !from_conduit && admin_room == pdu.room_id {
services().admin.process_message(body); services().admin.process_message(body);
} }
} }
} }
}
_ => {} _ => {}
} }
@ -815,7 +816,7 @@ impl Service {
let (pdu, pdu_json) = let (pdu, pdu_json) =
self.create_hash_and_sign_event(pdu_builder, sender, room_id, state_lock)?; self.create_hash_and_sign_event(pdu_builder, sender, room_id, state_lock)?;
let admin_room = services().admin.get_admin_room(); if let Some(admin_room) = services().admin.get_admin_room()? {
if admin_room == room_id { if admin_room == room_id {
match pdu.event_type() { match pdu.event_type() {
TimelineEventType::RoomEncryption => { TimelineEventType::RoomEncryption => {
@ -895,6 +896,7 @@ impl Service {
_ => {} _ => {}
} }
} }
}
// We append to state before appending the pdu, so we don't have a moment in time with the // We append to state before appending the pdu, so we don't have a moment in time with the
// pdu without it's state. This is okay because append_pdu can't fail. // pdu without it's state. This is okay because append_pdu can't fail.