fix: avoid panics when admin room is not available
Co-authored-by: strawberry <strawberry@puppygock.gay> Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
parent
5473631e1d
commit
c48535ef32
3 changed files with 233 additions and 241 deletions
|
@ -275,11 +275,15 @@ pub async fn register_route(body: Ruma<register::v3::Request>) -> Result<registe
|
||||||
|
|
||||||
// If this is the first real user, grant them admin privileges except for guest
|
// If this is the first real user, grant them admin privileges except for guest
|
||||||
// users Note: the server user, @conduit:servername, is generated first
|
// users Note: the server user, @conduit:servername, is generated first
|
||||||
if services().users.count()? == 2 && !is_guest {
|
if !is_guest {
|
||||||
|
if let Some(admin_room) = services().admin.get_admin_room()? {
|
||||||
|
if services().rooms.state_cache.room_joined_count(&admin_room)? == Some(1) {
|
||||||
services().admin.make_user_admin(&user_id, displayname).await?;
|
services().admin.make_user_admin(&user_id, displayname).await?;
|
||||||
|
|
||||||
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),
|
||||||
|
|
|
@ -473,18 +473,7 @@ 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()
|
if let Ok(Some(conduit_room)) = services().admin.get_admin_room() {
|
||||||
.rooms
|
|
||||||
.alias
|
|
||||||
.resolve_local_alias(
|
|
||||||
format!("#admins:{}", services().globals.server_name())
|
|
||||||
.as_str()
|
|
||||||
.try_into()
|
|
||||||
.expect("#admins:server_name is a valid room alias"),
|
|
||||||
)
|
|
||||||
.expect("Database data for admin room alias must be valid")
|
|
||||||
.expect("Admin room must exist");
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
Some(event) = receiver.recv() => {
|
Some(event) = receiver.recv() => {
|
||||||
|
@ -531,6 +520,7 @@ impl Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn process_message(&self, room_message: String, event_id: Arc<EventId>) {
|
pub fn process_message(&self, room_message: String, event_id: Arc<EventId>) {
|
||||||
self.sender.send(AdminRoomEvent::ProcessMessage(room_message, event_id)).unwrap();
|
self.sender.send(AdminRoomEvent::ProcessMessage(room_message, event_id)).unwrap();
|
||||||
|
@ -1111,14 +1101,13 @@ impl Service {
|
||||||
format!("#admins:{}", services().globals.server_name())
|
format!("#admins:{}", services().globals.server_name())
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("#admins:server_name is a valid alias name");
|
.expect("#admins:server_name is a valid alias name");
|
||||||
let admin_room_id = services()
|
|
||||||
.rooms
|
|
||||||
.alias
|
|
||||||
.resolve_local_alias(&admin_room_alias)?
|
|
||||||
.expect("Admin room must exist");
|
|
||||||
|
|
||||||
|
if let Some(admin_room_id) = services().admin.get_admin_room()? {
|
||||||
if room.to_string().eq(&admin_room_id) || room.to_string().eq(&admin_room_alias) {
|
if room.to_string().eq(&admin_room_id) || room.to_string().eq(&admin_room_alias) {
|
||||||
return Ok(RoomMessageEventContent::text_plain("Not allowed to ban the admin room."));
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
|
"Not allowed to ban the admin room.",
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let room_id = if room.is_room_id() {
|
let room_id = if room.is_room_id() {
|
||||||
|
@ -1282,24 +1271,16 @@ impl Service {
|
||||||
let mut room_ban_count = 0;
|
let mut room_ban_count = 0;
|
||||||
let mut room_ids: Vec<&RoomId> = Vec::new();
|
let mut room_ids: Vec<&RoomId> = Vec::new();
|
||||||
|
|
||||||
let admin_room_alias: Box<RoomAliasId> =
|
|
||||||
format!("#admins:{}", services().globals.server_name())
|
|
||||||
.try_into()
|
|
||||||
.expect("#admins:server_name is a valid alias name");
|
|
||||||
let admin_room_id = services()
|
|
||||||
.rooms
|
|
||||||
.alias
|
|
||||||
.resolve_local_alias(&admin_room_alias)?
|
|
||||||
.expect("Admin room must exist");
|
|
||||||
|
|
||||||
for &room_id in &rooms_s {
|
for &room_id in &rooms_s {
|
||||||
match <&RoomId>::try_from(room_id) {
|
match <&RoomId>::try_from(room_id) {
|
||||||
Ok(owned_room_id) => {
|
Ok(owned_room_id) => {
|
||||||
// silently ignore deleting admin room
|
// silently ignore deleting admin room
|
||||||
|
if let Some(admin_room_id) = services().admin.get_admin_room()? {
|
||||||
if owned_room_id.eq(&admin_room_id) {
|
if owned_room_id.eq(&admin_room_id) {
|
||||||
info!("User specified admin room in bulk ban list, ignoring");
|
info!("User specified admin room in bulk ban list, ignoring");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
room_ids.push(owned_room_id);
|
room_ids.push(owned_room_id);
|
||||||
},
|
},
|
||||||
|
@ -2443,15 +2424,23 @@ impl Service {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the room ID of the admin room
|
||||||
|
///
|
||||||
|
/// Errors are propagated from the database, and will have None if there is
|
||||||
|
/// no admin room
|
||||||
|
pub(crate) fn get_admin_room(&self) -> Result<Option<OwnedRoomId>> {
|
||||||
|
let admin_room_alias: Box<RoomAliasId> = format!("#admins:{}", services().globals.server_name())
|
||||||
|
.try_into()
|
||||||
|
.expect("#admins:server_name is a valid alias name");
|
||||||
|
|
||||||
|
services().rooms.alias.resolve_local_alias(&admin_room_alias)
|
||||||
|
}
|
||||||
|
|
||||||
/// Invite the user to the conduit admin room.
|
/// Invite the user to the conduit admin room.
|
||||||
///
|
///
|
||||||
/// In conduit, this is equivalent to granting admin privileges.
|
/// In conduit, this is equivalent to granting admin privileges.
|
||||||
pub(crate) async fn make_user_admin(&self, user_id: &UserId, displayname: String) -> Result<()> {
|
pub(crate) async fn make_user_admin(&self, user_id: &UserId, displayname: String) -> Result<()> {
|
||||||
let admin_room_alias: Box<RoomAliasId> = format!("#admins:{}", services().globals.server_name())
|
if let Some(room_id) = services().admin.get_admin_room()? {
|
||||||
.try_into()
|
|
||||||
.expect("#admins:server_name is a valid alias name");
|
|
||||||
let room_id = services().rooms.alias.resolve_local_alias(&admin_room_alias)?.expect("Admin room must exist");
|
|
||||||
|
|
||||||
let mutex_state =
|
let mutex_state =
|
||||||
Arc::clone(services().globals.roomid_mutex_state.write().await.entry(room_id.clone()).or_default());
|
Arc::clone(services().globals.roomid_mutex_state.write().await.entry(room_id.clone()).or_default());
|
||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
|
@ -2559,6 +2548,9 @@ impl Service {
|
||||||
).await?;
|
).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ use ruma::{
|
||||||
state_res,
|
state_res,
|
||||||
state_res::{Event, RoomVersion},
|
state_res::{Event, RoomVersion},
|
||||||
uint, user_id, CanonicalJsonObject, CanonicalJsonValue, EventId, OwnedEventId, OwnedRoomId, OwnedServerName,
|
uint, user_id, CanonicalJsonObject, CanonicalJsonValue, EventId, OwnedEventId, OwnedRoomId, OwnedServerName,
|
||||||
RoomAliasId, RoomId, RoomVersionId, ServerName, UserId,
|
RoomId, RoomVersionId, ServerName, UserId,
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::value::{to_raw_value, RawValue as RawJsonValue};
|
use serde_json::value::{to_raw_value, RawValue as RawJsonValue};
|
||||||
|
@ -461,10 +461,6 @@ impl Service {
|
||||||
if let Some(body) = content.body {
|
if let Some(body) = content.body {
|
||||||
services().rooms.search.index_pdu(shortroomid, &pdu_id, &body)?;
|
services().rooms.search.index_pdu(shortroomid, &pdu_id, &body)?;
|
||||||
|
|
||||||
let admin_room = services().rooms.alias.resolve_local_alias(
|
|
||||||
<&RoomAliasId>::try_from(format!("#admins:{}", services().globals.server_name()).as_str())
|
|
||||||
.expect("#admins:server_name is a valid room alias"),
|
|
||||||
)?;
|
|
||||||
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}: "))
|
||||||
|
@ -477,10 +473,12 @@ impl Service {
|
||||||
// the administrator can execute commands as conduit
|
// the administrator can execute commands as conduit
|
||||||
let from_conduit = pdu.sender == server_user && services().globals.emergency_password().is_none();
|
let from_conduit = pdu.sender == server_user && services().globals.emergency_password().is_none();
|
||||||
|
|
||||||
if to_conduit && !from_conduit && admin_room.as_ref() == Some(&pdu.room_id) {
|
if let Some(admin_room) = services().admin.get_admin_room()? {
|
||||||
|
if to_conduit && !from_conduit && admin_room == pdu.room_id {
|
||||||
services().admin.process_message(body, pdu.event_id.clone());
|
services().admin.process_message(body, pdu.event_id.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
@ -720,11 +718,8 @@ impl Service {
|
||||||
) -> Result<Arc<EventId>> {
|
) -> Result<Arc<EventId>> {
|
||||||
let (pdu, pdu_json) = self.create_hash_and_sign_event(pdu_builder, sender, room_id, state_lock)?;
|
let (pdu, pdu_json) = self.create_hash_and_sign_event(pdu_builder, sender, room_id, state_lock)?;
|
||||||
|
|
||||||
let admin_room = services().rooms.alias.resolve_local_alias(
|
if let Some(admin_room) = services().admin.get_admin_room()? {
|
||||||
<&RoomAliasId>::try_from(format!("#admins:{}", services().globals.server_name()).as_str())
|
if admin_room == room_id {
|
||||||
.expect("#admins:server_name is a valid room alias"),
|
|
||||||
)?;
|
|
||||||
if admin_room.filter(|v| v == room_id).is_some() {
|
|
||||||
match pdu.event_type() {
|
match pdu.event_type() {
|
||||||
TimelineEventType::RoomEncryption => {
|
TimelineEventType::RoomEncryption => {
|
||||||
warn!("Encryption is not allowed in the admins room");
|
warn!("Encryption is not allowed in the admins room");
|
||||||
|
@ -800,6 +795,7 @@ impl Service {
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We append to state before appending the pdu, so we don't have a moment in
|
// 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
|
// time with the pdu without it's state. This is okay because append_pdu can't
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue