Files
continuwuity/src/service/admin/create.rs
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

237 lines
5.5 KiB
Rust
Raw Normal View History

2026-04-10 11:47:01 -04:00
use conduwuit::{Result, info, pdu::PartialPdu};
2025-04-08 03:17:23 +00:00
use futures::FutureExt;
2024-06-10 06:02:17 +00:00
use ruma::{
Int, RoomId,
events::{
TimelineEventType,
room::{
canonical_alias::RoomCanonicalAliasEventContent,
create::RoomCreateEventContent,
guest_access::{GuestAccess, RoomGuestAccessEventContent},
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
join_rules::{JoinRule, RoomJoinRulesEventContent},
member::{MembershipState, RoomMemberEventContent},
name::RoomNameEventContent,
power_levels::RoomPowerLevelsEventContent,
topic::RoomTopicEventContent,
},
2024-06-10 06:02:17 +00:00
},
room_version_rules::RoomIdFormatVersion,
2024-06-10 06:02:17 +00:00
};
2024-07-20 23:38:20 +00:00
use crate::Services;
2024-06-10 06:02:17 +00:00
/// Create the admin room.
///
/// Users in this room are considered admins by conduwuit, and the room can be
2024-06-10 06:02:17 +00:00
/// used to issue admin commands by talking to the server user inside it.
pub async fn create_admin_room(services: &Services) -> Result {
let room_version = services.config.default_room_version.clone();
let room_version_rules = room_version
.rules()
.expect("default_room_version must be supported");
let room_id = match room_version_rules.room_id_format {
| RoomIdFormatVersion::V1 => {
let room_id = RoomId::new_v1(services.globals.server_name());
services
.rooms
.short
.get_or_create_shortroomid(&room_id)
.await;
Some(room_id)
},
| RoomIdFormatVersion::V2 => None,
| _ => panic!("Unknown room version format"),
};
2024-06-10 06:02:17 +00:00
let state_lock = services.rooms.state.mutex.lock("!new-room").await;
2024-06-10 06:02:17 +00:00
// Create a user for the server
let server_user = services.globals.server_user.as_ref();
services.users.create_shadow_account(server_user).await?;
2024-06-10 06:02:17 +00:00
let mut create_content = if room_version_rules.authorization.use_room_create_sender {
RoomCreateEventContent::new_v1(server_user.into())
} else {
RoomCreateEventContent::new_v11()
2024-06-10 06:02:17 +00:00
};
create_content.federate = true;
create_content.room_version = room_version.clone();
info!(
"Creating admin room {} with version {}",
room_id
.clone()
.map_or_else(|| "<not known ahead of time>".to_owned(), |id| id.as_str().to_owned()),
room_version
);
2025-09-17 20:46:03 +00:00
2024-06-10 06:02:17 +00:00
// 1. The room create event
let create_event_id = services
2024-06-10 06:02:17 +00:00
.rooms
.timeline
.build_and_append_pdu(
2026-04-10 11:47:01 -04:00
PartialPdu::state(String::new(), &create_content),
2024-06-10 06:02:17 +00:00
server_user,
room_id.as_deref(),
2024-06-10 06:02:17 +00:00
&state_lock,
)
2025-04-08 03:17:23 +00:00
.boxed()
2024-06-10 06:02:17 +00:00
.await?;
let room_id = room_id.unwrap_or_else(|| {
RoomId::new_v2(
create_event_id
.as_str()
.strip_prefix("$")
.expect("event ID must start with a $ sigil"),
)
.expect("event ID without sigil must be a valid room ID")
});
2024-06-10 06:02:17 +00:00
2024-12-14 21:58:01 -05:00
// 2. Make server user/bot join
2024-07-20 23:38:20 +00:00
services
2024-06-10 06:02:17 +00:00
.rooms
.timeline
.build_and_append_pdu(
2026-04-10 11:47:01 -04:00
PartialPdu::state(
String::from(server_user),
&RoomMemberEventContent::new(MembershipState::Join),
),
2024-06-10 06:02:17 +00:00
server_user,
2025-09-17 20:46:03 +00:00
Some(&room_id),
2024-06-10 06:02:17 +00:00
&state_lock,
)
2025-04-08 03:17:23 +00:00
.boxed()
2024-06-10 06:02:17 +00:00
.await?;
// 3. Power levels
let mut power_levels_content =
RoomPowerLevelsEventContent::new(&room_version_rules.authorization);
if !room_version_rules
.authorization
.explicitly_privilege_room_creators
{
power_levels_content
.users
.insert(server_user.into(), Int::MAX);
}
// Prevent common foot-shotguns
power_levels_content
.events
.insert(TimelineEventType::RoomTombstone, Int::MAX);
power_levels_content
.events
.insert(TimelineEventType::RoomEncryption, Int::MAX);
power_levels_content
.events
.insert(TimelineEventType::RoomCanonicalAlias, Int::MAX);
power_levels_content.invite = power_levels_content.state_default;
2024-07-20 23:38:20 +00:00
services
2024-06-10 06:02:17 +00:00
.rooms
.timeline
.build_and_append_pdu(
2026-04-10 11:47:01 -04:00
PartialPdu::state(String::new(), &power_levels_content),
2024-06-10 06:02:17 +00:00
server_user,
2025-09-17 20:46:03 +00:00
Some(&room_id),
2024-06-10 06:02:17 +00:00
&state_lock,
)
2025-04-08 03:17:23 +00:00
.boxed()
2024-06-10 06:02:17 +00:00
.await?;
// 4.1 Join Rules
2024-07-20 23:38:20 +00:00
services
2024-06-10 06:02:17 +00:00
.rooms
.timeline
.build_and_append_pdu(
2026-04-10 11:47:01 -04:00
PartialPdu::state(String::new(), &RoomJoinRulesEventContent::new(JoinRule::Invite)),
2024-06-10 06:02:17 +00:00
server_user,
2025-09-17 20:46:03 +00:00
Some(&room_id),
2024-06-10 06:02:17 +00:00
&state_lock,
)
2025-04-08 03:17:23 +00:00
.boxed()
2024-06-10 06:02:17 +00:00
.await?;
// 4.2 History Visibility
2024-07-20 23:38:20 +00:00
services
2024-06-10 06:02:17 +00:00
.rooms
.timeline
.build_and_append_pdu(
2026-04-10 11:47:01 -04:00
PartialPdu::state(
String::new(),
&RoomHistoryVisibilityEventContent::new(HistoryVisibility::Shared),
),
2024-06-10 06:02:17 +00:00
server_user,
2025-09-17 20:46:03 +00:00
Some(&room_id),
2024-06-10 06:02:17 +00:00
&state_lock,
)
2025-04-08 03:17:23 +00:00
.boxed()
2024-06-10 06:02:17 +00:00
.await?;
// 4.3 Guest Access
2024-07-20 23:38:20 +00:00
services
2024-06-10 06:02:17 +00:00
.rooms
.timeline
.build_and_append_pdu(
2026-04-10 11:47:01 -04:00
PartialPdu::state(
String::new(),
&RoomGuestAccessEventContent::new(GuestAccess::Forbidden),
),
2024-06-10 06:02:17 +00:00
server_user,
2025-09-17 20:46:03 +00:00
Some(&room_id),
2024-06-10 06:02:17 +00:00
&state_lock,
)
2025-04-08 03:17:23 +00:00
.boxed()
2024-06-10 06:02:17 +00:00
.await?;
// 5. Events implied by name and topic
let room_name = format!("{} Admin Room", services.config.server_name);
2024-07-20 23:38:20 +00:00
services
2024-06-10 06:02:17 +00:00
.rooms
.timeline
.build_and_append_pdu(
2026-04-10 11:47:01 -04:00
PartialPdu::state(String::new(), &RoomNameEventContent::new(room_name)),
2024-06-10 06:02:17 +00:00
server_user,
2025-09-17 20:46:03 +00:00
Some(&room_id),
2024-06-10 06:02:17 +00:00
&state_lock,
)
2025-04-08 03:17:23 +00:00
.boxed()
2024-06-10 06:02:17 +00:00
.await?;
let room_topic = format!("Manage {} | Run commands prefixed with `!admin` | Run `!admin -h` for help | Documentation: https://continuwuity.org/", services.config.server_name);
2024-07-20 23:38:20 +00:00
services
2024-06-10 06:02:17 +00:00
.rooms
.timeline
.build_and_append_pdu(
2026-04-10 11:47:01 -04:00
PartialPdu::state(String::new(), &RoomTopicEventContent::markdown(room_topic)),
2024-06-10 06:02:17 +00:00
server_user,
2025-09-17 20:46:03 +00:00
Some(&room_id),
2024-06-10 06:02:17 +00:00
&state_lock,
)
2025-04-08 03:17:23 +00:00
.boxed()
2024-06-10 06:02:17 +00:00
.await?;
// 6. Room alias
let mut alias_content = RoomCanonicalAliasEventContent::new();
alias_content.alias = Some(services.globals.admin_alias.clone());
2024-06-10 06:02:17 +00:00
2024-07-20 23:38:20 +00:00
services
2024-06-10 06:02:17 +00:00
.rooms
.timeline
.build_and_append_pdu(
2026-04-10 11:47:01 -04:00
PartialPdu::state(String::new(), &alias_content),
2024-06-10 06:02:17 +00:00
server_user,
2025-09-17 20:46:03 +00:00
Some(&room_id),
2024-06-10 06:02:17 +00:00
&state_lock,
)
2025-04-08 03:17:23 +00:00
.boxed()
2024-06-10 06:02:17 +00:00
.await?;
2024-07-20 23:38:20 +00:00
services
2024-06-10 06:02:17 +00:00
.rooms
.alias
.set_alias(&services.globals.admin_alias, &room_id, server_user)?;
2024-06-10 06:02:17 +00:00
Ok(())
}