|
|
|
|
@ -214,50 +214,51 @@ impl Service {
|
|
|
|
|
let conduit_user = UserId::parse(format!("@conduit:{}", services().globals.server_name())) |
|
|
|
|
.expect("@conduit:server_name is valid"); |
|
|
|
|
|
|
|
|
|
let conduit_room = services().admin.get_admin_room(); |
|
|
|
|
|
|
|
|
|
let send_message = |message: RoomMessageEventContent, mutex_lock: &MutexGuard<'_, ()>| { |
|
|
|
|
services() |
|
|
|
|
.rooms |
|
|
|
|
.timeline |
|
|
|
|
.build_and_append_pdu( |
|
|
|
|
PduBuilder { |
|
|
|
|
event_type: TimelineEventType::RoomMessage, |
|
|
|
|
content: to_raw_value(&message) |
|
|
|
|
.expect("event is valid, we just created it"), |
|
|
|
|
unsigned: None, |
|
|
|
|
state_key: None, |
|
|
|
|
redacts: None, |
|
|
|
|
}, |
|
|
|
|
&conduit_user, |
|
|
|
|
&conduit_room, |
|
|
|
|
mutex_lock, |
|
|
|
|
) |
|
|
|
|
.unwrap(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
loop { |
|
|
|
|
tokio::select! { |
|
|
|
|
Some(event) = receiver.recv() => { |
|
|
|
|
let message_content = match event { |
|
|
|
|
AdminRoomEvent::SendMessage(content) => content, |
|
|
|
|
AdminRoomEvent::ProcessMessage(room_message) => self.process_admin_message(room_message).await |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
let mutex_state = Arc::clone( |
|
|
|
|
services().globals |
|
|
|
|
.roomid_mutex_state |
|
|
|
|
.write() |
|
|
|
|
.unwrap() |
|
|
|
|
.entry(conduit_room.to_owned()) |
|
|
|
|
.or_default(), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
let state_lock = mutex_state.lock().await; |
|
|
|
|
|
|
|
|
|
send_message(message_content, &state_lock); |
|
|
|
|
|
|
|
|
|
drop(state_lock); |
|
|
|
|
if let Ok(Some(conduit_room)) = services().admin.get_admin_room() { |
|
|
|
|
let send_message = |message: RoomMessageEventContent, |
|
|
|
|
mutex_lock: &MutexGuard<'_, ()>| { |
|
|
|
|
services() |
|
|
|
|
.rooms |
|
|
|
|
.timeline |
|
|
|
|
.build_and_append_pdu( |
|
|
|
|
PduBuilder { |
|
|
|
|
event_type: TimelineEventType::RoomMessage, |
|
|
|
|
content: to_raw_value(&message) |
|
|
|
|
.expect("event is valid, we just created it"), |
|
|
|
|
unsigned: None, |
|
|
|
|
state_key: None, |
|
|
|
|
redacts: None, |
|
|
|
|
}, |
|
|
|
|
&conduit_user, |
|
|
|
|
&conduit_room, |
|
|
|
|
mutex_lock, |
|
|
|
|
) |
|
|
|
|
.unwrap(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
loop { |
|
|
|
|
tokio::select! { |
|
|
|
|
Some(event) = receiver.recv() => { |
|
|
|
|
let message_content = match event { |
|
|
|
|
AdminRoomEvent::SendMessage(content) => content, |
|
|
|
|
AdminRoomEvent::ProcessMessage(room_message) => self.process_admin_message(room_message).await |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
let mutex_state = Arc::clone( |
|
|
|
|
services().globals |
|
|
|
|
.roomid_mutex_state |
|
|
|
|
.write() |
|
|
|
|
.unwrap() |
|
|
|
|
.entry(conduit_room.to_owned()) |
|
|
|
|
.or_default(), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
let state_lock = mutex_state.lock().await; |
|
|
|
|
|
|
|
|
|
send_message(message_content, &state_lock); |
|
|
|
|
|
|
|
|
|
drop(state_lock); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -1097,9 +1098,8 @@ impl Service {
|
|
|
|
|
|
|
|
|
|
/// 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
|
|
|
|
|
// ^ was the case before this function when the following code was re-used in multiple places
|
|
|
|
|
pub(crate) fn get_admin_room(&self) -> OwnedRoomId { |
|
|
|
|
/// 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() |
|
|
|
|
@ -1109,8 +1109,6 @@ impl Service {
|
|
|
|
|
.rooms |
|
|
|
|
.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.
|
|
|
|
|
@ -1121,94 +1119,93 @@ impl Service {
|
|
|
|
|
user_id: &UserId, |
|
|
|
|
displayname: String, |
|
|
|
|
) -> Result<()> { |
|
|
|
|
let room_id = services().admin.get_admin_room(); |
|
|
|
|
|
|
|
|
|
let mutex_state = Arc::clone( |
|
|
|
|
services() |
|
|
|
|
.globals |
|
|
|
|
.roomid_mutex_state |
|
|
|
|
.write() |
|
|
|
|
.unwrap() |
|
|
|
|
.entry(room_id.clone()) |
|
|
|
|
.or_default(), |
|
|
|
|
); |
|
|
|
|
let state_lock = mutex_state.lock().await; |
|
|
|
|
|
|
|
|
|
// Use the server user to grant the new admin's power level
|
|
|
|
|
let conduit_user = |
|
|
|
|
UserId::parse_with_server_name("conduit", services().globals.server_name()) |
|
|
|
|
.expect("@conduit:server_name is valid"); |
|
|
|
|
|
|
|
|
|
// Invite and join the real user
|
|
|
|
|
services().rooms.timeline.build_and_append_pdu( |
|
|
|
|
PduBuilder { |
|
|
|
|
event_type: TimelineEventType::RoomMember, |
|
|
|
|
content: to_raw_value(&RoomMemberEventContent { |
|
|
|
|
membership: MembershipState::Invite, |
|
|
|
|
displayname: None, |
|
|
|
|
avatar_url: None, |
|
|
|
|
is_direct: None, |
|
|
|
|
third_party_invite: None, |
|
|
|
|
blurhash: None, |
|
|
|
|
reason: None, |
|
|
|
|
join_authorized_via_users_server: None, |
|
|
|
|
}) |
|
|
|
|
.expect("event is valid, we just created it"), |
|
|
|
|
unsigned: None, |
|
|
|
|
state_key: Some(user_id.to_string()), |
|
|
|
|
redacts: None, |
|
|
|
|
}, |
|
|
|
|
&conduit_user, |
|
|
|
|
&room_id, |
|
|
|
|
&state_lock, |
|
|
|
|
)?; |
|
|
|
|
services().rooms.timeline.build_and_append_pdu( |
|
|
|
|
PduBuilder { |
|
|
|
|
event_type: TimelineEventType::RoomMember, |
|
|
|
|
content: to_raw_value(&RoomMemberEventContent { |
|
|
|
|
membership: MembershipState::Join, |
|
|
|
|
displayname: Some(displayname), |
|
|
|
|
avatar_url: None, |
|
|
|
|
is_direct: None, |
|
|
|
|
third_party_invite: None, |
|
|
|
|
blurhash: None, |
|
|
|
|
reason: None, |
|
|
|
|
join_authorized_via_users_server: None, |
|
|
|
|
}) |
|
|
|
|
.expect("event is valid, we just created it"), |
|
|
|
|
unsigned: None, |
|
|
|
|
state_key: Some(user_id.to_string()), |
|
|
|
|
redacts: None, |
|
|
|
|
}, |
|
|
|
|
user_id, |
|
|
|
|
&room_id, |
|
|
|
|
&state_lock, |
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
// Set power level
|
|
|
|
|
let mut users = BTreeMap::new(); |
|
|
|
|
users.insert(conduit_user.to_owned(), 100.into()); |
|
|
|
|
users.insert(user_id.to_owned(), 100.into()); |
|
|
|
|
|
|
|
|
|
services().rooms.timeline.build_and_append_pdu( |
|
|
|
|
PduBuilder { |
|
|
|
|
event_type: TimelineEventType::RoomPowerLevels, |
|
|
|
|
content: to_raw_value(&RoomPowerLevelsEventContent { |
|
|
|
|
users, |
|
|
|
|
..Default::default() |
|
|
|
|
}) |
|
|
|
|
.expect("event is valid, we just created it"), |
|
|
|
|
unsigned: None, |
|
|
|
|
state_key: Some("".to_owned()), |
|
|
|
|
redacts: None, |
|
|
|
|
}, |
|
|
|
|
&conduit_user, |
|
|
|
|
&room_id, |
|
|
|
|
&state_lock, |
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
// Send welcome message
|
|
|
|
|
services().rooms.timeline.build_and_append_pdu( |
|
|
|
|
if let Some(room_id) = services().admin.get_admin_room()? { |
|
|
|
|
let mutex_state = Arc::clone( |
|
|
|
|
services() |
|
|
|
|
.globals |
|
|
|
|
.roomid_mutex_state |
|
|
|
|
.write() |
|
|
|
|
.unwrap() |
|
|
|
|
.entry(room_id.clone()) |
|
|
|
|
.or_default(), |
|
|
|
|
); |
|
|
|
|
let state_lock = mutex_state.lock().await; |
|
|
|
|
|
|
|
|
|
// Use the server user to grant the new admin's power level
|
|
|
|
|
let conduit_user = |
|
|
|
|
UserId::parse_with_server_name("conduit", services().globals.server_name()) |
|
|
|
|
.expect("@conduit:server_name is valid"); |
|
|
|
|
|
|
|
|
|
// Invite and join the real user
|
|
|
|
|
services().rooms.timeline.build_and_append_pdu( |
|
|
|
|
PduBuilder { |
|
|
|
|
event_type: TimelineEventType::RoomMember, |
|
|
|
|
content: to_raw_value(&RoomMemberEventContent { |
|
|
|
|
membership: MembershipState::Invite, |
|
|
|
|
displayname: None, |
|
|
|
|
avatar_url: None, |
|
|
|
|
is_direct: None, |
|
|
|
|
third_party_invite: None, |
|
|
|
|
blurhash: None, |
|
|
|
|
reason: None, |
|
|
|
|
join_authorized_via_users_server: None, |
|
|
|
|
}) |
|
|
|
|
.expect("event is valid, we just created it"), |
|
|
|
|
unsigned: None, |
|
|
|
|
state_key: Some(user_id.to_string()), |
|
|
|
|
redacts: None, |
|
|
|
|
}, |
|
|
|
|
&conduit_user, |
|
|
|
|
&room_id, |
|
|
|
|
&state_lock, |
|
|
|
|
)?; |
|
|
|
|
services().rooms.timeline.build_and_append_pdu( |
|
|
|
|
PduBuilder { |
|
|
|
|
event_type: TimelineEventType::RoomMember, |
|
|
|
|
content: to_raw_value(&RoomMemberEventContent { |
|
|
|
|
membership: MembershipState::Join, |
|
|
|
|
displayname: Some(displayname), |
|
|
|
|
avatar_url: None, |
|
|
|
|
is_direct: None, |
|
|
|
|
third_party_invite: None, |
|
|
|
|
blurhash: None, |
|
|
|
|
reason: None, |
|
|
|
|
join_authorized_via_users_server: None, |
|
|
|
|
}) |
|
|
|
|
.expect("event is valid, we just created it"), |
|
|
|
|
unsigned: None, |
|
|
|
|
state_key: Some(user_id.to_string()), |
|
|
|
|
redacts: None, |
|
|
|
|
}, |
|
|
|
|
user_id, |
|
|
|
|
&room_id, |
|
|
|
|
&state_lock, |
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
// Set power level
|
|
|
|
|
let mut users = BTreeMap::new(); |
|
|
|
|
users.insert(conduit_user.to_owned(), 100.into()); |
|
|
|
|
users.insert(user_id.to_owned(), 100.into()); |
|
|
|
|
|
|
|
|
|
services().rooms.timeline.build_and_append_pdu( |
|
|
|
|
PduBuilder { |
|
|
|
|
event_type: TimelineEventType::RoomPowerLevels, |
|
|
|
|
content: to_raw_value(&RoomPowerLevelsEventContent { |
|
|
|
|
users, |
|
|
|
|
..Default::default() |
|
|
|
|
}) |
|
|
|
|
.expect("event is valid, we just created it"), |
|
|
|
|
unsigned: None, |
|
|
|
|
state_key: Some("".to_owned()), |
|
|
|
|
redacts: None, |
|
|
|
|
}, |
|
|
|
|
&conduit_user, |
|
|
|
|
&room_id, |
|
|
|
|
&state_lock, |
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
// Send welcome message
|
|
|
|
|
services().rooms.timeline.build_and_append_pdu( |
|
|
|
|
PduBuilder { |
|
|
|
|
event_type: TimelineEventType::RoomMessage, |
|
|
|
|
content: to_raw_value(&RoomMessageEventContent::text_html( |
|
|
|
|
@ -1225,7 +1222,10 @@ impl Service {
|
|
|
|
|
&state_lock, |
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
Ok(()) |
|
|
|
|
} else { |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|