1
0
Fork 0
mirror of https://gitlab.com/famedly/conduit.git synced 2025-06-27 16:35:59 +00:00

feat(admin-room): Delete create-user command message

- Add the `event_id` of the user message to `AdminRoomEvent::ProcessMessage`
variant to work with it in `process_admin_message`
- Delete the user `create-user` command message if it's contain a plain password
because the admin room are unencrypted so the password
will be saved in the database if we didn't deleted it
- Create new function that delete the messages from admin room
called `delete_user_message`

Reported-by: Matthias Ahouansou <matthias@ahouansou.cz>
Helped-by: Matthias Ahouansou <matthias@ahouansou.cz>
Related-to: https://gitlab.com/famedly/conduit/-/issues/432
Signed-off-by: Awiteb <a@4rs.nl>
This commit is contained in:
Awiteb 2024-04-14 14:59:03 +03:00
parent 53d3f9ae89
commit 8a307dabd2
No known key found for this signature in database
GPG key ID: 3F6B55640AA6682F
2 changed files with 77 additions and 7 deletions

View file

@ -20,6 +20,7 @@ use ruma::{
message::RoomMessageEventContent, message::RoomMessageEventContent,
name::RoomNameEventContent, name::RoomNameEventContent,
power_levels::RoomPowerLevelsEventContent, power_levels::RoomPowerLevelsEventContent,
redaction::RoomRedactionEventContent,
topic::RoomTopicEventContent, topic::RoomTopicEventContent,
}, },
TimelineEventType, TimelineEventType,
@ -182,7 +183,7 @@ enum AdminCommand {
#[derive(Debug)] #[derive(Debug)]
pub enum AdminRoomEvent { pub enum AdminRoomEvent {
ProcessMessage(String), ProcessMessage(String, ruma::OwnedEventId),
SendMessage(RoomMessageEventContent), SendMessage(RoomMessageEventContent),
} }
@ -221,7 +222,7 @@ impl Service {
Some(event) = receiver.recv() => { Some(event) = receiver.recv() => {
let message_content = match event { let message_content = match event {
AdminRoomEvent::SendMessage(content) => content, 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( 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 self.sender
.send(AdminRoomEvent::ProcessMessage(room_message)) .send(AdminRoomEvent::ProcessMessage(
room_message,
event_id.into(),
))
.unwrap(); .unwrap();
} }
@ -270,8 +274,57 @@ impl Service {
.unwrap(); .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 // 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 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 command_line = lines.next().expect("each string has at least one line");
let body: Vec<_> = lines.collect(); 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, Ok(reply_message) => reply_message,
Err(error) => { Err(error) => {
let markdown_message = format!( let markdown_message = format!(
@ -330,6 +386,7 @@ impl Service {
&self, &self,
command: AdminCommand, command: AdminCommand,
body: Vec<&str>, body: Vec<&str>,
event_id: &EventId,
) -> Result<RoomMessageEventContent> { ) -> Result<RoomMessageEventContent> {
let reply_message_content = match command { let reply_message_content = match command {
AdminCommand::RegisterAppservice => { AdminCommand::RegisterAppservice => {
@ -591,6 +648,7 @@ impl Service {
} }
} }
AdminCommand::CreateUser { username, password } => { AdminCommand::CreateUser { username, password } => {
let is_auto_generated_password = password.is_none();
let password = let password =
password.unwrap_or_else(|| utils::random_string(AUTO_GEN_PASSWORD_LENGTH)); password.unwrap_or_else(|| utils::random_string(AUTO_GEN_PASSWORD_LENGTH));
// Validate user id // Validate user id
@ -645,6 +703,18 @@ impl Service {
.expect("to json value always works"), .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 // we dont add a device since we're not the user, just the creator
// Inhibit login does not work for guests // Inhibit login does not work for guests

View file

@ -499,7 +499,7 @@ impl Service {
if let Some(admin_room) = services().admin.get_admin_room()? { if let Some(admin_room) = services().admin.get_admin_room()? {
if to_conduit && !from_conduit && admin_room == pdu.room_id { if to_conduit && !from_conduit && admin_room == pdu.room_id {
services().admin.process_message(body); services().admin.process_message(body, &pdu.event_id);
} }
} }
} }