implement admin command to force join list of local users
Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
parent
0a281241ef
commit
c71db93e22
2 changed files with 153 additions and 1 deletions
|
@ -1,7 +1,11 @@
|
||||||
use std::{collections::BTreeMap, fmt::Write as _};
|
use std::{collections::BTreeMap, fmt::Write as _};
|
||||||
|
|
||||||
use api::client::{full_user_deactivate, join_room_by_id_helper, leave_room};
|
use api::client::{full_user_deactivate, join_room_by_id_helper, leave_room};
|
||||||
use conduit::{error, info, is_equal_to, utils, warn, PduBuilder, Result};
|
use conduit::{
|
||||||
|
debug_warn, error, info, is_equal_to,
|
||||||
|
utils::{self, ReadyExt},
|
||||||
|
warn, PduBuilder, Result,
|
||||||
|
};
|
||||||
use conduit_api::client::{leave_all_rooms, update_avatar_url, update_displayname};
|
use conduit_api::client::{leave_all_rooms, update_avatar_url, update_displayname};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
|
@ -376,6 +380,139 @@ pub(super) async fn list_joined_rooms(&self, user_id: String) -> Result<RoomMess
|
||||||
Ok(RoomMessageEventContent::notice_markdown(output_plain))
|
Ok(RoomMessageEventContent::notice_markdown(output_plain))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[admin_command]
|
||||||
|
pub(super) async fn force_join_list_of_local_users(
|
||||||
|
&self, room_id: OwnedRoomOrAliasId, yes_i_want_to_do_this: bool,
|
||||||
|
) -> Result<RoomMessageEventContent> {
|
||||||
|
const REASON: &str = "Bulk force joining this room as initiated by the server admin.";
|
||||||
|
|
||||||
|
if self.body.len() < 2 || !self.body[0].trim().starts_with("```") || self.body.last().unwrap_or(&"").trim() != "```"
|
||||||
|
{
|
||||||
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
|
"Expected code block in command body. Add --help for details.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !yes_i_want_to_do_this {
|
||||||
|
return Ok(RoomMessageEventContent::notice_markdown(
|
||||||
|
"You must pass the --yes-i-want-to-do-this-flag to ensure you really want to force bulk join all \
|
||||||
|
specified local users.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let Ok(admin_room) = self.services.admin.get_admin_room().await else {
|
||||||
|
return Ok(RoomMessageEventContent::notice_markdown(
|
||||||
|
"There is not an admin room to check for server admins.",
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
let (room_id, servers) = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.alias
|
||||||
|
.resolve_with_servers(&room_id, None)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if !self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.server_in_room(self.services.globals.server_name(), &room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
return Ok(RoomMessageEventContent::notice_markdown("We are not joined in this room."));
|
||||||
|
}
|
||||||
|
|
||||||
|
let server_admins: Vec<_> = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.active_local_users_in_room(&admin_room)
|
||||||
|
.map(ToOwned::to_owned)
|
||||||
|
.collect()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if !self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.room_members(&room_id)
|
||||||
|
.ready_any(|user_id| server_admins.contains(&user_id.to_owned()))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
return Ok(RoomMessageEventContent::notice_markdown(
|
||||||
|
"There is not a single server admin in the room.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let usernames = self
|
||||||
|
.body
|
||||||
|
.to_vec()
|
||||||
|
.drain(1..self.body.len().saturating_sub(1))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut user_ids: Vec<OwnedUserId> = Vec::with_capacity(usernames.len());
|
||||||
|
|
||||||
|
for username in usernames {
|
||||||
|
match parse_active_local_user_id(self.services, username).await {
|
||||||
|
Ok(user_id) => {
|
||||||
|
// don't make the server service account join
|
||||||
|
if user_id == self.services.globals.server_user {
|
||||||
|
self.services
|
||||||
|
.admin
|
||||||
|
.send_message(RoomMessageEventContent::text_plain(format!(
|
||||||
|
"{username} is the server service account, skipping over"
|
||||||
|
)))
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
user_ids.push(user_id);
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
self.services
|
||||||
|
.admin
|
||||||
|
.send_message(RoomMessageEventContent::text_plain(format!(
|
||||||
|
"{username} is not a valid username, skipping over: {e}"
|
||||||
|
)))
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut failed_joins: usize = 0;
|
||||||
|
let mut successful_joins: usize = 0;
|
||||||
|
|
||||||
|
for user_id in user_ids {
|
||||||
|
match join_room_by_id_helper(
|
||||||
|
self.services,
|
||||||
|
&user_id,
|
||||||
|
&room_id,
|
||||||
|
Some(String::from(REASON)),
|
||||||
|
&servers,
|
||||||
|
None,
|
||||||
|
&None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_res) => {
|
||||||
|
successful_joins = successful_joins.saturating_add(1);
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
debug_warn!("Failed force joining {user_id} to {room_id} during bulk join: {e}");
|
||||||
|
failed_joins = failed_joins.saturating_add(1);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(RoomMessageEventContent::notice_markdown(format!(
|
||||||
|
"{successful_joins} local users have been joined to {room_id}. {failed_joins} joins failed.",
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn force_join_room(
|
pub(super) async fn force_join_room(
|
||||||
&self, user_id: String, room_id: OwnedRoomOrAliasId,
|
&self, user_id: String, room_id: OwnedRoomOrAliasId,
|
||||||
|
|
|
@ -124,4 +124,19 @@ pub(super) enum UserCommand {
|
||||||
RedactEvent {
|
RedactEvent {
|
||||||
event_id: Box<EventId>,
|
event_id: Box<EventId>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// - Force joins a specified list of local users to join the specified
|
||||||
|
/// room.
|
||||||
|
///
|
||||||
|
/// Specify a codeblock of usernames.
|
||||||
|
///
|
||||||
|
/// At least 1 server admin must be in the room to prevent abuse.
|
||||||
|
///
|
||||||
|
/// Requires the `--yes-i-want-to-do-this` flag.
|
||||||
|
ForceJoinListOfLocalUsers {
|
||||||
|
room_id: OwnedRoomOrAliasId,
|
||||||
|
|
||||||
|
#[arg(long)]
|
||||||
|
yes_i_want_to_do_this: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue