@ -20,6 +20,7 @@ use ruma::{
message ::RoomMessageEventContent ,
name ::RoomNameEventContent ,
power_levels ::RoomPowerLevelsEventContent ,
redaction ::RoomRedactionEventContent ,
topic ::RoomTopicEventContent ,
} ,
TimelineEventType ,
@ -182,7 +183,7 @@ enum AdminCommand {
#[ derive(Debug) ]
pub enum AdminRoomEvent {
ProcessMessage ( String ) ,
ProcessMessage ( String , ruma ::OwnedEventId ) ,
SendMessage ( RoomMessageEventContent ) ,
}
@ -221,7 +222,7 @@ impl Service {
Some ( event ) = receiver . recv ( ) = > {
let message_content = match event {
AdminRoomEvent ::SendMessage ( content ) = > content ,
AdminRoomEvent ::ProcessMessage ( room_message ) = > self . process_admin_message ( room_message ) . await
AdminRoomEvent ::ProcessMessage ( room_message , event_id ) = > self . process_admin_message ( room_message , & event_id ) . await
} ;
let mutex_state = Arc ::clone (
@ -258,9 +259,12 @@ impl Service {
}
}
pub fn process_message ( & self , room_message : String ) {
pub fn process_message ( & self , room_message : String , event_id : & EventId ) {
self . sender
. send ( AdminRoomEvent ::ProcessMessage ( room_message ) )
. send ( AdminRoomEvent ::ProcessMessage (
room_message ,
event_id . into ( ) ,
) )
. unwrap ( ) ;
}
@ -270,8 +274,57 @@ impl Service {
. unwrap ( ) ;
}
/// Delete user message in the conduit admin room.
pub async fn delete_user_message (
& self ,
event_id : & EventId ,
reason : Option < impl Into < String > > ,
) -> Result < ( ) > {
let conduit_user =
UserId ::parse_with_server_name ( "conduit" , services ( ) . globals . server_name ( ) )
. expect ( "@conduit:server_name is valid" ) ;
if let Some ( room_id ) = services ( ) . admin . get_admin_room ( ) ? {
let mutex_state = Arc ::clone (
services ( )
. globals
. roomid_mutex_state
. write ( )
. await
. entry ( room_id . clone ( ) )
. or_default ( ) ,
) ;
let state_lock = mutex_state . lock ( ) . await ;
services ( )
. rooms
. timeline
. build_and_append_pdu (
PduBuilder {
event_type : TimelineEventType ::RoomRedaction ,
content : to_raw_value ( & RoomRedactionEventContent {
redacts : Some ( event_id . into ( ) ) ,
reason : reason . map ( Into ::into ) ,
} )
. expect ( "event is valid, we just created it" ) ,
unsigned : None ,
state_key : None ,
redacts : Some ( event_id . into ( ) ) ,
} ,
& conduit_user ,
& room_id ,
& state_lock ,
)
. await ? ;
}
Ok ( ( ) )
}
// Parse and process a message from the admin room
async fn process_admin_message ( & self , room_message : String ) -> RoomMessageEventContent {
async fn process_admin_message (
& self ,
room_message : String ,
event_id : & EventId ,
) -> RoomMessageEventContent {
let mut lines = room_message . lines ( ) . filter ( | l | ! l . trim ( ) . is_empty ( ) ) ;
let command_line = lines . next ( ) . expect ( "each string has at least one line" ) ;
let body : Vec < _ > = lines . collect ( ) ;
@ -287,7 +340,10 @@ impl Service {
}
} ;
match self . process_admin_command ( admin_command , body ) . await {
match self
. process_admin_command ( admin_command , body , event_id )
. await
{
Ok ( reply_message ) = > reply_message ,
Err ( error ) = > {
let markdown_message = format! (
@ -330,6 +386,7 @@ impl Service {
& self ,
command : AdminCommand ,
body : Vec < & str > ,
event_id : & EventId ,
) -> Result < RoomMessageEventContent > {
let reply_message_content = match command {
AdminCommand ::RegisterAppservice = > {
@ -591,6 +648,7 @@ impl Service {
}
}
AdminCommand ::CreateUser { username , password } = > {
let is_auto_generated_password = password . is_none ( ) ;
let password =
password . unwrap_or_else ( | | utils ::random_string ( AUTO_GEN_PASSWORD_LENGTH ) ) ;
// Validate user id
@ -645,6 +703,18 @@ impl Service {
. expect ( "to json value always works" ) ,
) ? ;
// We'll delete the user message because it's contain a plain password
// and the admin room are not encrypted
if ! is_auto_generated_password {
services ( )
. admin
. delete_user_message (
event_id ,
Some ( "Message contained a plaintext password" ) ,
)
. await ? ;
}
// we dont add a device since we're not the user, just the creator
// Inhibit login does not work for guests