diff --git a/fedora/continuwuity.spec.rpkg b/fedora/continuwuity.spec.rpkg index 19edf701..f2efa383 100644 --- a/fedora/continuwuity.spec.rpkg +++ b/fedora/continuwuity.spec.rpkg @@ -38,7 +38,7 @@ sed -i 's/^offline = true$//' .cargo/config.toml %cargo_build # Here's the one legally required mystery incantation in this file. -# Some of our dependencies have source files which are (for some reason) marked as excutable. +# Some of our dependencies have source files which are (for some reason) marked as executable. # Files in .cargo/registry/ are copied into /usr/src/ by the debuginfo machinery # at the end of the build step, and then the BRP shebang mangling script checks # the entire buildroot to find executable files, and fails the build because @@ -46,7 +46,7 @@ sed -i 's/^offline = true$//' .cargo/config.toml # So we have to clear the executable bit on all of them before that happens. find .cargo/registry/ -executable -name "*.rs" -exec chmod -x {} + -# TODO: this fails currently because it's forced to run in offline mode +# TODO: this fails currently because it's forced to run in offline mode # {cargo_license -- --no-dev} > LICENSE.dependencies %install @@ -77,4 +77,4 @@ install -Dpm0644 conduwuit-example.toml %{buildroot}%{_sysconfdir}/conduwuit/con %systemd_postun_with_restart conduwuit.service %changelog -{{{ git_repo_changelog }}} \ No newline at end of file +{{{ git_repo_changelog }}} diff --git a/src/admin/user/commands.rs b/src/admin/user/commands.rs index 56864a32..37ab030c 100644 --- a/src/admin/user/commands.rs +++ b/src/admin/user/commands.rs @@ -1,8 +1,8 @@ use std::{collections::BTreeMap, fmt::Write as _}; use api::client::{ - full_user_deactivate, join_room_by_id_helper, leave_all_rooms, leave_room, update_avatar_url, - update_displayname, + full_user_deactivate, join_room_by_id_helper, leave_all_rooms, leave_room, remote_leave_room, + update_avatar_url, update_displayname, }; use conduwuit::{ Err, Result, debug, debug_warn, error, info, is_equal_to, @@ -926,3 +926,29 @@ pub(super) async fn redact_event(&self, event_id: OwnedEventId) -> Result { )) .await } + +#[admin_command] +pub(super) async fn force_leave_remote_room( + &self, + user_id: String, + room_id: OwnedRoomOrAliasId, +) -> Result { + let user_id = parse_local_user_id(self.services, &user_id)?; + let (room_id, _) = self + .services + .rooms + .alias + .resolve_with_servers(&room_id, None) + .await?; + + assert!( + self.services.globals.user_is_local(&user_id), + "Parsed user_id must be a local user" + ); + remote_leave_room(self.services, &user_id, &room_id, None) + .boxed() + .await?; + + self.write_str(&format!("{user_id} has been joined to {room_id}.",)) + .await +} diff --git a/src/admin/user/mod.rs b/src/admin/user/mod.rs index 656cacaf..366f7dd5 100644 --- a/src/admin/user/mod.rs +++ b/src/admin/user/mod.rs @@ -103,6 +103,12 @@ pub enum UserCommand { room_id: OwnedRoomOrAliasId, }, + /// - Manually leave a remote room for a local user. + ForceLeaveRemoteRoom { + user_id: String, + room_id: OwnedRoomOrAliasId, + }, + /// - Forces the specified user to drop their power levels to the room /// default, if their permissions allow and the auth check permits ForceDemote { diff --git a/src/api/client/membership/join.rs b/src/api/client/membership/join.rs index dc170cbf..f3434bf5 100644 --- a/src/api/client/membership/join.rs +++ b/src/api/client/membership/join.rs @@ -156,31 +156,34 @@ pub(crate) async fn join_room_by_id_or_alias_route( .await?; let mut servers = body.via.clone(); - servers.extend( - services - .rooms - .state_cache - .servers_invite_via(&room_id) - .map(ToOwned::to_owned) - .collect::>() - .await, - ); + if servers.is_empty() { + debug!("No via servers provided for join, injecting some."); + servers.extend( + services + .rooms + .state_cache + .servers_invite_via(&room_id) + .map(ToOwned::to_owned) + .collect::>() + .await, + ); - servers.extend( - services - .rooms - .state_cache - .invite_state(sender_user, &room_id) - .await - .unwrap_or_default() - .iter() - .filter_map(|event| event.get_field("sender").ok().flatten()) - .filter_map(|sender: &str| UserId::parse(sender).ok()) - .map(|user| user.server_name().to_owned()), - ); + servers.extend( + services + .rooms + .state_cache + .invite_state(sender_user, &room_id) + .await + .unwrap_or_default() + .iter() + .filter_map(|event| event.get_field("sender").ok().flatten()) + .filter_map(|sender: &str| UserId::parse(sender).ok()) + .map(|user| user.server_name().to_owned()), + ); - if let Some(server) = room_id.server_name() { - servers.push(server.to_owned()); + if let Some(server) = room_id.server_name() { + servers.push(server.to_owned()); + } } servers.sort_unstable(); diff --git a/src/api/client/membership/leave.rs b/src/api/client/membership/leave.rs index f4f1666b..0aadd833 100644 --- a/src/api/client/membership/leave.rs +++ b/src/api/client/membership/leave.rs @@ -215,7 +215,7 @@ pub async fn leave_room( Ok(()) } -async fn remote_leave_room( +pub async fn remote_leave_room( services: &Services, user_id: &UserId, room_id: &RoomId, diff --git a/src/api/client/membership/mod.rs b/src/api/client/membership/mod.rs index 7a6f19ad..691419f6 100644 --- a/src/api/client/membership/mod.rs +++ b/src/api/client/membership/mod.rs @@ -29,7 +29,7 @@ pub(crate) use self::{ }; pub use self::{ join::join_room_by_id_helper, - leave::{leave_all_rooms, leave_room}, + leave::{leave_all_rooms, leave_room, remote_leave_room}, }; use crate::{Ruma, client::full_user_deactivate}; diff --git a/src/api/client/mod.rs b/src/api/client/mod.rs index e4be20b7..be335cba 100644 --- a/src/api/client/mod.rs +++ b/src/api/client/mod.rs @@ -55,7 +55,7 @@ pub(super) use keys::*; pub(super) use media::*; pub(super) use media_legacy::*; pub(super) use membership::*; -pub use membership::{join_room_by_id_helper, leave_all_rooms, leave_room}; +pub use membership::{join_room_by_id_helper, leave_all_rooms, leave_room, remote_leave_room}; pub(super) use message::*; pub(super) use openid::*; pub(super) use presence::*;